765cc632d5
Remove the Order demo (entity/feature/repo/config/gRPC/proto) and the three pre-marketplace migrations; regenerate a fresh InitialBaseline migration. Stand up the REST surface (PingController + System/Ping CQRS) proving the Mediator -> behaviors -> OperationResult -> ApiResult envelope end to end. Close wiring gaps: register LoggingBehavior (outermost) and add the built-in rate limiter (per-IP global + otp/auth/sensitive policies), placed before authentication. Add current-user + audit plumbing: ICurrentUser (HttpContext + null impls), rename BaseEntity audit fields to CreatedAt/ModifiedAt (DateTimeOffset) + CreatedById/ModifiedById, stamped by a new AuditFieldInterceptor. Introduce five cross-cutting seams (IDateTimeProvider, IFieldEncryptor, ICacheService, IObjectStorage, INotificationDispatcher) with in-memory/local mocks registered via AddCrossCuttingSeams. Add Baya.Test.Foundation (encryptor, audit interceptor, ping handler) and update docs, contracts (swagger.v1.json), handoff, report, and mocks registry.
3.1 KiB
3.1 KiB
After backend-phase-0 — what f0/b1 can rely on
The spine is clean and REST works. The inherited Order demo (entity/feature/repo/config/gRPC) and
the three pre-marketplace migrations are gone; Identity + JWE auth + dynamic permissions + the CQRS
behaviors + observability are untouched and the existing tests stay green. A real REST controller is
live and proves the full pipeline.
What the frontend (f0) can rely on now
- The response envelope is fixed. Every endpoint returns the server's
ApiResultenvelope, not a bare body. Success shape:Failure returns{ "isSuccess": true, "statusCode": 0, "message": "Success", "requestId": "<trace>", "data": <T> }400/401/403/404with the same envelope (field-level errors for validation). This is whatclientFetch/serverFetchmust unwrap. JSON casing is the server default (camelCase for the envelope/body properties; URL segments are snake_case). - A working endpoint to wire the type pipeline against:
GET /api/v1/ping/get_status→ApiResult<{ service, status, serverTimeUtc }>. - Rate limiting exists. Over-limit requests get
429;get_status_rate_limiteddemonstrates it (first 5/10s OK, then 429). - swagger.json is published:
dev/contracts/openapi/swagger.v1.json(envelope schemasApiResult,ApiResultStatusCode,PingQueryResult). Generate frontend types from it.
What b1 can rely on now
- Audit base type:
BaseEntity/IAuditableEntity(Domain/Common/BaseEntity.cs) withCreatedAt/ModifiedAt(DateTimeOffset) +CreatedById/ModifiedById(int?). New entities that deriveBaseEntityget audit stamping for free. - Audit interceptor:
AuditFieldInterceptor(Infrastructure.Persistence/Interceptors/) stamps those fields on save fromICurrentUser+IDateTimeProvider. b1 extends this to also write the append-onlyaudit_logsrows — the stamping plumbing and the clean extension point are in place. - Cross-cutting seams (DI-registered, mocked):
IDateTimeProvider,IFieldEncryptor(use it for every encrypted PII column — phone/national_id/IBAN/addresses/clinical notes; deterministicHashfor*_hashlookup columns),ICacheService(cacheplatform_configs/ read-heavy data through it),IObjectStorage,INotificationDispatcher. Contracts inApplication/Contracts/Common; mocks inInfrastructure.CrossCutting/Seams/; registered byAddCrossCuttingSeams. - Money rule: IRR is
long/BIGINT, integer-only, no floats (CONVENTIONS §6). - Migration baseline:
20260628191947_InitialBaseline. Add the marketplace schema on top of it; generate with the documenteddotnet ef migrations addcommand. - Rate-limit policies
otp/auth/sensitiveare defined and ready to apply via[EnableRateLimiting("...")]on the relevant endpoints (b2 auth/OTP).
Known caveat
Non-Development environments route Serilog to the logDb connection (Server=sql_server2022); if that
host isn't reachable, the API won't start there. Development logs to console/file and boots cleanly
against the configured SqlServer DB. This is pre-existing infra config, unrelated to phase-0 code.