Lay the cross-cutting platform backbone every later phase reads from. Adds the first marketplace EF migration baseline (new `ops` schema) and the mechanisms b2..b15 reuse: typed runtime config, an append-only audit trail, an analytics event log, the holiday/bank-closure calendar, in-app notifications, and the internal support-alert worklist. Schema & migration - New `ops` schema + migration InitialMarketplaceBaseline with 6 tables: PlatformConfigs (IAuditable), AuditLogs (append-only), SystemEvents, IranianHolidays, Notifications, SupportAlerts — with indexes/uniques and FKs to usr.Users. Seeded 12 config keys + 7 sample holidays via HasData. Domain / Application - IAuditable marker + [AuditRedacted] attribute; entities + string-code constant holders (config data_type, holiday type, alert type/severity/status). - Facade contracts: IPlatformConfig, IHolidayCalendar, IAnalyticsSink, IAuditLogger, INotificationService, ISupportAlertService; DTOs + PagedResult<T>; evolved the INotificationDispatcher.Notification record to carry Type + DataJson; Pagination helper. - 14 CQRS commands/queries (+ validators) wiring the endpoints to the facades. Infrastructure - DB-backed facade implementations in Persistence/Services/; real in-app INotificationDispatcher (removes the b0 log stub); notification-retention hosted service (purge is_read=1 AND age>90d). - Extended AuditFieldInterceptor to also append an old/new-diff audit_logs row for every IAuditable change in the same transaction (PII redacted). - Registered all facades + hosted service in AddPersistenceServices; removed the dispatcher registration from AddCrossCuttingSeams. API - 5 controllers: admin PlatformConfig/Holidays/Audit/SupportAlerts ([Authorize(DynamicPermission)]) + current-user Notifications ([Authorize]), all tenant-scoped and paginated. 16 Swagger paths total. Money-correctness & safety rules honoured - Config read at compute time (cached, parsed by data_type), never hardcoded; every config change is audited in the same transaction; audit_logs is append-only (no update/delete path); support alerts are admin-only; notifications are tenant-scoped; analytics is fire-and-forget. Tests & docs - 18 new foundation tests over in-memory SQLite (config typing + audit, holidays, notifications + tenancy + retention, support alerts, analytics); build clean (0 new code warnings), 22 tests green; migration applied to the dev DB and swagger.v1.json refreshed. - Updated server Project map + CONVENTIONS, product data-model doc 12 (seeded config defaults), config-reference contract, mock registry, backend handoff/ STATUS/report. Follow-ups: add FK constraints for SupportAlerts.BookingId (b9) and ReviewId (b14) when those tables land. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Shared working context — the parallel-agent handoff
This folder lets a backend agent and a frontend agent work at the same time without ever
editing the same file. It is the running, append-only record of what each side has done and what it
needs from the other. (Stable API shapes live in ../contracts/; this folder
is the running coordination on top of them.)
Lane ownership — the one rule that keeps it safe
Each lane writes only its own files. Neither lane edits the other's.
| Lane | Writes (only) | Reads |
|---|---|---|
| Backend | backend/STATUS.md, backend/handoff/after-backend-phase-N.md (new file per phase), reports/backend-phase-N-report.md, reports/mocks-registry.md |
frontend/requests/for-backend.md, prior backend handoffs |
| Frontend | frontend/STATUS.md, frontend/requests/for-backend.md (append), reports/frontend-phase-N-report.md |
backend/handoff/*, ../contracts/*, prior frontend reports |
Because each handoff is a new file per phase and each STATUS/requests file is append-only, two agents can run concurrently and only ever append — no merge conflicts, no clobbering.
Layout
shared-working-context/
├── backend/
│ ├── STATUS.md # append: one block per backend phase (what shipped, gate status)
│ └── handoff/
│ └── after-backend-phase-N.md # "context for frontend after backend phase N" (one per phase)
├── frontend/
│ ├── STATUS.md # append: one block per frontend phase
│ └── requests/
│ └── for-backend.md # append: contract gaps / shape requests the backend should fulfil
└── reports/
├── README.md # the per-phase report template
├── mocks-registry.md # master list of every mock/seam + how to make it real (backend-owned)
├── backend-phase-N-report.md # what was built / testable / mocked (one per backend phase)
└── frontend-phase-N-report.md # one per frontend phase
The handoff note (backend → frontend), per phase
backend/handoff/after-backend-phase-N.md should answer, for the frontend agent:
- Which endpoints/contracts are now live (link the
contracts/domains/*doc + the swagger snapshot). - What the frontend can now build because of this phase.
- What is mocked server-side (so the frontend knows responses are fake-but-shaped) and what's real.
- Any auth/enum/format detail the frontend must mirror.
- Open questions / things the frontend should not assume yet.
The request note (frontend → backend)
frontend/requests/for-backend.md is where the frontend appends: missing endpoints, fields it needs,
shape mismatches, pagination/filter needs — anything that should land in a later backend change. The
backend agent reads this at the start of each phase. The frontend never edits backend code to "fix" it.