Work the register due list, and add the one-check-per-sitting rule

Nine records checked. Five clean and climbed to 1h: RISK-F-0003, 0004,
0005, 0006, 0009 and RISK-REG-0001. Three moved and stay at instant —
RISK-F-0002 (RISK-V-0001 found the flex-auth-ops-warden policy admits no
ingress, so the live question there is now availability rather than
attestation), RISK-F-0007 (the on-request path walked for the first time
as RISK-V-0002), RISK-F-0008 (the determination now exists).

The rule: a finding recorded as moved is not clean-checked in the same
sitting. Re-reading your own keystrokes and climbing produces a rung that
says the world held still when what held still was the last five minutes.
The rung carries stability information or it carries nothing.

record_check.py now handles regulatory records as well as findings.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-08-20 12:03:12 +02:00
parent 2ebdc133bc
commit 56b8d61583
12 changed files with 116 additions and 36 deletions

View file

@ -8,13 +8,13 @@ Generated by `tools/register_index.py` from `findings/`. Do not edit by hand. La
| ID | Finding | System | Severity | Disclosure | Escalation | Fix owner | Status | Cadence | Next check |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| [RISK-F-0009](findings/RISK-F-0009-openbao-deny-set-covers-a-third-of-high-risk-lanes.md) | agent-high-risk-boundary denies 6 of 17 high-risk lanes; the direct bao path is unprotected for the rest | railiance-platform | **high** | embargoed | none | railiance-platform | open | instant (0) | **due** |
| [RISK-F-0009](findings/RISK-F-0009-openbao-deny-set-covers-a-third-of-high-risk-lanes.md) | agent-high-risk-boundary denies 6 of 17 high-risk lanes; the direct bao path is unprotected for the rest | railiance-platform | **high** | embargoed | none | railiance-platform | open | 1h (1) | 2026-08-20 11:02Z |
| [RISK-F-0008](findings/RISK-F-0008-audit-retention-legal-basis-assumed.md) | The legal basis for retaining audit facts against an erasure request has been assumed, never established | audit-core | medium | public | **required** (t2, partially-answered) | risk-nexus | open | instant (0) | **due** |
| [RISK-F-0007](findings/RISK-F-0007-unverified-tenant-boundary.md) | No consumer's tenant boundary is verified anywhere | estate | **high** | embargoed | **answered** (t4, assigned) | per-consumer, on request | accepted | instant (0) | **due** |
| [RISK-F-0006](findings/RISK-F-0006-apps-pg-no-backup-configured.md) | apps-pg has no backup configured at all: R0 means no recovery | railiance-platform | **high** | embargoed | **answered** (t3, approved) | railiance-platform | open | instant (0) | **due** |
| [RISK-F-0005](findings/RISK-F-0005-audit-core-unfiltered-read-path.md) | audit-core read path applies no tenant filter; the bound is deployment, not code | audit-core | medium | embargoed | none | audit-core | open | instant (0) | **due** |
| [RISK-F-0004](findings/RISK-F-0004-tenant-engine-unfiltered-event-read.md) | tenant-engine events() returns the entire event log unfiltered | tenant-engine | **high** | embargoed | none | tenant-engine | open | instant (0) | **due** |
| [RISK-F-0003](findings/RISK-F-0003-ops-warden-read-boundary-ungraded-lanes.md) | ops-warden agent read-boundary does not fire on ungraded catalog lanes | ops-warden | medium | embargoed | none | ops-warden | mitigated | instant (0) | **due** |
| [RISK-F-0006](findings/RISK-F-0006-apps-pg-no-backup-configured.md) | apps-pg has no backup configured at all: R0 means no recovery | railiance-platform | **high** | embargoed | **answered** (t3, approved) | railiance-platform | open | 1h (1) | 2026-08-20 11:02Z |
| [RISK-F-0005](findings/RISK-F-0005-audit-core-unfiltered-read-path.md) | audit-core read path applies no tenant filter; the bound is deployment, not code | audit-core | medium | embargoed | none | audit-core | open | 1h (1) | 2026-08-20 11:02Z |
| [RISK-F-0004](findings/RISK-F-0004-tenant-engine-unfiltered-event-read.md) | tenant-engine events() returns the entire event log unfiltered | tenant-engine | **high** | embargoed | none | tenant-engine | open | 1h (1) | 2026-08-20 11:02Z |
| [RISK-F-0003](findings/RISK-F-0003-ops-warden-read-boundary-ungraded-lanes.md) | ops-warden agent read-boundary does not fire on ungraded catalog lanes | ops-warden | medium | embargoed | none | ops-warden | mitigated | 1h (1) | 2026-08-20 11:02Z |
| [RISK-F-0002](findings/RISK-F-0002-ops-warden-sign-ungated.md) | ops-warden signs SSH certificates with no authorization decision, and its unblock is now unsafe | ops-warden | medium | embargoed | **withdrawn** (t6, withdrawn-hazard-window-closed) | ops-warden | open | instant (0) | **due** |
| [RISK-F-0001](findings/RISK-F-0001-flex-auth-unauthenticated-check.md) | flex-auth /v1/check authenticates no caller | flex-auth | **high** | public | **withdrawn** (t1, withdrawn-before-sending) | flex-auth | fixed | instant (0) | **due** |

View file

@ -53,6 +53,23 @@ make register
check that is not written down did not happen** — the same rule this register
applies to every repo it grades.
## One check per sitting
**A finding you recorded as `moved` is not clean-checked in the same sitting.**
The ladder says `instant` means "now, and again immediately until a check comes
back clean". The temptation is to record the movement, re-read what you just
wrote, find it consistent, and climb — which produces a `1h` rung seconds after
a change, on the evidence of your own keystrokes.
That is self-certification, and the rung is supposed to carry information about
how long the world has held still, not about how quickly the register can agree
with itself. A finding that moved stays at `instant` until a *later* pass finds
nothing new. It costs one extra check and it keeps the signal honest.
Applied on 2026-08-20: `RISK-F-0002`, `RISK-F-0007` and `RISK-F-0008` all moved
and were left due rather than climbed.
## What must not happen
**Stamping `clean` without doing the four questions.** It costs nothing, takes

View file

@ -8,10 +8,10 @@ determined: "2026-08-20"
finding: RISK-F-0008
sources_read: "GDPR Arts 5, 6, 17, 21, 32; Recitals 49, 65; HGB §257; AO §147"
external_review: none
last_checked: "2026-08-20T05:25:00Z"
next_check: "2026-08-20T05:25:00Z"
cadence: instant
clean_streak: 0
last_checked: "2026-08-20T10:02:42Z"
next_check: "2026-08-20T11:02:42Z"
cadence: 1h
clean_streak: 1
---
# RISK-REG-0001 — the retention basis, written down
@ -113,3 +113,7 @@ argument avoided by holding less data is better than a strong one relied upon.
happened.
Reviewed every 90 days with `RISK-F-0008`, or immediately on any trigger.
## Reviews
- **2026-08-20** — clean check: grounds unchanged; still waiting on audit-core's co-residency horizon. Cadence instant → 1h (1 clean in a row); next check 2026-08-20 11:02Z.

View file

@ -29,8 +29,8 @@ embargo_review: "2026-11-17"
escalation: withdrawn
escalation_trigger: 6
escalation_status: withdrawn-hazard-window-closed
last_checked: "2026-08-19T21:30:00Z"
next_check: "2026-08-19T21:30:00Z" # due now: the ladder starts at instant
last_checked: "2026-08-20T10:02:41Z"
next_check: "2026-08-20T10:02:41Z"
cadence: instant
clean_streak: 0
graded_by: risk-nexus
@ -234,3 +234,36 @@ the thing that had gone stale was this register's own grading, four hours old.
- **2026-08-19** — constraint lifted, escalation withdrawn, severity unchanged.
Open at review: has `ops-warden` presented SA tokens and enabled the gate;
is `FLEX-WP-0007` still the stated blocker or has it too gone stale.
## Check — 2026-08-20: a new availability fact, and it is the one that matters now
`RISK-V-0001` verified `flex-auth`'s NetworkPolicies against the live cluster
and found a third policy nobody had mentioned:
```
flex-auth-ops-warden, created 2026-08-19T12:47:18Z
policyTypes: [Ingress, Egress]
ingress: no rules at all
```
`Ingress` in `policyTypes` with zero rules means deny all ingress. On its face,
nothing reaches that pin.
**This is now the live question on this finding.** The attestation hazard
lifted when `flex-auth` shipped; what remained was whether enabling
`policy.enabled` breaks signing on availability grounds. If the pin
`ops-warden` calls admits no ingress, a `fail_closed: true` gate against it
fails closed — every `warden sign` stops.
The register is **not** concluding that, and said so to both owners: the policy
may be mid-rollout, it may not be the pin `ops-warden` targets, and another
policy may admit the traffic. Both were told on 2026-08-20, before either flips
a switch, which is the entire reason this finding is carried as a peer rather
than folded into `RISK-F-0001`.
The severity is unchanged at `medium`. What changed is the evidence, and it
changed in the direction of "do not enable this yet" for a completely different
reason than the one this finding was filed for. That is the second time in two
days that this finding's blocker turned out to be a claim about the world at a
date.
- **2026-08-20** — not clean: RISK-V-0001 found the flex-auth-ops-warden policy admits no ingress; the live question is now availability, not attestation. Cadence instant → instant; checked again immediately.

View file

@ -24,10 +24,10 @@ embargo_condition: "RISK-F-0009 resolved — the OpenBao deny set covers every h
embargo_since: "2026-08-19"
embargo_review: "2026-09-18"
escalation: none
last_checked: "2026-08-20T05:40:00Z"
next_check: "2026-08-20T05:40:00Z" # due now: the ladder starts at instant
cadence: instant
clean_streak: 0
last_checked: "2026-08-20T10:02:42Z"
next_check: "2026-08-20T11:02:42Z"
cadence: 1h
clean_streak: 1
graded_by: risk-nexus
ruling: RISK-RULING-2026-08-19
---
@ -225,3 +225,4 @@ finding's own fix has landed.
**Verification limit, recorded rather than assumed:** the mitigation is
`ops-warden`'s report and this register has not probed it. Their operator token
is expired, which is also why `RISK-F-0009` rests on a file comparison.
- **2026-08-20** — clean check: checked against the inbox and the owner's record; nothing moved. Cadence instant → 1h (1 clean in a row); next check 2026-08-20 11:02Z.

View file

@ -25,10 +25,10 @@ embargo_condition: "the read path filters by tenant in code"
embargo_since: "2026-08-19"
embargo_review: "2026-09-18"
escalation: none
last_checked: "2026-08-19T21:20:00Z"
next_check: "2026-08-19T21:20:00Z" # due now: the ladder starts at instant
cadence: instant
clean_streak: 0
last_checked: "2026-08-20T10:02:42Z"
next_check: "2026-08-20T11:02:42Z"
cadence: 1h
clean_streak: 1
graded_by: risk-nexus
ruling: RISK-RULING-2026-08-19-B
---
@ -88,3 +88,4 @@ tenant data, and that is what `production_rescore` is for.
- **2026-08-19** — filed and graded from `RISK-F-0001`'s unfiled list.
Open at review: does `tenant-engine` confirm; is a fix tracked; what does
the log actually contain.
- **2026-08-20** — clean check: checked against the inbox and the owner's record; nothing moved. Cadence instant → 1h (1 clean in a row); next check 2026-08-20 11:02Z.

View file

@ -25,10 +25,10 @@ embargo_condition: "AUDIT-WP-0008-T04 lands a tenant filter in the read path"
embargo_since: "2026-08-19"
embargo_review: "2026-11-17"
escalation: none
last_checked: "2026-08-19T21:20:00Z"
next_check: "2026-08-19T21:20:00Z" # due now: the ladder starts at instant
cadence: instant
clean_streak: 0
last_checked: "2026-08-20T10:02:42Z"
next_check: "2026-08-20T11:02:42Z"
cadence: 1h
clean_streak: 1
graded_by: risk-nexus
ruling: RISK-RULING-2026-08-19-B
---
@ -77,3 +77,4 @@ No escalation. Known, owned, tracked, moving.
- **2026-08-19** — filed and graded from `RISK-F-0001`'s unfiled list.
Open at review: has `AUDIT-WP-0008-T04` moved; is `may_read: false` still
true of every production credential, not only the sender.
- **2026-08-20** — clean check: checked against the inbox and the owner's record; nothing moved. Cadence instant → 1h (1 clean in a row); next check 2026-08-20 11:02Z.

View file

@ -31,10 +31,10 @@ escalation_answered: "2026-08-19"
escalation_answered_by: the-custodian
escalation_act: approve
decision: "spend for apps-pg backup storage approved; no ceiling stated"
last_checked: "2026-08-19T23:05:00Z"
next_check: "2026-08-19T23:05:00Z" # due now: the ladder starts at instant
cadence: instant
clean_streak: 0
last_checked: "2026-08-20T10:02:42Z"
next_check: "2026-08-20T11:02:42Z"
cadence: 1h
clean_streak: 1
graded_by: risk-nexus
ruling: RISK-RULING-2026-08-19-B
---
@ -115,3 +115,4 @@ claim, not a control.
- **2026-08-19** — escalation answered, spend approved. Open at review: is a
backup configured; has a restore been demonstrated; what does it cost.
- **2026-08-20** — clean check: checked against the inbox and the owner's record; nothing moved. Cadence instant → 1h (1 clean in a row); next check 2026-08-20 11:02Z.

View file

@ -34,8 +34,8 @@ accepted_by: the-custodian
accepted_on: "2026-08-19"
accepted_until: "production transition (hard expiry, not a date)"
decision: "pragmatic default before production — carried unverified; verification of a named consumer boundary on request"
last_checked: "2026-08-19T23:05:00Z"
next_check: "2026-08-19T23:05:00Z" # due now: the ladder starts at instant
last_checked: "2026-08-20T10:02:41Z"
next_check: "2026-08-20T10:02:41Z"
cadence: instant
clean_streak: 0
graded_by: risk-nexus
@ -155,3 +155,23 @@ production rather than at it.
- **2026-08-19** — escalation answered, accepted until production with
verification on request. Open at review: any request received; any further
instances found; whether production is close enough to re-take the default.
## Check — 2026-08-20: the on-request path has been walked once
`RISK-V-0002` — verification of `user-engine`'s tenant boundary, requested
through the documented path on 2026-08-20.
`user-engine` was chosen because they are a consumer with a boundary who is
**not** already carrying a finding about one. Using `tenant-engine`
(`RISK-F-0004`) or `audit-core` (`RISK-F-0005`) would have tested the path
against systems already known to fail it, which would have proved nothing about
the path.
The acceptance recorded here rests on that path working. Until 2026-08-20 it
had never been used, which made it a plan rather than a route. All three
outcomes are informative and the least comfortable one is the most useful:
if nothing comes back, the estate learns that it is carrying this finding on an
assumption that asking works.
Grade unchanged. Nothing about the boundary itself has moved.
- **2026-08-20** — not clean: On-request verification walked for the first time: RISK-V-0002 asks user-engine. Cadence instant → instant; checked again immediately.

View file

@ -32,8 +32,8 @@ escalation_act: rule
decision: "identity in audit records: opaque subject ids preferred, agent identifiers where possible, operator credentials only where necessary, policy decisions tracked to the responsible party; zone-level privacy guarantees may raise the floor"
outstanding: "a defensible retention period per category (waits on audit-core's co-residency horizon), and the trigger list for buying an external answer"
determination: RISK-REG-0001
last_checked: "2026-08-20T05:25:00Z"
next_check: "2026-08-20T05:25:00Z" # due now: the ladder starts at instant
last_checked: "2026-08-20T10:02:41Z"
next_check: "2026-08-20T10:02:41Z"
cadence: instant
clean_streak: 0
graded_by: risk-nexus
@ -308,3 +308,4 @@ The finding stays open. What remains is a retention period per category, which
waits on the co-residency horizon, and the trigger list for buying an external
determination. The record is reviewed every 90 days with this finding, or
immediately on any trigger.
- **2026-08-20** — not clean: The determination now exists: RISK-REG-0001 states the grounds per category and names duration as the weak point. Cadence instant → instant; checked again immediately.

View file

@ -25,10 +25,10 @@ disclosure: embargoed
embargo_condition: "the deny set covers every high-risk lane with a KV path, verified against live OpenBao"
embargo_since: "2026-08-20"
escalation: none
last_checked: "2026-08-20T05:40:00Z"
next_check: "2026-08-20T05:40:00Z"
cadence: instant
clean_streak: 0
last_checked: "2026-08-20T10:02:42Z"
next_check: "2026-08-20T11:02:42Z"
cadence: 1h
clean_streak: 1
graded_by: risk-nexus
ruling: RISK-RULING-2026-08-20
---
@ -177,3 +177,4 @@ otherwise.
about this has been checked twice yet. Open at the next check: does the
deployed policy match the file; do any agent tokens carry both policies; has
`railiance-platform` taken the catalog-generated deny set.
- **2026-08-20** — clean check: checked against the inbox and the owner's record; nothing moved. Cadence instant → 1h (1 clean in a row); next check 2026-08-20 11:02Z.

View file

@ -28,7 +28,7 @@ def main(argv: list[str]) -> int:
if len(argv) < 2:
fail(__doc__)
fid, outcome, rest = argv[0], argv[1], argv[2:]
matches = [f for f in lib.findings() if f["id"] == fid]
matches = [f for f in lib.findings() + lib.regulatory() if f.get("id") == fid]
if not matches:
fail(f"no finding with id {fid}")
f = matches[0]