Files
baya-monorepo/docs/status/backlog.md
T
2026-08-02 18:08:40 +03:30

67 KiB
Raw Blame History

Backlog — every open item, triaged

Last verified: 2026-08-02 against commit b876490.

Reconciled from five ledgers — hardening/issues.md (18 items), for-backend.md (67 REQs), 53 report "Follow-ups" sections, 22 backend handoff files, two manual-testing iterations — plus product/notes/open-questions.md, root CLAUDE.md §6, phase 2's drift list, and phase 3's 283 flow gaps (the primary, freshest, code-verified input; see docs/flows/index.md). ~700 raw candidate rows were harvested; this file is the deduped, triaged result. Old ids stay greppable in their source files — nothing was rewritten.

Area: client · server · contract · ops · product · docs. Sev: blocker (product is wrong or unusable) · major · minor · deferred. Status: open · in-progress · blocked (on what) · deferred (trigger). Blocks: the docs/flows/ journey(s) it degrades.

Closed items (with what closed them) are in backlog-closed.md. The distilled decision log is in decisions.md. The business-area overlay is in implemented.md.


Blockers (18)

ID Area Item Origin Status Blocks
BL-001 server Admin RBAC is structurally dead: DynamicPermissionService.CanAccess grants only the literal role admin; every seeded admin holds super_admin/finance and 403s on all DynamicPermission-gated controllers. No code path ever writes a DynamicPermission claim. H-04, H-05, admin-backoffice gap-1/3/12, bnpl gap-7, cancellation-and-refunds gap-9, messaging-tickets gap-1/3, nurse-verification gap-3, nurse-earnings-and-payouts gap-7, partner-center gap-8, reviews gap-1/2, booking-request gap-3, booking-lifecycle-evv gap-3/5, nurse-catalog-and-pricing gap-2 open admin-backoffice, bnpl-installments, cancellation-and-refunds, messaging-tickets, nurse-verification, nurse-earnings-and-payouts, partner-center, reviews, booking-request, booking-lifecycle-evv, nurse-catalog-and-pricing
BL-002 ops No seeded account holds the literal admin role (Seed:AdminUsername/Password unset, SeedDataBase.cs returns early) — even a fixed BL-001 is untestable out of the box. admin-backoffice gap-2 open admin-backoffice
BL-003 ops Committed live credentials (DB sa, JWE/field-encryption key halves, Kavenegar, Neshan, Finnotech, Telegram bot token) must be rotated and moved out of git before onboarding real users. CLAUDE.md §6, refinement-phase-0 follow-up 3 open — (pre-launch)
BL-004 ops GET /api/v1/dev/last_otp/{phone} is anonymous and Development-only by design, but the deployment runs as Development — live on api.balinyaar.ir, lets anyone who knows a phone read its login code. auth-login-otp gap-9, public-front-door gap-10 open auth-login-otp, public-front-door
BL-005 server Card payment is a dead end everywhere: MockPaymentProvider redirects to a non-existent host, and nothing fires the PSP webhook locally, so no new card payment can ever reach ConfirmPaymentAndPostLedger. checkout-and-payment gap-1/2 open checkout-and-payment
BL-006 contract Booking deadline timestamps ship without a timezone (DateTime not DateTimeOffset); the client reads the offset-less value as local time — in Tehran the 30-minute payment window renders ~4h and expires while the timer still shows time left. booking-request gap-1 open booking-request, checkout-and-payment
BL-007 ops No bnpl payment-gateway row is ever seeded — every BNPL initiate/eligibility call 400s with "No active BNPL gateway is configured" on the live server. bnpl gap-1 open bnpl-installments
BL-008 client The BNPL wizard is a dead end for every real booking-request id: its mock cross-imports the bookings-mock store (seeded ids 1-2 only), bypassing the real-data flip entirely. H-07, bnpl gap-2/3 open bnpl-installments
BL-009 client Refunds mock reads the retired bookings-mock store (ids 5001-5005 only), so any real booking id 404s inside the cancel-policy preview; flipping the flag today would also render a 10000% refund (percent-scale bug on an already-0-100 field). H-06, cancellation-and-refunds gap-1/2/4 open cancellation-and-refunds
BL-010 client Verification is 100% client-mocked under one flag covering nurse + public + admin; the mock resets to empty on every reload, so even a server-verified nurse renders unverified everywhere the app reads it, hiding the real search-visibility gate and "go live" CTA. submitCredentialDetails is also a no-op though the real endpoint matches field-for-field. H-08, nurse-verification gap-1/2/4, onboarding-nurse gap-1/2/3 open nurse-verification, onboarding-nurse, search-and-discovery, public-front-door
BL-011 client Patient/care records are 100% mocked on both the family record and nurse visit-note panel, and the real DTO shapes would break a naive flip: medication/routine fields mismatch server field-for-field, and care-plan ids are string client-side vs long server-side. care-circle-patients gap-1..4, patient-care-records gap-1..3, H-17 open care-circle-patients, patient-care-records, booking-lifecycle-evv
BL-012 server Nurse earnings/payouts: mock hides four working endpoints; no process operation exists anywhere in the client (the irreversible payout step has no UI); DeriveEarningsState marks a booking "paid" whenever it merely has a payout link regardless of that payout's actual status; the four earnings buckets don't reconcile against the ledger. H-09, nurse-earnings-and-payouts gap-1/4/5/9/10/11 open nurse-earnings-and-payouts
BL-013 client Partner center is 100% mocked with zero tenancy (any signed-in caller resolves to center id 1), and 5 core routes (centers/me, /me/nurses, /me/bookings, /me/bookings/{id}, /me/settlement) don't exist server-side; a center owner has no legal read of its own issued invoices. partner-center gap-1/2/3/9/10, REQ-032, REQ-033, REQ-064 open partner-center
BL-014 server Search results are index rows, not nurses — one nurse with 3 variants × 3 areas shows as "9 پرستار" with no de-dup; the trust dossier on results is mocked, and the by-id profile page asserts "verified" unconditionally, even for an in_review nurse. search-and-discovery gap-1/3/4 open search-and-discovery, public-front-door
BL-015 client Editing an address through the UI silently destroys data: the form never collects postalCode/recipientName/recipientPhone, and the update handler nulls them unconditionally on every save. addresses-and-map gap-4 open addresses-and-map
BL-016 server A booking whose remaining sessions get swept to missed never reaches a payable state — the allSettled → Completed re-check only lives inside the checkout path, so already-checked-out sessions can never enter a payout batch. The "today" session feed also applies no date filter and lists a nurse's whole history. booking-lifecycle-evv gap-1/2 open booking-lifecycle-evv, nurse-earnings-and-payouts
BL-017 server Reviews can never leave moderation on the live stack: the queue and status-PATCH sit behind BL-001, and AutoApproveClean is absent from config — a real review never reaches a nurse's profile except via the seeder. reviews gap-1/2/3 open reviews
BL-018 server A production database has zero option groups outside Development — the one seeded «نوع شیفت» group only exists because the demo seeder is Dev-only, so every builder collapses to two steps and every variant in a category duplicates every other, deployed. nurse-catalog-and-pricing gap-3 open nurse-catalog-and-pricing

Major (86)

ID Area Item Origin Status Blocks
BL-019 client Customer without an emergency contact cannot save name or language — the profile validator requires it non-empty but the UI has no field-level pre-check, and the resulting 400 is completely silent (no onError). account-and-settings gap-1/2 open account-and-settings
BL-020 client Partner settings hub shows fabricated identity — USE_PARTNER_MOCK resolves the same center for any caller, zero real tenancy on the screen. account-and-settings gap-6 open account-and-settings, partner-center
BL-021 client Sign-out confirmation is inconsistent — customer hub gates it behind a confirm dialog; nurse/admin/partner fire on the first tap and end every session on the account. account-and-settings gap-7 open account-and-settings
BL-022 client A customer cannot set an avatar — the real endpoint exists but the client's uploadAvatar only targets the nurse route. account-and-settings gap-8 open account-and-settings
BL-023 product preferredLanguage is stored and never consumed anywhere — the UI locale comes only from the URL prefix, so the زبان sheet has two controls that do different things. account-and-settings gap-3 open account-and-settings
BL-024 server Nurse avatars never load anywhere in the app — LocalDiskObjectStorage.GetUrl returns a file:// URI a browser cannot fetch. account-and-settings gap-4, onboarding-nurse gap-4, search-and-discovery gap-6, public-front-door gap-2 open account-and-settings, onboarding-nurse, search-and-discovery, public-front-door, booking-request
BL-025 ops NEXT_PUBLIC_NESHAN_KEY is unset in every environment, so the real map (tiles, address search, locate-me) never renders anywhere — every environment gets the keyless grid stand-in, and the response shapes are unverified against the live Neshan API. addresses-and-map gap-1/2 open addresses-and-map
BL-026 client CITY_CENTROIDS is keyed on mock-seed city ids; only Tehran matches the real seeded cities, so the map picker opens ~400km away for every other city. addresses-and-map gap-3 open addresses-and-map
BL-027 client Recipient name/phone/postal-code are never displayed anywhere on an address card either, even where the (broken, BL-015) form would collect them. addresses-and-map gap-5 open addresses-and-map
BL-028 contract Admin list pagination silently breaks on flip: admin/apis/clientApi.ts sends page_size; controllers declare PageSize. Binding is case- but not separator-insensitive, so every admin list falls back to the server default page size. admin-backoffice gap-6, search-and-discovery gap-13 open admin-backoffice, search-and-discovery
BL-029 server /fa/admin/roles and /fa/admin/users have no server — admin_roles/* and admin_users/* are phantom; REQ-061 (admin user directory) was never given a ledger header despite ten live client files citing it. admin-backoffice gap-7/8, REQ-031, REQ-061 open admin-backoffice
BL-030 client `admin_cancellation_policies/list upsert` are unwired — no screen edits the cancellation tiers; they are effectively read-only in production. admin-backoffice gap-11 open
BL-031 client Reuse-detection cannot tell theft from two tabs: the single-flight refresh guard is per-tab module state, so two tabs 401ing at once race and the loser's classified-as-reuse kills every session with no explanation. useSelectRole's own rotation bypasses the guard the same way. auth-login-otp gap-2/3 open auth-login-otp
BL-032 server Session revocation does not kill access tokens — RefreshTokenCommandHandler revokes sessions but never rotates the security stamp, so "logged out everywhere" is up to 60 minutes late. auth-login-otp gap-4 open auth-login-otp
BL-033 client The access cookie expires 45 minutes before the token does (900s vs 60min), so 15 idle minutes bounces any full page load to /login even though the refresh cookie could have recovered the session. auth-login-otp gap-5 open auth-login-otp
BL-034 client A ?next= pointing at /partner/... never survives login — appRoleForPath has no partner branch, and /me carries no signal that the caller administers a partner center. auth-login-otp gap-11, partner-center gap-4, REQ-038 open auth-login-otp, partner-center
BL-035 client useLogout always signs out every device — an absent refreshToken means "everywhere"; no UI offers a single-device choice. auth-login-otp gap-12 open auth-login-otp
BL-036 client resolveRoleDestination checks admin before customer/nurse, so a user holding both an admin sub-role and customer can never reach the family app from login. auth-login-otp gap-13 open auth-login-otp
BL-037 ops POST /auth/request_otp 500s on a fresh clone — the committed SMS provider is telegram with nothing listening; login is unreachable until booted with the mock provider. auth-login-otp gap-1 open auth-login-otp
BL-038 client Query cache is never cleared on logout/login — only authKeys are invalidated, so a device that signs out of one account and into another can render stale, cross-account data from the previous session's cache. H-11 open auth-login-otp, account-and-settings
BL-039 server BookingRoles.Admin over-grants: Support/Moderation roles get clinical care-instruction reads and financial nurse-payable-balance reads, wider than the "admin/finance" comment claims. H-05 open booking-lifecycle-evv, nurse-earnings-and-payouts
BL-040 client The «پاسخ‌داده» nurse-inbox tab is unpaged — the API filters one status at a time with no group filter, so nurse/requests fires three page-1 queries and concatenates; a nurse with >20 answered requests silently loses rows. booking-request gap-4, REQ-050 (residue) open booking-request
BL-041 ops Nothing seeded is actionable in the booking-request flow — no pending/accepted request survives the demo seeder's epoch-anchored aging, so the nurse inbox, accept/reject and payment-window handoff are all unwalkable without creating a fresh request. booking-request gap-2 open booking-request
BL-042 server nurseAvatarUrl on a booking request is served as a raw local-disk path — same root cause as BL-024, called out because checkout renders it directly. booking-request gap-11 open checkout-and-payment
BL-043 client NEXT_PUBLIC_EVV_MOCK_GPS now defaults to off (derived from the now-real bookings flag), so a tester away from the seeded Tehran address fires a real GPS mismatch — and a support alert — on every check-in; the doc-comment still describes the old default. booking-lifecycle-evv gap-6 open booking-lifecycle-evv
BL-044 server The nurse never sees the address on a confirmed booking — BookingMapper.ToDetailDto nulls the address snapshot for the nurse role even though the server itself reads it to compute the EVV match. booking-lifecycle-evv gap-7, REQ-051 open booking-lifecycle-evv
BL-045 client POST bookings/submit_care_instructions/{id} is unwired — no customer form exists anywhere; on a booking a tester creates, the nurse's care-instructions card is empty. booking-lifecycle-evv gap-10 open booking-lifecycle-evv
BL-046 client The nurse booking detail is half real: the bookings/EVV half is server truth, but the mounted visit-notes panel (task checklist, continuity history, note-save) is entirely patientRecords-mocked — same root cause as BL-011. booking-lifecycle-evv gap-12 open booking-lifecycle-evv
BL-047 client H-06's exact mocked-cross-import defect also shows up as: CHANNEL_BY_BOOKING pins the BNPL-revert refund channel to one fixture id, so every real booking silently demos as a card refund. cancellation-and-refunds gap-3 (folded severity note) open cancellation-and-refunds
BL-048 contract The client discards six fields the server now serves on refund status (platformFeeRefundedIrr, nursePayoutRefundedIrr, refundPercentageApplied, cancellationPolicyCode, createdAt, completedAt) — the fee-split transparency section can never render even once BL-009 is fixed. cancellation-and-refunds gap-5 open cancellation-and-refunds
BL-049 contract Cancellation enum drift on three fields (CancellationPolicyCode, CancellationLeadTime, appliesTo) between client and the seeded/wire values — every one drives an i18n lookup that will miss on flip. cancellation-and-refunds gap-6 open cancellation-and-refunds
BL-050 server POST admin_refunds creates and executes in one call — no preview/approve/reject route exists, so the admin RefundPanel's three-step console has no real backend. cancellation-and-refunds gap-10, REQ-035 deferred (trigger: admin refund console prioritized) cancellation-and-refunds
BL-051 client No admin console exists for refund/clawback settlement — confirm_settlement, mark_failed, write_off all have server handlers but zero client screens. cancellation-and-refunds gap-12 open cancellation-and-refunds
BL-052 server expectedCustomerRefundEta is hardcoded null in the cancellation preview — the BNPL 10-business-day window is invisible before the customer confirms, exactly where it matters most. cancellation-and-refunds gap-14 open cancellation-and-refunds
BL-053 ops customer_no_show has no seeded cancellation-policy row — the product doc's "up to 100% charge" tier does not exist; a customer no-show falls through to the 50%-back tier. cancellation-and-refunds gap-15 open cancellation-and-refunds
BL-054 server No credit note / invoice reversal on refund — a refunded booking's VAT-bearing commission invoice stays as originally issued. cancellation-and-refunds gap-16 open cancellation-and-refunds
BL-055 server Seeded visit-note taskResults labels are lost — the handler deserializes with case-sensitive options against camelCase seeded JSON; any externally-written JSON in that column silently degrades to blank labels. care-circle-patients gap-5, patient-care-records gap-7 open care-circle-patients, patient-care-records
BL-056 client Editing a patient destroys their birth date — the form always submits ageToBirthDate(age) = YYYY-01-01, overwriting the real recorded date on every save even with no change. care-circle-patients gap-10 open care-circle-patients
BL-057 server Tenancy leak on patient records: a foreign patient returns 403, not 404, across all three handlers — confirms the patient exists to an unauthorized caller, violating the repo's 404-not-403 invariant. patient-care-records gap-8 open care-circle-patients, patient-care-records
BL-058 contract A verified nurse is shown as unverified on the checkout screen — the checkout summary DTO declares nurseVerified but the server never constructs it. checkout-and-payment gap-3, REQ-046 open checkout-and-payment
BL-059 client Payment confirmation cannot deep-link to the booking — the server does serve bookingId but the client types it away and hardcodes null; the receipt also always hides the tracking code and paid-at. checkout-and-payment gap-5, H-10, REQ-046 open checkout-and-payment
BL-060 client The invoice screen derives a money row client-side (gross commission vat) that is wrong by exactly the VAT amount, and never shows the server's real totalIrr — violates the "client never computes money" rule. checkout-and-payment gap-7 open checkout-and-payment
BL-061 server Customer payment history is a live 404 — bookings/payment_history doesn't exist; the wallet «پرداخت‌ها» tab is permanently empty for a card-paying customer. checkout-and-payment gap-8, REQ-047 open checkout-and-payment
BL-062 server The escrow ledger has no read surface at all — a customer, admin or tester has no way to see the balanced capture group the flow's core money invariant depends on. checkout-and-payment gap-10 open checkout-and-payment
BL-063 client getUnreadTotal is a hardcoded null on the real path — the chrome support badge can never light up. messaging-tickets gap-4, account-and-settings gap-10, REQ-059 open messaging-tickets, account-and-settings
BL-064 client mapSummary hardcodes lastMessagePreview/lastAuthorRole to null on the real path — the ticket inbox card shows no message preview. messaging-tickets gap-5, REQ-059 open messaging-tickets
BL-065 client POST /tickets/emergency has zero client callers — the nurse's emergency banner only dials tel:; the "then opens a ticket" half of the business playbook is manual. messaging-tickets gap-6 open messaging-tickets
BL-066 contract 11 of 14 server notification types are unknown to the client's parser — only 3 deep-link; the nurse's most important notification (booking_confirmed_nurse) and the entire booking_request_* lifecycle are non-navigable. notifications gap-1/2/3 open notifications, booking-request
BL-067 client The client handles 10 notification types the server never emits, while the server's real payout-paid/payout-failed events have no client branch at all — a nurse is never told a payout paid or failed. notifications gap-6 open notifications, nurse-earnings-and-payouts
BL-068 server Every notification title/body is an English literal rendered verbatim into the Persian RTL feed — no i18n path for notification content, only for chrome. notifications gap-7 open notifications
BL-069 client No catalogue-authoring UI exists at all — all seven admin_catalog/* routes have zero client callers; an admin cannot add a pricing dimension without SQL, compounding BL-018. nurse-catalog-and-pricing gap-1 open nurse-catalog-and-pricing
BL-070 server ZWNJ is stripped from every stored Persian string via a global FixPersianChars normalizer, contradicting the repo's "with a ZWNJ, always" naming rule. nurse-catalog-and-pricing gap-4 open nurse-catalog-and-pricing
BL-071 server A nurse's price edit is not shielded from an in-flight booking request — the conversion reads the live variant price, not a request-time snapshot, so editing price inside the 30-minute payment window changes what the customer pays. nurse-catalog-and-pricing gap-5 open nurse-catalog-and-pricing, booking-request
BL-072 client The «همراهی و مراقبت روزمره» category is data-only per its own seed comment, but the builder offers it like any real pricing path. nurse-catalog-and-pricing gap-8 open nurse-catalog-and-pricing
BL-073 client toHistoryItem hardcodes failureReason: null though the live wire carries it — a failed payout loses its reason in the nurse's history on flip. nurse-earnings-and-payouts gap-3 open nurse-earnings-and-payouts
BL-074 client previewPayoutBatch sums net amounts and fabricates a processing date client-side — the client computing money and a payout date, violating the "client never computes money" rule. nurse-earnings-and-payouts gap-6 open nurse-earnings-and-payouts
BL-075 contract recordTransferReference targets a route that doesn't exist — the batch-detail reconcile field 404s on flip. nurse-earnings-and-payouts gap-12, REQ-036 deferred (trigger: payout reconciliation console prioritized) nurse-earnings-and-payouts
BL-076 client POST admin_payouts/{id}/mark_failed exists server-side but has no client op — a reconciled bank rejection cannot be recorded from the console. nurse-earnings-and-payouts gap-14 open nurse-earnings-and-payouts
BL-077 server Whole-city + a specific district in the same city are both accepted for one nurse, and search then returns her twice with no de-dup on (nurseId, variantId). nurse-service-areas gap-1 open nurse-service-areas, search-and-discovery
BL-078 client The coverage screen has no error state — isError is dropped, so a failed list load renders the "no area registered" empty state, telling a nurse with real coverage she is invisible in search. nurse-service-areas gap-3 open nurse-service-areas
BL-079 contract No edit and no deactivate for a service area — changing a district means remove-then-add, which silently drops the nurse from search between the two calls. nurse-service-areas gap-5 open nurse-service-areas
BL-080 client nurse/verification/page.tsx unconditionally imports the verification mock module — the one production seam breach in the client; the mock ships in every build regardless of the render gate. nurse-verification gap-4 open nurse-verification
BL-081 client foldQueueRows folds the per-step admin verification queue to per-nurse items but leaves the step-progress counts at zero and the pager count wrong — a nurse's steps can straddle a page boundary. nurse-verification gap-6, REQ-062 open nurse-verification
BL-082 contract approveVerification/rejectVerification/getDocumentSignedUrl target routes that don't exist — the admin case page's visible approve/reject CTAs would 404 the moment BL-001 is fixed. nurse-verification gap-7, REQ-034 deferred (trigger: verification-admin console prioritized) nurse-verification
BL-083 client No admin UI exists for suspend/scan_expiring or the verification step-type catalog — the "data-driven catalog" design rule has no admin surface. nurse-verification gap-8 open nurse-verification
BL-084 client Admin verification case URLs are mistyped — the route folder is [nurseId] but the value passed is a nurseVerificationId; typing a nurse id into the URL opens the wrong case. nurse-verification gap-11 open nurse-verification
BL-085 product Onboarding never creates a customer_profile — it creates a patient and stops; nothing blocks a customer from booking without ever setting an emergency contact. onboarding-customer gap-1 open onboarding-customer
BL-086 contract A customer's own gender is unsettable through the app — no client call and no command field carries it; a fresh account's /me.gender stays null forever. onboarding-customer gap-3 open onboarding-customer
BL-087 client The customer profile upsert has no PATCH semantics — every sheet save rewrites the whole profile including name, so a stale form on one device can silently overwrite a name changed on another. onboarding-customer gap-5 open onboarding-customer, account-and-settings
BL-088 client /fa/select-role is reachable by any authenticated user with no guard, letting a customer permanently self-grant the nurse role by typing a URL, with no confirmation step for an irreversible grant. onboarding-customer gap-7 open onboarding-customer
BL-089 client useSelectRole swallows a failed post-select token rotation — the role persists server-side but the client keeps a stale token until the next silent refresh happens to fire, so a role-gated call in between 403s. onboarding-customer gap-9 open onboarding-customer
BL-090 client The duplicate-IBAN error message never reaches the nurse — the bank page discards the server's field error and shows a generic "registration failed" toast. onboarding-nurse gap-7 open onboarding-nurse
BL-091 server Bank-ownership inquiry ignores the national id entirely — a nurse who never did identity KYC (national_id = NULL) still gets matchedNationalId = true, so the payout gate opens on a claim nothing actually checked. onboarding-nurse gap-8 open onboarding-nurse, nurse-earnings-and-payouts
BL-092 client verifyOwnership is a dead seam op — no hook calls it, so a mismatch bank account has no re-inquiry affordance; the UI only offers "re-enter the IBAN". onboarding-nurse gap-9 open onboarding-nurse
BL-093 contract Shape mismatch blocks the partner portal even once mocked data is off: the server serves one capped/inline dashboard aggregate; the portal needs paginated /me-scoped splits it cannot get from that shape. partner-center gap-5 open partner-center
BL-094 client GET /centers/{id}/dashboard — the one portal endpoint that is real — needs a center id the portal has no way to discover, so it goes unused. partner-center gap-6 open partner-center
BL-095 server Structured taskResults are discarded in both directions on the real patient-records path — accepted on write and returned on read by the server, but the client hardcodes them away; the "wire has no structured field" client comments are simply wrong. patient-care-records gap-6 open patient-care-records
BL-096 product Tier (c) of the public front door (guest search + public nurse profiles) is unbuilt — REQ-066/067 need a backend phase plus an explicit privacy sign-off before any guest-facing search/profile screen is built. public-front-door gap-6, ui-phase-13 follow-up deferred (trigger: privacy sign-off + REQ-066/067 delivered) public-front-door, search-and-discovery
BL-097 product /terms and /privacy ship placeholder legal copy behind a draft banner, flagged for human/legal review since ui-phase-3 and still unreviewed — a real pre-launch item. public-front-door gap-5, ui-phase-3 follow-up 1 open public-front-door
BL-098 server GET /api/v1/nurses/{id}/profile returns 200 anonymously for an unverified (in_review) nurse — the persona that "must never appear in search" is reachable and enumerable by id, even though search itself correctly hides her. public-front-door gap-3 open public-front-door, search-and-discovery
BL-099 client The nurse cannot see their own reviews anywhere in the app — the only signal is a notification the (BL-001-blocked) moderation handler dispatches. reviews gap-8 open reviews
BL-100 client The client hardcodes the five review tag codes instead of reading the server's tag master — a newly seeded tag is invisible to the UI and an unseeded code fails submit outright. reviews gap-7 open reviews
BL-101 server ReviewModerationStatus.Rejected is unreachable end to end — the submit-time banned-word path maps to Hidden, not Rejected, and the only other producer is the BL-001-blocked admin PATCH; the client still renders a rejected chip nobody can ever trigger. reviews gap-4 open reviews
BL-102 server Review eligibility distinguishes "booking not found" from "not your booking" with a 200, letting any authenticated caller probe whether an arbitrary booking id exists — violates the repo's 404-not-403 tenancy invariant. reviews gap-9 open reviews
BL-103 product No free-text search exists — a customer who knows a nurse's name by name cannot find her; category/city/gender/price filters only. search-and-discovery gap-10, REQ-041 open search-and-discovery
BL-104 client Guests cannot reach search at all — every search route sits behind a customer-only route guard and /search is not in the public-path list, even though the underlying endpoints are already anonymous. search-and-discovery gap-11 open search-and-discovery, public-front-door

Minor (115)

ID Area Item Origin Status Blocks
BL-105 client Admin hub renders a raw i18n key as the role label — the translation keys were never added. account-and-settings gap-5 open account-and-settings
BL-106 client Customer hub navigates with a hand-built locale prefix instead of the shared navigation helper — works today, breaks silently if localePrefix ever changes. account-and-settings gap-11 open account-and-settings
BL-107 client UNVERIFIED: a system-theme user may see one light/dark flip after hydration (SSR cookie vs. post-hydration MUI resolution can disagree). account-and-settings gap-12 open account-and-settings
BL-108 product No notification-preference surface exists anywhere — the settings row only deep-links to the notification centre. account-and-settings gap-9 open account-and-settings, notifications
BL-109 client The pin is a required address-form field, so the API's "no pin" state and its UI badge are unreachable except via direct API calls or seed data. addresses-and-map gap-6 open addresses-and-map
BL-110 ops Geography is seeded one city per province; districts exist only for Tehran, so the region cascade is a two-step formality everywhere else. addresses-and-map gap-7 open addresses-and-map
BL-111 client GET geo/tree is live but unused — the region cascade makes three round trips instead of one. addresses-and-map gap-8 open addresses-and-map
BL-112 client Map-pin RTL geometry is dodged via inline style, untested for RTL drift beyond the keyless fallback path. addresses-and-map gap-9 open addresses-and-map
BL-113 docs No product/ doc describes address entry, the map-pin picker, or the Neshan integration. addresses-and-map gap-10 open addresses-and-map
BL-114 client /fa/admin/notifications is a placeholder stub and a true orphan — no link reaches it and no bell is mounted in the admin shell. admin-backoffice gap-9, notifications gap-8 open admin-backoffice, notifications
BL-115 client POST holidays/delete_holiday is unwired — the admin console offers no delete affordance for a holiday row. admin-backoffice gap-10 open admin-backoffice
BL-116 ops admin_search/rebuild_index and admin_booking_requests/expire are reachable only by curl, and both 403 for a seeded admin anyway. admin-backoffice gap-12 open admin-backoffice, booking-request
BL-117 client useAdminCapabilities hides tabs but never blocks the route itself — every admin console stays URL-reachable regardless of capability; server enforcement is currently just the blanket BL-001 403. admin-backoffice gap-13, H-14 open admin-backoffice
BL-118 client A 429 on OTP verify renders as "wrong code" — the empty error body leaves nothing to branch on, unlike the phone-step's correct 429 handling. auth-login-otp gap-6 open auth-login-otp
BL-119 contract The client ignores the server's OTP metadata (codeLength, expiresInSeconds) and hardcodes its own — the 60-second code expiry is never shown, only the 120-second resend cooldown. auth-login-otp gap-7 open auth-login-otp
BL-120 docs Stale client comments claim the server exposes no OTP code length or machine-readable failure code — it exposes both. auth-login-otp gap-8 open auth-login-otp
BL-121 client A signed-in user visiting /login sees the phone form again instead of being redirected away, unlike /welcome. auth-login-otp gap-10 open auth-login-otp
BL-122 product The OTP SMS template is not WebOTP-conformant, so the client's WebOTP autofill ships but never fires; landing this is a Kavenegar-dashboard template edit (ops action), not a code change. auth-login-otp gap-14, REQ-039 open auth-login-otp
BL-123 ops No seeded account is role-less, so /fa/select-role has no natural path in the demo world. auth-login-otp gap-15, onboarding-nurse gap-10 open onboarding-customer, onboarding-nurse
BL-124 client Client hardcodes English toasts for 401/403/5xx/network errors — no i18n dictionary. H-13 open (all authenticated flows)
BL-125 client Admin read-only consoles are inconsistently client-guarded — some pages check capabilities only to gate mutation buttons, admin/audit has zero check, and no shared CapabilityGuard component exists. H-14 open admin-backoffice
BL-126 docs bnpl/apis/clientApi.ts and its header comment both claim the by-request BNPL read 404s — it exists and returns 200, a stale comment blocking a partial de-mock. bnpl gap-5 open bnpl-installments
BL-127 client acceptBnplSchedule derives request status client-side from the order status, mislabelling a failed/reverted/cancelled order as awaiting-payment — the expired-window branch can never fire on the real path. bnpl gap-6 open bnpl-installments
BL-128 product providerCommissionReversedAmount is left null on a reverted BNPL order — nothing in the UI or admin surfaces the resulting commission shortfall. bnpl gap-8 open bnpl-installments
BL-129 ops Seeded BNPL eligibility status ("approved") is not in the closed status vocabulary on either side of the wire. bnpl gap-9 open bnpl-installments
BL-130 server D3 KYC inputs are half-wired — the client sends nationalId/mobile/consent, but eligibility only reads the mobile; legal consent is collected and silently discarded. bnpl gap-10, REQ-023 (residue note) open bnpl-installments
BL-131 ops Nothing fires the BNPL provider webhook in dev, so even a successfully initiated real order would never reach settled — settlement is webhook-driven by design. bnpl gap-11 open bnpl-installments
BL-132 client /fa/bookings/checkout/bnpl/gateway is an orphan route on the real path, reachable only from the mock and gated outside development. bnpl gap-12 open bnpl-installments
BL-133 client No client path produces a disputed booking status — it renders in the status map but nothing ever raises one. booking-lifecycle-evv gap-4 open booking-lifecycle-evv
BL-134 contract The nurse's today-feed session row carries no service/variant label — every row says patient name + visit index only. booking-lifecycle-evv gap-8, REQ-052 open booking-lifecycle-evv
BL-135 contract A booking list row has no patientId — a booking card can never deep-link to the care record. booking-lifecycle-evv gap-9, care-circle-patients gap-13, REQ-057 open booking-lifecycle-evv, care-circle-patients
BL-136 client POST booking_sessions/cancel/{id} is unwired — a nurse cannot cancel a single visit from the UI. booking-lifecycle-evv gap-11 open booking-lifecycle-evv
BL-137 docs services/bookings/apis/serverApi.ts is dead code with no importer, and its own doc-block still claims the domain is mock-primary. booking-lifecycle-evv gap-13 open booking-lifecycle-evv
BL-138 contract No structured rejection-reason code exists — the client runs a seven-keyword heuristic on free text to decide whether to offer "retry with the same nurse," and it silently misses any other wording. booking-request gap-5, REQ-044 open booking-request
BL-139 contract variantLabel is typed as client-augmented/optional though the server always serves it, and the list row still lacks variantPrice/variantPriceUnit, so the nurse inbox card can't show the money without opening the detail. booking-request gap-6/7, REQ-050 (residue) open booking-request
BL-140 contract patientAge is served on every nurse-inbox row but never modelled client-side — a pure client-side type-widening fix. booking-request gap-8 open booking-request
BL-141 client The customer's pending-request list doesn't poll while the detail view does, so countdowns on /bookings go stale until a manual refresh. booking-request gap-9 open booking-request
BL-142 client useBookingRequest has no auth gate (unlike both list hooks) — a hard reload before hydration can flash an error card. booking-request gap-10 open booking-request
BL-143 product The nurse sees the patient's display name pre-accept, wider than the integration doc's "notes + coarse address only" — confirm this is the intended stage-1 boundary. booking-request gap-12 open booking-request
BL-144 client The client's 22 in-memory mocks are module-scoped and reset on reload/HMR — a mocked cancel demo doesn't survive navigating to the refund-status screen. cancellation-and-refunds gap-17 open cancellation-and-refunds
BL-145 contract preview.refundableSessionIds doesn't exist on the wire (only sessions[]) — harmless today, but the client type lies. cancellation-and-refunds gap-7 open cancellation-and-refunds
BL-146 docs The refunds clientApi.ts doc-block is stale — claims REQ-019/020/021 are contract gaps; all three routes exist and return 200. cancellation-and-refunds gap-8 open cancellation-and-refunds
BL-147 server No GET refunds/my — the wallet «استردادها» tab renders empty on the real path. cancellation-and-refunds gap-11, REQ-048 open cancellation-and-refunds
BL-148 client /fa/admin/finance is a hub with a single payouts tile — no refunds, clawbacks, or invoice-issue surface. cancellation-and-refunds gap-13 open cancellation-and-refunds
BL-149 client Client discards a field the server does serve on the visit-note read — the "N of M tasks" summary chip can never render on the real path. care-circle-patients gap-6 open care-circle-patients
BL-150 contract deniedReason enum mismatch on patient-record access denial — server sends not_authorized, client/docs declare no_access/not_found. care-circle-patients gap-7, patient-care-records gap-5 open care-circle-patients, patient-care-records
BL-151 docs Stale client comments assert patient-record endpoints "have no backend" — all exist, are authorized, and were probed 200. care-circle-patients gap-8/9, patient-care-records gap-12 open care-circle-patients, patient-care-records
BL-152 ops Seeded care plans are empty and seeded patients have no relation/conditions — three of four record tabs would be blank the moment the mock flag flips. care-circle-patients gap-11/12, patient-care-records gap-9 open care-circle-patients, patient-care-records
BL-153 docs No product/business/ file covers patient care records at all — no documented rule for append-only, encryption, or the clinical-access gate. care-circle-patients gap-14, patient-care-records gap-10 open care-circle-patients, patient-care-records
BL-154 client Archiving a patient is optimistic with no undo — a stale/cross-tenant id 404s and the card silently reappears with a generic toast. care-circle-patients gap-15 open care-circle-patients
BL-155 client The only way to demo patient-record access-denial uses a hardcoded sentinel patient id — untested against how the real server denies. patient-care-records gap-11 open patient-care-records
BL-156 contract sessionCount is served nullable but typed non-null client-side; UNVERIFIED how the i18n label renders a null count. checkout-and-payment gap-4 open checkout-and-payment
BL-157 docs Payment client constants/comments are stale — claim a live endpoint 404s, claim the mock is still primary, and hardcode a platform-fee rate that no longer matches the server's seeded value. checkout-and-payment gap-6 open checkout-and-payment
BL-158 server Invoice carries no payment method, transaction reference, or seller fiscal identity — those rows never render on the real path. checkout-and-payment gap-9, REQ-049 open checkout-and-payment
BL-159 server GET invoices/{bookingId} tenancy is enforced only inside the query handler; UNVERIFIED whether a foreign customer actually gets 404. checkout-and-payment gap-11 open checkout-and-payment
BL-160 server Staff authorization is inconsistent by layer for tickets — the handler-level role set includes Support/Finance, but the controller attribute blocks them; two different definitions of "staff" in one request path. messaging-tickets gap-3 open messaging-tickets
BL-161 client POST/DELETE tickets/{id}/participants are unwired — no UI can attach a third party to a thread. messaging-tickets gap-7 open messaging-tickets
BL-162 client close/reopen are live and working server-side but unreachable client-side — one shared flag gates them alongside the genuinely-missing assign, so two already-shippable features stay dark. messaging-tickets gap-8, REQ-063 (residue) open messaging-tickets
BL-163 server POST tickets/{id}/assign is a phantom endpoint the client already targets. messaging-tickets gap-9, REQ-063 deferred (trigger: ticket assignment prioritized) messaging-tickets
BL-164 docs Stale client comment claims the server has no field for clientMessageId echo — it is sent and echoed today. messaging-tickets gap-10 open messaging-tickets
BL-165 contract Client TicketAuthorRole declares system; the server's role vocabulary doesn't — one side must move. messaging-tickets gap-11 open messaging-tickets
BL-166 product Auto-created coordination tickets open with no first message — both actors see an empty thread with no explanation of what it's for. messaging-tickets gap-12 open messaging-tickets
BL-167 contract Ticket message history is unpaginated by contract — a long thread has no incremental read. messaging-tickets gap-13 open messaging-tickets
BL-168 client Ticket attachments are fully designed but gated off behind a flag. messaging-tickets gap-14, REQ-060 deferred (trigger: attachment upload prioritized) messaging-tickets
BL-169 contract refund_issued/refund_processed and review_moderated/review_published are near-miss names on either side of the same contract. notifications gap-4 open notifications
BL-170 server verification_expiry_prompt is dispatched with a null data payload — even a matching client branch couldn't route it. notifications gap-5 open notifications, nurse-verification
BL-171 client NotificationBellPopover (full mark-read + deep-link logic) is exported but mounted nowhere — dead UI. notifications gap-9 open notifications
BL-172 client Notification "load more" isn't real pagination — it grows the page size and refetches the whole feed every time. notifications gap-10 open notifications
BL-173 server Notification retention (90d/24h) is a hardcoded constant rather than a platform_configs row, against the repo's config-is-rows convention. notifications gap-11 open notifications
BL-174 client Both notification pages are client components with no generateMetadata, departing from the thin-RSC-page convention. notifications gap-12 open notifications
BL-175 product No unread-notification cap or archive — the feed grows until the 90-day sweep; unread rows are never separately swept. notifications gap-13 open notifications
BL-176 docs IVariantSnapshotSerializer's doc-comment names the wrong table for the frozen JSON snapshot. nurse-catalog-and-pricing gap-6 open nurse-catalog-and-pricing
BL-177 server Category iconKey and description fields are null for all seeded categories — the catalog grid falls back to a generic icon with no explainer copy. nurse-catalog-and-pricing gap-7 open nurse-catalog-and-pricing
BL-178 server sessionCount is unvalidated against priceUnit — nothing stops an invalid combination from being saved. nurse-catalog-and-pricing gap-9 open nurse-catalog-and-pricing
BL-179 client The mock payout store's fixture booking ids deep-link into the (now real) bookings screens and 404. nurse-earnings-and-payouts gap-2 open nurse-earnings-and-payouts
BL-180 contract The client sends Idempotency-Key on payout generate/retry, which the controller never reads — decorative and misleading to a reader. nurse-earnings-and-payouts gap-13 open nurse-earnings-and-payouts
BL-181 server holidayShifted is always false — PayoutBatchDto carries no such flag, so a bank-holiday date shift can never be shown. nurse-earnings-and-payouts gap-15 open nurse-earnings-and-payouts
BL-182 product No payout forecast — the nurse dashboard's "next batch" line renders nothing on the real path. nurse-earnings-and-payouts gap-16, REQ-053 open nurse-earnings-and-payouts
BL-183 client Only one bank-rail failure reason is mapped to a label; every other reason falls back to a generic message. nurse-earnings-and-payouts gap-17 open nurse-earnings-and-payouts
BL-184 docs Stale payouts doc-blocks assert three live endpoints don't exist server-side — all three return 200. nurse-earnings-and-payouts gap-18 open nurse-earnings-and-payouts
BL-185 client Duplicate React keys on the nurse-service-areas search results whenever the BL-077 duplicate-listing bug fires. nurse-service-areas gap-2, search-and-discovery gap-2 open nurse-service-areas, search-and-discovery
BL-186 docs The service-areas integration doc states a conflict rule that the live server doesn't enforce (probed 200 where it claims a conflict). nurse-service-areas gap-4 open nurse-service-areas
BL-187 client No warning that removing a nurse's last service area de-lists her from search — the confirm-dialog copy doesn't distinguish this case. nurse-service-areas gap-6 open nurse-service-areas
BL-188 ops Remove-service-area was left end-to-end unverified this pass (token expired mid-probe); code-traced only. nurse-service-areas gap-7 open nurse-service-areas
BL-189 ops The shared demo DB has drifted from the seeder's own definitions (nurse 1 now has 5 service areas, not the seeded 3) and the idempotent seeder will never correct it. nurse-service-areas gap-8 open nurse-service-areas
BL-190 client Verification step model omits isRequired though the wire serves it, so the "X of Y" progress meter would be wrong the moment an optional step type is added. nurse-verification gap-9 open nurse-verification
BL-191 contract No submittedAt on the nurse verification status, and no per-step detail on the public trust-badge read. nurse-verification gap-10, REQ-043, REQ-055 open nurse-verification, search-and-discovery
BL-192 ops Seeded verification data leaves two of six catalog step types unexercisable in the demo world. nurse-verification gap-12 open nurse-verification
BL-193 client POST customer_profiles/avatar is live and implemented but no client code calls it — a customer can never set a photo. onboarding-customer gap-2 open onboarding-customer, account-and-settings
BL-194 client preferredLanguage write silently commits a default 'fa' the customer never chose, the first time they open and save the language sheet. onboarding-customer gap-4/6 open onboarding-customer
BL-195 client avatarUrl on the nurse-profile upsert input is dead on the real path — populated by the form but never sent (harmless today, since the multipart route already persisted it separately). onboarding-nurse gap-5 open onboarding-nurse
BL-196 docs The onboarding integration doc states duplicate-IBAN returns 409; the handler actually returns 400 with a field error. onboarding-nurse gap-6 open onboarding-nurse
BL-197 client The bank-account page polls a stuck ownership inquiry forever, with no ceiling and no timeout copy. onboarding-nurse gap-11 open onboarding-nurse
BL-198 server The HTTP merchant-of-record resolver (internal/bookings/{id}/center) is DynamicPermission-gated and 403s for both seeded admins — reachable only in-process today. partner-center gap-7 open partner-center
BL-199 server Two merchant-of-record resolvers can disagree — BNPL reads a platform config value while invoicing resolves the actual center, so a MoR center's BNPL order and invoice could name different sellers. partner-center gap-10 (folded severity, see BL-013) open partner-center, bnpl-installments
BL-200 ops Seeded partner-center invoices carry null Moadian reference/PDF fields — the settlement view's document columns have nothing real to render. partner-center gap-11 open partner-center
BL-201 product Center self-onboarding (write-then-masked IBAN) is deferred and has never been exercised on a real route. partner-center gap-12 deferred (trigger: center self-service onboarding prioritized) partner-center
BL-202 client Welcome page's Open-Graph image is Latin-only — no Persian glyph rendering for the fa share card. public-front-door gap-7 open public-front-door
BL-203 client /fa/welcome has no in-app link at all — reachable only as the / rewrite body or by typing the URL. public-front-door gap-8 open public-front-door
BL-204 ops NEXT_PUBLIC_SITE_URL is unset in dev, so robots.txt/sitemap.xml/OG tags fall back to localhost (dev-only caveat, .env.production is correct). public-front-door gap-9 open public-front-door
BL-205 ops next dev misrepresents this flow entirely — stale prerenders serve ahead of the middleware; only a production build reproduces real behavior. public-front-door gap-1 open public-front-door
BL-206 server No anonymous rate limit on the public search/profile reads — falls back to the shared global per-IP limiter. public-front-door gap-4, search-and-discovery gap-12, REQ-066 (residue) open public-front-door, search-and-discovery
BL-207 client GET nurses/{id}/review_tags (the "% of reviewers said X" rollup) and POST reviews/{id}/tags are both unwired — no chip-aggregate view and no post-submit tag amendment. reviews gap-5/6 open reviews
BL-208 server The low-rating support alert is raised on submit but has no reachable triage surface — reads sit behind BL-001. reviews gap-10 open reviews
BL-209 docs Stale review doc comments claim the mock is still primary; the real client is live and the 14.6KB mock module is dead behind the flag. reviews gap-11 open reviews
BL-210 server distanceKm is always null on search results — the covering index carries no coordinate, so the distance chip can never render. search-and-discovery gap-7 open search-and-discovery
BL-211 contract topReviewTag and variantDisplayName are never served on search results — dead code on the client's tag chip and no multi-variant collapse. search-and-discovery gap-8, REQ-040 open search-and-discovery
BL-212 client nurseGender is hardcoded 'female' in the public-profile mapping because the DTO carries no gender field — unused today, but a live lie in the typed model. search-and-discovery gap-9, REQ-042 open search-and-discovery
BL-213 server attributeChips is empty for every seeded nurse, and a masked reviewer name maps to an empty string — the profile snippet renders a bare separator with nothing around it. search-and-discovery gap-14 open search-and-discovery
BL-214 contract No nurse-facing read-back of submitted credential details (INO-on-file, specialties) — the returning-nurse form can't hydrate from the server. REQ-056 open nurse-verification
BL-215 contract Policy numbers (dispute-window hours, cancellation lead-time, refund ETA) have no public/authenticated read — the client keeps them single-sourced in a local constants file. REQ-065, ui-phase-12 follow-up 3 open cancellation-and-refunds
BL-216 contract No typed address/variant snapshot objects — BookingDetailDto still carries opaque JSON strings, forcing the client's defensive multi-key parse in three separate places. REQ-045, ui-phase-6 follow-up 2, ui-phase-7 follow-up 2 open booking-lifecycle-evv, checkout-and-payment
BL-217 client Two admin-only multi-field dialogs (GrantRoleDialog in admin/roles, PreviewBatchDialog in admin/payouts) still hold raw useState instead of react-hook-form — the only genuine residue of the app-wide form migration. iteration-2 #7 open admin-backoffice
BL-218 client H-01 residue: the auth-gate root-cause fix landed, but client/middleware.ts was never migrated to Next 16's src/proxy.ts as the original fix prescribed, and outputFileTracingRoot was never added alongside turbopack.root — a production build may still warn from the stray root-level lockfile. H-01 open auth-login-otp
BL-219 docs Rename the SET_VIA_USER_SECRETS_OR_ENV placeholder sentinel now that user-secrets is confirmedly removed — filed by phase 2 with an exact 7-file worklist (appsettings.*.json, StartupSecretsGuard.PlaceholderMarkers, .githooks/pre-commit, .githooks/README.md, StartupSecretsGuardTests.cs, docs/rules/shared/git-and-gates.md, docs/rules/server/structure.md). Optional cleanup, not urgent — the name is a load-bearing sentinel and the mechanism is already documented correctly elsewhere. C-2 (open-contradictions.md) deferred (trigger: none — cleanup-of-convenience)

Deferred (43)

These are recorded decisions with pull-triggers, not bugs — carried here (per this phase's Status vocabulary) for phase 5's roadmap/deferred.md to pick up. Grouped by theme; each origin id is greppable in the source handoff/report files for the full context.

ID Area Item Origin Trigger Blocks
BL-220 ops Redis (shared cache, cross-instance scheduler/money lock) is not deployed — every current seam is correct only for a single instance. handoff-after-refinement-phase-7/8, refinement-phase-7/8/9 follow-ups running more than one instance
BL-221 server Elasticsearch INurseSearch backend + outbox feeder not built — SQL search is the real MVP implementation. handoff-after-backend-phase-7, handoff-after-refinement-phase-7/8/9, backend-phase-7 follow-up SQL search shows real strain search-and-discovery
BL-222 product IAnalyticsSink / an analytics warehouse is not built — events aren't routed anywhere durable yet. handoff-after-backend-phase-1, handoff-after-refinement-phase-9 product pulls it
BL-223 server A real holiday-calendar feed (vs. the seeded/admin-CRUD calendar) is not built. handoff-after-backend-phase-1, handoff-after-refinement-phase-9 product pulls it
BL-224 server organizations/organization_nurses (employer model) tables are not built. handoff-after-refinement-phase-9, frontend-phase-15 follow-up 2 product pulls it
BL-225 product fraud_flags / ML fraud scoring is not built — manual suspension + support alerts cover this for now. handoff-after-backend-phase-6/14, handoff-after-refinement-phase-9 product pulls it
BL-226 server recurring_booking_schedules is not built. handoff-after-refinement-phase-9, frontend-phase-15 follow-up 2 product pulls it
BL-227 server bnpl_settlement_entries (tranched settlement) is modelled but not built. handoff-after-backend-phase-12, handoff-after-refinement-phase-9 product pulls it bnpl-installments
BL-228 product Nurse availability slots/exceptions (soft scheduling guidance) are not built. handoff-after-backend-phase-5/7, handoff-after-refinement-phase-9 product pulls it booking-request
BL-229 product Customer national-ID KYC collection is deliberately not built — the product decision is to never gate browsing/booking on it. handoff-after-backend-phase-3, handoff-after-refinement-phase-9 never, by design (informational)
BL-230 server A geography bulk-import feed (IGeoDataImporter) is deferred — the idempotent seed + admin CRUD is sufficient for MVP. handoff-after-backend-phase-4, backend-phase-4 follow-up product pulls it addresses-and-map
BL-231 product Holiday/surge pricing, a distinct Companionship pricing tier, and tiered per-category commission are all deferred. handoff-after-backend-phase-5, backend-phase-5 follow-up product pulls it nurse-catalog-and-pricing
BL-232 product GPS-radius "nurses near me" map discovery is explicitly not planned — coverage stays named-district-only. handoff-after-backend-phase-4/7 none — permanent product decision search-and-discovery
BL-233 server Automated MoH/INO license lookup and a professional-liability-insurance verification step type are both deferred. handoff-after-backend-phase-6 a lookup portal exists / product pulls it nurse-verification
BL-234 ops The credential-expiry scan and the EVV no-show sweep both run only via manual admin endpoints — no cron calls either yet. handoff-after-backend-phase-6/9, backend-phase-6 follow-up scheduled-ops phase nurse-verification, booking-lifecycle-evv
BL-235 server SMS.ir/Ghasedak SMS adapters are not built — only Kavenegar's real-SMS path is wired (attempting either throws at startup by design, never silently mocks). handoff-after-refinement-phase-8, refinement-phase-8 follow-up a second SMS vendor is needed auth-login-otp
BL-236 ops Finnotech/Moadian token-exchange refresh and the Moadian signing certificate are not wired — both are deploy-time actions once real credentials exist. handoff-after-refinement-phase-8 going to a real Moadian integration partner-center
BL-237 ops The Moadian reconciliation poll and the refund-settlement (BNPL processing→succeeded) poll are both thin/manual — no scheduled cron for either. handoff-after-backend-phase-11, handoff-after-refinement-phase-7/8, refinement-phase-6/7/8 follow-ups scheduled-ops phase cancellation-and-refunds, bnpl-installments
BL-238 server Per-provider-code BNPL revert is incomplete — the refund path only drives the SnappPay default regardless of the transaction's actual provider. handoff-after-refinement-phase-8, refinement-phase-8 follow-up a second BNPL provider goes live bnpl-installments
BL-239 product A dedicated merchant-of-record center-settlement payout path (تسهیم split leg) is deferred per decision 6.6. handoff-after-refinement-phase-8, refinement-phase-6/8 follow-ups product pulls it partner-center
BL-240 ops The weekly payout-batch cron generates automatically, but processing a batch stays a deliberate, explicit admin action by design (not a bug). handoff-after-refinement-phase-7, backend-phase-13 follow-up none — permanent product decision nurse-earnings-and-payouts
BL-241 product On-demand/instant nurse payout withdrawal and per-nurse payout-frequency configuration are both deferred (MVP is one fixed weekly cadence for everyone). handoff-after-backend-phase-13, frontend-phase-12 follow-up 4 product pulls it nurse-earnings-and-payouts
BL-242 server Automated clawback recovery beyond simple next-batch netting is not built. handoff-after-backend-phase-13 product pulls it nurse-earnings-and-payouts
BL-243 server Two-way (nurse-reviews-customer) double-blind reviews with timed reveal are not built. handoff-after-backend-phase-14 product pulls it reviews
BL-244 server A first-class incidents entity is not built — manual suspension + support alerts stand in for now. handoff-after-backend-phase-14 product pulls it admin-backoffice
BL-245 server SuspendNurse/ResolveSupportAlert/FlagConcern admin actions were never confirmed built in b15 — worth a direct re-check before relying on them. backend-phase-14 follow-up phase 5 verification pass admin-backoffice
BL-246 server Partner-center license verification is mocked to manual-approve at MVP rather than an automated eNamad/MoH check. handoff-after-backend-phase-15 product pulls it partner-center
BL-247 product There is no telephony seam for emergencies — the emergency contact is an out-of-platform tel: link by deliberate design. handoff-after-backend-phase-15 none — permanent product decision messaging-tickets
BL-248 client SMS/push notification channels are not built — only in-app notifications are real. handoff-after-refinement-phase-9 notification UX demands out-of-app reach notifications
BL-249 server Legacy UserRefreshTokens (gRPC auth path) still exists alongside the real session-based REST auth. backend-phase-2 follow-up gRPC moves to sessions, or is dropped auth-login-otp
BL-250 client The ESLint unused-vars gate is a repo-wide no-op — the config patches an export path that doesn't carry the rule, so @typescript-eslint/no-unused-vars never actually runs despite client/CLAUDE.md's golden rule 11 claiming it does. frontend-phase-13 follow-up 1 dedicated infra task
BL-251 client PWA/offline caching (Workbox) is unbuilt — marked "maybe" in the original product backlog, i.e. optional. product/notes open-questions.md product pulls it
BL-252 server Optional short-TTL cache over hot search result pages was shipped no-cache at MVP. backend-phase-7 follow-up search read latency becomes a real problem search-and-discovery
BL-253 server A single explicit DB transaction for the payment-webhook confirm path (currently two commits, kept safe via idempotency + a forward-only guard) is flagged as future hardening. backend-phase-10 follow-up IUnitOfWork grows a transaction scope checkout-and-payment
BL-254 server The partner-center dashboard's sponsored-nurse list is capped at 50 with an exact count — needs pagination if a center's roster grows past that. backend-phase-15 follow-up a center exceeds 50 sponsored nurses partner-center
BL-255 server Bookings/Invoices.partner_center_id columns exist with no DB-level FK — only nurse_profiles.partner_center_id got one, per the shipping phase's own Definition of Done. backend-phase-15 follow-up, backend-phase-11 follow-up a data-integrity pass on partner-center columns partner-center
BL-256 client Skeleton→content crossfade exists as a one-line-per-screen pattern but was never retrofitted onto every list/detail page. ui-phase-12 follow-up 1 a dedicated visual-polish pass
BL-257 client No true desktop search layout — a full responsive pass beyond the phone-width frame was explicitly deferred post-chain. ui-phase-12 follow-up 2 product decides to support desktop search-and-discovery
BL-258 client Persian OG image variant is Latin-only by deliberate scope cut on /welcome and other share cards. ui-phase-13 follow-up, public-front-door gap-7 Persian social sharing becomes a priority public-front-door
BL-259 server List-row EVV presence indicator (a lightweight "currently checked in" flag on the booking list DTO) was never built — needs a product/API decision to avoid an N+1 read. ui-phase-5 follow-up 1 product prioritizes a list-level EVV signal booking-lifecycle-evv
BL-260 client Web-push for new nurse booking requests remains deferred — the 15-second poll is the only freshness mechanism. ui-phase-7 follow-up 5, REQ-054 push infra (service worker + VAPID + dispatch rail) is built booking-request
BL-261 client Ticket attachments' composer button is fully built but gated off pending the upload/signed-URL backend. REQ-060 (see also BL-168) attachment backend delivered messaging-tickets
BL-262 product Real payment-gateway/Shaparak logos near the pay CTA are deferred — no licensed assets yet; a generic lock-icon trust notice stands in. ui-phase-6 follow-up 5 licensed gateway assets obtained checkout-and-payment