RISK-WP-0001-T07: rule on what was waiting outside the register
Four in as findings — tenant-engine unfiltered event read (high), audit-core read path bounded by a flag not by code (medium), apps-pg with no backup at all (high, escalated on spend), and the unverified tenant boundary itself (high now, critical at production, escalated on ownership, fix_owner deliberately unset). Two out as notes — noisy neighbours and erasure-versus-audit, both real, neither changing a decision this month, both carrying an event to be re-read at. The round amended the scale twice: build mode lowers impact as well as likelihood, and non-adversarial findings get their own likelihood reading. The escalation rule gained a ratio test that distinguishes a first sweep from steady-state intake, and a batching rule. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
d5a3953f2e
commit
4daff5503f
10 changed files with 612 additions and 15 deletions
19
REGISTER.md
19
REGISTER.md
|
|
@ -2,12 +2,16 @@
|
|||
|
||||
Generated by `tools/register_index.py` from `findings/`. Do not edit by hand. Last built 2026-08-19.
|
||||
|
||||
3 open of 3 findings; 0 notes below the floor.
|
||||
7 open of 7 findings; 2 notes below the floor.
|
||||
|
||||
## Findings
|
||||
|
||||
| ID | Finding | System | Severity | Disclosure | Escalation | Fix owner | Status | Review by |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| [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-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-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-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 |
|
||||
|
|
@ -26,10 +30,23 @@ Held from publication with a stated condition. A hold with no moving condition i
|
|||
|
||||
| Finding | Since | Lifts when | Re-decided |
|
||||
| --- | --- | --- | --- |
|
||||
| RISK-F-0007 | 2026-08-19 | a verification exists for at least one consumer boundary | 2026-09-18 |
|
||||
| RISK-F-0006 | 2026-08-19 | a backup exists and a restore has been demonstrated once | 2026-09-18 |
|
||||
| RISK-F-0005 | 2026-08-19 | AUDIT-WP-0008-T04 lands a tenant filter in the read path | 2026-11-17 |
|
||||
| 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-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)
|
||||
|
||||
Seen, deliberately not findings. Not graded, not reviewed, not published.
|
||||
|
||||
| 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-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
|
||||
|
||||
Severity is `docs/method/severity.md`; disclosure `docs/method/disclosure.md`;
|
||||
|
|
|
|||
|
|
@ -134,15 +134,48 @@ Stated so the rule bites in both directions.
|
|||
|
||||
## Testing the rule against the register
|
||||
|
||||
The draft was tested against all three open findings before it was proposed;
|
||||
the rulings are in `docs/rulings/2026-08-19-first-grading.md`.
|
||||
The draft was tested against the first three findings before it was proposed
|
||||
(`docs/rulings/2026-08-19-first-grading.md`) and then against the four filed
|
||||
out of the backlog the same day
|
||||
(`docs/rulings/2026-08-19-second-grading.md`).
|
||||
|
||||
Summary: `RISK-F-0001` escalates on trigger 1. `RISK-F-0002` does not escalate
|
||||
on triggers 1-5 — agreeing with the reporter's own reading — but the
|
||||
`RISK-F-0001`/`RISK-F-0002` ordering constraint escalates once on trigger 6,
|
||||
which is the disagreement the rule was worth writing to surface. `RISK-F-0003`
|
||||
does not escalate; it is known, owned, tracked, and moving.
|
||||
| Finding | Escalates | Trigger |
|
||||
| --- | --- | --- |
|
||||
| `RISK-F-0001` flex-auth oracle | yes | 1 — governs access to tenant data |
|
||||
| `RISK-F-0002` signing gate off | yes, once | 6 — ordering hazard, jointly with `RISK-F-0001` |
|
||||
| `RISK-F-0003` ungraded lanes | no | known, owned, tracked, moving |
|
||||
| `RISK-F-0004` tenant-engine reads | no | no real tenant data yet |
|
||||
| `RISK-F-0005` audit-core reads | no | known, owned, tracked, moving |
|
||||
| `RISK-F-0006` apps-pg no backup | yes | 3 — recurring spend nobody can self-authorise |
|
||||
| `RISK-F-0007` unverified boundary | yes | 4 — estate-wide and unowned |
|
||||
|
||||
One escalation, covering two findings, out of three findings. That ratio is
|
||||
the rule doing its job. If it ever reaches "most findings", the rule is wrong,
|
||||
not the register.
|
||||
`RISK-F-0002` is the case worth reading: `ops-warden` judged it did not need
|
||||
the operator, the register agrees on triggers 1-5, and it escalates anyway on
|
||||
6. That disagreement is the reason the rule was worth writing down.
|
||||
|
||||
## The ratio, and what it would mean
|
||||
|
||||
Four of seven escalate. That is more than this rule should produce in steady
|
||||
state, and it is not evidence the rule is loose — it is what a **first sweep**
|
||||
looks like. Three of the four are the backlog: items that sat outside the
|
||||
register precisely because nobody had decided them, and undecided items are
|
||||
exactly the population that needs the person who can decide.
|
||||
|
||||
The test therefore applies to intake, not to sweeps:
|
||||
|
||||
> If more than one in three **newly reported** findings escalates over any
|
||||
> rolling ninety days, the rule is wrong, not the register.
|
||||
|
||||
If that trips, the first suspects are triggers 3 and 4 — spend thresholds set
|
||||
too low, and "unowned" being read where "not yet routed" is meant.
|
||||
|
||||
## Escalations are batched
|
||||
|
||||
Four escalations are one conversation, not four interruptions. Open items go
|
||||
to the operator together, in register order, each with its own decision and
|
||||
its own default-if-no-answer. Escalating is not the same as escalating
|
||||
separately, and a rule that produces four messages in an afternoon has made the
|
||||
operator the queue by a different route.
|
||||
|
||||
`make check` lists everything awaiting an answer, so the batch is a report and
|
||||
not somebody's recollection.
|
||||
|
|
|
|||
|
|
@ -108,15 +108,37 @@ Every finding is graded twice:
|
|||
- `severity_at_production` — the same impact, with likelihood re-read for a
|
||||
system carrying real users and real tenant data.
|
||||
|
||||
Build mode is a legitimate likelihood input. "No consumer holds real data
|
||||
here yet" genuinely lowers reach. It is *not* an impact input: what the defect
|
||||
would do on the day it is exercised does not change because the calendar has
|
||||
not reached production.
|
||||
Build mode legitimately lowers **both** axes, for different reasons:
|
||||
likelihood, where the reach itself depends on a production deployment that has
|
||||
not happened; and impact, where the data that would be exposed does not exist
|
||||
yet. What it must never lower is `severity_at_production` — the defect does
|
||||
not improve because the calendar has not reached it.
|
||||
|
||||
> *Amended 2026-08-19 (`RISK-WP-0001-T07`).* This paragraph originally said
|
||||
> build mode was a likelihood input and never an impact one. Grading the
|
||||
> unverified tenant boundary broke that: what build mode changes there is the
|
||||
> consequence of an occurrence, not the reach of it. The instrument was wrong
|
||||
> on first hard use and is corrected rather than worked around.
|
||||
|
||||
Where the two grades differ, the production transition is a mandatory
|
||||
re-score. `docs/method/review.md` binds the review date to it, so the re-score
|
||||
is a scheduled event and not somebody's memory.
|
||||
|
||||
## Non-adversarial findings
|
||||
|
||||
Likelihood is written as reach because most findings are about someone getting
|
||||
somewhere. Where a finding is about loss, corruption or outage — no backup, no
|
||||
recovery path, an eviction-prone deployment — there is no attacker to model.
|
||||
|
||||
For those, likelihood reads as **the chance of the triggering event inside one
|
||||
review interval**: `L1` would be surprising, `L2` is an ordinary failure the
|
||||
estate has seen before, `L3` is expected in the normal course of running,
|
||||
`L4` is already happening. Impact is unchanged: what is lost, and whether it
|
||||
comes back.
|
||||
|
||||
> *Added 2026-08-19 (`RISK-WP-0001-T07`).* Forced by `RISK-F-0006`, where the
|
||||
> defect is an absent backup and the reach reading produced nonsense.
|
||||
|
||||
## The floor
|
||||
|
||||
`INTENT.md`: if a finding would not change anyone's decision, it is a note,
|
||||
|
|
|
|||
100
docs/rulings/2026-08-19-second-grading.md
Normal file
100
docs/rulings/2026-08-19-second-grading.md
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
---
|
||||
id: RISK-RULING-2026-08-19-B
|
||||
type: ruling
|
||||
title: "What was waiting outside the register: four findings, two notes"
|
||||
status: recorded
|
||||
owner: risk-nexus
|
||||
date: "2026-08-19"
|
||||
workplan: RISK-WP-0001-T07
|
||||
---
|
||||
|
||||
# What was waiting outside the register — 2026-08-19
|
||||
|
||||
`INTENT.md` named six things as visible but unfiled, held back "pending this
|
||||
repo setting the precedent for what warrants a record of its own". The
|
||||
precedent now exists (`docs/method/severity.md`), so each is ruled here. "Still
|
||||
waiting on the precedent" is no longer an available answer.
|
||||
|
||||
| Item | Ruling | Why |
|
||||
| --- | --- | --- |
|
||||
| `tenant-engine` unfiltered event read | `RISK-F-0004`, high | Live cross-tenant read, owner can act, ordering changes |
|
||||
| `audit-core` unfiltered read path | `RISK-F-0005`, medium | Bounded by a deployment flag, not by code |
|
||||
| `apps-pg` no backup | `RISK-F-0006`, high, escalated | Unrecoverable loss; needs spend nobody can self-authorise |
|
||||
| Unverified tenant boundary | `RISK-F-0007`, high, escalated | Estate-wide, unowned, two confirmed instances |
|
||||
| Noisy neighbours uncharacterised | `RISK-N-0001`, note | Measurement work, no decision changes today |
|
||||
| Erasure versus audit | `RISK-N-0002`, note | No obligation exists yet; regulatory-intake work |
|
||||
|
||||
Four in, two out. If everything had cleared the floor, the floor would not be
|
||||
one.
|
||||
|
||||
## The three from RISK-F-0001's unfiled list
|
||||
|
||||
They were recorded inside another finding "so they are visible, not filed as
|
||||
findings, because filing them was not asked for". Filing is now asked for.
|
||||
|
||||
Each is filed on the owning repo's own self-report, unverified by this repo,
|
||||
and says so in its own text. `risk-nexus` reads from everywhere and is
|
||||
downstream by construction; the system remains authoritative about itself.
|
||||
Each owner has been asked to confirm or correct, and two of the three
|
||||
(`RISK-F-0004`, `RISK-F-0006`) have `fix_tracking: unset`, which is a question
|
||||
put to the owner rather than a criticism.
|
||||
|
||||
`RISK-F-0006` is the surprise of the round. It is the least dramatic item on
|
||||
the list — a missing configuration block — and it grades highest of the three,
|
||||
because it is the only one where nothing comes back afterwards. It also
|
||||
escalates, on spend, which is the trigger that most needed a real case to
|
||||
prove it is not decorative.
|
||||
|
||||
## The unverified tenant boundary
|
||||
|
||||
`RISK-F-0007`, and the one this register was arguably built to hold.
|
||||
`INTENT.md` calls it the estate's largest known gap and complains that it lives
|
||||
as open question 3 of an unratified draft, with no owner, no severity and no
|
||||
date. It now has three of the four; `fix_owner` stays `unset` deliberately,
|
||||
because the escalation is precisely about who owns it.
|
||||
|
||||
Two design points, both deliberate:
|
||||
|
||||
- **It is not a duplicate of `RISK-F-0004` and `RISK-F-0005`.** Those are two
|
||||
instances; this is the absence of anything that would have found them. The
|
||||
instances get fixed by their owners and this one does not go away when they
|
||||
do.
|
||||
- **It grades `high` today and `critical` at production**, which is the first
|
||||
real use of `production_rescore`. Today's consequence is bounded because the
|
||||
estate holds no real tenant data. That bound is a fact about the calendar, so
|
||||
it belongs in the build-mode column and not in a comfortable headline.
|
||||
|
||||
## What the notes are for
|
||||
|
||||
`RISK-N-0001` and `RISK-N-0002` are the floor doing its job: both are real,
|
||||
both are known, neither changes a decision this month. The note keeps "we saw
|
||||
it" without inflating a register that has to stay small enough to read.
|
||||
|
||||
Both carry a `revisit` condition that is an event rather than a date, and both
|
||||
events are ones the estate cannot miss — two tenants sharing a saturating
|
||||
workload, and the first real person's data. Neither note is a promise to
|
||||
remember; both are promises to be re-read when the condition arrives.
|
||||
|
||||
## What this round did to the instruments
|
||||
|
||||
Two amendments, both dated in `docs/method/severity.md`:
|
||||
|
||||
1. **Build mode lowers impact as well as likelihood.** The original text said
|
||||
it was a likelihood input and never an impact one. `RISK-F-0007` broke that
|
||||
in one sentence: what build mode changes for an unverified boundary is the
|
||||
consequence of an occurrence, not the reach of it. Corrected rather than
|
||||
worked around.
|
||||
2. **Non-adversarial findings get their own likelihood reading.** `RISK-F-0006`
|
||||
has no attacker in it, and reading likelihood as "reach" produced nonsense.
|
||||
Likelihood there is the chance of the triggering event inside one review
|
||||
interval.
|
||||
|
||||
An instrument that survives its first hard use unchanged has probably not been
|
||||
used hard.
|
||||
|
||||
## Register size
|
||||
|
||||
Seven findings, six open, two notes. `INTENT.md` requires the register stay
|
||||
small enough to read, and `REGISTER.md` is still one screen. The next thing
|
||||
that would break it is a batch — a review round producing ten entries at once.
|
||||
When that happens the answer is a harder floor, not a wider table.
|
||||
88
findings/RISK-F-0004-tenant-engine-unfiltered-event-read.md
Normal file
88
findings/RISK-F-0004-tenant-engine-unfiltered-event-read.md
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
---
|
||||
id: RISK-F-0004
|
||||
type: finding
|
||||
title: "tenant-engine events() returns the entire event log unfiltered"
|
||||
status: open
|
||||
reported_by: tenant-engine
|
||||
reported_via: flex-auth
|
||||
routed_by: risk-nexus
|
||||
date_reported: "2026-08-17"
|
||||
date_filed: "2026-08-19"
|
||||
system: tenant-engine
|
||||
environment: production
|
||||
fix_owner: tenant-engine
|
||||
fix_tracking: unset
|
||||
related: [RISK-F-0001]
|
||||
# Graded by risk-nexus 2026-08-19 — docs/rulings/2026-08-19-second-grading.md
|
||||
severity: high
|
||||
severity_at_production: critical
|
||||
impact: I3
|
||||
likelihood: L3
|
||||
fidelity_modifier: false
|
||||
production_rescore: true
|
||||
disclosure: embargoed
|
||||
embargo_condition: "the read path filters by tenant in code"
|
||||
embargo_since: "2026-08-19"
|
||||
embargo_review: "2026-09-18"
|
||||
escalation: none
|
||||
last_reviewed: "2026-08-19"
|
||||
review_by: "2026-09-18"
|
||||
graded_by: risk-nexus
|
||||
ruling: RISK-RULING-2026-08-19-B
|
||||
---
|
||||
|
||||
# RISK-F-0004 — the tenant event log is readable across tenants
|
||||
|
||||
## What is true, as reported
|
||||
|
||||
`tenant-engine`'s `events()` returns the entire event log with no tenant
|
||||
filter. Reported by `tenant-engine` as a live cross-tenant read at `E2` on the
|
||||
Tenancy Posture E ladder, surfaced in the same review round as `RISK-F-0001`
|
||||
and recorded inside that finding as visible-but-unfiled.
|
||||
|
||||
**This repo has not verified it and does not own the code.** It is filed on the
|
||||
owning repo's own self-report. `tenant-engine` confirms or corrects it.
|
||||
|
||||
## Why it is being filed now
|
||||
|
||||
It was held back pending the precedent this register set for what warrants a
|
||||
record of its own. That precedent now exists (`docs/method/severity.md`), and
|
||||
"still waiting on the precedent" has stopped being an available answer. This
|
||||
finding clears the floor on both tests: `tenant-engine` can act, and recording
|
||||
it changes when they act.
|
||||
|
||||
## What is not established
|
||||
|
||||
- Whether any caller other than `tenant-engine` itself currently reaches
|
||||
`events()`.
|
||||
- What the log contains — whether the rows are metadata or carry tenant
|
||||
payload. The grade assumes cross-tenant *visibility*, not payload
|
||||
disclosure, and would rise if it is the latter.
|
||||
- Whether a fix is tracked anywhere. `fix_tracking` is `unset` and this repo
|
||||
has asked.
|
||||
|
||||
## Register ruling — 2026-08-19
|
||||
|
||||
`high` today (`I3` × `L3`), `critical` at production, embargoed until the read
|
||||
path filters in code, no escalation.
|
||||
|
||||
`I3`: a cross-tenant read crosses a tenant boundary inside one system. `L3`:
|
||||
no additional step is needed by anything that can already call the method, and
|
||||
the authorization that would otherwise constrain the caller is `RISK-F-0001`,
|
||||
which authenticates nobody.
|
||||
|
||||
`production_rescore: true`. Today the log holds no real counterparty's events,
|
||||
which lowers what one occurrence costs; it does not lower what the defect is.
|
||||
At production the same read is `I4` — real tenant data crossing a boundary
|
||||
that nothing verifies — and the re-score is owed before any production
|
||||
declaration completes.
|
||||
|
||||
No escalation: no real tenant data yet (trigger 1 reads *real*), owned, and
|
||||
not yet stalled. It becomes an escalation on the day the estate takes real
|
||||
tenant data, and that is what `production_rescore` is for.
|
||||
|
||||
## Reviews
|
||||
|
||||
- **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.
|
||||
77
findings/RISK-F-0005-audit-core-unfiltered-read-path.md
Normal file
77
findings/RISK-F-0005-audit-core-unfiltered-read-path.md
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
---
|
||||
id: RISK-F-0005
|
||||
type: finding
|
||||
title: "audit-core read path applies no tenant filter; the bound is deployment, not code"
|
||||
status: open
|
||||
reported_by: audit-core
|
||||
reported_via: flex-auth
|
||||
routed_by: risk-nexus
|
||||
date_reported: "2026-08-17"
|
||||
date_filed: "2026-08-19"
|
||||
system: audit-core
|
||||
environment: production
|
||||
fix_owner: audit-core
|
||||
fix_tracking: AUDIT-WP-0008-T04
|
||||
related: [RISK-F-0004]
|
||||
# Graded by risk-nexus 2026-08-19 — docs/rulings/2026-08-19-second-grading.md
|
||||
severity: medium
|
||||
severity_at_production: high
|
||||
impact: I3
|
||||
likelihood: L2
|
||||
fidelity_modifier: false
|
||||
production_rescore: true
|
||||
disclosure: embargoed
|
||||
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_reviewed: "2026-08-19"
|
||||
review_by: "2026-11-17"
|
||||
graded_by: risk-nexus
|
||||
ruling: RISK-RULING-2026-08-19-B
|
||||
---
|
||||
|
||||
# RISK-F-0005 — the audit read path is bounded by a flag, not by code
|
||||
|
||||
## What is true, as reported
|
||||
|
||||
`audit-core`'s read path applies no tenant filter. A credential holding
|
||||
`may_read` can read any tenant's events. The production sender is deployed with
|
||||
`may_read: false`, so the exposure today is bounded **by deployment
|
||||
configuration and not by code**. Self-reported in the same review round as
|
||||
`RISK-F-0001`; tracked by `audit-core` as `AUDIT-WP-0008-T04`.
|
||||
|
||||
Not verified by this repo. `audit-core` owns it and confirms or corrects it.
|
||||
|
||||
## Why the bound is the finding
|
||||
|
||||
A defect held shut by a flag is one edit from open, and the edit does not look
|
||||
dangerous to whoever makes it — enabling a read credential is an ordinary
|
||||
operational act. The register carries it because the safety here lives in a
|
||||
value someone can change without reading this file.
|
||||
|
||||
That is also why it is filed separately from `RISK-F-0004` rather than as one
|
||||
"cross-tenant reads" entry: different owner, different fix, and this one has a
|
||||
tracked fix already.
|
||||
|
||||
## Register ruling — 2026-08-19
|
||||
|
||||
`medium` today (`I3` × `L2`), `high` at production, embargoed until
|
||||
`AUDIT-WP-0008-T04` lands, no escalation.
|
||||
|
||||
`I3`: crossing a tenant boundary in the audit store. `L2`: it needs a
|
||||
credential with `may_read`, which the estate grants somewhere but not to the
|
||||
production sender. It is not `L3` because the flag is genuinely off today, and
|
||||
not `L1` because the flag is a deployment value rather than an absent code
|
||||
path.
|
||||
|
||||
`production_rescore: true` for the same reason as `RISK-F-0004`: the audit log
|
||||
does not hold a real counterparty's events yet.
|
||||
|
||||
No escalation. Known, owned, tracked, moving.
|
||||
|
||||
## Reviews
|
||||
|
||||
- **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.
|
||||
88
findings/RISK-F-0006-apps-pg-no-backup-configured.md
Normal file
88
findings/RISK-F-0006-apps-pg-no-backup-configured.md
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
---
|
||||
id: RISK-F-0006
|
||||
type: finding
|
||||
title: "apps-pg has no backup configured at all: R0 means no recovery"
|
||||
status: open
|
||||
reported_by: railiance-platform
|
||||
reported_via: flex-auth
|
||||
routed_by: risk-nexus
|
||||
date_reported: "2026-08-17"
|
||||
date_filed: "2026-08-19"
|
||||
system: railiance-platform
|
||||
environment: production
|
||||
fix_owner: railiance-platform
|
||||
fix_tracking: unset
|
||||
related: [RISK-F-0001]
|
||||
# Graded by risk-nexus 2026-08-19 — docs/rulings/2026-08-19-second-grading.md
|
||||
severity: high
|
||||
severity_at_production: critical
|
||||
impact: I4
|
||||
likelihood: L2
|
||||
fidelity_modifier: false
|
||||
production_rescore: true
|
||||
disclosure: embargoed
|
||||
embargo_condition: "a backup exists and a restore has been demonstrated once"
|
||||
embargo_since: "2026-08-19"
|
||||
embargo_review: "2026-09-18"
|
||||
escalation: required
|
||||
escalation_trigger: 3
|
||||
escalation_status: pending-operator
|
||||
last_reviewed: "2026-08-19"
|
||||
review_by: "2026-09-18"
|
||||
graded_by: risk-nexus
|
||||
ruling: RISK-RULING-2026-08-19-B
|
||||
---
|
||||
|
||||
# RISK-F-0006 — the platform database cannot be recovered
|
||||
|
||||
## What is true, as reported
|
||||
|
||||
`apps-pg` (`railiance-platform`) has no backup configured at all: no
|
||||
`barmanObjectStore`, no retention policy, and `BestEffort` QoS on the pod.
|
||||
Reported in the same round as `RISK-F-0001`, whose author noted that `R0` here
|
||||
means **no recovery**, not merely no erasure policy.
|
||||
|
||||
Not verified by this repo. `railiance-platform` owns it.
|
||||
|
||||
## Why it is graded highest of the round despite being the least exciting
|
||||
|
||||
The other findings in this round are about someone reaching something. This one
|
||||
is about nothing coming back. There is no attacker in it and no clever step —
|
||||
an ordinary node failure, a lost volume, a mistaken `DROP`, and the data that
|
||||
was in `apps-pg` is gone.
|
||||
|
||||
`BestEffort` QoS makes the pod the first candidate for eviction under memory
|
||||
pressure. Eviction alone is an availability event and recoverable. What is not
|
||||
recoverable is anything that damages the volume, and that is the case with no
|
||||
answer today.
|
||||
|
||||
## Register ruling — 2026-08-19
|
||||
|
||||
`high` today (`I4` × `L2`, non-adversarial reading), `critical` at production,
|
||||
embargoed, and **escalated on trigger 3 (spend)**.
|
||||
|
||||
`I4`: `apps-pg` is shared platform infrastructure, so the loss is not confined
|
||||
to one system, and it is unrecoverable rather than degraded. `L2` on the
|
||||
non-adversarial reading the scale gained for this finding: irrecoverable loss
|
||||
needs a volume or corruption event, which is an ordinary failure the estate
|
||||
has seen the shape of but not an expected weekly occurrence.
|
||||
|
||||
`production_rescore: true`: at production this is `L3`, because the surface
|
||||
area of ordinary operational events grows with real traffic and real operators.
|
||||
|
||||
**Escalation, trigger 3.** Object storage for backups is recurring spend that
|
||||
is not currently committed, and no repo can authorise it for itself. The ask
|
||||
is narrow: approve a backup target and its cost, or state that the estate
|
||||
accepts running `apps-pg` with no recovery and for how long. The second is a
|
||||
legitimate answer in build mode and needs saying out loud rather than
|
||||
happening by default.
|
||||
|
||||
The disclosure condition deliberately includes a demonstrated restore. A
|
||||
backup nobody has restored from is a claim, not a control — the same class of
|
||||
error as the gate in `RISK-F-0002`.
|
||||
|
||||
## Reviews
|
||||
|
||||
- **2026-08-19** — filed and graded from `RISK-F-0001`'s unfiled list.
|
||||
Open at review: has the spend been ruled on; is a backup configured; has a
|
||||
restore been demonstrated; does `railiance-platform` track it anywhere.
|
||||
99
findings/RISK-F-0007-unverified-tenant-boundary.md
Normal file
99
findings/RISK-F-0007-unverified-tenant-boundary.md
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
---
|
||||
id: RISK-F-0007
|
||||
type: finding
|
||||
title: "No consumer's tenant boundary is verified anywhere"
|
||||
status: open
|
||||
reported_by: net-kingdom
|
||||
reported_via: risk-nexus
|
||||
routed_by: risk-nexus
|
||||
date_reported: "2026-08-19"
|
||||
date_filed: "2026-08-19"
|
||||
system: estate
|
||||
environment: build
|
||||
fix_owner: unset
|
||||
fix_tracking: unset
|
||||
related: [RISK-F-0004, RISK-F-0005]
|
||||
# Graded by risk-nexus 2026-08-19 — docs/rulings/2026-08-19-second-grading.md
|
||||
severity: high
|
||||
severity_at_production: critical
|
||||
impact: I3
|
||||
likelihood: L3
|
||||
fidelity_modifier: false
|
||||
production_rescore: true
|
||||
disclosure: embargoed
|
||||
embargo_condition: "a verification exists for at least one consumer boundary"
|
||||
embargo_since: "2026-08-19"
|
||||
embargo_review: "2026-09-18"
|
||||
escalation: required
|
||||
escalation_trigger: 4
|
||||
escalation_status: pending-operator
|
||||
last_reviewed: "2026-08-19"
|
||||
review_by: "2026-09-18"
|
||||
graded_by: risk-nexus
|
||||
ruling: RISK-RULING-2026-08-19-B
|
||||
---
|
||||
|
||||
# RISK-F-0007 — nothing checks that tenants stay apart
|
||||
|
||||
## What is true
|
||||
|
||||
No consumer's tenant boundary is verified anywhere in the estate. This is
|
||||
Broken Object Level Authorization, first on the OWASP API Security Top 10
|
||||
since that list launched.
|
||||
|
||||
It is currently **open question 3 in NetKingdom's *Tenancy Posture*, which is a
|
||||
draft and not a register** — which is precisely why `INTENT.md` names it as the
|
||||
thing that had nowhere to live. Filing it here does not amend that standard,
|
||||
does not ratify it, and does not settle the question it poses. A finding may
|
||||
say a standard is wrong; it cannot change one.
|
||||
|
||||
## Why it is a finding and not a research note
|
||||
|
||||
The floor asks whether an owner could act and whether recording it changes a
|
||||
decision. Both are yes, and the second is now demonstrable rather than
|
||||
asserted: every time a repo has looked at its own boundary this month, it has
|
||||
found a defect. `RISK-F-0004` (`tenant-engine`, unfiltered event read) and
|
||||
`RISK-F-0005` (`audit-core`, no tenant filter on read) are two instances found
|
||||
by two repos in one round.
|
||||
|
||||
An absent verification is not the same as an absent boundary. But the sample so
|
||||
far is two for two, and the register does not get to assume the unexamined
|
||||
cases are better than the examined ones.
|
||||
|
||||
## What is not established
|
||||
|
||||
- Whether any consumer boundary *is* in fact correct. Nobody has checked; that
|
||||
is the finding.
|
||||
- Who owns the fix. `fix_owner` is `unset` deliberately — see the escalation.
|
||||
|
||||
## Register ruling — 2026-08-19
|
||||
|
||||
`high` today (`I3` × `L3`), `critical` at production, embargoed, **escalated on
|
||||
trigger 4 (ownership)**.
|
||||
|
||||
Today's impact is `I3` and not `I4` because there is no real tenant data behind
|
||||
the unverified boundary yet; the consequence of one occurrence is bounded by
|
||||
what the estate is currently holding. `L3`: no additional step is needed by
|
||||
anything already inside, and the two confirmed instances say the reach is real
|
||||
rather than theoretical.
|
||||
|
||||
`production_rescore: true`, and this is the finding that matters most on that
|
||||
day: at production the same defect is `I4` × `L3` — `critical` — and the
|
||||
re-score is not optional.
|
||||
|
||||
**Escalation, trigger 4.** This is the ownership case the trigger was written
|
||||
for, in its purest form: the defect is estate-wide, no repo owns "every
|
||||
consumer's boundary", and a routing exchange cannot settle it because there is
|
||||
nobody to route it to. Only the operator can say who verifies tenant
|
||||
boundaries — a repo, a test suite, a review obligation on each consumer — or
|
||||
that the estate deliberately carries it unverified until production.
|
||||
|
||||
Until that is answered, `fix_owner` stays `unset` rather than being assigned to
|
||||
a repo that has not accepted it. An unowned finding with an honest `unset` is
|
||||
better than a routed one nobody agreed to.
|
||||
|
||||
## Reviews
|
||||
|
||||
- **2026-08-19** — filed and graded. Open at review: has an owner been named;
|
||||
have any further instances been found; is the Tenancy Posture question still
|
||||
open.
|
||||
35
notes/RISK-N-0001-noisy-neighbour-uncharacterised.md
Normal file
35
notes/RISK-N-0001-noisy-neighbour-uncharacterised.md
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
id: RISK-N-0001
|
||||
type: note
|
||||
title: "Noisy-neighbour behaviour is uncharacterised"
|
||||
date: "2026-08-19"
|
||||
source: "NetKingdom Tenancy Posture (draft), open question"
|
||||
floor_reason: "no decision changes today — no tenant shares a saturating workload, and what is missing is measurement work, not a defect to route"
|
||||
revisit: "when two tenants first share a saturating workload, or at the production transition"
|
||||
ruling: RISK-RULING-2026-08-19-B
|
||||
---
|
||||
|
||||
# RISK-N-0001 — noisy neighbours, uncharacterised
|
||||
|
||||
Named in `INTENT.md` as waiting: NetKingdom's *Tenancy Posture* leaves the
|
||||
noisy-neighbour behaviour of shared components uncharacterised — how one
|
||||
tenant's load degrades another's service is not measured anywhere.
|
||||
|
||||
**Ruled a note, not a finding, on 2026-08-19.**
|
||||
|
||||
The floor asks two questions. *Could an owner act?* Yes —
|
||||
`railiance-platform` could characterise it. *Does recording it change a
|
||||
decision?* Today, no. Nothing in the estate currently has two tenants sharing a
|
||||
workload heavy enough for the answer to matter, so a register entry would
|
||||
change nobody's ordering and would sit there being read past.
|
||||
|
||||
What is missing here is measurement, not remediation. That is work someone
|
||||
schedules, not a defect the register routes — and the register is explicitly
|
||||
not the place where undone work is logged.
|
||||
|
||||
It comes back the day two tenants first share a saturating workload, or at the
|
||||
production transition, whichever is first. If characterisation then shows one
|
||||
tenant can degrade another, that is a finding with a severity, and this note is
|
||||
its provenance.
|
||||
|
||||
Filed as a note so that "we saw it" survives without inflating the register.
|
||||
38
notes/RISK-N-0002-erasure-versus-audit.md
Normal file
38
notes/RISK-N-0002-erasure-versus-audit.md
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue