cleanup phase 7

This commit is contained in:
hamid
2026-08-02 18:58:46 +03:30
parent 51e86a1e5f
commit 72ab290da1
15 changed files with 329 additions and 189 deletions
+7 -5
View File
@@ -2,10 +2,12 @@
The entry point. Start here, follow one link, stop reading.
> **Built by the clarify chain**, phases 06, 2026-07-29 → 2026-08-02. The chain's own plan — inventory,
> **Built by the clarify chain**, phases 07, 2026-07-29 → 2026-08-02. The chain's own plan — inventory,
> contradiction log, phase files, and their progress table — is now history, kept at
> [`archive/clarify-chain/`](../archive/clarify-chain/README.md). Phase 7 (skills & guardrails) is still
> open.
> [`archive/clarify-chain/`](../archive/clarify-chain/README.md). Phase 7 (skills & guardrails) is done:
> three playbooks live in [`.claude/skills/`](../.claude/skills/); the anti-drift convention below is
> enforced by review rather than a git hook (an MVP-stage call — see
> [decisions.md](status/decisions.md)).
---
@@ -55,5 +57,5 @@ Two documents stay outside this tree on purpose:
it would defeat that.
4. **English throughout**, including in files that describe Persian UI copy.
The full convention is in [docs/rules/documentation.md](rules/documentation.md), to be enforced by a
pre-commit warning (phase 7).
The full convention is in [docs/rules/documentation.md](rules/documentation.md) enforced by review,
not tooling (an MVP-stage call; see [git-and-gates.md](rules/shared/git-and-gates.md)).
+9 -11
View File
@@ -3,7 +3,7 @@
Every configuration key on both sides of the seam, plus docker and the OTP relay, with where it is set and
who reads it.
> Last verified: 2026-07-30 against commit `d3ec723`. Built by **mechanically enumerating** every leaf key
> Last verified: 2026-08-02 against commit `51e86a1`. Built by **mechanically enumerating** every leaf key
> in both `appsettings*.json`, every `environment:` entry in `docker-compose.yml`, every assignment in the
> three `client/.env*` files and `telegram-otp-bot/.env.example`, and every `process.env.*` read under
> `client/src/` — then diffing the sets. The gaps that diff found are in
@@ -79,7 +79,7 @@ Every one has a working default, so nothing is broken — but none is discoverab
| --- | --- | --- | --- |
| `OpenTelemetry:Otlp:Endpoint` | `SetupOpenTelemetry` | **OTLP export is not wired at all.** Prometheus `/metrics` still works | Opt-in by design, so no exporter spams an absent collector |
| `Search:Backend` | `AddPersistenceServices` | `SqlNurseSearch` | Any value other than `sql`/empty **throws at startup** — Elasticsearch is deferred and fails loudly |
| `Seed:AdminUsername` / `:AdminPassword` / `:AdminEmail` | `SeedDataBase` | no break-glass admin is seeded | The hardcoded `admin`/`qw123321` was removed in refinement-phase-5 and the pre-commit hook blocks its return |
| `Seed:AdminUsername` / `:AdminPassword` / `:AdminEmail` | `SeedDataBase` | no break-glass admin is seeded | The hardcoded `admin`/`qw123321` was removed in refinement-phase-5 |
| `Seams:<rail>:Provider` (×11) | `AddCrossCuttingSeams` | **`mock`** | The seam selectors, below |
### The seam selectors
@@ -252,13 +252,11 @@ places where the config is not discoverable from the config files.
### The placeholder's name
`SET_VIA_USER_SECRETS_OR_ENV` names a store that no longer exists (contradiction **C-2**). The *behaviour*
is correct — it is a sentinel that `StartupSecretsGuard` and the pre-commit hook both reject — but the name
instructs a reader to use a removed mechanism.
is correct — it is a sentinel that `StartupSecretsGuard` rejects — but the name instructs a reader to use a
removed mechanism.
It was **not renamed in this phase**, because the string is load-bearing in seven live files:
`appsettings.json` (×6), `StartupSecretsGuard.cs`, `.githooks/pre-commit`, `.githooks/README.md`,
`Baya.Test.Api/StartupSecretsGuardTests.cs` (×2), `docs/rules/shared/git-and-gates.md` and
`docs/rules/server/structure.md`. Renaming it is a server-code + git-hook + test change requiring
`dotnet build` and `dotnet test` to prove the gate still fires — out of scope for a documentation phase.
**This section is the authoritative statement of the mechanism**; the rename is filed for Phase 4 with that
exact seven-file worklist.
It was **not renamed in this phase**, because the string is load-bearing in several live files:
`appsettings.json` (×6), `StartupSecretsGuard.cs`, `Baya.Test.Api/StartupSecretsGuardTests.cs` (×2), and
`docs/rules/server/structure.md`. Renaming it is a server-code + test change requiring `dotnet build` and
`dotnet test` to prove the gate still fires — out of scope for a documentation phase. **This section is the
authoritative statement of the mechanism**; the rename is filed for Phase 4 with that worklist.
+2 -2
View File
@@ -1,6 +1,6 @@
# Deferred — recorded, not re-decided
> Last verified: 2026-08-02 against commit `cd8144e`. Populated by phase 5 of the
> Last verified: 2026-08-02 against commit `51e86a1`. Populated by phase 5 of the
> [documentation clean-up chain](../../archive/clarify-chain/README.md).
**51 items** carry deferred status in [backlog.md](../status/backlog.md): the 43 in its dedicated
@@ -96,7 +96,7 @@ Correct for a single instance / MVP load; each has a concrete, measurable trigge
| 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-219](../status/backlog.md#minor-115) — rename the `SET_VIA_USER_SECRETS_OR_ENV` placeholder sentinel | The name is a load-bearing sentinel `StartupSecretsGuard` checks for; renaming touches several 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 |
+3 -3
View File
@@ -2,7 +2,7 @@
How this repository keeps its own docs from lying. Read before writing or editing any `.md`.
> Last verified: 2026-07-30 against commit `d3ec723`.
> Last verified: 2026-08-02 against commit `51e86a1`.
---
@@ -43,8 +43,8 @@ regenerate — never hand-edit the HTML. If you add or rename a `.md`, update th
## 2. What to update when X changes
This is the anti-drift contract. Each row is enforced by review, and (from phase 7) warned about by the
pre-commit hook.
This is the anti-drift contract. Each row is enforced by review — there is no pre-commit tooling behind
it (a deliberate MVP-stage call; see [git-and-gates.md](shared/git-and-gates.md)).
| When you change… | Update, in the same change |
| --- | --- |
+3 -3
View File
@@ -2,7 +2,7 @@
What must never be broken, and nothing else.
> Last verified: 2026-07-30 against commit `d3ec723`.
> Last verified: 2026-08-02 against commit `51e86a1`.
---
@@ -14,7 +14,7 @@ Three tiers, and a rule lives in exactly one of them.
| --- | --- | --- | --- |
| **Hard rules** | [root CLAUDE.md](../../CLAUDE.md) · [client/CLAUDE.md](../../client/CLAUDE.md) · [server/CLAUDE.md](../../server/CLAUDE.md) | Constraints whose violation breaks the build, the gate, or a business invariant. Imperative, no explanation. | ≤250 lines each |
| **Reference** | `docs/rules/{shared,client,server}/*.md` — here | The *how* and the *why*. Read on demand when you are working in that area. | ≤400 lines per file |
| **Procedure** | `.claude/skills/` | Step-by-step playbooks for recurring tasks. The [frontend-designer](../../.claude/skills/frontend-designer/SKILL.md) skill is the design playbook. | — |
| **Procedure** | `.claude/skills/` | Step-by-step playbooks for recurring tasks: [frontend-designer](../../.claude/skills/frontend-designer/SKILL.md) (design), [backend-feature](../../.claude/skills/backend-feature/SKILL.md) (adding a server feature), [flow-testing](../../.claude/skills/flow-testing/SKILL.md) (walking a flow end to end). | — |
The test: **a rule that only matters once you are already editing theme code is reference.** A rule like
"never change `Seams:FieldEncryption:Key`" is hard — it belongs inline where nobody can miss it.
@@ -31,7 +31,7 @@ touching. Not both trees, not every file.
| File | Covers |
| --- | --- |
| [shared/naming.md](shared/naming.md) | `Baya*` vs `balinyaar-client`, the `@/*` alias, file and directory conventions |
| [shared/git-and-gates.md](shared/git-and-gates.md) | Branches, commits, the pre-commit secret scan, what "done" means per project |
| [shared/git-and-gates.md](shared/git-and-gates.md) | Branches, commits, what "done" means per project |
| [shared/code-quality.md](shared/code-quality.md) | No dead code, comment the *why*, no starter scaffolding, the seam rule for mocks |
### Client — `client/`
+3 -3
View File
@@ -2,7 +2,7 @@
Auth, JWE, sessions, field encryption, tenancy, and the two-stage clinical disclosure rule.
> Last verified: 2026-07-30 against commit `d3ec723`.
> Last verified: 2026-08-02 against commit `51e86a1`.
---
@@ -101,8 +101,8 @@ The full vocabulary is in `Domain/Entities/User/RoleNames`.
- **`SeedDataBase` always seeds the roles**, and seeds a **bootstrap admin only when
`Seed:AdminUsername`/`Seed:AdminPassword` are configured** — break-glass only. There is no committed
`admin`/`qw123321` any more (the pre-commit hook rejects that string outright). Day-to-day admins come from
the phone-OTP demo seeds or are provisioned out-of-band.
`admin`/`qw123321` any more. Day-to-day admins come from the phone-OTP demo seeds or are provisioned
out-of-band.
- **`customer` and `nurse` are self-selectable** via `POST me/select_role` — audited (`granted_by`,
`granted_at`), idempotent, and **both can be held** by one user (a dual session moves freely between the
family and nurse apps).
+9 -34
View File
@@ -2,7 +2,7 @@
What must pass before work is done, and what the repo refuses to let you commit.
> Last verified: 2026-07-30 against commit `d3ec723`.
> Last verified: 2026-08-02 against commit `51e86a1`.
---
@@ -63,40 +63,15 @@ A change that doesn't pass its own gate is **not done**, regardless of how compl
---
## 3. The pre-commit secret scan
## 3. No pre-commit secret scan (for now)
Repo-managed hooks live in `.githooks/` (in version control, unlike `.git/hooks`). **Enable them once per
clone:**
```bash
git config core.hooksPath .githooks
```
`pre-commit` is a fast, dependency-free backstop against a credential leaking into a file that shouldn't
hold one. It scans **only staged additions**, so it is quick. It rejects a commit that stages:
- the retired hardcoded admin password `qw123321`, anywhere;
- private-key material or an AWS access-key id, anywhere;
- the deployment's SQL Server host `87.107.152.16` **outside the declared config files**;
- a **real** connection-string password in any `appsettings*.json` **outside the declared config files**
(elsewhere only the `SET_VIA_USER_SECRETS_OR_ENV` placeholder is allowed).
### The declared-config allow-list
The pre-launch demo deployment configures itself from committed files rather than a secret store (see
[`DEPLOY.md`](../../../DEPLOY.md)), so a short allow-list is exempt from the last two checks:
`appsettings.Development.json` · `docker-compose.yml` · `telegram-otp-bot/.env.example` · `DEPLOY.md`
It is maintained in the `declared_config` function in the hook, and it is **the honest record of where
this repo's secrets are**. **Shrink it, never grow it.** Once real users exist, those values must be
rotated and moved out of git.
### Limits
This is the local first line of defence, **not** a replacement for a full scanner (gitleaks, trufflehog)
in CI. Bypass a false positive with `git commit --no-verify` — sparingly, and only when you are certain
the flagged line is not a secret.
There is no git hook enforcing anything in this repo — `.githooks/` was removed in phase 7 as an
MVP-stage call: this is a pre-launch demo project and the mechanical backstop wasn't worth the overhead
yet. The underlying rule is unchanged — **never commit a real secret** — it's just unenforced by tooling.
Root [CLAUDE.md](../../../CLAUDE.md) §6 already documents the repo's actual trade: config lives in
committed files, including live credentials, until real users exist (see
[DEPLOY.md](../../../DEPLOY.md) "Going to Production" for the rotation step that unblocks that). Revisit
adding a hook — or a CI scanner (gitleaks, trufflehog) — if that trade changes before this one does.
---
+2 -2
View File
@@ -1,6 +1,6 @@
# Backlog — every open item, triaged
> Last verified: 2026-08-02 against commit `b876490`.
> Last verified: 2026-08-02 against commit `51e86a1`.
Reconciled from five ledgers — [hardening/issues.md](../../archive/post-phase/hardening/issues.md) (18 items),
[for-backend.md](../../archive/build-chain/working-context/frontend/requests/for-backend.md) (67 REQs), 53
@@ -251,7 +251,7 @@ log is in [decisions.md](decisions.md). The business-area overlay is in [impleme
| 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) | — |
| 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 a worklist (`appsettings.*.json`, `StartupSecretsGuard.PlaceholderMarkers`, `StartupSecretsGuardTests.cs`, `docs/rules/server/structure.md`); the two `.githooks/*` files in the original worklist no longer exist (phase 7 dropped the pre-commit hook — see [decisions.md](decisions.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)
+13 -3
View File
@@ -1,6 +1,6 @@
# Decisions — the distilled engineering decision log
> Last verified: 2026-08-02 against commit `b876490`.
> Last verified: 2026-08-02 against commit `51e86a1`.
Non-obvious decisions with a reason, extracted from `dev/`'s ~3MB of build history so they survive
`dev/`'s move to `archive/` in phase 6. **`product/` wins for business rules** — this file is for
@@ -91,10 +91,20 @@ Decided ui-phase-13, chosen specifically so `/` stays a stable, shareable, index
## Engineering decisions
**Phase 2 → Phase 4 handoff, "the rename is filed."** The placeholder secret sentinel
`SET_VIA_USER_SECRETS_OR_ENV` keeps its name — renaming it needs a server-code + git-hook + test change that
is out of a documentation phase's scope, and the string is load-bearing across 7 live files. Filed as
`SET_VIA_USER_SECRETS_OR_ENV` keeps its name — renaming it needs a server-code + test change that is out of
a documentation phase's scope, and the string is load-bearing across several live files. Filed as
[backlog.md](backlog.md) BL-219, deferred (cleanup-of-convenience, no urgency).
**Phase 7 dropped the pre-commit secret-scan hook — MVP stage, no need for it yet.** `.githooks/pre-commit`
(the `qw123321`/private-key/AWS-key/SQL-host/connection-string scan) and `.githooks/README.md` were deleted
outright, along with every doc reference to them (root `CLAUDE.md`'s repo-layout table and quick start,
[git-and-gates.md](../rules/shared/git-and-gates.md), [documentation.md](../rules/documentation.md),
[identity.md](../rules/server/identity.md), [config-matrix.md](../integration/config-matrix.md),
[DEPLOY.md](../../DEPLOY.md)). The underlying trade this repo already made — committed live credentials,
config in files not a secret store (root [CLAUDE.md](../../CLAUDE.md) §6) — is unchanged; this only removes
the local mechanical backstop against a *new* leak. Revisit before onboarding real users, alongside the
credential rotation already required by that trade.
**Hardening ledger re-verification (C-10) confirms the ledger was right to distrust its own checkboxes.**
All 18 hardening items were re-traced against `b876490` rather than trusted as-filed: 3 were already fixed
(client-only, landed in the "manual improvement" commits well before this doc chain started), 4 are