104 lines
9.6 KiB
Markdown
104 lines
9.6 KiB
Markdown
# Open contradictions
|
||
|
||
> Opened 2026-07-29 by [phase 0](phase-0-inventory-and-scaffold.md), against commit `c99e3f4`.
|
||
> **Phase 0 only finds these. It resolves none of them.**
|
||
|
||
Each row is *claim A* vs *claim B* with a location for both, and the phase that owns the resolution.
|
||
When a phase resolves one, it moves the row to **Resolved** at the bottom with the decision, and — per
|
||
the chain's non-negotiable #5 — records the decision in `docs/status/decisions.md`.
|
||
|
||
Three of the five contradictions the plan seeded turned out to be **narrower than stated**. Those are
|
||
written up as they actually are, with the evidence, in [§ Corrections to the seeded list](#corrections-to-the-seeded-list).
|
||
|
||
---
|
||
|
||
## Open
|
||
|
||
| # | Claim A | Claim B | Owner | Status |
|
||
| --- | --- | --- | --- | --- |
|
||
| C-1 | **Set the crypto keys with `dotnet user-secrets`** — [manual-testing-plan.md:22](../../dev/post-phase/manual-testing-plan.md), [:233](../../dev/post-phase/manual-testing-plan.md) | **`user-secrets` is not used; `<UserSecretsId>` was removed so the store is not read** — [CLAUDE.md:90](../../CLAUDE.md), [DEPLOY.md:20](../../DEPLOY.md), [server/CLAUDE.md:70](../../server/CLAUDE.md), and `Baya.Web.Api.csproj` (no `UserSecretsId` element) | 3 | open |
|
||
| C-2 | **Placeholder value is literally `SET_VIA_USER_SECRETS_OR_ENV`** — `server/src/API/Baya.Web.Api/appsettings.json` (6 occurrences), enforced by `StartupSecretsGuard` and by the pre-commit hook | **That store does not exist any more** (C-1's B side). The name instructs a reader to use a removed mechanism | 2 | open — naming only, behaviour is correct |
|
||
| C-3 | **The server listens on `https://localhost:5002`** — [CLAUDE.md:62](../../CLAUDE.md), [:135](../../CLAUDE.md), [api-conventions.md:6](../../dev/contracts/conventions/api-conventions.md), [RUNBOOK.md:7](../../dev/post-phase/refinement/RUNBOOK.md), [:84](../../dev/post-phase/refinement/RUNBOOK.md), [:112](../../dev/post-phase/refinement/RUNBOOK.md), + 12 more | **It listens on `http://localhost:5002`** — `launchSettings.json:25` (`"applicationUrl": "http://localhost:5002"`), and `client/.env.development:20` (`NEXT_PUBLIC_API_URL = http://localhost:5002`) | 2 + 3 | open |
|
||
| C-4 | **RUNBOOK's `dotnet dev-certs https --trust` step is required**, because the browser would otherwise reject the API — [RUNBOOK.md:26](../../dev/post-phase/refinement/RUNBOOK.md) | **The API is plain HTTP locally** (C-3's B side), so there is no certificate to trust | 3 | open — likely a dead step |
|
||
| C-5 | **Bring-up starts a local SQL Server in Docker on `localhost:1433`** — [RUNBOOK.md:18](../../dev/post-phase/refinement/RUNBOOK.md), [:35–48](../../dev/post-phase/refinement/RUNBOOK.md), [:63](../../dev/post-phase/refinement/RUNBOOK.md) | **The committed dev config points at a remote SQL Server** — `appsettings.Development.json` (`Server=87.107.152.16,1433`), and [manual-testing-plan.md:20](../../dev/post-phase/manual-testing-plan.md) calls the remote one "currently" the target | 3 | open — the two bring-up paths give *different worlds*: the remote DB is already seeded, a fresh local one is not |
|
||
| C-6 | **`GET /api/v1/webhooks/payouts/{provider}` does not exist** — absent from `dev/contracts/openapi/swagger.v1.json` (frozen 2026-07-13) and from every `dev/contracts/domains/*.md` | **It exists** — present in the fresh snapshot `docs/integration/openapi/swagger.v1.json` (2026-07-29). See [§ OpenAPI drift](#openapi-drift) | 2 | open |
|
||
| C-7 | **`GeneratePayoutBatchCommand`'s shape** per the 07-13 snapshot | **A different shape** in the 07-29 snapshot — the only schema of 339 whose definition changed | 2 | open |
|
||
| C-8 | **Two contract files describe the same domain** — [`dev/contracts/domains/messaging.md`](../../dev/contracts/domains/messaging.md) is a headerless 851-byte fragment ("Refinement phase 3 additions (REQ-028)") sitting beside the 10.8 K [`messaging-notifications-admin.md`](../../dev/contracts/domains/messaging-notifications-admin.md), which it silently amends | — | 2 | open — merge, don't move both |
|
||
| C-9 | **The OpenAPI folder publishes documents `v1` *and* `v1.1`** — [openapi/README.md:3](../../dev/contracts/openapi/README.md) | **Only `swagger.v1.json` has ever been committed**; `v1.1` was not fetched during this survey | 2 | open — `UNVERIFIED`, check `/swagger/v1.1/swagger.json` when the server is next up |
|
||
| C-10 | **18 hardening items are open** — [issues.md](../../dev/post-phase/hardening/issues.md), 18 of 18 checkboxes unticked, last touched 2026-07-17 | **Fourteen UI phases, two manual-testing iterations, a Telegram integration and a deploy commit ran afterwards** (`12ce7fa` → `96b57eb`, 07-20 → 07-28) without ticking any box | 4 | open — Phase 4 must re-verify each item against code, not trust the checkbox |
|
||
| C-11 | **The frontend-designer skill is the design-language authority** — [SKILL.md §§1–7](../../.claude/skills/frontend-designer/SKILL.md) | **`client/CLAUDE.md` also states theme, tokens, typography, icons and anti-patterns** — [§Theme System:646](../../client/CLAUDE.md), [§Forms:590](../../client/CLAUDE.md), [:22–23](../../client/CLAUDE.md) (icons). Overlapping scope, two files, no stated precedence | 1 + 7 | open |
|
||
| C-12 | **The skill is current** | **It is exactly one iteration behind the code.** SKILL.md's last commit is `baa3cc6` ("manual improvement 1"); `client/CLAUDE.md`'s is `e6a8f93` ("manual improvement 2"), which changed **44 files, +3419/−2449** under `client/src`. Anything iteration 2 changed is absent from the skill | 7 | open |
|
||
| C-13 | **`dev/` is "the plan for building Balinyaar"**, written in the imperative — [dev/README.md:3](../../dev/README.md) | **It is a record of work already done.** `dev/phases/` last touched 2026-06-28; the code it describes shipped weeks ago | 6 | open — resolved by the archive banner, not by editing 199 files |
|
||
| C-14 | **`temp/swagger.json` is a stale committed duplicate** — [_plan/README.md](README.md) diagnosis table | **It is not committed at all** — `.gitignore:1` ignores `temp`, and `git ls-files temp/` is empty. It is local clutter, not repo content | 0 | see [§ Corrections](#corrections-to-the-seeded-list) |
|
||
|
||
---
|
||
|
||
## OpenAPI drift
|
||
|
||
The fresh snapshot is at [`docs/integration/openapi/swagger.v1.json`](../integration/openapi/swagger.v1.json).
|
||
See its [README](../integration/openapi/README.md) for provenance. Measured against the 2026-07-13 snapshot
|
||
at `dev/contracts/openapi/swagger.v1.json`:
|
||
|
||
| | 2026-07-13 | 2026-07-29 |
|
||
| --- | --- | --- |
|
||
| paths | 177 | **178** |
|
||
| operations | 185 | **186** |
|
||
| component schemas | 339 | **339** |
|
||
|
||
**Added (1)**
|
||
|
||
- `POST /api/v1/webhooks/payouts/{provider}`
|
||
|
||
**Removed (0)** · **Methods changed on an existing path (0)** · **Schemas added/removed (0)**
|
||
|
||
**Schema definitions changed (1)**
|
||
|
||
- `GeneratePayoutBatchCommand`
|
||
|
||
> **This is Phase 2's worklist for the machine contract, and it is two lines long.** The 16-day gap
|
||
> between the snapshot and the code produced almost no wire-level drift. Phase 2 should therefore spend
|
||
> its budget on the **hand-written** `dev/contracts/domains/*.md` — 17 files, frozen the same day, never
|
||
> mechanically checked against anything — rather than on the JSON. See
|
||
> [§ Corrections](#corrections-to-the-seeded-list) C-14b.
|
||
|
||
---
|
||
|
||
## Corrections to the seeded list
|
||
|
||
The plan seeded five contradictions. Two hold as written; three are narrower than stated. Recording
|
||
this here so later phases do not budget for work that is already done.
|
||
|
||
**Holds — `user-secrets`.** The plan says 18 files still instruct you to use it. 32 mentions across 18
|
||
files is right, but the split matters: **6 files document the removal correctly** (root `CLAUDE.md`,
|
||
`DEPLOY.md`, `server/CLAUDE.md`, `server/CONVENTIONS.md`, and `RUNBOOK.md` twice — including a
|
||
troubleshooting row that names the error you now get). **12 are historical** — refinement prompts,
|
||
handoffs and reports written before the removal, all headed for `archive/`. Only **one live document
|
||
still gives the wrong instruction**: [manual-testing-plan.md](../../dev/post-phase/manual-testing-plan.md)
|
||
(last commit `bd06ef0`, the day *before* the removal in `5885280`), plus the archived
|
||
[telegram-otp-bot/INTEGRATION-PROMPT.md](../../telegram-otp-bot/INTEGRATION-PROMPT.md).
|
||
→ **The plan's statement that "both `manual-testing-plan.md` and `RUNBOOK.md` are stale on secrets
|
||
handling" is half wrong. `RUNBOOK.md` is current.** Phase 3 fixes one file, not two.
|
||
|
||
**Holds — hardening.** C-10 above. 18 of 18 unticked, four later chains, nothing reconciled.
|
||
|
||
**Narrower — contract drift (C-14b).** "`dev/contracts/` frozen 07-13 vs `server/src` through 07-28"
|
||
is true by date but nearly empty in substance at the OpenAPI layer: 1 endpoint, 1 schema. The drift
|
||
that matters, if any, is in the 17 hand-written domain markdown files. Phase 2 should re-scope
|
||
accordingly.
|
||
|
||
**Narrower — the design-language skill.** The plan says the skill "predates that overhaul" (mobile-scoped
|
||
shell, bottom nav, react-hook-form, new icon set). It does not: SKILL.md was rewritten at `baa3cc6`
|
||
during iteration 1 and already covers `AppFrame` (4×), `BottomBar`, `APP_FRAME_MAX_WIDTH` (2×) and the
|
||
Lucide-only icon registry with `@mui/icons-material` removed. `react-hook-form` is absent from the skill,
|
||
but it is an engineering rule that `client/CLAUDE.md` §Forms owns — not a design-language gap. The real
|
||
gap is C-12: the skill stopped at iteration 1 while the code went on to iteration 2.
|
||
|
||
**Wrong — `temp/swagger.json`.** C-14 above. It is `.gitignore`d and untracked, so it was never part of
|
||
the repo's documentation surface. Phase 0's brief says to delete it; that deletes a local file only.
|
||
|
||
---
|
||
|
||
## Resolved
|
||
|
||
_(none yet — phases move rows here with the decision and the commit that made it)_
|