All checks were successful
CI / Lint, typecheck, test (pull_request) Successful in 6m12s
CI / Build container images (pull_request) Successful in 4m2s
CI / Auth e2e pack (pull_request) Successful in 8m29s
CI / Import/export fidelity gate (pull_request) Successful in 54s
CD / Build and push images (push) Successful in 31s
CD / Deploy to Test (push) Successful in 14s
CD / Smoke tests against Test (push) Successful in 1m29s
CD / Promote to Int (push) Successful in 14s
CI / Build container images (push) Has been skipped
CI / Lint, typecheck, test (push) Successful in 6m30s
CI / Auth e2e pack (push) Successful in 8m6s
CI / Import/export fidelity gate (push) Successful in 57s
The deployment declares through VS_NFD_MODE (off | marked | hidden | enforced, default off) how the application treats configuration that violates the VS-NfD reference profile — deploy-level like BACKUP_ALLOWED_TARGETS, so a compromised Site Admin cannot widen it. The catalog in shared (vs-nfd-profile.ts) is the single source of truth: every profile-relevant setting with a decidable compliant value, judgement calls in an explicit advisory list, and a fence test parsing the hardening guide's reference tables so neither can drift (pattern #201). The api evaluates the catalog against the typed settings registry and validated env and exposes mode + verdict on GET /admin/system/vs-nfd-profile; the admin settings view shows the card whenever the mode is not off. Display only — the treatments land with #244–#246 (ADR 0027, proposed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AUtYMxwTCMHG9mVHnwbFg8
67 lines
3.3 KiB
Markdown
67 lines
3.3 KiB
Markdown
# ADR 0027: VS-NfD hardening-profile mode and configuration catalog
|
|
|
|
- Status: proposed
|
|
- Date: 2026-07-31
|
|
|
|
## Context
|
|
|
|
The hardening guide (issue #227, `docs/vs-nfd/50-haertungsleitfaden.md`)
|
|
names a reference configuration for VS-NfD operation, but it is prose: the
|
|
application cannot answer whether the running configuration matches it,
|
|
and an operator flipping a switch in the admin UI gets no hint that the
|
|
choice leaves the profile. Requested by the operator (2026-07-30) as a
|
|
follow-up to the M24/M25 switches: the application itself should know
|
|
which options violate the profile — while deployments outside any VS
|
|
context stay entirely unaffected.
|
|
|
|
## Decision
|
|
|
|
1. **A deploy-level mode, not a runtime setting.** `VS_NFD_MODE`
|
|
(`off | marked | hidden | enforced`) is an environment variable,
|
|
validated in the shared env schema and passed through compose — for the
|
|
same reason as `BACKUP_ALLOWED_TARGETS` (#192, ADR 0026): a
|
|
compromised Site-Admin account must not be able to widen it. The modes
|
|
escalate: `marked` shows violations at the point of decision (#244),
|
|
`hidden` removes violating options and marks the hiding (#245),
|
|
`enforced` additionally rejects violating writes server-side (#246) —
|
|
hiding alone is UI cosmetics a scripted client bypasses.
|
|
2. **`off` is the default.** Outside a VS context the profile is not a
|
|
topic: no marking, no card, no behavioural difference. Existing
|
|
deployments upgrade without noticing the feature exists.
|
|
3. **The machine-readable catalog is the single source of truth**
|
|
(`packages/shared/src/vs-nfd-profile.ts`): every profile-relevant
|
|
setting with a decidable compliant value (a tiny predicate model —
|
|
equals, upper bound, non-empty) and its hardening-guide section.
|
|
Judgement-call entries ("only what the service needs") live in an
|
|
explicit advisory list. A fence test (pattern of the audit-catalogue
|
|
fence #201) parses the guide's reference tables and fails when a
|
|
switch is neither in the catalog nor in the advisory list — the guide
|
|
keeps its binding maintenance rule, the catalog can never silently lag.
|
|
4. **Pond-level opt-ins are deliberately absent** (`apiEnabled`,
|
|
`mcpEnabled`): their instance master switches govern; a pond opt-in
|
|
under a compliant master switch cannot violate the profile on its own.
|
|
The evaluation and enforcement paths are scope-generic, so pond
|
|
entries can be added if that judgement changes.
|
|
5. **Exposure first** (#243): the api evaluates the catalog against the
|
|
typed settings registry and the validated env and reports mode +
|
|
verdict on `GET /admin/system/vs-nfd-profile`; the admin settings view
|
|
shows the card whenever the mode is not `off`. The three treatments
|
|
build on exactly this evaluation.
|
|
|
|
## Consequences
|
|
|
|
- The guide gains a second consumer: every new switch line must be
|
|
triaged (catalog or advisory) or CI fails — a deliberate speed bump,
|
|
same trade-off as the audit-catalogue fence.
|
|
- Deploy-level means changing the mode requires a deployment change and
|
|
an api restart; that is the point (role separation, operations
|
|
handbook §6).
|
|
- The verdict describes decidable entries only; advisory entries remain
|
|
an assessor's reading of the guide. The card says what deviates, the
|
|
guide says why it matters.
|
|
|
|
## Implementing issues
|
|
|
|
#243 (mode, catalog, fence, exposure), #244 (`marked`), #245 (`hidden`),
|
|
#246 (`enforced`).
|