82561c4cc6
Adds the province -> city -> district reference hierarchy (geo schema, seeded with 31 provinces + capital cities + Tehran's 22 districts), nurse service areas (district_id NULL = whole city, filtered-index-pair uniqueness -> 409), and encrypted, geocoded customer addresses with a single-primary invariant. Introduces the IGeocoder seam (mocked) and 409 Conflict on the result envelope. Public cascading lookups are cached behind a generation-token scheme with invalidate-on-admin-write. One EF migration (GeographyAddressesServiceAreas, applied). Contract + swagger snapshot + handoff/report/registry updated. 103 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
8.6 KiB
8.6 KiB
Backend status log (append-only)
One block per completed backend phase. Newest at the top. Backend lane writes here; frontend reads.
backend-phase-4 — Geography, addresses & nurse service areas — 2026-07-02
- Shipped: five tables via one migration (
GeographyAddressesServiceAreas) — newgeoschemaProvinces1:NCities1:NDistricts(+NurseServiceAreas) andusr.CustomerAddresses; seed (31 provinces + capital cities + Tehran's 22 مناطق viaHasData); 20 CQRS slices across 4 controllers (geopublic lookups incl./tree,admin_geoCRUD + set_active,nurse_service_areas,customer_addresses); newIGeocoderseam (deterministic mock,Seams:Geocoding); per-domain repos onIUnitOfWork; enc value converters for the address PII columns;409 Conflictadded toOperationResult/BaseController. Whole-city (district_id NULL) uniqueness via a filtered-index pair; single-primary address via filteredUNIQUE(customer_id) WHERE is_primary=1; geo reads cached behind a generation-token scheme with invalidate-on-admin-write. - Contracts: dev/contracts/domains/geography-addresses.md + openapi snapshot refreshed (yes — 20 new geo/service-area/address paths).
- Mocked:
IGeocoder→ 🟡 (see reports/mocks-registry.md). - Gate: build clean (0 new code warnings) / tests green (103 pass: +16
Baya.Test.Apiintegration, +12 handler unit tests). MigrationGeographyAddressesServiceAreasapplies on startup; swagger exposes all b4 paths. - Handoff: backend/handoff/after-backend-phase-4.md
- Notes for frontend:
districtId=nullmeans whole city (a real choice) everywhere. Duplicate service area → 409. Addresses come back decrypted for the owner withlatitude/longitude(nullable when ungeocoded — geocoding is mocked). Routes are action-style (admin_geo/create_city,nurse_service_areas/add,customer_addresses/create, …). Admin geo needs an admin token.
backend-phase-3 — Identity: profiles, patients & nurse bank accounts — 2026-07-02
- Shipped: four
usrtables via one migration (IdentityProfilesPatientsBankAccounts) —NurseProfiles(1:1Users; guardedis_verifiedno public setter; read-only aggregates; soft-delete),CustomerProfiles(thin payer; enc emergency contact),Patients(care recipient, tenancy-scoped;is_activearchive; encinitial_medical_notes),NurseBankAccounts(enciban+UNIQUE(iban_hash)+ filteredUNIQUE(nurse_id) WHERE is_primary=1; استعلام شبا inquiry fields); 15 CQRS slices across 4 controllers (nurse_profiles,customer_profiles,patients,nurse_bank_accounts); newIBankAccountOwnershipVerifierseam (mock = deterministic شبا match); per-domain repositories onIUnitOfWork; enc value converters for the new PII columns. Also activated FluentValidation repo-wide (AddApplicationServicesnow registers everyAbstractValidator<T>— theValidateCommandBehavior/model-state filter were previously starved). - Contracts: dev/contracts/domains/identity-profiles.md + openapi snapshot refreshed (yes — new nurse/customer/patient/bank paths).
- Mocked:
IBankAccountOwnershipVerifier→ 🟡 (see reports/mocks-registry.md). - Gate: build clean (0 new code warnings) / tests green (75 pass: +13
Baya.Test.Apiintegration, +15 handler unit tests). Migration applied to the dev DB on startup; swagger exposes all b3 paths. - Handoff: backend/handoff/after-backend-phase-3.md
- Notes for frontend: role scoping needs the role claim in the token — refresh after
select_rolebefore calling these. IBAN comes back masked (last-4).isVerified/aggregates are read-only. Patientget/updateof another customer's id → 404. Addresses/service-areas are deferred to b4.
backend-phase-2 — Identity: phone-OTP auth, sessions & roles (REST) — 2026-07-02
- Shipped: the six-endpoint REST auth surface (
auth/request_otp,auth/verify_otp,auth/refresh,auth/logout,me,me/select_role) wrapping the existing JWE/TOTP/RBAC engine; newusr.UserSessions(refresh-token rotation + revoke-all on replayed token);usr.Usersextended (Gender,NationalIdenc NULL,ShahkarVerifiedAtauto-reset on phone change,PhoneHashUNIQUE,IsActive,DeletedAt+ soft-delete filter); phone/email/national-id encrypted at rest (EF value converter overIFieldEncryptor);usr.UserRolesgrant/revoke audit trail + revoked filter; 7 roles seeded;ISmsSenderseam (mock logs the code); 3 auth config keys;OperationResult/BaseControllerlearned 401/403. - Contracts: dev/contracts/domains/identity-auth.md + openapi snapshot refreshed (yes — 22 paths).
- Mocked:
ISmsSender→ 🟡 (see reports/mocks-registry.md). - Gate: build clean (0 new code warnings) / tests green (47 pass: 10 new
Baya.Test.Apiintegration + 14 new handler unit tests). MigrationIdentitySessionsAndUserExtensionsapplied to the dev DB; full §7 flow verified live (OTP in log, tokens, 401/403/429, rotation, replay-revoke, logout stamp-kill). - Handoff: backend/handoff/after-backend-phase-2.md
- Notes for frontend: exact paths are
request_otp/verify_otp/select_role(snake_case transformer — not theotp/requestsketch). Bodies camelCase. Fresh users:roles: []→ role router →me/select_role→ refresh tokens to pick up role claims./mephone is masked. SMS is mocked — read the OTP from the server log.
backend-phase-1 — Config, reference & platform signals — 2026-07-02
- Shipped: first marketplace migration baseline (
InitialMarketplaceBaseline, newopsschema) with 6 tables (PlatformConfigs,AuditLogs,SystemEvents,IranianHolidays,Notifications,SupportAlerts) + seed (12 config keys, 7 holidays); platform-signal facadesIPlatformConfig/IHolidayCalendar/IAnalyticsSink/IAuditLogger/INotificationService/ISupportAlertService(Persistence/Services/);AuditFieldInterceptorextended to write append-onlyaudit_logsrows forIAuditableentities; real in-appINotificationDispatcher(b0 stub removed); notification-retention hosted service; 5 controllers (admin config/holidays/audit/support-alerts + current-user notifications). - Contracts:
dev/contracts/domains/config-reference.md+ openapi snapshot refreshed (yes — 16 paths). - Mocked:
IHolidayCalendar,IAnalyticsSink, retentionIJobScheduler→ 🟡;INotificationDispatcherflipped to in-app-real 🟡 (SMS/push deferred). See reports/mocks-registry.md. - Gate: build clean (0 new code warnings) / tests green (22 pass: 4 identity + 18 foundation). Migration applied to the dev DB; API boots with all 16 paths in Swagger; retention job runs on startup.
- Handoff: backend/handoff/after-backend-phase-1.md
- Notes for frontend: f14 =
notifications/*(envelope unchanged; unread-first lists;data_jsonis a typed deep-link payload). f15 = adminplatform_config/*,holidays/*,audit/get_audit_trail,support_alerts/*(DynamicPermission). Paginationpage/page_size(default 50, max 100).
backend-phase-0 — Foundation, cross-cutting seams & starter cleanup — 2026-06-28
- Shipped: removed the
Orderdemo (entity/feature/repo/config/gRPC) + 3 old migrations; freshInitialBaselinemigration; REST surface (PingController+System/PingCQRS);ICurrentUser+AuditFieldInterceptor; five cross-cutting seams (IDateTimeProvider,IFieldEncryptor,ICacheService,IObjectStorage,INotificationDispatcher) with mocks;LoggingBehavior+ rate limiter (per-IP global +otp/auth/sensitive). - Contracts:
dev/contracts/openapi/swagger.v1.jsonpublished (envelope + ping schemas). - Mocked: the 5 seams above → 🟡 (see reports/mocks-registry.md).
- Gate: build clean (0 new warnings) / tests green (10 pass). Live API verified vs
192.168.100.14(migration applied + seeded; ping200; rate-limit429). - Handoff: backend/handoff/after-backend-phase-0.md
- Notes for frontend:
ApiResultenvelope is fixed (camelCase body, snake_case URLs);GET /api/v1/ping/get_statusis live to wire types against;429on over-limit.