39a979b1a7
backend phase 3: identity profiles, patients & nurse bank accounts Add the role-attached identity layer on top of the b2 auth spine: nurse seller profiles (guarded is_verified, read-only aggregates), thin customer payer profiles, first-class patients (tenancy-scoped), and nurse payout bank accounts hardened with an iban_hash uniqueness guard and an automated استعلام شبا IBAN-ownership inquiry. - Four usr tables via one migration (1:1 uniques, UNIQUE(iban_hash), filtered UNIQUE(nurse_id) WHERE is_primary=1, guarded is_verified, encrypted PII, soft-delete on nurse_profiles) - 15 CQRS slices + 4 role-scoped controllers; reads projected + paginated, IBAN masked (last-4); ownership-inquiry endpoints rate-limited - New IBankAccountOwnershipVerifier seam (mock deterministic شبا match) + per-domain repositories on IUnitOfWork + encrypted-PII value converters - Activate FluentValidation repo-wide (validators were never registered) - Handler unit tests + WebApplicationFactory integration tests (76 pass); contract identity-profiles.md + swagger snapshot; docs, handoff & report Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> @
6.8 KiB
6.8 KiB
Backend status log (append-only)
One block per completed backend phase. Newest at the top. Backend lane writes here; frontend reads.
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.