Closes round 2 of the deployment feature

Records the stage as complete and logs the two defects that local testing
turned up after U3 and U4 were generated: ciphertext predating the key-ring
move, and an integrity check that could not tell an unreachable slave from
one that does not recognise the master.

Both were fixed in this branch rather than filed. The second is master/slave
domain behaviour rather than deployment work, so the state file says so
plainly — it sits here by decision, not because it belongs to the feature.

Verified at close: build 0 errors, 372 backend tests, 237 frontend tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HHoJpxYXzHACSQguHrC5fw
This commit is contained in:
2026-07-28 12:35:44 +02:00
co-authored by Claude Opus 5
parent 6957ec7c60
commit 247d8be241
2 changed files with 86 additions and 2 deletions
@@ -86,7 +86,7 @@ Execution rounds (Q4 = B): **R1** = U1 + U2 · **R2** = U3 + U4 · **R3** = U5 +
- **Lifecycle Phase**: CONSTRUCTION
- **Current Stage**: Round 2 complete — U3 Security Headers & CSP and U4 Observability generated, built and tested
- **Next Stage**: Round 3 — U5 CI Workflow & Gates + U6 Deploy Workflow (U6 needs Infrastructure Design first)
- **Status**: Awaiting Round 2 code approval. Rounds 1 and 2 committed, nothing pushed
- **Status**: Round 2 **closed** 2026-07-28. Rounds 1 and 2 committed, nothing pushed. Awaiting approval to start Round 3
## Round 2 Design Record (2026-07-28)
- Functional Design U3 + U4 complete and committed (`357d395`)
@@ -108,11 +108,15 @@ Execution rounds (Q4 = B): **R1** = U1 + U2 · **R2** = U3 + U4 · **R3** = U5 +
## Round 2 Verification Record (2026-07-28)
- `dotnet build SlpModularCms.sln -c Release` — 0 errors (70 warnings, all pre-existing package advisories)
- Backend tests — **366 passed, 0 failed** (Core 196, Availability 82, Master 51, Identity 37); was 253 after Round 1
- Backend tests — **372 passed, 0 failed** at stage close (Core 196, Availability 82, Master 57, Identity 37); was 253 after Round 1, 366 after U4, +6 from the integrity-check fix
- Frontend tests — **237 passed, 0 failed**; baseline 213
- `npx tsc -b` clean; eslint on every changed frontend file reports 0 problems; full `pnpm run lint` unchanged at the pre-existing 5 errors / 1 warning (FR-21, U5)
- `Sentry.AspNetCore` 6.8.0 ships a native **`net10.0`** asset — the carried-forward compatibility question is closed
- `@sentry/react` 10.68.0; `pnpm-lock.yaml` diff is additions only
- **Two findings**: `z.string().url()` accepts `htp://` in Zod 4 (URL constructor accepts any scheme), so the pre-existing frontend validation never caught the typo BR-U4-24 names — now `z.url({ protocol: /^https?$/ })`. And `appsettings.json` comments are verified by `DeployedConfigurationTests` against the real provider rather than assumed, because the failure mode is both hosts refusing to start
- **One deviation**: `IAdminTokenValidator` collapsed to a single `Validate``AdminTokenResult` instead of adding an overload. Two methods with an invisible difference at the call site let a substitute silently invert the access decision while both compiled — see U4's `generation-summary.md`
- **Two defects found in local testing after Round 2, both fixed in this branch** rather than filed, per the standing rule that tech debt is for large or high-impact changes only:
1. Ciphertext written before U2 cannot be decrypted by the database key ring (`980dc80`). Recorded as ASM-08; local rows cleared and re-registered
2. `VerifyIntegrityAsync` could not tell an unreachable slave from one that does not recognise the master, so the only recoverable state was never repaired (`6957ec7`). Now four distinct outcomes; automatic registration on a rejected key is safe because the slave refuses any key that does not match an existing registration
- **Note**: fix 2 is master/slave **domain** behaviour, not deployment work. It sits in this branch by explicit decision, not because it belongs to the feature
- **Carried to phase-level Build and Test**: trace-ID propagation master → slave, `TraceId` present in rendered console output, tunnel status codes, the `security_event` tag on a real Sentry event, threshold behaviour end to end, and CSP/HSTS header presence on real static assets and error responses