Compare commits

..

No commits in common. "38e083ed3de28ae6139aaa83b500e86df7f3e758" and "d8b18f29721cabc60954aa835aa8ef0f43d6dd0f" have entirely different histories.

3 changed files with 1 additions and 240 deletions

125
INTENT.md
View file

@ -1,125 +0,0 @@
# INTENT — risk-nexus
## Why this repo exists
`risk-nexus` is where the estate holds what it knows is wrong, what might be
wrong, and what the outside world requires of it — with a severity, an owner,
and a date. It serves `risk.coulomb.social`.
**Owned by `the-custodian`**, alongside `policy-nexus`. One of its duties is
deciding what must reach the operator personally rather than sitting in a
register.
Before this repo existed, three things had nowhere to live.
**Findings landed in whichever document was open.** The estate's largest known
gap — that no consumer's tenant boundary is verified anywhere, which is
Broken Object Level Authorization, top of the OWASP API Security Top 10 since
that list launched — is currently open question 3 in an unratified draft
standard. It was found by research, it has no owner, no severity, and no date.
A finding recorded in the document that happened to discover it is a finding
that disappears when that document is superseded.
**Disclosure had no mechanism.** In build mode the estate publishes everything,
which is right: there are no users to expose. That stops being right at
production, when the same architecture disclosure a consumer must read becomes
a map for an attacker. There is currently no way to hold a finding while it is
fixed and publish it once it is — only publish-now or forget.
**Regulation was consulted and discarded.** Whether key destruction satisfies
an erasure obligation, whether the estate is an in-scope entity under a given
regime, what a procurement rule requires — each was researched at the moment
someone needed it and never retained. The same question gets asked twice and
the answer silently expires.
## What it owns
- **Finding intake.** Security, architecture, operational and compliance
findings, from any source: research, review, incident, external report.
- **Severity and triage.** What this actually risks, how likely, how bad.
- **Remediation tracking** — not remediation. Who owns the fix, what state it
is in, and whether it has stalled.
- **Disclosure timing.** Whether a finding is publishable now, embargoed until
fixed, or permanently restricted; and the record that a delay was deliberate
rather than a document quietly going missing.
- **Regulatory intake**, scoped to regulation bearing on the estate — rules
constraining data it holds, markets it sells into, or obligations it has
taken on. Moved here from `policy-nexus`, because deciding what a rule
demands of us is a judgement about risk, not an act of publishing.
- **The escalation rule.** What must be discussed with the operator personally
rather than recorded and routed. This is the duty `the-custodian` carries as
owner, and the rule itself must be written down rather than exercised by
instinct.
## What it does not own
- **Fixing anything.** A finding is routed to the repo that owns the defect,
which fixes it under its own workplan. A risk service that fixes things
becomes a second engineering team with no boundary.
- **Publication.** `policy-nexus` is the publication surface. This repo decides
*whether and when* something is published; it does not host it.
- **Blocking delivery.** In build mode a finding is information, not a gate.
If that changes it will be a deliberate decision recorded here, not a habit
that accretes.
- **Legal advice.** A regulatory record states what a source said and when.
What the estate must therefore do is the owning repo's decision.
- **Deciding what canon says.** Canon is `the-custodian`'s and NetKingdom's. A
finding may say a standard is wrong; it cannot amend one.
## The failure this repo must avoid
A risk register nobody reads is worse than no register, because it converts
"we did not know" into "we knew and did nothing" while changing no behaviour.
Two consequences for design:
- **Findings must expire or escalate.** A finding that has sat untouched past
its review date is itself a finding. Silence is not resolution.
- **The register must be small enough to read.** Recording everything makes
nothing legible. If a finding would not change anyone's decision, it is a
note, not a risk.
## The escalation duty
Most findings should be routed and tracked without the operator's attention.
Some must not be. Deciding which is the substance of the oversight `the-
custodian` holds here, and getting it wrong in either direction is a failure:
escalating everything makes the operator the queue, escalating nothing makes
the register a place where serious things go quiet.
The rule is not yet written. Candidate triggers, to be settled rather than
assumed: anything exposing real tenant data; anything creating a legal or
regulatory obligation; anything requiring spend; anything where two repos
disagree about who owns the fix; and any finding whose remediation has stalled
past a stated interval.
## Relationship to the rest of the estate
`risk-nexus` reads from everywhere, decides severity and timing, and routes
work to the repo that owns it. It publishes through `policy-nexus` and never
directly. Like that repo, it is downstream by construction and must not become
a second source of truth — a finding is a claim about a system, and the system
remains authoritative about itself.
The register is no longer empty. `RISK-F-0001` arrived on 2026-08-17: a live
authorization bypass in `flex-auth`, self-reported during a framework review.
Three more defects surfaced in the same round and are recorded inside it as
visible-but-unfiled, pending this repo setting the precedent for what warrants
a record of its own.
**The first finding already tested the deferral.** Controlled disclosure is
recorded above as deferred to production, on the reasoning that build mode has
no users to expose. `RISK-F-0001` is a live authorization bypass in the service
every other service trusts, and today the choice is publish or hold with
nothing in between. That may still be the right deferral — but it is now a
decision taken with a real case in hand rather than a hypothetical one.
Also waiting: the unverified tenant boundary, the absent noisy-neighbour
characterisation, and the erasure-versus-audit tension — open questions in
NetKingdom's *Tenancy Posture*, which is a draft and not a register.
## What good looks like
Nobody is surprised. A gap that was known is recorded with a severity and an
owner, a regulation that applies was found before it was needed, a fix that
stalled was visible while it stalled, and the things that genuinely needed the
operator's judgement reached them without the things that did not.

View file

@ -1,14 +1,3 @@
# risk-nexus
Risk register and regulatory intake for the estate. Serves
`risk.coulomb.social`. Owned by `the-custodian`.
Holds findings — security, architecture, operational, compliance — with a
severity, an owner and a date; decides whether and when each is published; and
decides which must reach the operator personally rather than sitting in a
register.
It does not fix things: findings route to the repo that owns the defect. It
does not host: `policy-nexus` is the publication surface.
- Intent: `INTENT.md`
A risk management service.

View file

@ -1,103 +0,0 @@
---
id: RISK-F-0001
type: finding
title: "flex-auth /v1/check authenticates no caller"
status: open
reported_by: flex-auth
reported_via: rapp-postgres
routed_by: rapp-postgres
date_reported: "2026-08-17"
system: flex-auth
environment: production
fix_owner: flex-auth
fix_tracking: FLEX-WP-0015-T02
# The three fields below are risk-nexus's, not the reporter's. Left unset
# deliberately: the reporter says what is true, this repo says how bad it is
# and who hears about it (INTENT, "What it does not own").
severity: unset
disclosure: unset
escalation: unset
---
# RISK-F-0001 — flex-auth authenticates no caller on the decision surface
## What is true
`POST /v1/check` and `POST /v1/batch_check` authenticate no caller. Any
workload with network reach to the ClusterIP Service can assert any subject and
any tenant and receive an authoritative **allow**.
`flex-auth` is the estate's authorization oracle. Every service that delegates
a decision to it is relying on an answer that anyone able to reach the pod can
obtain for any identity they care to name.
Self-reported by `flex-auth` as `A0` on their own inbound surface, in their
Tenancy Posture review. Their words: "flex-auth is the estate's authorization
oracle and it trusts its callers completely."
## How it was found
Not by a probe, an incident, or an alert. By `flex-auth` assessing themselves
against the Tenancy Posture A ladder during a review they were asked to do —
and their own note says they did not know they were carrying it.
That provenance matters for triage: nothing was watching for this, and nothing
would have found it. It has presumably been true for as long as the endpoint
has existed.
## Exposure, as far as the reporter stated it
- The Service is `ClusterIP`, so reach requires a workload inside the cluster.
- No claim was made that network policy restricts which workloads can reach it,
and this record does not assume one. **If a default-deny NetworkPolicy fronts
the service, that materially changes the exposure and should be verified
rather than inferred** — `flex-auth` did not state it either way, and I have
not checked, because doing so would be reporting on a system I do not own.
## What makes it worse than a single service's defect
A false allow from this endpoint is not confined to `flex-auth`. It is the
answer other services act on. `tenant-engine` separately reports that its own
mutations are authorized by `flex-auth` and that direct authority over its rows
would mean "privilege escalation across NetKingdom rather than data tampering
confined to one store". The same reasoning applies to a forged allow.
## Owner and state
`flex-auth` owns the fix and has tracked it as `FLEX-WP-0015-T02`, to ship
through the staged-promotion path rather than a direct apply. They classify it
as the only urgent item of their five follow-ups. Nothing is asked of them by
this record beyond what they have already committed to.
## What this repo is asked to decide
1. **Severity.** Not the reporter's to set.
2. **Disclosure.** Build mode is currently public-by-default, and this is
precisely the class of finding where that stops being obviously right — a
live authorization bypass in the service every other service trusts. The
controlled-disclosure scheme this repo anticipates does not exist yet, so
the choice today is publish or hold, with no mechanism between them.
3. **Escalation.** Whether this reaches the operator personally. The candidate
triggers in INTENT include "anything exposing real tenant data" — this
exposes the decision that governs access to it, which may or may not be the
same thing, and that judgement is this repo's.
## Related, reported at the same time and not yet filed
Three further defects surfaced from the same review round. They are recorded
here so they are visible, not filed as findings, because filing them was not
asked for:
- `tenant-engine``events()` returns the entire event log unfiltered. A live
cross-tenant read at `E2`.
- `audit-core` — read path applies no tenant filter; a credential with
`may_read` can read any tenant's events. Bounded by deployment (`may_read:
false` on the production sender) and not by code. Tracked `AUDIT-WP-0008-T04`.
- `apps-pg` (`railiance-platform`) — no backup configured at all: no
`barmanObjectStore`, no retention policy, `BestEffort` QoS. `R0` there means
no recovery, not merely no erasure policy.
All four were found the same way, by repos reading their own code against a
ladder, within a day of each other. That is a fact about the estate's
observability worth carrying into triage: **four live defects, none found by
monitoring.**