Settles how the headers and observability units get built

NFR Design for U3 and U4. Two decisions the earlier stages had deliberately
left open, plus four risks the functional design did not name.

OPEN-01 closed: the correlation ID is the W3C trace ID from the ambient
Activity, with TraceIdentifier as the fallback. It propagates across the
master/slave boundary via traceparent, which TraceIdentifier cannot do at
all, and it is the same value ProblemDetails already returns to the client.

REF-U3-01 raised: BR-U3-22's Umami-origin startup warning cannot work. The
backend never sees VITE_UMAMI_WEBSITE_ID, so the check would either always
warn or never warn. Withdrawn from U3 and replaced by a blocking U5 CI gate
that compares the frontend build variable against that environment's CSP
origins, where both values are visible.

Four additions beyond the functional design:
- Set-Cookie added to the scrub list; the login response issues the
  refreshToken there, so scrubbing only the request cookie protects nothing
- SetBeforeSendTransaction alongside SetBeforeSend; transactions carry
  request data too
- OnRejected on the rate limiter; today a 429 leaves no trace anywhere
- FlushAsync before the migration-failure rethrow, or the one Critical
  event in the system dies with the process

Two traps recorded with tests attached: Sentry groups log events by message
template, so interpolated messages make FR-19's rate-based alert rules
unimplementable while appearing to work; and DefaultHttpContext.Response
.OnStarting is a no-op, so the obvious middleware test asserts nothing.

Three values chosen rather than escalated, each one line to change and all
three listed for review at the end of U4's pattern document: JSON console
outside Development, TracesSampleRate 0.1, tunnel cap 200 KB.

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 10:25:11 +02:00
co-authored by Claude Opus 5
parent 589146a167
commit 5102f8668b
7 changed files with 1210 additions and 9 deletions
@@ -342,7 +342,7 @@ DEV-01…04 are **pre-existing or cost-driven** and none is introduced by this f
| ID | Item | To be resolved |
|---|---|---|
| OPEN-01 | **Correlation/request ID in logs** is required by SECURITY-03 but does not exist today. Needs a decision on mechanism (ASP.NET Core `TraceIdentifier` versus `W3C traceparent`). | NFR Design / Construction |
| ~~OPEN-01~~ | ~~**Correlation/request ID in logs** is required by SECURITY-03 but does not exist today. Needs a decision on mechanism (ASP.NET Core `TraceIdentifier` versus `W3C traceparent`).~~ **RESOLVED 2026-07-28** at NFR Design for U4: the **W3C trace ID** from the ambient `Activity`, with `TraceIdentifier` as the fallback when no `Activity` exists. Enabled through `ActivityTrackingOptions` plus `IncludeScopes`, so every entry from every category carries it without changing any call site. Chosen because it propagates across the master/slave HTTP boundary via `traceparent` — the one diagnostic question `TraceIdentifier` cannot answer — and because it is the same value ASP.NET Core's `ProblemDetails` already returns to the client. See `construction/u4-observability/nfr-design/nfr-design-patterns.md` Pattern 1. | Closed |
| ~~OPEN-02~~ | ~~`AvailabilityMiddleware.IsAdminBypass` reads the JWT without validating its signature.~~ **RESOLVED 2026-07-27** at Application Design (Q12 = A): folded into this feature as **FR-24**, landing in the same unit as the `/health` bypass since both touch the same middleware. | Closed |
| OPEN-03 | **Exact patched versions** for `Microsoft.OpenApi` and `System.Security.Cryptography.Xml` (FR-22) must be resolved and verified against the advisories. | Construction |
| OPEN-04 | **Whether production stays on the Pi long enough** that FTPS is never built. D-02 requires only that the design allows it; the trigger for actually building it is a business decision. | Deferred by design |
@@ -353,9 +353,9 @@ DEV-01…04 are **pre-existing or cost-driven** and none is introduced by this f
This feature turns a manually deployed modular-monolith CMS into one with an automated, auditable pipeline, on hosting where nothing can be configured server-side.
**24 functional requirements, 10 non-functional requirements, 32 traced decisions, 7 assumptions, 3 remaining open items, 4 documented security deviations.**
**24 functional requirements, 10 non-functional requirements, 32 traced decisions, 7 assumptions, 2 remaining open items, 4 documented security deviations.**
*(FR-24 added and OPEN-02 closed at Application Design on 2026-07-27.)*
*(FR-24 added and OPEN-02 closed at Application Design on 2026-07-27. OPEN-01 closed at NFR Design on 2026-07-28.)*
The three requirements that carry the most risk if implemented carelessly: