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.
46 lines
3.1 KiB
Markdown
46 lines
3.1 KiB
Markdown
# 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 `ApiResult` envelope, not a
|
|
bare body. Success shape:
|
|
```json
|
|
{ "isSuccess": true, "statusCode": 0, "message": "Success", "requestId": "<trace>", "data": <T> }
|
|
```
|
|
Failure returns `400/401/403/404` with the same envelope (field-level errors for validation). This is
|
|
what `clientFetch`/`serverFetch` must 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_limited` demonstrates it
|
|
(first 5/10s OK, then 429).
|
|
- **swagger.json is published:** `dev/contracts/openapi/swagger.v1.json` (envelope schemas
|
|
`ApiResult`, `ApiResultStatusCode`, `PingQueryResult`). Generate frontend types from it.
|
|
|
|
## What b1 can rely on now
|
|
- **Audit base type:** `BaseEntity`/`IAuditableEntity` (`Domain/Common/BaseEntity.cs`) with
|
|
`CreatedAt`/`ModifiedAt` (`DateTimeOffset`) + `CreatedById`/`ModifiedById` (`int?`). New entities that
|
|
derive `BaseEntity` get audit stamping for free.
|
|
- **Audit interceptor:** `AuditFieldInterceptor` (`Infrastructure.Persistence/Interceptors/`) stamps
|
|
those fields on save from `ICurrentUser` + `IDateTimeProvider`. **b1 extends this** to also write the
|
|
append-only `audit_logs` rows — 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; deterministic `Hash`
|
|
for `*_hash` lookup columns), `ICacheService` (cache `platform_configs` / read-heavy data through it),
|
|
`IObjectStorage`, `INotificationDispatcher`. Contracts in `Application/Contracts/Common`; mocks in
|
|
`Infrastructure.CrossCutting/Seams/`; registered by `AddCrossCuttingSeams`.
|
|
- **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 documented `dotnet ef migrations add` command.
|
|
- **Rate-limit policies** `otp`/`auth`/`sensitive` are 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.
|