From c99e3f4a6e1193953bef1177d9d0a9be76bcd76d Mon Sep 17 00:00:00 2001 From: hamid Date: Wed, 29 Jul 2026 22:46:38 +0330 Subject: [PATCH] making the mess clean plans added --- docs/_plan/README.md | 162 +++++++++++++++ docs/_plan/phase-0-inventory-and-scaffold.md | 148 ++++++++++++++ docs/_plan/phase-1-rules-consolidation.md | 175 ++++++++++++++++ docs/_plan/phase-2-integration.md | 149 ++++++++++++++ docs/_plan/phase-3-flow-atlas.md | 203 +++++++++++++++++++ docs/_plan/phase-4-backlog.md | 158 +++++++++++++++ docs/_plan/phase-5-roadmap.md | 121 +++++++++++ docs/_plan/phase-6-archive.md | 124 +++++++++++ docs/_plan/phase-7-skills-and-guardrails.md | 125 ++++++++++++ 9 files changed, 1365 insertions(+) create mode 100644 docs/_plan/README.md create mode 100644 docs/_plan/phase-0-inventory-and-scaffold.md create mode 100644 docs/_plan/phase-1-rules-consolidation.md create mode 100644 docs/_plan/phase-2-integration.md create mode 100644 docs/_plan/phase-3-flow-atlas.md create mode 100644 docs/_plan/phase-4-backlog.md create mode 100644 docs/_plan/phase-5-roadmap.md create mode 100644 docs/_plan/phase-6-archive.md create mode 100644 docs/_plan/phase-7-skills-and-guardrails.md diff --git a/docs/_plan/README.md b/docs/_plan/README.md new file mode 100644 index 0000000..cb4c66d --- /dev/null +++ b/docs/_plan/README.md @@ -0,0 +1,162 @@ +# The Clarify Chain — a plan to clean up Balinyaar's documentation + +**Status:** planned, not started · **Written:** 2026-07-29 · **Baseline commit:** `96b57eb` + +This folder is a **plan**, not documentation. It describes eight phases that take the repo from its +current state — 260 markdown files, ~10 competing rule sources, five unreconciled backlogs, and a +contract layer that stopped tracking the code on 2026-07-13 — to a single navigable `docs/` tree that +tells the truth. + +When the chain finishes, **this folder moves to `archive/`**. It is temporary by design. + +--- + +## Why this exists (the diagnosis) + +Measured against the working tree at `96b57eb`: + +| Finding | Evidence | +| --- | --- | +| **3.0 MB / 199 files of build history in [`dev/`](../../dev/)** reads as instruction, not record | [`dev/phases/`](../../dev/phases/) last touched 2026-06-28 (already-executed prompts) sits beside [`dev/post-phase/`](../../dev/post-phase/) touched 2026-07-28 (live plan). Nothing marks the difference. | +| **Rules live in ~10 places** | root [CLAUDE.md](../../CLAUDE.md) · [client/CLAUDE.md](../../client/CLAUDE.md) **161 KB** · [server/CLAUDE.md](../../server/CLAUDE.md) 75 KB · [server/CONVENTIONS.md](../../server/CONVENTIONS.md) · [client/messages/STYLE.md](../../client/messages/STYLE.md) · [.claude/skills/frontend-designer/SKILL.md](../../.claude/skills/frontend-designer/SKILL.md) · [dev/phases/_shared/](../../dev/phases/_shared/) ×4 · [dev/contracts/conventions/](../../dev/contracts/conventions/) ×2 · 3× `AGENTS.md` · [.githooks/README.md](../../.githooks/README.md) | +| **Loading `client/CLAUDE.md` costs ~40k tokens** on any client edit | 161 KB, of which lines 103–421 are a project-structure listing and lines 421–1100 are explanatory reference | +| **Remaining work is split across 5 ledgers** | 67 REQs in a 1,115-line append-only file · **18 hardening items, none ticked** · per-phase "Follow-ups" buried in 50+ reports · backend deferrals-with-pull-triggers · [product/notes/open-questions.md](../../product/notes/open-questions.md) · two raw feedback notes in [dev/manual-testing/](../../dev/manual-testing/) | +| **Contracts drifted from code** | [`dev/contracts/`](../../dev/contracts/) frozen 2026-07-13; `server/src` moved through 2026-07-28. OpenAPI snapshot is from 07-13; a second stale copy sits at [temp/swagger.json](../../temp/swagger.json) (07-06). | +| **18 files still instruct you to use `dotnet user-secrets`** — removed in `5885280` | includes [manual-testing-plan.md](../../dev/post-phase/manual-testing-plan.md), the closest thing to a test guide | +| **No single "what's implemented + how to test it"** | knowledge split across manual-testing-plan, [RUNBOOK.md](../../dev/post-phase/refinement/RUNBOOK.md), `product/business/`, and 18 contract files | +| **The client↔server dependency is implicit** | envelope shape, casing, idempotency, cookies/refresh, CORS, `NEXT_PUBLIC_API_URL`, 3 containers + Caddy + remote SQL + the OTP bot — described nowhere as one thing | + +The code itself is **not** the mess. 83 client routes, 22 service domains, 125 client tests; 56 +controllers, 199 handlers, 24 migrations. The problem is that nothing tells you which parts of that +are real, which are mocked, and which are described by a document written three weeks ago. + +--- + +## Decisions this plan implements + +Agreed 2026-07-29, before any file was written: + +| Decision | Choice | +| --- | --- | +| Doc home | **New top-level `docs/` tree.** `product/` stays as-is; `dev/` becomes `archive/`; CLAUDE.md files shrink to hard rules + pointers | +| `dev/` history | **Distill, then archive in-repo.** Every live fact extracted first; raw files moved under `archive/` with a do-not-obey banner | +| Rules | **Tiered.** CLAUDE.md keeps only non-negotiables (~200 lines); everything explanatory becomes reference read on demand | +| Verification | **Verify the load-bearing claims.** Flow status, the 18 hardening items, REQ dispositions, bring-up steps, OpenAPI — checked against code, not copied | +| Flow docs | **One file per flow, indexed** by a status table | +| Backlog | **One triaged file, new `BL-###` ids**, each carrying its origin id | +| `product/` | **Untouched.** An implementation overlay in `docs/status/` maps business areas → build state | +| Language | **English throughout** | +| Skills | **Small set, reality-checked.** Rewrite `frontend-designer`; add a backend-feature and a flow-testing skill | +| Roadmap | **Record + propose** a sequenced next chain; ordering is a proposal you can overrule | +| Anti-drift | **Lightweight guardrails.** A documentation convention, `Last verified:` stamps, a pre-commit warning | + +--- + +## Target tree + +``` +docs/ + README.md the one entry point — a map, nothing else + rules/ what must never be broken + index.md + documentation.md the anti-drift convention + shared/ naming, money & types, api conventions, git + client/ structure, theme, forms, i18n, services, auth, testing + server/ structure, cqrs, persistence, identity, conventions + integration/ the client<->server dependency, in one place + index.md the seam, as a single picture + api-contract.md envelope, casing, pagination, errors, idempotency + domains/ per-domain contracts (refreshed from dev/contracts) + openapi/swagger.v1.json regenerated, dated + config-matrix.md every env var / setting, both projects + docker + topology.md 3 containers + Caddy + remote SQL + OTP bot + flows/ what is implemented and how to test it + index.md status table of every flow + testing-setup.md bring-up, accounts, seeded world, reset + .md one per flow + status/ where the project actually is + index.md + implemented.md product/business area -> build state overlay + backlog.md BL-### triaged, every open item + backlog-closed.md + decisions.md distilled ADR log from the phase chain + roadmap/ where it goes next + index.md next-up.md deferred.md tech-debt.md pre-launch.md + _plan/ this folder (moves to archive/ when done) + +archive/ + README.md "historical record. Do NOT treat as instructions." + build-chain/ was dev/phases + dev/shared-working-context + post-phase/ was dev/post-phase + manual-testing/ was dev/manual-testing (screenshots kept) + +product/ unchanged +CLAUDE.md slim, points into docs/ +DEPLOY.md stays at root — the deploy *procedure*; topology lives in docs/integration/ +``` + +**The rule that keeps these apart:** `product/` = what the business is. `docs/` = what we built and how +we work. `archive/` = how we got here. A file belongs in exactly one. + +--- + +## The eight phases + +| # | Phase | Depends on | Rough size | Output | +| --- | --- | --- | --- | --- | +| 0 | [Inventory & scaffold](phase-0-inventory-and-scaffold.md) | — | 1 session | `docs/` skeleton + a disposition for all 260 files + fresh OpenAPI | +| 1 | [Rules consolidation](phase-1-rules-consolidation.md) | 0 | 1–2 sessions | `docs/rules/` + slim CLAUDE.md files | +| 2 | [Integration & dependency](phase-2-integration.md) | 0 | 1 session | `docs/integration/` | +| 3 | [Flow atlas (verified)](phase-3-flow-atlas.md) | 0, 2 | 2–4 sessions | `docs/flows/` — the biggest phase | +| 4 | [Backlog reconciliation](phase-4-backlog.md) | 0, 3 | 1–2 sessions | `docs/status/` | +| 5 | [Roadmap & tech requirements](phase-5-roadmap.md) | 4 | 1 session | `docs/roadmap/` | +| 6 | [Archive & prune](phase-6-archive.md) | 1–5 | 1 session | `archive/`, `dev/` gone, links fixed | +| 7 | [Skills & guardrails](phase-7-skills-and-guardrails.md) | 1, 3 | 1 session | `.claude/skills/` rewritten + anti-drift hooks | + +``` + ┌─ 1 rules ──────────────┐ +0 ──────┼─ 2 integration ─ 3 flows ─ 4 backlog ─ 5 roadmap ─┼─ 6 archive + └────────────────────────┴──── 7 skills ────────────┘ +``` + +Phases 1 and 2 can run in parallel with each other after 0. Everything else is a chain. + +--- + +## How to run a phase + +Point a fresh agent session at one phase file: + +> Execute `docs/_plan/phase-2-integration.md`. + +Each phase file states its own inputs, outputs, steps, verification, and definition of done. It ends +by ticking its own row in the progress table below and writing a short handoff note at the bottom of +its own file. **Do not run two phases in one session** — the point of this exercise is that context +stays small. + +## Non-negotiables for every phase + +1. **Nothing is deleted before it is distilled.** Phase 6 is the only phase that removes files, and it + may only remove files that Phase 0's inventory marked as *archived* or *extracted*. +2. **Verify, don't copy.** If a claim is load-bearing (a flow works, an item is closed, a command + boots the app), check it against the code or run it. If you cannot verify it, write it with an + explicit `UNVERIFIED:` prefix rather than asserting it. +3. **Every status/flow doc carries a `> Last verified: against ` header line.** +4. **Write short.** The failure mode this chain fixes is length. A reference doc over ~400 lines + should be split. A phase that produces a 30 KB file has misunderstood the assignment. +5. **Record contradictions, don't silently pick.** When two docs disagree, check the code, write the + truth, and log the contradiction in `docs/status/decisions.md`. +6. **Update this README's progress table** in the same change that finishes a phase. + +## Progress + +| Phase | Status | Finished | Notes | +| --- | --- | --- | --- | +| 0 Inventory & scaffold | not started | | | +| 1 Rules consolidation | not started | | | +| 2 Integration & dependency | not started | | | +| 3 Flow atlas | not started | | | +| 4 Backlog reconciliation | not started | | | +| 5 Roadmap | not started | | | +| 6 Archive & prune | not started | | | +| 7 Skills & guardrails | not started | | | diff --git a/docs/_plan/phase-0-inventory-and-scaffold.md b/docs/_plan/phase-0-inventory-and-scaffold.md new file mode 100644 index 0000000..e00372a --- /dev/null +++ b/docs/_plan/phase-0-inventory-and-scaffold.md @@ -0,0 +1,148 @@ +# Phase 0 — Inventory & scaffold + +**Depends on:** nothing · **Blocks:** every other phase · **Size:** one session + +## Goal + +Before anything is moved, merged, or deleted, produce two things: + +1. **A disposition for every one of the ~260 markdown files in the repo** — so that "summarize + without losing data" is a checkable claim rather than a hope. +2. **The empty `docs/` skeleton** with a real entry point, so later phases have somewhere to write. + +Plus one piece of housekeeping every later phase needs: a **fresh OpenAPI snapshot**, because the +committed one is 16 days behind the server code. + +This phase writes almost no prose. It is a survey. + +--- + +## Inputs + +- The whole repo. Specifically: `dev/` (199 files), `product/` (48), root (4), `client/` (5), + `server/` (6), `telegram-otp-bot/` (2), `.claude/skills/` (1), `.githooks/` (1). +- [`../README.md`](README.md) — the target tree and the decisions. + +## Outputs + +| File | What it is | +| --- | --- | +| `docs/_plan/inventory.md` | The disposition table — every markdown file, one row | +| `docs/README.md` | The single entry point: a map of `docs/`, `product/`, `archive/` and what belongs where | +| `docs/rules/index.md` `docs/integration/index.md` `docs/flows/index.md` `docs/status/index.md` `docs/roadmap/index.md` | Stub indexes, each with a one-line purpose and a "populated by phase N" note | +| `docs/integration/openapi/swagger.v1.json` | Regenerated from the running server | +| `docs/_plan/open-contradictions.md` | Running list of doc-vs-doc and doc-vs-code conflicts spotted during the survey — later phases resolve these | + +--- + +## Steps + +### 1. Build the inventory + +Walk every `.md` file (exclude `node_modules`, `bin`, `obj`, `.git`). For each, record: + +| Column | Meaning | +| --- | --- | +| `path` | repo-relative | +| `bytes` | size | +| `last commit` | `git log -1 --format=%ad --date=short -- ` | +| `kind` | `rule` · `reference` · `contract` · `plan` · `report` · `history` · `business` · `ops` · `feedback` | +| `disposition` | `keep-as-is` · `move` · `distill` · `merge-into` · `archive` · `delete` | +| `target` | where its content ends up (a `docs/…` path, or `archive/…`) | +| `owner phase` | which phase (1–7) handles it | +| `live facts?` | `yes` / `no` — does it contain anything not yet captured elsewhere? | + +Rules for assigning disposition: + +- **`dev/phases/backend/*` and `dev/phases/frontend/*`** (32 files, ~1 MB): these are *prompts that + were already executed*. Disposition `archive`. But scan each for **decisions and constraints stated + in the prompt that are not visible in the code** — those are `live facts: yes` and go to Phase 1 + (if a rule) or Phase 4 (`decisions.md`). +- **`dev/shared-working-context/reports/*` (50 files)**: `archive`, but every "Follow-ups for later + phases" / "Deferred" / "Known gap" section is a live fact for **Phase 4**. Extract the section + headings now; Phase 4 reads them in detail. +- **`dev/shared-working-context/*/STATUS.md`** (86 KB combined): `distill` → Phase 4 (`decisions.md` + + `implemented.md`), then `archive`. +- **`dev/shared-working-context/frontend/requests/for-backend.md`** (67 REQs): `distill` → Phase 4. +- **`dev/post-phase/hardening/issues.md`** (18 open items): `distill` → Phase 4, **with + re-verification** — the UI and refinement chains ran after this file was written and some items are + probably already fixed. +- **`dev/contracts/**`**: `move` → `docs/integration/` — Phase 2 owns it, and refreshes it against code. +- **`dev/post-phase/manual-testing-plan.md`** + **`refinement/RUNBOOK.md`**: `distill` → Phase 3 + (`docs/flows/testing-setup.md` + the per-flow files). Both are stale on secrets handling. +- **`dev/manual-testing/iteration-*/`**: `distill` → Phase 4 (unfinished items) then `archive` + (**keep the PNG screenshots** — they are the only visual record of the pre-overhaul UI). +- **`product/**`**: `keep-as-is`, every one. Not this chain's business. +- **`client/CLAUDE.md`, `server/CLAUDE.md`, `server/CONVENTIONS.md`, `client/messages/STYLE.md`, + `dev/phases/_shared/*`, `dev/contracts/conventions/*`, `.claude/skills/*/SKILL.md`**: `distill` → + Phase 1. +- **`DEPLOY.md`**: `keep-as-is` at root (it is the deploy *procedure* and it is current) — but Phase 2 + fixes its stale `user-secrets` reference and Phase 2's `topology.md` links to it. +- **`Prompt.md`** (0 bytes): `delete`. +- **`temp/swagger.json`** (stale duplicate): `delete` — Phase 2 replaces it. +- **`client/graphify-out/GRAPH_REPORT.md`, `server/graphify-out/GRAPH_REPORT.md`**: generated tool + output. Decide `keep-as-is` if the tool is still used, else `delete`; check `.gitignore` first. + +### 2. Log contradictions as you go + +Write `docs/_plan/open-contradictions.md` with one row per conflict: *claim A (file:line) vs claim B +(file:line or code:line) — unresolved*. Seed it with the ones already known: + +- **`user-secrets` is required** (18 files) vs **`user-secrets` was removed and the store isn't read** + (root [CLAUDE.md](../../CLAUDE.md) §6, commit `5885280`). +- **`dev/contracts/` describes the API** (frozen 2026-07-13) vs **`server/src`** (through 2026-07-28). +- **Design language in [.claude/skills/frontend-designer/SKILL.md](../../.claude/skills/frontend-designer/SKILL.md) §§1–7** + vs **[client/CLAUDE.md](../../client/CLAUDE.md) "Theme System" / "Anti-patterns"** — overlapping, possibly divergent. +- **Both** vs **the reality after iterations 1–2** (mobile-scoped shell, bottom nav, react-hook-form, + new icon set) — the skill predates that overhaul. +- **18 hardening items open** (2026-07-16) vs **UI phases 0–13 and the deploy commits that ran after**. + +Do **not** resolve these here. Phase 0 only finds them. + +### 3. Regenerate the OpenAPI snapshot + +Boot the server and capture the live swagger document: + +```bash +cd server && dotnet run --project src/API/Baya.Web.Api/Baya.Web.Api.csproj +# then, from another shell: +curl -sk https://localhost:5002/swagger/v1/swagger.json -o docs/integration/openapi/swagger.v1.json +``` + +Record in the file's sibling `README.md`: the date, the commit, and the endpoint count. Diff the +endpoint *paths* against the old `dev/contracts/openapi/swagger.v1.json` and write the added/removed +list into `docs/_plan/open-contradictions.md` — Phase 2 uses it as its worklist. + +If the server will not boot (config, DB reachability), **stop and report** rather than guessing. A +stale snapshot is what caused half of this mess. + +### 4. Scaffold `docs/` + +Create the directories and stub index files from the target tree in [`README.md`](README.md). Each +stub is ~10 lines: what lives here, which phase fills it, and a `> Populated by phase N — not yet +written` banner. `docs/README.md` is the only one with real content: the map, and the +`product/` vs `docs/` vs `archive/` rule. + +Do **not** create `archive/` yet — Phase 6 does that, once there is something safe to put in it. + +--- + +## Verification + +- [ ] `docs/_plan/inventory.md` has a row for every `.md` file the survey walked; the count matches + `find . -name "*.md" -not -path "./node_modules/*" … | wc -l` (~260 at baseline). +- [ ] No row has an empty `disposition` or `owner phase`. +- [ ] Every row with `live facts: yes` names the phase that will extract them. +- [ ] `docs/integration/openapi/swagger.v1.json` exists and its endpoint count is recorded. +- [ ] Every stub index exists and says which phase fills it. +- [ ] Nothing outside `docs/` was modified, except deleting `Prompt.md` and `temp/swagger.json`. + +## Definition of done + +You can answer, for any markdown file in the repo, "where does this end up and who handles it?" +without re-reading the file. + +## Handoff + +_(filled in by the agent that runs this phase — file counts, surprises, anything that changes a later +phase's scope)_ diff --git a/docs/_plan/phase-1-rules-consolidation.md b/docs/_plan/phase-1-rules-consolidation.md new file mode 100644 index 0000000..4bfcc66 --- /dev/null +++ b/docs/_plan/phase-1-rules-consolidation.md @@ -0,0 +1,175 @@ +# Phase 1 — Rules consolidation + +**Depends on:** Phase 0 · **Can run in parallel with:** Phase 2 · **Size:** 1–2 sessions + +## Goal + +Collapse ~10 rule sources into one tiered system, and cut the cost of editing client code from +~40k tokens to ~5k. + +**The tiering rule:** + +| Tier | Where | What goes in it | Budget | +| --- | --- | --- | --- | +| **Hard rules** | `client/CLAUDE.md`, `server/CLAUDE.md`, root `CLAUDE.md` | Constraints whose violation breaks the build, the gate, or a business invariant. Stated imperatively, no explanation. | ~200 lines each | +| **Reference** | `docs/rules/{shared,client,server}/*.md` | The *how* and the *why*. Read on demand when working on that area. | ~200–400 lines per file | +| **Procedure** | `.claude/skills/` | Step-by-step playbooks for recurring tasks. **Phase 7** owns these. | — | + +A rule that only matters when you are already editing theme code is **reference**, not a hard rule. +A rule like "never change `Seams:FieldEncryption:Key`" is a hard rule — it belongs inline. + +--- + +## Inputs + +Read these in full; they are the raw material: + +| Source | Size | Contains | +| --- | --- | --- | +| [client/CLAUDE.md](../../client/CLAUDE.md) | 161 KB | 22 sections; lines 103–421 are a structure listing, 421+ is reference | +| [server/CLAUDE.md](../../server/CLAUDE.md) | 75 KB | 11 sections; lines 89–603 are the project map | +| [server/CONVENTIONS.md](../../server/CONVENTIONS.md) | 27 KB | naming, layering, CQRS shape | +| [client/messages/STYLE.md](../../client/messages/STYLE.md) | 8 KB | Persian copy rules (enforced by `lint:copy`) | +| [.claude/skills/frontend-designer/SKILL.md](../../.claude/skills/frontend-designer/SKILL.md) | 21 KB | brand, tokens, typography, component library, layout, icons | +| [dev/phases/_shared/agent-operating-rules.md](../../dev/phases/_shared/agent-operating-rules.md) | 13 KB | how agents were told to work | +| [dev/phases/_shared/definition-of-done.md](../../dev/phases/_shared/definition-of-done.md) | 3 KB | the gate | +| [dev/phases/_shared/backend-conventions-checklist.md](../../dev/phases/_shared/backend-conventions-checklist.md) | 4 KB | | +| [dev/phases/_shared/frontend-conventions-checklist.md](../../dev/phases/_shared/frontend-conventions-checklist.md) | 3 KB | | +| [dev/contracts/conventions/api-conventions.md](../../dev/contracts/conventions/api-conventions.md) | 3 KB | → **Phase 2 owns this**; read for cross-check only | +| [dev/contracts/conventions/money-and-types.md](../../dev/contracts/conventions/money-and-types.md) | 3 KB | → **Phase 2 owns this**; read for cross-check only | +| root [CLAUDE.md](../../CLAUDE.md) · 3× `AGENTS.md` · [.githooks/README.md](../../.githooks/README.md) | small | working agreements, pointers, the pre-commit hook | + +Plus: `docs/_plan/inventory.md` and `docs/_plan/open-contradictions.md` from Phase 0. + +## Outputs + +``` +docs/rules/ + index.md what's here, and the tiering rule restated + documentation.md the anti-drift convention (Phase 7 adds the hook that enforces it) + shared/ + naming.md Baya* vs balinyaar-client, @/* alias, file/dir conventions + git-and-gates.md branch, commit, pre-commit hook, what "done" means per project + code-quality.md no dead code, comment the why, no starter scaffolding + client/ + structure.md the route/folder map (regenerated from reality, not copied) + theme.md tokens, palette, dark mode, RTL, fonts + components.md the App* library, when to reach for it vs raw MUI + forms.md react-hook-form (post-iteration-2), validation, field components + i18n.md next-intl v4, en/fa parity, STYLE.md copy rules folded in + services.md services/{domain} pattern, fetch layer, envelope, query keys + auth.md cookies, session state, refresh, RoleGuard, middleware/PUBLIC_PATHS + testing.md what is tested, how, the 125 existing tests + server/ + structure.md the project map (condensed from server/CLAUDE.md lines 89-603) + cqrs.md how a feature is shaped: command/query/handler/validator + persistence.md EF Core, migrations, interceptors, the audit interceptor + identity.md JWE, sessions, rotation, field encryption, PhoneHash + conventions.md successor to CONVENTIONS.md +``` + +Rewritten in place: `CLAUDE.md` (root), `client/CLAUDE.md`, `server/CLAUDE.md`, 3× `AGENTS.md`. +Deleted after distillation: `server/CONVENTIONS.md`, `client/messages/STYLE.md` (content moves to +`docs/rules/client/i18n.md`; **check `lint:copy` doesn't read STYLE.md by path before deleting**). + +--- + +## Steps + +### 1. Extract every distinct rule into a ledger first + +Before writing any output file, build a working list (scratch, not committed) of every *rule* found +across all inputs, tagged with: source file:line, scope (client/server/shared), tier +(hard/reference), and whether it is **contradicted or obsoleted** by another source or by the code. + +This is the step that prevents loss. Merging by reading two documents side by side and writing a +third loses whatever was in neither's first half. + +### 2. Reality-check the client rules against the post-overhaul code + +`client/CLAUDE.md` and the frontend-designer skill both predate iterations 1–2 (commits `baa3cc6`, +`e6a8f93`). Those commits changed load-bearing things: + +- **Mobile-scoped shell** — max-width container, no desktop sidebar for the nurse side +- **Bottom navigation** replacing the drawer, grouped root pages with domain summaries +- **Icon set replaced** wholesale +- **react-hook-form** for every form with >1 field (28 files currently import it — confirm coverage + and note any state-based forms left behind; that gap belongs in Phase 4's backlog) +- **Theme/language switches** moved into settings only, out of every top bar +- **Paper border-radius** reduced globally + +Any rule in either document that describes the *old* behaviour is obsolete. Rewrite it against the +code, and log the correction in `docs/_plan/open-contradictions.md` as resolved. + +Do the same, more briefly, for the server: `server/CLAUDE.md`'s "Project map" (514 lines) must match +the 14 `.csproj` projects and 56 controllers actually present. + +### 3. Write the reference layer + +One file per row of the Outputs tree. Each opens with a two-line purpose and a +`> Last verified: against ` line. Keep them under ~400 lines; if `client/structure.md` +wants to be longer, it is listing files it should be describing patterns for. + +### 4. Rewrite the three CLAUDE.md files + +Each becomes, in order: + +1. One paragraph: what this project is. +2. **Stack** and **Commands** (keep — they are consulted constantly). +3. **Quality gates** — the exact commands that must pass. +4. **Hard rules** — a numbered list, imperative, no prose. Target 15–25 items. +5. **Where to read more** — a table mapping "working on X" → `docs/rules/…/X.md`. + +Root `CLAUDE.md` keeps its "What Balinyaar is", "Repository layout" (updated for `docs/` and +`archive/`), and the working agreements — but agreement 7 ("keep the architecture map current") now +points at `docs/rules/` as well. + +Rules that must survive into the hard-rule lists verbatim (do not soften): + +- `Seams:FieldEncryption:Key` / `:HashKey` are load-bearing — changing them makes every PII read throw + and every phone lookup miss. +- Config lives in files, not a secret store — **`dotnet user-secrets` is not used and is not read**. + (This is the single most-repeated stale instruction in the repo; state it loudly.) +- Stay within one project per change. +- No dead code; the client fails the build on unused vars. +- Don't reintroduce starter scaffolding or `_TITLE_`/`_DESCRIPTION_` placeholders. +- Read `product/` before changing behaviour. + +### 5. Rewrite the three `AGENTS.md` + +They stay thin pointers. Update the paths they point at. + +### 6. Write `docs/rules/documentation.md` + +The anti-drift convention, as agreed: + +- What to update when X changes (endpoint → `docs/integration/`; flow ships → `docs/flows/.md`; + backlog item closed → tick it in `docs/status/backlog.md`, never delete it; structure changes → + the matching architecture section). +- The `> Last verified: against ` header convention, and which docs must carry it. +- The one-home rule: `product/` = business, `docs/` = engineering + status, `archive/` = history. +- Length budgets, so this doesn't regrow. + +Phase 7 adds the pre-commit warning that enforces the first bullet. + +--- + +## Verification + +- [ ] `client/CLAUDE.md` under 250 lines; `server/CLAUDE.md` under 250 lines. +- [ ] Every rule in the Step-1 ledger appears in exactly one output file — spot-check 20 at random. +- [ ] No rule describes pre-iteration-1/2 client behaviour. +- [ ] `grep -rn "user-secrets" client/ server/ CLAUDE.md docs/` returns only statements that it is + **not** used. +- [ ] `cd client && npm run check` still passes (in case `lint:copy` referenced `STYLE.md` by path). +- [ ] Both `AGENTS.md` pointer files resolve. +- [ ] Every contradiction Phase 0 logged in the rules domain is marked resolved with its resolution. + +## Definition of done + +An agent opening `client/CLAUDE.md` learns what it may not do in under 250 lines, and knows exactly +which one file to open next for the area it is touching. + +## Handoff + +_(filled in by the agent that runs this phase)_ diff --git a/docs/_plan/phase-2-integration.md b/docs/_plan/phase-2-integration.md new file mode 100644 index 0000000..021f659 --- /dev/null +++ b/docs/_plan/phase-2-integration.md @@ -0,0 +1,149 @@ +# Phase 2 — Integration & dependency + +**Depends on:** Phase 0 · **Can run in parallel with:** Phase 1 · **Blocks:** Phase 3 · **Size:** one session + +## Goal + +Make the client↔server dependency a **thing you can read in one place**, and re-sync the contract +layer with the code it stopped tracking on 2026-07-13. + +Right now the seam is real but scattered: envelope shape and casing in one contract doc, cookies and +refresh in `client/CLAUDE.md`, CORS in a refinement report, `NEXT_PUBLIC_API_URL` in `.env` files, +the container topology in `DEPLOY.md` and `docker-compose.yml`, and the OTP relay in its own README. +Nobody can answer "what does the client actually need from the server?" without reading six files. + +--- + +## Inputs + +- `docs/integration/openapi/swagger.v1.json` — the **fresh** snapshot from Phase 0, plus the + added/removed endpoint diff Phase 0 wrote into `docs/_plan/open-contradictions.md`. +- [dev/contracts/](../../dev/contracts/) — 18 domain files + 2 convention files + the stale snapshot. +- [dev/shared-working-context/frontend/requests/for-backend.md](../../dev/shared-working-context/frontend/requests/for-backend.md) — + 67 REQs; many *are* contract amendments that were delivered but never folded back into the domain docs. +- [dev/shared-working-context/reports/mocks-registry.md](../../dev/shared-working-context/reports/mocks-registry.md) — which seams are mocked. +- [DEPLOY.md](../../DEPLOY.md) · [docker-compose.yml](../../docker-compose.yml) · [deploy/Caddyfile](../../deploy/Caddyfile) +- [telegram-otp-bot/README.md](../../telegram-otp-bot/README.md) + [INTEGRATION-PROMPT.md](../../telegram-otp-bot/INTEGRATION-PROMPT.md) +- `client/.env.development`, `client/.env.production`, `server/src/API/Baya.Web.Api/appsettings*.json` +- Code, for the seam itself: `client/src/lib/api/`, `client/src/services/*/`, the server's + `ApiResult` envelope, CORS setup, and auth middleware. + +## Outputs + +``` +docs/integration/ + index.md THE seam, one page: what crosses the wire and what each side owes the other + api-contract.md envelope, casing, pagination, errors, idempotency, auth headers/cookies + domains/ 22 files, one per service domain — refreshed against the live swagger + openapi/ + swagger.v1.json (from Phase 0) + README.md how to regenerate, when it was last taken, endpoint count + config-matrix.md every env var / appsettings key, both projects + docker + the bot + topology.md the runtime dependency graph +``` + +Also updated: [DEPLOY.md](../../DEPLOY.md) — fix the stale `user-secrets` reference and link to +`docs/integration/topology.md`. It stays at root and stays the deploy *procedure*. + +--- + +## Steps + +### 1. Write `index.md` first — the seam on one page + +Before touching the per-domain detail, answer these in one page: + +- **Transport**: HTTP/JSON over `NEXT_PUBLIC_API_URL`; where gRPC exists and whether it is used. +- **The envelope**: `ApiResult` — `{ isSuccess, statusCode, message, requestId, data }`, payload + always under `data`, `requestId` is a W3C trace id (refinement-phase-9). Client unwraps in + `clientFetch`/`unwrap()`. +- **Casing**: JSON bodies camelCase; URL segments snake_case. (REQ-001 settled this — confirm against + the live swagger, don't trust the doc.) +- **Pagination**: `{ items, total, page, pageSize }`; the server binds `pageSize` case-insensitively + (REQ-010). +- **Errors**: status codes, machine-readable error codes (REQ-003), what the client does with 401 / + 403 / 5xx / network. +- **Auth**: the cookie set, JWE opacity to the client, silent refresh, session rotation and + reuse-detection, `/me` and `me/select_role`, role hydration. +- **Idempotency**: which endpoints require `Idempotency-Key` and what the client generates. +- **Money**: IRR on the wire, Toman at the UI boundary — link to `docs/rules/shared/`. +- **What the server owes the client** and **what the client owes the server**, as two short lists. + +### 2. Refresh the 22 domain contracts against the live swagger + +For each domain, compare the contract doc against `swagger.v1.json` and the handler code. Mark each +endpoint: `matches` · `drifted (describe)` · `undocumented (in code, not in contract)` · +`phantom (in contract, not in code)`. + +Fold in the delivered REQs — 17+ were delivered in refinement-phase-3 and amended shapes that the +domain docs still describe the old way. **The domain doc is the thing that should be true; the REQ +ledger is a change log.** After this phase, a reader should never need to read the REQ file to know +the current shape. + +Note the domain-file cleanup: there is both a `messaging.md` (851 B stub) and a +`messaging-notifications-admin.md` (10.6 KB) — merge. Align the file set with the client's 22 +`services/` domains so the mapping is one-to-one where it can be. + +Anything you cannot verify from swagger or code: mark `UNVERIFIED:` and add a row to Phase 4's input +list. Do not guess a shape. + +### 3. Write `config-matrix.md` + +One table: **key · where it's set (appsettings / .env / docker-compose / Caddyfile) · consumed by · +required? · default · notes**. Cover at minimum: + +- `NEXT_PUBLIC_API_URL`, `NEXT_PUBLIC_NESHAN_KEY`, and the rest of the client's `NEXT_PUBLIC_*` +- `IdentitySettings:SecretKey` / `:Encryptkey` +- `Seams:FieldEncryption:Key` / `:HashKey` — **flag as load-bearing and immutable** +- the connection strings (app DB + log DB), and that the DB is remote and **not** containerised +- `OpenTelemetry:Otlp:Endpoint`, the health endpoints (`/healthz/live`, `/healthz/ready`) +- the seam selectors that choose real vendor adapters vs mocks (refinement-phase-8) +- the Telegram OTP bot's token/chat config +- CORS origins, and the Caddy hostnames `balinyaar.ir` / `api.balinyaar.ir` + +State plainly, once, that config lives in files and `dotnet user-secrets` is not used — and that this +is a deliberate pre-launch trade with live credentials in git (link to `DEPLOY.md` "Going to +Production" and to Phase 5's `pre-launch.md`). + +### 4. Write `topology.md` + +The runtime dependency graph — a mermaid diagram plus a short table: + +``` +browser -> Caddy (caddy_net) -> client container (Next.js) -> server container (ASP.NET) + -> server container -> remote SQL Server (not containerised) + -> telegram-otp-bot (OTP relay) + -> object storage / external rails (per seam config) +``` + +For each edge: what flows over it, what breaks if it is down, and where it is configured. This is the +"dependency between projects, documented in a proper place" deliverable. + +### 5. Point the old locations at the new one + +`dev/contracts/README.md` gets a one-line "moved to `docs/integration/`" banner (Phase 6 archives the +folder; until then, don't leave two live copies competing). + +--- + +## Verification + +- [ ] Every endpoint in `swagger.v1.json` appears in exactly one `docs/integration/domains/*.md`, or + is listed in that file's "undocumented, intentionally" section with a reason. +- [ ] No `phantom` endpoints remain undeclared — each is either removed from the doc or listed as + "planned, not built" with a backlog reference for Phase 4. +- [ ] `config-matrix.md` accounts for every key in `appsettings.Production.json`, + `docker-compose.yml`, and both `.env` files — diff mechanically, don't eyeball. +- [ ] `DEPLOY.md` no longer instructs anyone to use `user-secrets`. +- [ ] `index.md` fits on one screen-and-a-half and answers the seam question without a single click. + +## Definition of done + +A frontend agent can build against the API by reading `docs/integration/index.md` plus one domain +file, and a deploy question is answered by `topology.md` + `config-matrix.md` without opening +`docker-compose.yml`. + +## Handoff + +_(filled in by the agent that runs this phase — especially: the drift list, since Phase 4 turns the +`phantom` and `drifted` rows into backlog items)_ diff --git a/docs/_plan/phase-3-flow-atlas.md b/docs/_plan/phase-3-flow-atlas.md new file mode 100644 index 0000000..45a719f --- /dev/null +++ b/docs/_plan/phase-3-flow-atlas.md @@ -0,0 +1,203 @@ +# Phase 3 — The flow atlas (verified) + +**Depends on:** Phase 0, Phase 2 · **Blocks:** Phase 4 · **Size:** 2–4 sessions — the biggest phase + +## Goal + +Build **the one go-to place** that answers, for every flow in the product: + +1. What is it, and who does it? +2. **Is it actually implemented — really, or only mocked?** +3. What screens and endpoints does it use? +4. **How do I test it, step by step, with which account?** +5. What's known to be broken or missing? + +This is the phase where "verify the load-bearing claims" earns its keep. The existing +[manual-testing-plan.md](../../dev/post-phase/manual-testing-plan.md) is the closest predecessor and +it is already wrong about bring-up (it tells you to set `user-secrets`, which the code no longer +reads). Copying it forward would reproduce the problem this chain exists to fix. + +**Run this phase in slices.** One session does `testing-setup.md` + 4–6 flows. Later sessions pick up +the next slice. The index table tracks which flows are done. + +--- + +## Inputs + +- [dev/post-phase/manual-testing-plan.md](../../dev/post-phase/manual-testing-plan.md) — flow + walkthroughs, test accounts, the seeded world, the mock-vs-real map, the numbers the UI must respect +- [dev/post-phase/refinement/RUNBOOK.md](../../dev/post-phase/refinement/RUNBOOK.md) — bring-up, demo + accounts, login round-trip, reset, troubleshooting +- [dev/shared-working-context/reports/mocks-registry.md](../../dev/shared-working-context/reports/mocks-registry.md) +- `docs/integration/` — from Phase 2, the endpoint truth +- `product/business/*` — the 14 requirement areas; what "correct" means +- The seeder code (`DemoWorldSeeder`, `DemoLifecycleSeeder`) — **the authority on test accounts and + seeded state**, over any doc +- `client/src/app/[locale]/**` — 83 routes across `(customer)`, `(customer-focused)`, `nurse`, + `admin`, `partner`, `(public-routes)` +- `client/src/services/*/` — 22 domains, each with a mock/real flag + +## Outputs + +``` +docs/flows/ + index.md the status table — every flow, one row + testing-setup.md bring-up, accounts, seeded world, OTP, reset, troubleshooting + .md one per flow (see the candidate list) +``` + +--- + +## Candidate flow list + +Derived from the route groups, the 22 service domains, and the 14 business areas. Confirm and adjust +in the first session; the point is one file per *user-meaningful journey*, not per screen. + +| # | Flow | Actor | Primary routes | +| --- | --- | --- | --- | +| 1 | `auth-login-otp` | all | `(public-routes)/login`, `select-role` | +| 2 | `public-front-door` | guest | `/`, `welcome`, `terms`, `privacy` | +| 3 | `onboarding-customer` | customer | onboarding, account | +| 4 | `care-circle-patients` | customer | patients / care-circle | +| 5 | `addresses-and-map` | customer | addresses, Neshan pin | +| 6 | `onboarding-nurse` | nurse | profile, bank account | +| 7 | `nurse-service-areas` | nurse | coverage, whole-city (`districtId = null`) | +| 8 | `nurse-verification` | nurse + admin | verification journey, document upload, review queue | +| 9 | `nurse-catalog-and-pricing` | nurse | services, variant builder | +| 10 | `search-and-discovery` | customer | C1–C3, filters, nurse profile | +| 11 | `booking-request` | customer + nurse | C4/C5, nurse inbox, countdown, accept/reject | +| 12 | `checkout-and-payment` | customer | C6, gateway return, confirmation, escrow | +| 13 | `bnpl-installments` | customer | D1–D5 | +| 14 | `booking-lifecycle-evv` | nurse + customer | check-in/out, two-stage clinical gate | +| 15 | `cancellation-and-refunds` | customer + admin | cancel, policy, refund settlement | +| 16 | `reviews` | customer | post-visit review, moderation | +| 17 | `patient-care-records` | nurse + customer | append-only records | +| 18 | `nurse-earnings-and-payouts` | nurse | earnings, weekly payout run | +| 19 | `messaging-tickets` | all | threads, `is_internal` boundary | +| 20 | `notifications` | all | bell, day-grouped list | +| 21 | `admin-backoffice` | admin | config, holidays, audit, RBAC, queues | +| 22 | `partner-center` | partner | the separately-scoped portal | +| 23 | `account-and-settings` | all | profile, theme/language (settings-only since iteration 1) | + +--- + +## Steps + +### 1. Write `testing-setup.md` — and **actually boot it** + +Do not transcribe RUNBOOK.md. Follow it, note where it is wrong, and write what really happens. + +Must cover: + +- Prerequisites and the two-terminal run (`dotnet run` + `npm run dev`). +- **Configuration** — the current, correct story: config in `appsettings.*.json` and `.env.*`; + `user-secrets` **is not used and is not read** (`` was removed). The four crypto + values still matter and must match whatever the target DB was encrypted under — booting with + different `Seams:FieldEncryption` keys makes every phone lookup miss and every PII read throw + `Padding is invalid`. Say where they live now. +- **Which database.** The dev config has pointed at a *remote* SQL Server. Confirm the current + target, and give the local-DB alternative. +- **Test accounts** — read them out of the seeder, not the old doc. Note the phone-OTP admins + (`09120000020` super_admin, `09120000021` finance) and what each demo account is set up to + demonstrate. +- **Getting the OTP** — server console (`MOCK SMS — OTP code …`), `GET /api/v1/dev/last_otp/{phone}`, + or the Telegram relay. Note the limits: 120 s resend window, 5 wrong attempts, 60 s validity, and + that the OTP endpoints are IP rate-limited (scripted logins will 429). +- **The seeded world** — what `DemoLifecycleSeeder` builds (the 8-booking world), and the fact that + **time-relative scenarios age out** and need a reseed. +- **Reset** — the drop-and-reseed procedure, verified. +- **Troubleshooting** — the failures you actually hit while doing the above. + +### 2. Build the mock-vs-real map — from code + +The single most important input to every flow file, and the thing most likely to be stale in the +docs. For each of the 22 client `services/` domains, read the code: + +- Is the mock flag on or off? +- If real, does the whole domain hit the API, or only part of it? +- Server-side: which seams are mocked (SMS, payment gateway, BNPL provider, object storage, + geocoder, search) and which have a real adapter available behind config (refinement-phase-8)? + +Cross-check `mocks-registry.md` and **correct it** — Phase 0 already flagged that the registry has +had stale rows before. Put the result in `docs/flows/index.md` as a column, and in each flow file as +a header block. + +Known suspects from the hardening audit (2026-07-16, never ticked off — verify each against current +code, do not assume): verification fully mocked while catalog/search are real; the refunds mock +reading a retired store; the BNPL wizard on a disconnected store; nurse earnings fabricated despite +live endpoints; `patientRecords` id-type mismatch. + +### 3. Write one file per flow + +Template — keep each under ~200 lines: + +```markdown +# Flow — + +> Last verified: against + +**Actor(s):** · **Status:** built | partial | mocked | not started +**Business source:** product/business/NN-….md + +## What it does +Two or three sentences. The user's intent, not the implementation. + +## Screens +| Step | Route | Component/notes | + +## API +| Call | Endpoint | Notes | +Link to docs/integration/domains/.md — don't restate shapes here. + +## Rules that must hold +The load-bearing numbers and invariants, with their product/ source. +(e.g. commission 0.15, VAT 0.10 on commission only; forward-only status; + escrow released after confirmed check-out; whole-city = districtId NULL) + +## How to test +1. Log in as (see testing-setup.md) +2. … +**Expect:** … + +## Known gaps +- [BL-xxx] … (filled by Phase 4; leave a plain list here for now) +``` + +**Verification standard per flow.** For each, do at least the cheap check — trace the route → service +→ endpoint → handler and confirm the chain is real. For the money flows (11–15, 18) and auth (1), do +the expensive check too: run the walkthrough against a booted app. If you cannot run it, mark the +flow's status `UNVERIFIED` in the index and say why — an honest gap beats a confident guess. + +### 4. Write `index.md` + +The status table, and nothing else of substance: + +| Flow | Actor | Status | Client | Server | Verified | File | +| --- | --- | --- | --- | --- | --- | --- | +| booking-request | customer + nurse | built | real | real | 2026-…-… | [link] | + +Statuses: `built` (end-to-end real) · `partial` (real but with gaps) · `mocked` (UI real, data fake) · +`not started`. `Client`/`Server` columns say `real`/`mock` independently — a flow can have a real UI +on a mocked service, which is exactly the trap the hardening audit found. + +--- + +## Verification + +- [ ] `testing-setup.md` was executed, not transcribed — the agent booted the API and the client. +- [ ] Every flow file has a status backed by a code trace, or an explicit `UNVERIFIED` mark. +- [ ] The mock-vs-real map was derived from code and disagreements with `mocks-registry.md` are logged. +- [ ] No flow file restates an API shape that `docs/integration/` already owns. +- [ ] The index accounts for all 22 client service domains and all 14 business areas — anything with + no flow is either intentional or a Phase 4 backlog item. +- [ ] Every flow file carries a `Last verified:` line. + +## Definition of done + +You can hand someone `docs/flows/testing-setup.md` and `docs/flows/index.md` and they can test the +product without asking you a single question — and without hitting an instruction that no longer works. + +## Handoff + +_(filled in per slice — which flows are done, which are `UNVERIFIED` and why, and the running list of +gaps found, which is Phase 4's primary input)_ diff --git a/docs/_plan/phase-4-backlog.md b/docs/_plan/phase-4-backlog.md new file mode 100644 index 0000000..1d642d4 --- /dev/null +++ b/docs/_plan/phase-4-backlog.md @@ -0,0 +1,158 @@ +# Phase 4 — Backlog reconciliation + +**Depends on:** Phase 0, Phase 3 (and consumes Phase 2's drift list) · **Blocks:** Phase 5 · **Size:** 1–2 sessions + +## Goal + +Turn **five unreconciled ledgers plus 50+ scattered "follow-ups" sections** into one triaged backlog +where every open item is real, deduplicated, and carries its origin. + +This is the "remaining works from plans, dev, refine and ui phases should be well documented" +deliverable. Today the honest answer to "what's left?" is *nobody knows* — the hardening ledger has +18 items with **zero ticked**, written before three more chains ran on top of it. + +--- + +## Inputs + +| Source | Volume | Note | +| --- | --- | --- | +| [dev/post-phase/hardening/issues.md](../../dev/post-phase/hardening/issues.md) | 18 items, **all unticked** | Written 2026-07-16. UI phases 0–13 and the deploy commits ran after. **Every item must be re-verified against current code.** | +| [dev/shared-working-context/frontend/requests/for-backend.md](../../dev/shared-working-context/frontend/requests/for-backend.md) | 67 REQs, 1,115 lines | Most delivered in refinement-phase-3; some `partially delivered`; REQ-066/067 blocked on a privacy sign-off | +| `dev/shared-working-context/reports/*.md` | 50 files | Each has a "Follow-ups for later phases" / "Deferred" section | +| `dev/shared-working-context/backend/STATUS.md` + `frontend/STATUS.md` | 86 KB | Deferrals recorded with explicit **pull-triggers** (e.g. Elasticsearch `INurseSearch`, SMS/push dispatcher, analytics, holiday feed, 8 unbuilt product tables) | +| [dev/manual-testing/iteration-1/](../../dev/manual-testing/iteration-1/) + [iteration-2/](../../dev/manual-testing/iteration-2/) | 2 raw notes + screenshots | Your own most recent feedback. Some applied in `baa3cc6` / `e6a8f93`; **which parts landed is unknown** | +| [product/notes/open-questions.md](../../product/notes/open-questions.md) | build backlog + research questions | | +| Phase 2's output | drift list | `phantom` and `drifted` endpoints | +| Phase 3's output | gap list | everything found while verifying flows | +| Root [CLAUDE.md](../../CLAUDE.md) §6 | | credential rotation before real users — a real pre-launch item | + +## Outputs + +``` +docs/status/ + index.md where the project is, in one page + implemented.md the product/business overlay: 14 areas -> build state + backlog.md BL-### — every open item, triaged + backlog-closed.md items confirmed done, with what closed them + decisions.md the distilled decision log +``` + +--- + +## Steps + +### 1. Harvest everything into one raw list + +One row per candidate item, with its **origin id** (`H-01`, `REQ-042`, `ui-phase-9 follow-up`, +`iteration-2`, `deferral: elasticsearch`, `phase-3 finding`, `phase-2 drift`). Expect 150–250 raw +rows before dedup. Do not filter while harvesting. + +### 2. Verify each item's current state + +This is the phase's real work, and the reason it comes after Phase 3. + +- **The 18 hardening items**: re-locate each in the code. The file itself warns that line numbers + drifted. Several are likely fixed by the UI chain — e.g. **H-01** (the auth gate never running, + traced to a stray `pnpm-lock.yaml` and the `middleware.ts` → `proxy.ts` question) overlaps directly + with what ui-phase-13 did to the root route and matcher. Verify; don't assume either way. +- **The 67 REQs**: classify `delivered` / `partially delivered — what's left` / `open` / `obsolete`. + The ones marked `partially delivered in refinement-phase-3` need the residue spelled out. Once + Phase 2 folded delivered REQs into the domain docs, a delivered REQ is *closed*, not an item. +- **Iterations 1 & 2**: walk each bullet against the code. The clearest testable one: + *"replace all forms with more than 1 field with react-hook-form"* — 28 files import it today; + find the forms that still use raw state and file the residue. +- **Deferrals**: these are not bugs; they are *decisions with pull-triggers*. Keep them as + `deferred`, carry the trigger, and hand them to Phase 5's `roadmap/deferred.md`. + +### 3. Dedup and assign `BL-###` + +Many items appear in three ledgers. Merge them into one `BL-###` carrying **all** origin ids. +Old ids stay greppable — never rewrite the archived sources. + +### 4. Write `backlog.md` + +```markdown +> Last verified: against + +| ID | Area | Sev | Item | Origin | Status | Blocks | +|----|------|-----|------|--------|--------|--------| +| BL-001 | client | blocker | … | H-01 | open | flow: auth-login-otp | +``` + +- **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 flow(s) from `docs/flows/` it degrades — this is what connects the backlog to + something a user can feel + +Sort by severity, then area. Anything closed goes to `backlog-closed.md` with *what* closed it +(commit or phase), so the count of open items is honest at a glance. + +### 5. Write `implemented.md` — the product overlay + +The agreed alternative to touching `product/`. One row per business area: + +| Business area | Doc | State | Flows | Gaps | +| --- | --- | --- | --- | --- | +| 08 Payments & escrow | [product/business/08-…](../../product/business/08-payments-and-escrow.md) | built | checkout-and-payment, cancellation-and-refunds | BL-023 | + +States: `built` · `partial` · `mocked` · `not started` · `deferred`. Add the reverse link from each +`docs/flows/*.md` back to its business area. This gives the two-way mapping without editing a single +`product/` file. + +Do the same, briefly, for the data model: the STATUS logs mention **8 product tables that were never +built** — name them here rather than leaving them in a status log. + +### 6. Write `decisions.md` + +The distilled decision log — the highest-value thing buried in 3 MB of reports. Extract every +**non-obvious decision with a reason** and write it as a short ADR-style entry: *what was decided, +when, why, and where it binds*. Candidates already visible in the STATUS logs and memory: + +- Commission 0.15 / VAT 0.10 **on commission only** (the canonical fee model, refinement-phase-3) +- `district_id = NULL` means whole-city — in both directions +- Verification `status` is the source of truth; `is_verified` is a guarded flip +- Booking status is forward-only; the three-amount split has a CHECK constraint +- The two-stage clinical-disclosure gate; EVV is **advisory**, never a block +- Webhook idempotency is upsert-first; ledger postings must balance +- Reviews recompute from source; nurse care records are append-only +- `is_internal` ticket messages never appear in user-facing types +- One payout per booking (UNIQUE); whole-clawback greedy netting +- Escrow released after a confirmed check-out; weekly payout generation automatic, processing manual +- Config in files, not a secret store — deliberate pre-launch trade +- Error state is never an empty state (the client convention) +- Root `/` forks by auth via middleware **rewrite**, never redirect + +Each entry: 3–6 lines. Where a decision is already stated in `product/`, link rather than restate — +`product/` wins for business rules; `decisions.md` is for *engineering* decisions and for business +decisions that were made **during** the build and never made it back into `product/`. Anything in the +second category should also get a note in `product/notes/` so the business truth stays complete. + +### 7. Write `index.md` + +One page: how many flows are built/partial/mocked, how many backlog items are open by severity, the +top five things standing between here and a usable product, and links to everything. This is the page +you open when you come back after two weeks away. + +--- + +## Verification + +- [ ] Every one of the 18 hardening items has a verdict backed by a code check — none carried over + unexamined. +- [ ] Every REQ-001…067 is classified; the count of `open` is explicit. +- [ ] Every "Follow-ups for later phases" section across the 50 reports was read and harvested. +- [ ] Both iteration notes are fully accounted for, bullet by bullet. +- [ ] No `BL-###` duplicates another; every one names its origin id(s). +- [ ] Every `blocker` names the flow it blocks. +- [ ] `implemented.md` covers all 14 business areas and all 23 flows. + +## Definition of done + +"What's left?" is answered by one file, and every number in it was checked rather than inherited. + +## Handoff + +_(filled in by the agent that runs this phase — item counts by severity, and anything that turned out +to be worse than the old ledgers claimed)_ diff --git a/docs/_plan/phase-5-roadmap.md b/docs/_plan/phase-5-roadmap.md new file mode 100644 index 0000000..44647bd --- /dev/null +++ b/docs/_plan/phase-5-roadmap.md @@ -0,0 +1,121 @@ +# Phase 5 — Roadmap & technical requirements + +**Depends on:** Phase 4 · **Size:** one session + +## Goal + +Answer "what next?" — recording every already-decided future item **and** proposing a sequenced +order, with the technical prerequisites each step needs. The ordering is a proposal you can overrule; +the recording is not negotiable. + +--- + +## Inputs + +- `docs/status/backlog.md` and `implemented.md` — Phase 4's output, the ground truth +- `docs/flows/index.md` — what's mocked vs built +- The **deferrals with pull-triggers** from the STATUS logs: Elasticsearch `INurseSearch`, real + SMS/push `INotificationDispatcher`, the analytics pipeline, the holiday feed, **8 unbuilt product + tables**, and the refinement-phase-9 items 9.7–9.11 +- [product/notes/future-ideas.md](../../product/notes/future-ideas.md) and + [open-questions.md](../../product/notes/open-questions.md) — including PWA/Workbox caching +- ui-phase-13's follow-ups: **tier (c)** — guest search + public nurse profiles (REQ-066/067), blocked + on a backend phase **and an explicit privacy sign-off on the nurse-profile field list**; the OG + image Persian variant +- Root [CLAUDE.md](../../CLAUDE.md) §6 + [DEPLOY.md](../../DEPLOY.md) "Going to Production" — the + credential-rotation obligation +- `product/business/*` — anything specified but never built +- `product/research/*` — go-to-market, legal landscape (informs sequencing, not scope) + +## Outputs + +``` +docs/roadmap/ + index.md the proposed sequence + the reasoning, in one page + next-up.md the next 3-5 units of work, each spec'd enough to start + deferred.md recorded, with the trigger that pulls each one forward + tech-debt.md what must be paid before scale, and what it costs to defer + pre-launch.md the hard gate before real users touch this +``` + +--- + +## Steps + +### 1. `pre-launch.md` first — it's the one with a deadline + +Everything that must be true before a real user with real money uses the platform. Known already: + +- **Rotate the committed credentials** and move the secret half out of git. The repo currently + contains live credentials by deliberate pre-launch decision. Note the exception: `Seams:FieldEncryption:Key` + / `:HashKey` decrypt existing PII and derive the phone-lookup hash — rotating those requires a data + migration, not a config edit. Spell out that migration as its own item. +- **Real external rails** — which seams are still mocked in production config (payment gateway, SMS, + BNPL provider, object storage). Phase 3's mock-vs-real map is the input; this is the list of seams + that must flip. +- **Running as Development in production** — `DEPLOY.md` documents this as a deliberate trade. + State what it implies (gRPC reflection, dev endpoints such as `/dev/last_otp`, seeding behaviour, + log verbosity) and what must change. +- Anything Phase 4 marked `blocker`. +- Legal/tax items from `product/business/13-tax-invoicing-and-legal.md` that are code-side. + +Each item: what, why it blocks launch, roughly what it takes. + +### 2. `deferred.md` — record faithfully, don't re-decide + +One row per deferral: **item · why deferred · the pull-trigger (the condition that makes it +necessary) · rough size · where it was decided**. The pull-triggers already exist in the STATUS logs +— preserve them verbatim in substance. A deferral with a trigger is a decision; a deferral without +one is just a forgotten task, so any you find without a trigger, give one. + +Include the 8 unbuilt product tables, named individually. + +### 3. `tech-debt.md` + +Debt is different from backlog: it doesn't block a flow, it raises the cost of everything after it. +Candidates to assess: the single-instance in-process scheduler; search without Elasticsearch; the +absence of E2E tests over the money paths; the remaining raw-state forms; the Windows-generated +client lockfile wrinkle in `DEPLOY.md`; test coverage asymmetry between the two projects. + +For each: what it costs now, what it costs at 10× usage, and the trigger to pay it. + +### 4. `next-up.md` — the opinionated part + +Three to five units of work, each with: goal, why now, what it unblocks, technical prerequisites, +affected flows, rough size, and the backlog ids it closes. Enough that a fresh agent session could +start one without re-deriving the context. + +**Sequencing principle to apply, and state explicitly in `index.md`:** the product's own promise is +trust-first and money-holding. So the order is (1) anything that makes a *money or trust* flow lie to +a user, (2) anything that makes a built flow unusable, (3) anything that makes a mocked flow real, +(4) new surface area. Tier (c) guest search is new surface — it ranks below making the authenticated +flows honest, regardless of how visible it is. + +Where a proposed item conflicts with something in `product/`, say so and defer to `product/`. + +### 5. `index.md` + +The one-page sequence: a table of the proposed order with rationale per step, plus the standing +answer to "what are we not doing, and why" (a pointer to `deferred.md`). Mark clearly which parts are +**recorded decisions** and which are **this document's proposal** — the reader must be able to tell +your judgement from the project's. + +--- + +## Verification + +- [ ] Every `deferred` item in `docs/status/backlog.md` appears in `deferred.md` with a trigger. +- [ ] Every recorded deferral from the STATUS logs is present, including the 8 unbuilt tables. +- [ ] `pre-launch.md` covers credential rotation, every still-mocked production seam, and the + Development-in-production trade. +- [ ] Every `next-up.md` item names the backlog ids it closes and the flows it affects. +- [ ] Proposal is visibly distinguished from record. + +## Definition of done + +You can pick the next piece of work in five minutes, and you can explain to someone else why it's +that piece and not another. + +## Handoff + +_(filled in by the agent that runs this phase)_ diff --git a/docs/_plan/phase-6-archive.md b/docs/_plan/phase-6-archive.md new file mode 100644 index 0000000..eba5078 --- /dev/null +++ b/docs/_plan/phase-6-archive.md @@ -0,0 +1,124 @@ +# Phase 6 — Archive & prune + +**Depends on:** Phases 1–5 all complete · **Size:** one session + +## Goal + +Move the 3 MB build-chain history out of the way — **after**, and only after, every live fact in it +has been extracted. Then fix every link that pointed into it. + +This phase is mechanical. Its only real risk is running it early, so it has a hard gate. + +--- + +## Gate — do not start until all of these are true + +- [ ] Phase 0's `docs/_plan/inventory.md` has a disposition for every file, with no blanks. +- [ ] Phases 1, 2, 3, 4, 5 are marked complete in [`README.md`](README.md)'s progress table. +- [ ] `docs/_plan/open-contradictions.md` has no unresolved rows (or each remaining one is explicitly + accepted with a reason). +- [ ] Every inventory row marked `live facts: yes` has been extracted by its owner phase — check them + off one by one, not in bulk. + +If any box is unticked, stop and report which phase is incomplete. + +--- + +## Inputs + +- `docs/_plan/inventory.md` — the authority on what moves where +- The whole `dev/` tree + +## Outputs + +``` +archive/ + README.md "Historical record. Do NOT treat as instructions." + build-chain/ + phases/ was dev/phases (32 executed prompt files + _shared) + working-context/ was dev/shared-working-context (STATUS, handoffs, 50 reports) + contracts/ was dev/contracts (superseded by docs/integration/) + post-phase/ was dev/post-phase (hardening, refinement, server, ui + audits) + manual-testing/ was dev/manual-testing (notes + screenshots) +docs/_plan/ moved to archive/clarify-chain/ at the very end +``` + +--- + +## Steps + +### 1. Write `archive/README.md` before moving anything + +It must say, unambiguously and at the top: + +> **This folder is a historical record of how Balinyaar was built. It is not instruction.** +> Nothing here describes current behaviour, current rules, or current plans. Do not follow a +> procedure from this folder. Current truth lives in [`docs/`](../docs/README.md) and +> [`product/`](../product/README.md). + +Then: what each subfolder was, the date range it covers, and a table mapping each archived area to +the `docs/` file that superseded it. Someone finding `archive/post-phase/hardening/issues.md` must be +able to see in one step that it became `docs/status/backlog.md`. + +### 2. Move, with `git mv` + +Preserve history. Move whole directories rather than file-by-file. Keep the screenshots in +`manual-testing/` — they are the only visual record of the pre-overhaul UI. + +Delete outright (per Phase 0's inventory): `Prompt.md` (0 bytes), `temp/swagger.json` (stale +duplicate), and the `graphify-out/GRAPH_REPORT.md` files if Phase 0 marked them generated-and-unused. + +### 3. Fix inbound links + +Every doc outside `archive/` that links into `dev/` must be repointed at its `docs/` successor — not +at the archived copy. Sweep at minimum: root `CLAUDE.md`, `client/CLAUDE.md`, `server/CLAUDE.md`, +`DEPLOY.md`, all three `AGENTS.md`, `product/README.md`, `product/index.md`, +`telegram-otp-bot/README.md`, `.githooks/README.md`, and everything under `docs/`. + +Mechanical check: + +```bash +grep -rn "](\.\./dev/\|](dev/\|(dev/" --include="*.md" . | grep -v "^./archive/" +``` + +should return nothing. Do the same sweep for `product/*.html` — the generated view has its own +cross-links, and if any point at `dev/`, fix the **`.md` source** and regenerate +(`cd product && node build-docs.mjs`), never the HTML. + +### 4. Update the architecture map + +Root `CLAUDE.md`'s "Repository layout" table is canonical for repo structure (its own working +agreement 7). Update it: `dev/` is gone, `docs/` and `archive/` are in, and the sentence describing +`dev/` as the build plan is replaced. + +### 5. Update the memory index + +`MEMORY.md` has ~50 entries, most of them phase memories whose file paths now point into `archive/`. +Add a single note at its top recording that the build-chain docs moved and where current truth lives, +so a future session doesn't chase dead paths. Don't rewrite 50 memory files. + +### 6. Retire this plan + +Move `docs/_plan/` → `archive/clarify-chain/`, and leave one line in `docs/README.md` noting when the +cleanup ran and where its plan lives. + +--- + +## Verification + +- [ ] `dev/` no longer exists. +- [ ] The link grep above returns nothing outside `archive/`. +- [ ] `cd product && node build-docs.mjs` runs clean and the regenerated HTML has no `dev/` links. +- [ ] `cd client && npm run check` passes; `cd server && dotnet build Baya.sln` passes — confirming + nothing moved was referenced by tooling. +- [ ] `git status` shows moves as renames, not delete+add. +- [ ] `archive/README.md` maps every archived area to its successor. + +## Definition of done + +Nothing in the repo tells you to do something that was true three weeks ago, and nothing that was +learned in those three weeks is gone. + +## Handoff + +_(filled in by the agent that runs this phase)_ diff --git a/docs/_plan/phase-7-skills-and-guardrails.md b/docs/_plan/phase-7-skills-and-guardrails.md new file mode 100644 index 0000000..df356ed --- /dev/null +++ b/docs/_plan/phase-7-skills-and-guardrails.md @@ -0,0 +1,125 @@ +# Phase 7 — Skills & anti-drift guardrails + +**Depends on:** Phase 1 (rules) and Phase 3 (reality) · **Can run before or after Phase 6** · **Size:** one session + +## Goal + +Two things: + +1. **Skills that match reality.** The one existing skill was written before the UI overhaul; parts of + it describe an app that no longer exists. +2. **Guardrails so this doesn't happen again** — the reason the cleanup was needed at all. + +**The division of labour, restated:** a *rule* is a constraint that must never break → `docs/rules/`. +A *skill* is a procedure for a recurring task → `.claude/skills/`. If you're writing "always do X", +it's a rule. If you're writing "to do X: first…, then…", it's a skill. + +--- + +## Inputs + +- [.claude/skills/frontend-designer/SKILL.md](../../.claude/skills/frontend-designer/SKILL.md) — 21 KB, + 10 sections (brand, tokens, typography, component library, layout, icons, hard rules, workflow, + anti-patterns, Figma) +- `docs/rules/` — Phase 1's output, so the skill can stop restating rules and link instead +- `docs/flows/` — Phase 3's output, especially `testing-setup.md` and the mock-vs-real map +- The client code as it is **after** iterations 1–2 +- [.githooks/pre-commit](../../.githooks/pre-commit) (3.4 KB) + [.githooks/README.md](../../.githooks/README.md) +- `client/package.json` scripts (`check`, `lint:copy`, `test:ci`) and the server's build/test commands + +## Outputs + +``` +.claude/skills/ + frontend-designer/SKILL.md rewritten against current reality + backend-feature/SKILL.md NEW — adding a feature to the .NET server + flow-testing/SKILL.md NEW — boot, seed, and walk a flow end-to-end +``` + +Updated: `.githooks/pre-commit`, `docs/rules/documentation.md` (Phase 1 wrote the convention; this +phase adds the enforcement note), and status-doc headers. + +--- + +## Steps + +### 1. Rewrite `frontend-designer` + +Reality-check every section against the code, then rewrite. Specifically at risk (confirm each): + +- **§5 Layout & page shells** — the app is now **mobile-scoped**: a max-width container so the shell + never stretches on desktop, and the nurse side moved from a drawer to a **bottom navigation** with + grouped root pages that summarize their domain. Any desktop-sidebar guidance is obsolete except + where admin still uses one. +- **§6 Icons** — the icon set was replaced wholesale in iteration 1. The old mapping guidance is dead. +- **§2 Design tokens / §3 Typography** — check against the current theme, including the reduced + Paper border-radius. +- **§7 Non-negotiable rules** — most of these are now **rules**, not skill content. Cut them down to + a link into `docs/rules/client/`, keeping only what's design-specific. +- **§1 Brand / §4 Component library** — verify the `App*` inventory against `client/src/components/` + (which currently holds ~40 feature components in addition to the shared kit). +- Add what's missing: **forms are react-hook-form** now, so the "build a form" procedure changes; and + theme/language switches live **only in settings**, not in top bars. + +Target: shorter than the current 21 KB, because the rules half moves out. + +### 2. Write `backend-feature` + +The procedure for adding a feature to the server, derived from how the 199 handlers are actually +shaped: where the command/query goes, the handler and validator, the DTO, the controller action, the +EF configuration and migration, the tests, and the doc updates it must trigger +(`docs/integration/domains/.md` + the OpenAPI snapshot). Link to `docs/rules/server/` for +constraints; keep the skill to the sequence. + +### 3. Write `flow-testing` + +The procedure a session follows to actually exercise a flow: boot both sides per +`docs/flows/testing-setup.md`, get an OTP, log in as the right seeded account, walk the flow, and — +importantly — **check the mock-vs-real map first** so a "working" flow isn't just a mock answering. +Include the reseed step for when the time-relative scenarios age out. + +### 4. Extend the pre-commit hook + +Read the existing hook first and match its style. Add **warnings, not blocks** — a hook that blocks +commits gets bypassed, and then it protects nothing. + +Warn when: + +- files under `server/src/**/Controllers/**` or `**/Handlers/**` changed but nothing under + `docs/integration/` did → *"API surface changed — update `docs/integration/domains/…` and refresh + the OpenAPI snapshot."* +- `client/src/services/**` changed but no `docs/integration/` or `docs/flows/` change → + *"a service domain changed — does a flow doc need updating?"* +- a file under `docs/status/` or `docs/flows/` is committed with a `Last verified:` date more than + ~30 days old → *"this doc claims to be verified as of ."* +- root `CLAUDE.md`, `client/CLAUDE.md`, or `server/CLAUDE.md` exceeds its line budget → + *"the rulebook is regrowing; move reference material to `docs/rules/`."* + +Document each warning in `.githooks/README.md` and in `docs/rules/documentation.md`. + +### 5. Stamp the freshness convention + +Ensure every file under `docs/status/` and `docs/flows/` carries +`> Last verified: against ` as its second line, and that +`docs/rules/documentation.md` names exactly which files must carry it and who updates it. + +--- + +## Verification + +- [ ] No sentence in `frontend-designer` describes pre-iteration-1/2 behaviour — spot-check the + layout, icon, and form sections against real components. +- [ ] No skill restates a rule that `docs/rules/` owns; each links instead. +- [ ] The three skills' trigger descriptions don't overlap (a task should match exactly one). +- [ ] The pre-commit hook runs and its new warnings fire on a deliberate test commit — and **never** + block one. +- [ ] Every `docs/status/` and `docs/flows/` file has a `Last verified:` line. + +## Definition of done + +The skills describe the app that exists, and the next time someone changes an endpoint without +touching a doc, something says so. + +## Handoff + +_(filled in by the agent that runs this phase)_