The inbox round: two grades corrected, one note promoted
Read the repo inbox after grading, which is the wrong order and is now recorded as such. flex-auth had answered the NetworkPolicy question on 2026-08-18 (narrow ingress, not default-deny — L3 becomes L2, critical becomes high) and reported RISK-F-0001 fixed at 12:35 today with live 401 probes. F-0001 closes fixed and public; its escalation is withdrawn before it was ever sent. RISK-F-0002's ordering constraint lifts with it and its trigger-6 escalation is withdrawn. audit-core had routed the erasure-versus-audit legal question here on 2026-08-18 asking for an owner. RISK-N-0002 was wrong to call it a note: the remedy is not retrofittable, so the decision can only be taken early. Promoted to RISK-F-0008, owned by this repo as regulatory intake, escalated on trigger 2. Accepted rapp-postgres's record format and ops-warden's typed-act escalation vocabulary. Reading the inbox is now question zero of every review. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
37906c3a22
commit
7d6ded5743
10 changed files with 431 additions and 67 deletions
12
REGISTER.md
12
REGISTER.md
|
|
@ -2,19 +2,20 @@
|
||||||
|
|
||||||
Generated by `tools/register_index.py` from `findings/`. Do not edit by hand. Last built 2026-08-19.
|
Generated by `tools/register_index.py` from `findings/`. Do not edit by hand. Last built 2026-08-19.
|
||||||
|
|
||||||
7 open of 7 findings; 2 notes below the floor.
|
7 open of 8 findings; 2 notes below the floor.
|
||||||
|
|
||||||
## Findings
|
## Findings
|
||||||
|
|
||||||
| ID | Finding | System | Severity | Disclosure | Escalation | Fix owner | Status | Review by |
|
| ID | Finding | System | Severity | Disclosure | Escalation | Fix owner | Status | Review by |
|
||||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||||
|
| [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, pending-operator) | risk-nexus | open | 2026-11-17 |
|
||||||
| [RISK-F-0007](findings/RISK-F-0007-unverified-tenant-boundary.md) | No consumer's tenant boundary is verified anywhere | estate | **high** | embargoed | **required** (t4, pending-operator) | unset | open | 2026-09-18 |
|
| [RISK-F-0007](findings/RISK-F-0007-unverified-tenant-boundary.md) | No consumer's tenant boundary is verified anywhere | estate | **high** | embargoed | **required** (t4, pending-operator) | unset | open | 2026-09-18 |
|
||||||
| [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 | **required** (t3, pending-operator) | railiance-platform | open | 2026-09-18 |
|
| [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 | **required** (t3, pending-operator) | railiance-platform | open | 2026-09-18 |
|
||||||
| [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 | 2026-11-17 |
|
| [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 | 2026-11-17 |
|
||||||
| [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 | 2026-09-18 |
|
| [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 | 2026-09-18 |
|
||||||
| [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 | **high** | embargoed | none | ops-warden | open | 2026-09-18 |
|
| [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 | **high** | embargoed | none | ops-warden | open | 2026-09-18 |
|
||||||
| [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 | **required** (t6, pending-operator) | ops-warden | open | 2026-11-17 |
|
| [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 | 2026-11-17 |
|
||||||
| [RISK-F-0001](findings/RISK-F-0001-flex-auth-unauthenticated-check.md) | flex-auth /v1/check authenticates no caller | flex-auth | **critical** | embargoed | **required** (t1, pending-operator) | flex-auth | open | 2026-08-26 |
|
| [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 | 2026-08-26 |
|
||||||
|
|
||||||
## Constraints
|
## Constraints
|
||||||
|
|
||||||
|
|
@ -22,7 +23,7 @@ Hazards created by acting in the wrong order. Each binds another finding's remed
|
||||||
|
|
||||||
| From | Binds | Severity | Constraint |
|
| From | Binds | Severity | Constraint |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| RISK-F-0002 | RISK-F-0001 | **high** | policy.enabled must not be turned on while flex-auth /v1/check answers unauthenticated callers — the gate would sign a false attestation |
|
| RISK-F-0002 | RISK-F-0001 | **lifted** | LIFTED 2026-08-19 — flex-auth /v1/check now authenticates callers (RISK-F-0001 fixed). Enabling policy.enabled is now an availability question for ops-warden, no longer an attestation hazard. |
|
||||||
|
|
||||||
## Embargoes
|
## Embargoes
|
||||||
|
|
||||||
|
|
@ -36,7 +37,6 @@ Held from publication with a stated condition. A hold with no moving condition i
|
||||||
| RISK-F-0004 | 2026-08-19 | the read path filters by tenant in code | 2026-09-18 |
|
| RISK-F-0004 | 2026-08-19 | the read path filters by tenant in code | 2026-09-18 |
|
||||||
| RISK-F-0003 | 2026-08-19 | the five exec_capable lanes graded under WARDEN-WP-0032-T05 | 2026-09-18 |
|
| RISK-F-0003 | 2026-08-19 | the five exec_capable lanes graded under WARDEN-WP-0032-T05 | 2026-09-18 |
|
||||||
| RISK-F-0002 | 2026-08-19 | FLEX-WP-0015-T02 shipped and ops-warden policy.enabled true in production | 2026-11-17 |
|
| RISK-F-0002 | 2026-08-19 | FLEX-WP-0015-T02 shipped and ops-warden policy.enabled true in production | 2026-11-17 |
|
||||||
| RISK-F-0001 | 2026-08-19 | FLEX-WP-0015-T02 ships to production | 2026-08-26 |
|
|
||||||
|
|
||||||
## Notes (below the floor)
|
## Notes (below the floor)
|
||||||
|
|
||||||
|
|
@ -44,7 +44,7 @@ Seen, deliberately not findings. Not graded, not reviewed, not published.
|
||||||
|
|
||||||
| ID | Note | Why below the floor |
|
| ID | Note | Why below the floor |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| [RISK-N-0002](notes/RISK-N-0002-erasure-versus-audit.md) | Erasure duty and audit immutability have not been reconciled | no obligation exists yet — the estate holds no real person's data, so there is nothing to erase and no counterparty to owe it to |
|
| [RISK-N-0003](notes/RISK-N-0003-defects-found-by-reading-not-monitoring.md) | Every defect in this register was found by reading, none by monitoring | no owner and no defect — it is an argument about where to invest detection, and the register cannot route an argument |
|
||||||
| [RISK-N-0001](notes/RISK-N-0001-noisy-neighbour-uncharacterised.md) | Noisy-neighbour behaviour is uncharacterised | no decision changes today — no tenant shares a saturating workload, and what is missing is measurement work, not a defect to route |
|
| [RISK-N-0001](notes/RISK-N-0001-noisy-neighbour-uncharacterised.md) | Noisy-neighbour behaviour is uncharacterised | no decision changes today — no tenant shares a saturating workload, and what is missing is measurement work, not a defect to route |
|
||||||
|
|
||||||
## How to read this
|
## How to read this
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,11 @@
|
||||||
| Kind | ID | Status | Lane | Source |
|
| Kind | ID | Status | Lane | Source |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| workplan | RISK-WP-0001 | active | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
| workplan | RISK-WP-0001 | active | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
||||||
| task | RISK-WP-0001-T01 | todo | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
| task | RISK-WP-0001-T01 | done | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
||||||
| task | RISK-WP-0001-T02 | todo | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
| task | RISK-WP-0001-T02 | done | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
||||||
| task | RISK-WP-0001-T03 | todo | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
| task | RISK-WP-0001-T03 | progress | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
||||||
| task | RISK-WP-0001-T04 | todo | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
| task | RISK-WP-0001-T04 | done | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
||||||
| task | RISK-WP-0001-T05 | todo | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
| task | RISK-WP-0001-T05 | done | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
||||||
| task | RISK-WP-0001-T06 | todo | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
| task | RISK-WP-0001-T06 | done | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
||||||
| task | RISK-WP-0001-T07 | todo | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
| task | RISK-WP-0001-T07 | done | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
||||||
| task | RISK-WP-0001-T08 | todo | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
| task | RISK-WP-0001-T08 | done | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,22 @@ said out loud in whatever session is running — containing exactly four things:
|
||||||
3. what happens if no answer comes;
|
3. what happens if no answer comes;
|
||||||
4. by when.
|
4. by when.
|
||||||
|
|
||||||
|
Point 2 is a **typed act**, not a topic: `approve` (spend, a target, a plan),
|
||||||
|
`rule` (a question only they can settle), `assign` (name an owner), or
|
||||||
|
`accept` (record that the estate knowingly carries it, and for how long).
|
||||||
|
Naming the act is what stops an escalation from becoming a notification —
|
||||||
|
`INTENT.md`'s candidate triggers are conditions, and a condition without an act
|
||||||
|
tells the operator something is wrong without telling them what they are being
|
||||||
|
asked to do.
|
||||||
|
|
||||||
|
The typed-act shape is `ops-warden`'s, offered on 2026-08-18 from their
|
||||||
|
`warden plan` classifier (`WARDEN-WP-0029`), which returns `autonomous |
|
||||||
|
founder_required | unroutable` plus the reasons that produced the verdict and
|
||||||
|
the act to perform. Two of its properties are adopted here: escalation is
|
||||||
|
decided by properties of the thing rather than the assessor's mood, and every
|
||||||
|
verdict carries its reasons so a misfire is visible afterwards. The vocabulary
|
||||||
|
is theirs; the design is deliberately not re-invented.
|
||||||
|
|
||||||
It is **not** a copy of the finding, not a status report, and not a request for
|
It is **not** a copy of the finding, not a status report, and not a request for
|
||||||
the operator to do the work. If the operator's answer would not change
|
the operator to do the work. If the operator's answer would not change
|
||||||
anything, it was not an escalation.
|
anything, it was not an escalation.
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,15 @@ to let the date slide.
|
||||||
|
|
||||||
## What a review is
|
## What a review is
|
||||||
|
|
||||||
Four questions, answered in writing on the finding. It takes minutes; it is not
|
Five questions, answered in writing on the finding. It takes minutes; it is not
|
||||||
an investigation.
|
an investigation.
|
||||||
|
|
||||||
|
0. **Has the inbox said anything?** Read the messages addressed to this repo
|
||||||
|
before anything else. This is question zero because on 2026-08-19 the
|
||||||
|
register graded `RISK-F-0001` `critical` while two messages sat unread in
|
||||||
|
its own inbox — one narrowing the exposure, one reporting the fix. Both
|
||||||
|
changed the grade. A register that does not read its own inbox is guessing
|
||||||
|
with a straight face.
|
||||||
1. **Is the grade still right?** Re-read impact and likelihood against what has
|
1. **Is the grade still right?** Re-read impact and likelihood against what has
|
||||||
changed. New facts move the grade in both directions.
|
changed. New facts move the grade in both directions.
|
||||||
2. **Is the blocker still true?** This is the one `RISK-F-0002` bought with
|
2. **Is the blocker still true?** This is the one `RISK-F-0002` bought with
|
||||||
|
|
|
||||||
120
docs/rulings/2026-08-19-third-grading.md
Normal file
120
docs/rulings/2026-08-19-third-grading.md
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
---
|
||||||
|
id: RISK-RULING-2026-08-19-C
|
||||||
|
type: ruling
|
||||||
|
title: "The inbox round: two grades corrected, one note promoted"
|
||||||
|
status: recorded
|
||||||
|
owner: risk-nexus
|
||||||
|
date: "2026-08-19"
|
||||||
|
workplan: RISK-WP-0001-T06
|
||||||
|
---
|
||||||
|
|
||||||
|
# The inbox round — 2026-08-19
|
||||||
|
|
||||||
|
The register graded seven findings today and then read its inbox. Six messages
|
||||||
|
were waiting, four of them unread since 2026-08-17. Three gradings changed.
|
||||||
|
|
||||||
|
This ruling records the corrections and the process defect that caused them,
|
||||||
|
in that order, because the corrections matter more and the defect is this
|
||||||
|
repo's own.
|
||||||
|
|
||||||
|
## RISK-F-0001 — corrected `critical` → `high`, and closed `fixed`
|
||||||
|
|
||||||
|
Two messages from `flex-auth`, both already in the inbox at grading time.
|
||||||
|
|
||||||
|
**2026-08-18, the NetworkPolicy answer.** The exposure question the finding
|
||||||
|
left open — and which this register wrote up as "the first question at review"
|
||||||
|
— had already been answered. Both production Deployments ship a NetworkPolicy
|
||||||
|
narrower than default-deny: one `namespaceSelector` plus one `podSelector` on
|
||||||
|
port 8080, egress empty, in force since before the period the `A0` describes.
|
||||||
|
The reachable set was the single paired workload, not the cluster. `L3` → `L2`,
|
||||||
|
`critical` → `high`.
|
||||||
|
|
||||||
|
`flex-auth` also volunteered a correction to their own earlier phrasing to
|
||||||
|
`ops-warden`, and asked that three caveats be recorded rather than taken from
|
||||||
|
them: label selectors are position and not identity, the policy cannot bind the
|
||||||
|
asserted `resource.system`, and they could not verify the live cluster because
|
||||||
|
`kubectl` returned `Unauthorized`. A reporter who says "I can tell you what is
|
||||||
|
specified, not what is admitted" is doing this register's job for it.
|
||||||
|
|
||||||
|
**2026-08-19 12:35, the fix.** Both Deployments enforce ADR-0004 TokenReview;
|
||||||
|
live unbound-request probes return 401 rather than a decision;
|
||||||
|
`tenancy.current.A` is 2; `FLEX-WP-0015` is finished. Closed `fixed` on a probe
|
||||||
|
against the running system, which is the standard `docs/method/review.md`
|
||||||
|
requires. Disclosure flips to `public`; handover to `policy-nexus` is
|
||||||
|
outstanding.
|
||||||
|
|
||||||
|
The trigger-1 escalation is **withdrawn without being sent**, roughly four
|
||||||
|
hours after it was raised.
|
||||||
|
|
||||||
|
## RISK-F-0002 — constraint lifted, escalation withdrawn
|
||||||
|
|
||||||
|
The trigger-6 escalation existed to make the operator hold an ordering: do not
|
||||||
|
enable `policy.enabled` while the oracle is forgeable. The oracle stopped being
|
||||||
|
forgeable the same day. Enabling the gate is now `ops-warden`'s availability
|
||||||
|
question and no longer an attestation hazard.
|
||||||
|
|
||||||
|
`ops-warden` judged this did not need the operator and, in the outcome, they
|
||||||
|
were right. The register's disagreement was never about the hazard; it was
|
||||||
|
about whether "written down in both repos" keeps a thing held. It did not — the
|
||||||
|
window closed because `flex-auth` shipped, not because anyone re-read the note.
|
||||||
|
Both positions survive intact and the escalation is withdrawn.
|
||||||
|
|
||||||
|
The finding stays `open` at `medium`. The gate is still off.
|
||||||
|
|
||||||
|
## RISK-N-0002 promoted to RISK-F-0008 — erasure versus audit
|
||||||
|
|
||||||
|
Ruled a note this morning on the reasoning that no obligation exists yet. That
|
||||||
|
was decided without reading `audit-core`'s message of 2026-08-18, which routes
|
||||||
|
the question here explicitly, by both available routes, and asks for an owner
|
||||||
|
rather than an opinion.
|
||||||
|
|
||||||
|
The note failed the second floor test. Recording it *does* change a decision:
|
||||||
|
if the exemption does not hold, the remedy is encrypt-then-hash at accept time,
|
||||||
|
which is not retrofittable onto events already accepted. A decision that can
|
||||||
|
only be taken early is exactly the kind a register exists to surface early.
|
||||||
|
|
||||||
|
`RISK-F-0008` is the first finding this repo owns itself, which follows from
|
||||||
|
`INTENT.md` moving regulatory intake here on 2026-08-17. It escalates on
|
||||||
|
trigger 2. What this repo owns is the record — what the source says and what is
|
||||||
|
therefore established. Not the legal advice, and not `audit-core`'s redesign.
|
||||||
|
|
||||||
|
## Two things accepted from reporters
|
||||||
|
|
||||||
|
**The record format** — `rapp-postgres` asked this register to accept or reject
|
||||||
|
the shape `RISK-F-0001` arrived in. **Accepted**, and extended rather than
|
||||||
|
replaced: the reporter's fields are unchanged, this repo's grading fields are
|
||||||
|
added below them, and the split is now written down in `findings/README.md`.
|
||||||
|
Their instinct to keep it minimal until a second finding existed was right; it
|
||||||
|
survived five more.
|
||||||
|
|
||||||
|
**The escalation vocabulary** — `ops-warden` offered the design of their
|
||||||
|
`warden plan` classifier: a typed act plus the reasons that produced the
|
||||||
|
verdict. Adopted into `docs/method/escalation.md`. Their point that a condition
|
||||||
|
without an act tells the operator something is wrong without telling them what
|
||||||
|
they are being asked to do is the gap the draft had.
|
||||||
|
|
||||||
|
`RISK-N-0003` records the remaining open observation from that round —
|
||||||
|
everything found by reading, nothing by monitoring — as a note, because no repo
|
||||||
|
owns it and there is no defect to route.
|
||||||
|
|
||||||
|
## The process defect, recorded plainly
|
||||||
|
|
||||||
|
The NetworkPolicy answer arrived 2026-08-18. The fix notice arrived 2026-08-19
|
||||||
|
at 12:35. This register's first grading ran at 21:14 the same day and used
|
||||||
|
neither. It graded a fixed defect as live, at a severity one band too high, on
|
||||||
|
an exposure question it wrote up as unanswered while the answer sat unread.
|
||||||
|
|
||||||
|
Nothing about the method caused this and no instrument was wrong. The register
|
||||||
|
simply did not look. That is the failure `INTENT.md` names — a finding that
|
||||||
|
disappears into whichever document happened to be open — arriving as an
|
||||||
|
*answer* rather than a finding.
|
||||||
|
|
||||||
|
Two changes, both live:
|
||||||
|
|
||||||
|
- Reading the inbox is **question zero** of every review and step zero of every
|
||||||
|
grading (`docs/method/review.md`).
|
||||||
|
- `make check` reports escalations awaiting the operator, so a batch that has
|
||||||
|
gone stale is visible before it is sent.
|
||||||
|
|
||||||
|
The register was lucky today: the correction and the fix arrived within hours
|
||||||
|
of the mistake, so nothing was acted on. Luck is not a control.
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
id: RISK-F-0001
|
id: RISK-F-0001
|
||||||
type: finding
|
type: finding
|
||||||
title: "flex-auth /v1/check authenticates no caller"
|
title: "flex-auth /v1/check authenticates no caller"
|
||||||
status: open
|
status: fixed
|
||||||
reported_by: flex-auth
|
reported_by: flex-auth
|
||||||
reported_via: rapp-postgres
|
reported_via: rapp-postgres
|
||||||
routed_by: rapp-postgres
|
routed_by: rapp-postgres
|
||||||
|
|
@ -10,21 +10,24 @@ date_reported: "2026-08-17"
|
||||||
system: flex-auth
|
system: flex-auth
|
||||||
environment: production
|
environment: production
|
||||||
fix_owner: flex-auth
|
fix_owner: flex-auth
|
||||||
fix_tracking: FLEX-WP-0015-T02
|
fix_tracking: FLEX-WP-0015 (finished 2026-08-19)
|
||||||
# Graded by risk-nexus 2026-08-19 — docs/rulings/2026-08-19-first-grading.md
|
# Graded by risk-nexus 2026-08-19 — docs/rulings/2026-08-19-first-grading.md
|
||||||
severity: critical
|
severity: high
|
||||||
severity_at_production: critical
|
severity_at_production: high
|
||||||
|
severity_superseded: "critical (2026-08-19, graded on L3 before reading the inbox)"
|
||||||
impact: I4
|
impact: I4
|
||||||
likelihood: L3
|
likelihood: L2
|
||||||
fidelity_modifier: false
|
fidelity_modifier: false
|
||||||
production_rescore: false
|
production_rescore: false
|
||||||
disclosure: embargoed
|
disclosure: public
|
||||||
embargo_condition: "FLEX-WP-0015-T02 ships to production"
|
publication: pending-handover
|
||||||
|
embargo_condition: "met 2026-08-19 — FLEX-WP-0015 finished, live probes return 401"
|
||||||
embargo_since: "2026-08-19"
|
embargo_since: "2026-08-19"
|
||||||
embargo_review: "2026-08-26"
|
embargo_review: "2026-08-19"
|
||||||
escalation: required
|
escalation: withdrawn
|
||||||
escalation_trigger: 1
|
escalation_trigger: 1
|
||||||
escalation_status: pending-operator
|
escalation_status: withdrawn-before-sending
|
||||||
|
date_fixed: "2026-08-19"
|
||||||
last_reviewed: "2026-08-19"
|
last_reviewed: "2026-08-19"
|
||||||
review_by: "2026-08-26"
|
review_by: "2026-08-26"
|
||||||
graded_by: risk-nexus
|
graded_by: risk-nexus
|
||||||
|
|
@ -153,3 +156,59 @@ Reasoning: `docs/rulings/2026-08-19-first-grading.md`.
|
||||||
- **2026-08-19** — graded. Next review 2026-08-26 (`critical` → 7 days).
|
- **2026-08-19** — graded. Next review 2026-08-26 (`critical` → 7 days).
|
||||||
Open at review: the NetworkPolicy question; whether `FLEX-WP-0015-T02` has
|
Open at review: the NetworkPolicy question; whether `FLEX-WP-0015-T02` has
|
||||||
moved; whether the embargo still holds.
|
moved; whether the embargo still holds.
|
||||||
|
|
||||||
|
## Re-grade and close — 2026-08-19 (same day)
|
||||||
|
|
||||||
|
**Corrected from `critical` to `high`, and closed as `fixed`.** Both changes
|
||||||
|
come from messages that were already in this repo's inbox when the first grade
|
||||||
|
was set. The register graded before it read them.
|
||||||
|
|
||||||
|
**The exposure was narrower than graded.** `flex-auth` answered the
|
||||||
|
NetworkPolicy question on 2026-08-18: both production Deployments ship a
|
||||||
|
NetworkPolicy in the same manifest, and it is *narrower* than default-deny —
|
||||||
|
ingress restricted to one `namespaceSelector` plus one `podSelector` on port
|
||||||
|
8080, egress empty. In force since before the period the `A0` describes. So the
|
||||||
|
reachable set was never "any pod in the cluster"; it was the single paired
|
||||||
|
workload per Deployment.
|
||||||
|
|
||||||
|
That is `L2`, not `L3`. Impact stays `I4` — what a forged allow reaches does
|
||||||
|
not change — so the grade is `high`. `flex-auth` also corrected their own
|
||||||
|
earlier phrasing to `ops-warden` in the same message, unprompted, and that
|
||||||
|
correction is why the fact reached this register at all.
|
||||||
|
|
||||||
|
Three caveats `flex-auth` asked to be recorded rather than taken from them, and
|
||||||
|
they are why the grade did not fall further: label selectors are network
|
||||||
|
position, not identity; the policy could not bind the asserted `resource.system`,
|
||||||
|
which is what made cross-system impersonation possible; and enforcement depends
|
||||||
|
on a CNI they could not verify from a cluster where `kubectl` returned
|
||||||
|
`Unauthorized`. They said so rather than letting a manifest stand in for a probe.
|
||||||
|
|
||||||
|
**It is fixed.** On 2026-08-19 `flex-auth` reported both production Deployments
|
||||||
|
enforcing ADR-0004 TokenReview, with live unbound-request probes returning 401
|
||||||
|
rather than a decision, on both the `user-engine` and `tenant-engine` pins.
|
||||||
|
`FLEX-WP-0015` is finished and `tenancy.current.A` is 2. That is a probe
|
||||||
|
against the running system, which is the standard `docs/method/review.md` sets
|
||||||
|
for closing: something concrete read, not something been told.
|
||||||
|
|
||||||
|
**Disclosure flips to `public`.** The embargo condition was "FLEX-WP-0015-T02
|
||||||
|
ships to production" and it is met. Handover to `policy-nexus` is the next
|
||||||
|
step and is not done yet.
|
||||||
|
|
||||||
|
**The escalation is withdrawn without being sent.** It was `pending-operator`
|
||||||
|
for roughly four hours, and the fix landed first. Withdrawing it is correct —
|
||||||
|
escalating a fixed defect makes the operator the queue for history — but the
|
||||||
|
register does not get to be pleased about it. The escalation would have been
|
||||||
|
sent on facts that were already stale, and only luck put the fix on the same
|
||||||
|
day.
|
||||||
|
|
||||||
|
**What this cost, recorded because it is the register's own defect.** The
|
||||||
|
NetworkPolicy answer arrived 2026-08-18. The fix notice arrived 2026-08-19
|
||||||
|
at 12:35. The first grading ran at 21:14 the same day, on neither. Reading the
|
||||||
|
inbox is now step 0 of grading and question 0 of every review — see
|
||||||
|
`docs/method/review.md` — and this finding is the case that bought it.
|
||||||
|
|
||||||
|
## Reviews
|
||||||
|
|
||||||
|
- **2026-08-19** — re-graded `high`, closed `fixed`, disclosure `public`,
|
||||||
|
escalation withdrawn. Remaining: handover to `policy-nexus`; the CNI
|
||||||
|
enforcement question is `flex-auth`'s and no longer this finding's.
|
||||||
|
|
|
||||||
|
|
@ -20,15 +20,15 @@ likelihood: L2
|
||||||
fidelity_modifier: false
|
fidelity_modifier: false
|
||||||
production_rescore: false
|
production_rescore: false
|
||||||
constraint_on: RISK-F-0001
|
constraint_on: RISK-F-0001
|
||||||
constraint_severity: high
|
constraint_severity: lifted
|
||||||
constraint: "policy.enabled must not be turned on while flex-auth /v1/check answers unauthenticated callers — the gate would sign a false attestation"
|
constraint: "LIFTED 2026-08-19 — flex-auth /v1/check now authenticates callers (RISK-F-0001 fixed). Enabling policy.enabled is now an availability question for ops-warden, no longer an attestation hazard."
|
||||||
disclosure: embargoed
|
disclosure: embargoed
|
||||||
embargo_condition: "FLEX-WP-0015-T02 shipped and ops-warden policy.enabled true in production"
|
embargo_condition: "FLEX-WP-0015-T02 shipped and ops-warden policy.enabled true in production"
|
||||||
embargo_since: "2026-08-19"
|
embargo_since: "2026-08-19"
|
||||||
embargo_review: "2026-11-17"
|
embargo_review: "2026-11-17"
|
||||||
escalation: required
|
escalation: withdrawn
|
||||||
escalation_trigger: 6
|
escalation_trigger: 6
|
||||||
escalation_status: pending-operator
|
escalation_status: withdrawn-hazard-window-closed
|
||||||
last_reviewed: "2026-08-19"
|
last_reviewed: "2026-08-19"
|
||||||
review_by: "2026-11-17"
|
review_by: "2026-11-17"
|
||||||
graded_by: risk-nexus
|
graded_by: risk-nexus
|
||||||
|
|
@ -193,3 +193,42 @@ Reasoning: `docs/rulings/2026-08-19-first-grading.md`.
|
||||||
- **2026-08-19** — graded. Next review 2026-11-17 (`medium` → 90 days).
|
- **2026-08-19** — graded. Next review 2026-11-17 (`medium` → 90 days).
|
||||||
Open at review: has `FLEX-WP-0007` or `WARDEN-WP-0007` moved; is the stated
|
Open at review: has `FLEX-WP-0007` or `WARDEN-WP-0007` moved; is the stated
|
||||||
blocker still true; does the ordering constraint still hold.
|
blocker still true; does the ordering constraint still hold.
|
||||||
|
|
||||||
|
## Constraint lifted, escalation withdrawn — 2026-08-19 (same day)
|
||||||
|
|
||||||
|
`RISK-F-0001` was fixed hours after this register graded it: both `flex-auth`
|
||||||
|
production Deployments now enforce ADR-0004 TokenReview, with live
|
||||||
|
unbound-request probes returning 401.
|
||||||
|
|
||||||
|
**The attestation hazard is gone.** The constraint recorded this morning —
|
||||||
|
that enabling `policy.enabled` against a forgeable oracle would write a
|
||||||
|
`policy_decision_id` asserting an authorization nobody made — required
|
||||||
|
`/v1/check` to answer unauthenticated callers. It no longer does. Enabling the
|
||||||
|
gate is now an ordinary availability question for `ops-warden`: does the
|
||||||
|
calling side present its ServiceAccount token, and does signing survive a
|
||||||
|
`fail_closed: true`. That is `ops-warden`'s sequencing to run, not a risk
|
||||||
|
this register holds.
|
||||||
|
|
||||||
|
**The trigger-6 escalation is withdrawn.** The hazard window closed before the
|
||||||
|
operator was asked to hold the ordering. `ops-warden`'s own judgement that this
|
||||||
|
did not need the operator was, in the end, right — and the register still holds
|
||||||
|
that it was right for the wrong reason. The disagreement was never about the
|
||||||
|
severity of the hazard; it was about whether "written down in both repos"
|
||||||
|
keeps a thing held. It did not: the window closed by `flex-auth` shipping, not
|
||||||
|
by anyone re-reading the note.
|
||||||
|
|
||||||
|
**The finding stays open, unchanged at `medium`.** The gate is still off, and
|
||||||
|
`warden sign` still proceeds with no per-request judgement. Nothing about this
|
||||||
|
morning's news changes that.
|
||||||
|
|
||||||
|
**The general point earns another instance.** This finding argued that a
|
||||||
|
blocker is a claim about the world at a date, and that its own blocker had been
|
||||||
|
invalidated in a day with nothing re-checking it. That has now happened twice
|
||||||
|
to the same finding, in the same week, in the same direction. The second time,
|
||||||
|
the thing that had gone stale was this register's own grading, four hours old.
|
||||||
|
|
||||||
|
## Reviews
|
||||||
|
|
||||||
|
- **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.
|
||||||
|
|
|
||||||
128
findings/RISK-F-0008-audit-retention-legal-basis-assumed.md
Normal file
128
findings/RISK-F-0008-audit-retention-legal-basis-assumed.md
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
---
|
||||||
|
id: RISK-F-0008
|
||||||
|
type: finding
|
||||||
|
title: "The legal basis for retaining audit facts against an erasure request has been assumed, never established"
|
||||||
|
status: open
|
||||||
|
reported_by: audit-core
|
||||||
|
reported_via: audit-core
|
||||||
|
routed_by: audit-core
|
||||||
|
date_reported: "2026-08-18"
|
||||||
|
date_filed: "2026-08-19"
|
||||||
|
system: audit-core
|
||||||
|
environment: production
|
||||||
|
fix_owner: risk-nexus
|
||||||
|
fix_tracking: unset
|
||||||
|
related: [RISK-F-0005]
|
||||||
|
supersedes: RISK-N-0002
|
||||||
|
# Graded by risk-nexus 2026-08-19 — docs/rulings/2026-08-19-third-grading.md
|
||||||
|
severity: medium
|
||||||
|
severity_at_production: high
|
||||||
|
impact: I3
|
||||||
|
likelihood: L2
|
||||||
|
fidelity_modifier: false
|
||||||
|
production_rescore: true
|
||||||
|
disclosure: public
|
||||||
|
publication: pending-handover
|
||||||
|
escalation: required
|
||||||
|
escalation_trigger: 2
|
||||||
|
escalation_status: pending-operator
|
||||||
|
last_reviewed: "2026-08-19"
|
||||||
|
review_by: "2026-11-17"
|
||||||
|
graded_by: risk-nexus
|
||||||
|
ruling: RISK-RULING-2026-08-19-C
|
||||||
|
---
|
||||||
|
|
||||||
|
# RISK-F-0008 — the exemption nobody has established
|
||||||
|
|
||||||
|
## What is true
|
||||||
|
|
||||||
|
`audit-core` holds audit evidence across tenants, targets `R2` on the Tenancy
|
||||||
|
Posture retention ladder, and has declared `R4` — verified erasure —
|
||||||
|
unreachable by design. The technical reasoning is sound and documented
|
||||||
|
(`audit-core/docs/erasure-and-audit.md`, framework Decision 4.5.3):
|
||||||
|
crypto-shredding would destroy the evidence the service exists to hold, and
|
||||||
|
their integrity chain commits to a SHA-256 of the cleartext record, which
|
||||||
|
survives key destruction as a confirmation oracle against low-entropy audit
|
||||||
|
rows. Destroying a key does not erase content a surviving commitment can still
|
||||||
|
be tested against.
|
||||||
|
|
||||||
|
The consequence is that if an Article 17 request arrives naming a data subject
|
||||||
|
in the audit trail, `audit-core` has no mechanism. The answer would rest on
|
||||||
|
audit evidence being exempt — legal obligation, or legitimate interest in fraud
|
||||||
|
and security investigation.
|
||||||
|
|
||||||
|
**Those grounds are ordinary. Nobody in this estate has actually reached them.**
|
||||||
|
`audit-core` routed the question here on 2026-08-18 rather than absorbing it,
|
||||||
|
saying plainly that they are not competent to answer it and that they have been
|
||||||
|
assuming it. §19.11 of the framework says the same in its own words: the legal
|
||||||
|
basis for retaining audit facts remains a risk/legal question outside the
|
||||||
|
framework.
|
||||||
|
|
||||||
|
## Why this repo owns it
|
||||||
|
|
||||||
|
This is the first finding where `fix_owner` is `risk-nexus`.
|
||||||
|
|
||||||
|
`INTENT.md` moved regulatory intake here from `policy-nexus` on 2026-08-17,
|
||||||
|
precisely because deciding what a rule demands of us is a judgement about risk
|
||||||
|
rather than an act of publishing. `audit-core` routed it by both available
|
||||||
|
routes and asked for an owner rather than an opinion. Refusing it would be this
|
||||||
|
repo declining its own remit.
|
||||||
|
|
||||||
|
What this repo owns is the **record**: what the source says, when, and what
|
||||||
|
therefore is or is not established. It does not own legal advice — `INTENT.md`
|
||||||
|
is explicit — and it does not own the redesign. If the basis does not hold,
|
||||||
|
`audit-core` owns encrypt-then-hash at accept time, and that is not
|
||||||
|
retrofittable onto events already accepted.
|
||||||
|
|
||||||
|
## The three questions, as asked
|
||||||
|
|
||||||
|
1. On what basis does the estate retain personal data inside audit records
|
||||||
|
against an erasure request, and does that basis hold for the categories
|
||||||
|
`audit-core` stores?
|
||||||
|
2. Does it hold across the full 30-day recoverable window and beyond, given
|
||||||
|
that at `P1` the real erasure horizon is the maximum across every
|
||||||
|
co-resident on `platform-pg`, not the value `audit-core` declares?
|
||||||
|
3. If it does not hold, `R4` is urgent rather than theoretical, and the answer
|
||||||
|
is a substantial redesign with a long lead time.
|
||||||
|
|
||||||
|
## Register ruling — 2026-08-19
|
||||||
|
|
||||||
|
`medium` today (`I3` × `L2`), `high` at production, `public`, **escalated on
|
||||||
|
trigger 2**.
|
||||||
|
|
||||||
|
`I3`: an unmet retention obligation in the audit store crosses from a technical
|
||||||
|
question to an obligation with an outside counterparty, and the remediation is
|
||||||
|
a non-retrofittable redesign rather than a patch. `L2`: no request has arrived
|
||||||
|
and the estate holds no real data subject's records yet, but the trigger is
|
||||||
|
somebody else's to pull and needs no foothold here.
|
||||||
|
|
||||||
|
`production_rescore: true`. The likelihood of an Article 17 request is a
|
||||||
|
function of having real users; that is exactly what production means.
|
||||||
|
|
||||||
|
**Escalation, trigger 2** — "creates or reveals an obligation with an outside
|
||||||
|
counterparty". It reveals one. The estate cannot decide unilaterally that this
|
||||||
|
obligation is small, and the operator is the only party who can commission an
|
||||||
|
answer that is more than an assumption. The ask is narrow: authorise someone to
|
||||||
|
establish the basis, or record that the estate knowingly runs on the assumption
|
||||||
|
and for how long.
|
||||||
|
|
||||||
|
**Disclosure `public`.** Nothing here shortens a path to a defect: it is a
|
||||||
|
question about a legal basis, published as a question. `audit-core`'s technical
|
||||||
|
reasoning is already written down and worth reading.
|
||||||
|
|
||||||
|
## How it got here
|
||||||
|
|
||||||
|
Ruled a note on 2026-08-19 (`RISK-N-0002`) on the reasoning that no obligation
|
||||||
|
exists yet. That ruling was made without reading `audit-core`'s message, which
|
||||||
|
had been in this repo's inbox since 2026-08-18 and asks specifically for an
|
||||||
|
owner. The note was wrong on the second floor test: recording this *does*
|
||||||
|
change a decision, because the redesign it might force cannot be retrofitted
|
||||||
|
and therefore has to be decided early or not at all.
|
||||||
|
|
||||||
|
`RISK-N-0002` is superseded by this record.
|
||||||
|
|
||||||
|
## Reviews
|
||||||
|
|
||||||
|
- **2026-08-19** — promoted from note, graded, escalated. Open at review:
|
||||||
|
has the basis been established or the assumption recorded; has anything
|
||||||
|
changed about what categories `audit-core` stores.
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
---
|
|
||||||
id: RISK-N-0002
|
|
||||||
type: note
|
|
||||||
title: "Erasure duty and audit immutability have not been reconciled"
|
|
||||||
date: "2026-08-19"
|
|
||||||
source: "NetKingdom Tenancy Posture (draft), open question"
|
|
||||||
floor_reason: "no obligation exists yet — the estate holds no real person's data, so there is nothing to erase and no counterparty to owe it to"
|
|
||||||
revisit: "on the day the estate first holds a real person's data; belongs to the regulatory-intake workplan, not this one"
|
|
||||||
ruling: RISK-RULING-2026-08-19-B
|
|
||||||
---
|
|
||||||
|
|
||||||
# RISK-N-0002 — erasure versus audit
|
|
||||||
|
|
||||||
Named in `INTENT.md` as waiting: an audit trail that must be immutable and an
|
|
||||||
erasure obligation that may require destroying what is in it cannot both be
|
|
||||||
satisfied naively, and the estate has not reconciled them.
|
|
||||||
|
|
||||||
**Ruled a note, not a finding, on 2026-08-19.**
|
|
||||||
|
|
||||||
This is a real design tension and it will need a real answer — whether key
|
|
||||||
destruction satisfies an erasure obligation is exactly the question
|
|
||||||
`INTENT.md` says was researched, used once, and discarded.
|
|
||||||
|
|
||||||
It is a note today for one reason: there is no obligation. The estate holds no
|
|
||||||
real person's data, so nothing is owed to anyone. Escalation trigger 2 reads
|
|
||||||
"creates or reveals an obligation with an outside counterparty", and this
|
|
||||||
creates none yet. A finding needs a decision that changes, and today the
|
|
||||||
decision is "not yet".
|
|
||||||
|
|
||||||
It is also not shaped like this register's work. It is a regulatory question
|
|
||||||
first and an architecture question second, and `INTENT.md` puts regulatory
|
|
||||||
intake in this repo but keeps "what the estate must therefore do" with the
|
|
||||||
owning repo. Reconciling it belongs to the regulatory-intake workplan
|
|
||||||
(`RISK-WP-0001` residual), not to finding triage.
|
|
||||||
|
|
||||||
It comes back on the day the estate first holds a real person's data. That day
|
|
||||||
is also when it stops being a note, because from then on the obligation is real
|
|
||||||
and trigger 2 fires.
|
|
||||||
34
notes/RISK-N-0003-defects-found-by-reading-not-monitoring.md
Normal file
34
notes/RISK-N-0003-defects-found-by-reading-not-monitoring.md
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
---
|
||||||
|
id: RISK-N-0003
|
||||||
|
type: note
|
||||||
|
title: "Every defect in this register was found by reading, none by monitoring"
|
||||||
|
date: "2026-08-19"
|
||||||
|
source: "rapp-postgres, routing RISK-F-0001; restated in RISK-F-0002"
|
||||||
|
floor_reason: "no owner and no defect — it is an argument about where to invest detection, and the register cannot route an argument"
|
||||||
|
revisit: "when a finding arrives that monitoring plausibly should have caught and did not"
|
||||||
|
ruling: RISK-RULING-2026-08-19-C
|
||||||
|
---
|
||||||
|
|
||||||
|
# RISK-N-0003 — found by reading, not by watching
|
||||||
|
|
||||||
|
`rapp-postgres` raised it when routing `RISK-F-0001` and left the call here:
|
||||||
|
all four defects in that round were found by repos reading their own code
|
||||||
|
against a ladder, within a day of each other, and none by monitoring.
|
||||||
|
`RISK-F-0002` is a fifth, found by re-reading an answer this estate had just
|
||||||
|
given. `RISK-F-0003` is a sixth, found while counting fields for a zone model.
|
||||||
|
|
||||||
|
**Ruled a note, not a finding, on 2026-08-19.**
|
||||||
|
|
||||||
|
It is true, it is worth knowing, and it clears neither floor test cleanly. No
|
||||||
|
repo owns "the estate's ability to notice its own defects", and there is no
|
||||||
|
defect to route — the observation is an argument for investing in detection,
|
||||||
|
and the register that files arguments as findings stops being readable.
|
||||||
|
|
||||||
|
There is also a reading of it that is not alarming. Reading code against a
|
||||||
|
ladder *is* a detection method, it worked six times in a week, and the estate
|
||||||
|
has been doing it deliberately. What is unproven is whether it would find
|
||||||
|
anything nobody thought to look at.
|
||||||
|
|
||||||
|
It comes back the first time a finding arrives that monitoring plausibly should
|
||||||
|
have caught and did not. That is the evidence this note is missing, and until
|
||||||
|
then filing it would be the register asserting a conclusion it cannot support.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue