Files
baya-monorepo/docs/roadmap/deferred.md
T
2026-08-02 18:33:43 +03:30

141 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Deferred — recorded, not re-decided
> Last verified: 2026-08-02 against commit `cd8144e`. Populated by phase 5 of the
> [documentation clean-up chain](../_plan/README.md).
**51 items** carry deferred status in [backlog.md](../status/backlog.md): the 43 in its dedicated
["Deferred" section](../status/backlog.md#deferred-43) (BL-220BL-262), plus 8 more filed by severity
elsewhere in the same file whose Status column also reads `deferred` (BL-050, BL-075, BL-082, BL-096,
BL-163, BL-168, BL-201, BL-219). This file **records them faithfully** — it does not re-litigate any of
them. A deferral with a trigger is a decision; every row below has one, preserved in substance from its
source. Grouped by theme, as backlog.md itself groups its Deferred section.
**How to read "size" below**: this column is this document's own estimate (S / M / L / XL), not carried from
any source file — backlog.md doesn't size deferred items, so sizing them is this phase's proposal, made to
help a future reader triage, and open to revision.
---
## The 8 unbuilt product tables
Named individually per the phase brief, cross-referenced from [implemented.md](../status/implemented.md):
| Table | Backs | BL-### | Pull-trigger |
| --- | --- | --- | --- |
| `organizations` | Employer/company account model | [BL-224](../status/backlog.md#deferred-43) | Product pulls it |
| `organization_nurses` | Employer↔nurse membership | [BL-224](../status/backlog.md#deferred-43) | Product pulls it |
| `fraud_flags` | ML-scored fraud signals | [BL-225](../status/backlog.md#deferred-43) | Product pulls it (manual suspension + support alerts cover this today) |
| `recurring_booking_schedules` | Recurring/subscription bookings | [BL-226](../status/backlog.md#deferred-43) | Product pulls it |
| `bnpl_settlement_entries` | Tranched BNPL settlement | [BL-227](../status/backlog.md#deferred-43) | Product pulls it, or a future BNPL provider tranches settlement (one settlement row covers today's provider) |
| `nurse_availability_slots` | Soft scheduling-guidance windows | [BL-228](../status/backlog.md#deferred-43) | Product pulls it |
| `nurse_availability_exceptions` | Time-off exceptions to the above | [BL-228](../status/backlog.md#deferred-43) | Product pulls it |
| `incidents` | First-class incident entity | [BL-244](../status/backlog.md#deferred-43) | Product pulls it (support alerts cover this today) |
All eight are, per refinement-phase-9's own framing (item 9.11 in that phase's handoff, distilled in
[decisions.md](../status/decisions.md)), **pure additive migrations** — nothing in the current schema needs
to change first when one is pulled forward. The same source item 9.11 also grouped in customer national-ID
KYC ([BL-229](#product-scope-cuts-not-building-yet-by-decision)) and geo bulk-import
([BL-230](#product-scope-cuts-not-building-yet-by-decision)) alongside the tables; backlog.md split those into
their own rows below since neither is a table.
---
## Scale-later infrastructure
Correct for a single instance / MVP load; each has a concrete, measurable trigger, not a date.
| Item | Why deferred | Pull-trigger | Size | Decided |
| --- | --- | --- | --- | --- |
| [BL-220](../status/backlog.md#deferred-43) — Redis (shared cache, cross-instance scheduler/money lock) not deployed | Every current seam (the in-process scheduler, rate limiting) is correct only for one running instance | Running more than one instance | M | refinement-phase 7/8/9 handoffs |
| [BL-221](../status/backlog.md#deferred-43) — Elasticsearch `INurseSearch` + outbox feeder not built | `SqlNurseSearch` is real, correct, and sufficient at MVP scale | SQL search shows real strain (latency/throughput on `nurse_search_index`) | L | backend-phase-7 follow-up, refinement-phase 9.7 |
| [BL-252](../status/backlog.md#deferred-43) — no short-TTL cache over hot search-result pages | Shipped no-cache at MVP; premature to cache before there's a measured hot path | Search read latency becomes a real problem | S | backend-phase-7 follow-up |
## Product-scope cuts (not building yet, by decision)
| Item | Why deferred | Pull-trigger | Size | Decided |
| --- | --- | --- | --- | --- |
| [BL-222](../status/backlog.md#deferred-43) — `IAnalyticsSink` / analytics warehouse not built | Events write to `ops.SystemEvents` (real, queryable) fire-and-forget; no cross-event pipeline yet | Product needs cross-event analytics beyond SQL queries | L | backend-phase-1, refinement-phase 9.8 |
| [BL-223](../status/backlog.md#deferred-43) — no real holiday-calendar feed | `IHolidayCalendar` reads a real, seeded, manually-maintained table; a yearly ops top-up is an acceptable MVP alternative to an automated feed | Product pulls it (manual refresh becomes a burden) | M | backend-phase-1, refinement-phase 9.9 |
| [BL-229](../status/backlog.md#deferred-43) — customer national-ID KYC collection not built | Deliberate: never gate browsing/booking on it | **Never, by design** — informational only | — | backend-phase-3, refinement-phase-9, business/01 |
| [BL-230](../status/backlog.md#deferred-43) — geography bulk-import feed (`IGeoDataImporter`) not built | The idempotent seed + admin CRUD is sufficient for MVP | Product pulls it | M | backend-phase-4 follow-up |
| [BL-231](../status/backlog.md#deferred-43) — holiday/surge pricing, a distinct Companionship tier, tiered per-category commission | All explicitly out of MVP scope in business/03 | Product pulls it | M (pricing rule) / L (new tier) | backend-phase-5 follow-up, business/03 |
| [BL-232](../status/backlog.md#deferred-43) — GPS-radius "nurses near me" map discovery | Coverage stays named-district-only by design | **None — permanent product decision** | — | backend-phase 4/7, business/04 |
| [BL-233](../status/backlog.md#deferred-43) — automated MoH/INO license lookup + professional-liability-insurance step type | Manual verification is the MVP path; no B2B lookup API is confirmed to exist yet | A lookup portal is confirmed to exist, or product pulls the insurance step | M | backend-phase-6, business/02 |
| [BL-239](../status/backlog.md#deferred-43) — dedicated MoR center-settlement payout path (تسهیم split leg) | Per decision 6.6; the platform pays nurses directly today regardless of MoR | Product pulls it | M | refinement-phase 6/8 follow-ups |
| [BL-241](../status/backlog.md#deferred-43) — on-demand/instant nurse payout, per-nurse payout frequency | MVP is one fixed weekly cadence for everyone | Product pulls it | M | backend-phase-13, business/10 |
| [BL-242](../status/backlog.md#deferred-43) — automated clawback recovery beyond next-batch netting | Simple greedy netting covers MVP | Product pulls it | M | backend-phase-13 |
| [BL-243](../status/backlog.md#deferred-43) — two-way double-blind reviews with timed reveal | One-way customer review is MVP scope per business/11 | Product pulls it | L | backend-phase-14, business/11 |
| [BL-246](../status/backlog.md#deferred-43) — automated eNamad/MoH license verification for partner centers | Manual-approve is MVP scope per business/13 | Product pulls it | M | backend-phase-15 |
| [BL-247](../status/backlog.md#deferred-43) — no telephony seam for emergencies | The emergency contact is an out-of-platform `tel:` link, by deliberate design | **None — permanent product decision** | — | backend-phase-15 |
| [BL-248](../status/backlog.md#deferred-43) — SMS/push notification channels not built | Only in-app notifications are real; deliberate MVP scope (business/14) | Notification UX demands out-of-app reach | M | refinement-phase-9, refinement-phase 9.10 |
| [BL-251](../status/backlog.md#deferred-43) — PWA/offline caching (Workbox) unbuilt | Marked "maybe" in the original product backlog — optional from the start | Product pulls it | M | product/notes/open-questions.md |
| [BL-254](../status/backlog.md#deferred-43) — partner dashboard's sponsored-nurse list capped at 50, no pagination | No center has exceeded 50 sponsored nurses yet | A center exceeds 50 sponsored nurses | S | backend-phase-15 follow-up |
| [BL-257](../status/backlog.md#deferred-43) — no true desktop search layout | The phone-width frame is the whole app's deliberate design; a full responsive pass was explicitly deferred post-chain | Product decides to support desktop | L | ui-phase-12 follow-up |
| [BL-258](../status/backlog.md#deferred-43) — Persian OG image is Latin-only (also [BL-202](../status/backlog.md#minor-115)) | Deliberate scope cut on `/welcome` and other share cards | Persian social sharing becomes a priority | S | ui-phase-13 follow-up |
| [BL-259](../status/backlog.md#deferred-43) — no list-row EVV "currently checked in" indicator | Needs a product/API decision to avoid an N+1 read; not free to add | Product prioritizes a list-level EVV signal | S | ui-phase-5 follow-up |
| [BL-260](../status/backlog.md#deferred-43) — no web-push for new nurse booking requests | The 15-second poll is the only freshness mechanism today | Push infra (service worker + VAPID + dispatch rail) is built | L | ui-phase-7 follow-up, REQ-054 |
| [BL-262](../status/backlog.md#deferred-43) — no real payment-gateway/Shaparak logos near the pay CTA | No licensed assets yet; a generic lock-icon notice stands in | Licensed gateway assets obtained | S | ui-phase-6 follow-up |
## Vendor / integration deferrals
| Item | Why deferred | Pull-trigger | Size | Decided |
| --- | --- | --- | --- | --- |
| [BL-235](../status/backlog.md#deferred-43) — SMS.ir/Ghasedak adapters not built | Only Kavenegar's real-SMS path is wired; either alternative throws at startup by design rather than silently mocking | A second SMS vendor is needed | M | refinement-phase-8 follow-up |
| [BL-236](../status/backlog.md#deferred-43) — Finnotech/Moadian token-exchange refresh + signing certificate not wired | Both are deploy-time actions that need real credentials, which don't exist yet | Going to a real Moadian integration ([pre-launch.md §5](pre-launch.md#5-legal--tax-items-that-are-code-side)) | S once credentials exist | refinement-phase-8 handoff |
| [BL-238](../status/backlog.md#deferred-43) — per-provider-code BNPL revert incomplete (always drives SnappPay) | Only one BNPL provider is live today | A second BNPL provider goes live | S | refinement-phase-8 follow-up |
## Scheduled-ops deferrals (manual today, by choice or by not-yet-built)
| Item | Why deferred | Pull-trigger | Size | Decided |
| --- | --- | --- | --- | --- |
| [BL-234](../status/backlog.md#deferred-43) — credential-expiry scan + EVV no-show sweep are manual-only endpoints | No cron calls either yet | A scheduled-ops phase | S | backend-phase 6/9 follow-ups |
| [BL-237](../status/backlog.md#deferred-43) — Moadian reconciliation poll + refund-settlement poll are manual | No scheduled cron for either | A scheduled-ops phase | S | backend-phase-11, refinement 6/7/8 follow-ups |
| [BL-240](../status/backlog.md#deferred-43) — payout batch *generation* is automatic; *processing* a batch stays a deliberate, explicit admin action | Not a bug — moving real money should have a human in the loop at this scale | **None — permanent product decision** | — | refinement-phase-7, backend-phase-13 |
## Cleanup-of-convenience and data-integrity hygiene
| Item | Why deferred | Pull-trigger | Size | Decided |
| --- | --- | --- | --- | --- |
| [BL-219](../status/backlog.md#minor-115) — rename the `SET_VIA_USER_SECRETS_OR_ENV` placeholder sentinel | The name is a load-bearing sentinel `StartupSecretsGuard` and the pre-commit hook both check for; renaming touches 7 files for a cosmetic gain | None — cleanup-of-convenience | S | phase 2 (`open-contradictions.md` C-2) |
| [BL-250](../status/backlog.md#deferred-43) — the ESLint unused-vars gate is a repo-wide no-op | Config patches an export path that doesn't carry the rule; fixing it is a dedicated infra task, not a drive-by | A dedicated infra task | S | frontend-phase-13 follow-up |
| [BL-253](../status/backlog.md#deferred-43) — payment-webhook confirm path uses two DB commits instead of one transaction | Kept safe today via idempotency + a forward-only guard; a real fix needs `IUnitOfWork` to grow a transaction scope first | `IUnitOfWork` grows a transaction scope | M | backend-phase-10 follow-up |
| [BL-255](../status/backlog.md#deferred-43) — `Bookings`/`Invoices.partner_center_id` have no DB-level FK | Only `nurse_profiles.partner_center_id` got one, per that phase's own Definition of Done | A data-integrity pass on partner-center columns | S | backend-phase 11/15 follow-ups |
| [BL-256](../status/backlog.md#deferred-43) — skeleton→content crossfade never retrofitted onto every list/detail page | Exists as a one-line-per-screen pattern; applying it everywhere is a dedicated visual pass, not a drive-by | A dedicated visual-polish pass | M | ui-phase-12 follow-up |
| [BL-249](../status/backlog.md#deferred-43) — legacy `UserRefreshTokens` (gRPC auth path) still exists alongside real session-based REST auth | Removing it means confirming nothing still depends on the gRPC path | gRPC moves to sessions, or is dropped | S | backend-phase-2 follow-up |
---
## Deferred at the item level — gated behind a console that isn't prioritized yet
These 7 are filed by severity (major/minor) rather than in backlog.md's thematic Deferred section, because
each is a specific, already-scoped gap rather than a standing product decision — but each is genuinely blocked
on the same thing: an admin console this roadmap hasn't prioritized building yet. Recorded here for the same
reason: each has a trigger, and none should be picked up piecemeal ahead of its console.
| Item | Why deferred | Pull-trigger | Size | Decided |
| --- | --- | --- | --- | --- |
| [BL-050](../status/backlog.md#major-86) — no preview/approve/reject route for admin refunds (`POST admin_refunds` creates+executes in one call) | The three-step admin `RefundPanel` console has no real backend to call | Admin refund console prioritized | M | phase 3 flow gap |
| [BL-075](../status/backlog.md#major-86) — `recordTransferReference` targets a route that doesn't exist | The payout batch-detail reconcile field would 404 on flip | Payout reconciliation console prioritized | S | phase 3 flow gap, REQ-036 |
| [BL-082](../status/backlog.md#major-86) — `approveVerification`/`rejectVerification`/`getDocumentSignedUrl` target routes that don't exist | The admin verification case page's approve/reject CTAs would 404 the moment BL-001 (RBAC) is fixed | Verification-admin console prioritized | M | phase 3 flow gap, REQ-034 |
| [BL-096](../status/backlog.md#major-86) — tier (c) of the public front door (guest search + public nurse profiles) unbuilt | Needs a backend phase (anonymous rate-limited search read, privacy-reviewed profile shape) **and** an explicit privacy sign-off on the nurse-profile field list — a decision, not a coding task | Privacy sign-off obtained **and** REQ-066/REQ-067 delivered | L | ui-phase-13, product/notes/open-questions.md |
| [BL-163](../status/backlog.md#minor-115) — `POST tickets/{id}/assign` is a phantom endpoint the client already targets | Client-side assign UI exists; server route doesn't | Ticket assignment prioritized | S | phase 3 flow gap, REQ-063 |
| [BL-168](../status/backlog.md#minor-115) / [BL-261](../status/backlog.md#deferred-43) — ticket attachments are fully designed/built client-side, gated off behind a flag | Waiting on the upload/signed-URL backend | Attachment backend delivered | M | phase 3 flow gap + REQ-060 (**note:** these are the same underlying fact filed as two BL-### by two different harvest passes — treat as one item when picking it up) |
| [BL-201](../status/backlog.md#minor-115) — center self-onboarding (write-then-masked IBAN) never exercised on a real route | Deferred pending partner-center de-mock generally | Center self-service onboarding prioritized | M | phase 3 flow gap |
---
## Verification note
[BL-245](../status/backlog.md#deferred-43) is not listed above: its own trigger was "phase 5 verification
pass," which this phase executed directly against the code rather than deferring further — see
[decisions.md](../status/decisions.md) for the finding (2 of 3 admin actions confirmed built; only
`FlagConcern` is a genuine, small, unfiled gap).
## What this file is not
This is a record, not a plan — nothing here is re-ranked or newly triggered by this phase. The proposed order
of work that **isn't** deferred is [next-up.md](next-up.md); what the deferrals above cost to keep deferring
is partly covered in [tech-debt.md](tech-debt.md) where a deferral and a debt item are the same underlying
fact (e.g. Redis/BL-220 appears in both, because "not built yet" and "costs more the longer it's not built"
are two different questions about the same gap).