RISK-WP-0001 T01-T06,T08: the four instruments, the index, and the first grading
Severity (impact x likelihood, fidelity modifier for controls that lie, headline-vs-constraint, build-mode double grade, the floor), disclosure (publish/embargoed/restricted, and the build-mode deferral re-taken and narrowed with RISK-F-0001 in hand), escalation (the five INTENT triggers settled plus an ordering-hazard trigger the RISK-F-0002 case forced; proposed, awaiting the custodian), review (intervals, what a review is, what missing one produces, the production re-score). Then applied: RISK-F-0001 critical/embargoed/escalated, RISK-F-0002 medium with a high constraint on RISK-F-0001's remediation, filed as a peer and escalated only on the ordering, RISK-F-0003 high/embargoed/no escalation. No unset field remains. REGISTER.md is generated; make check reports overdue, stalled, ungraded and unanswered escalations without changing anything. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
e268259f94
commit
d5a3953f2e
15 changed files with 1334 additions and 14 deletions
116
docs/method/disclosure.md
Normal file
116
docs/method/disclosure.md
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
---
|
||||
id: RISK-METHOD-DISCLOSURE
|
||||
type: method
|
||||
title: "Disclosure: publish now, hold, or restrict"
|
||||
status: adopted
|
||||
owner: risk-nexus
|
||||
adopted: "2026-08-19"
|
||||
workplan: RISK-WP-0001-T02
|
||||
review_interval: 180d
|
||||
---
|
||||
|
||||
# Disclosure
|
||||
|
||||
Whether and when a finding is published. `policy-nexus` is the surface; this
|
||||
document decides what it is handed.
|
||||
|
||||
## What disclosure is not
|
||||
|
||||
**A finding file in this repo is not a publication.** This repo is a private
|
||||
checkout on a private forge. Holding a finding means not routing it to
|
||||
`policy-nexus`; it does not mean hiding it from the estate, from the owning
|
||||
repo, or from the operator. Every state below is fully visible internally.
|
||||
|
||||
## The states
|
||||
|
||||
| State | Meaning | Entry condition |
|
||||
| --- | --- | --- |
|
||||
| `public` | Published through `policy-nexus` now. | The finding is fixed, or reading it gives no one an advantage they do not already have. |
|
||||
| `embargoed` | Held, with a stated condition that lifts it. | Live, unfixed, and the text would help someone reach the defect faster than they could without it. |
|
||||
| `restricted` | Held with no expected lift. | Publication would remain harmful after the fix — third-party material, a named person, or a credential-shaped detail that survives remediation. |
|
||||
|
||||
There is no fourth state and no `unset` after grading. A finding whose
|
||||
disclosure has not been decided is an ungraded finding.
|
||||
|
||||
## Embargo is a record, not a silence
|
||||
|
||||
`INTENT.md` requires the record that a delay was deliberate rather than a
|
||||
document quietly going missing. An `embargoed` finding therefore carries:
|
||||
|
||||
```yaml
|
||||
disclosure: embargoed
|
||||
embargo_condition: "FLEX-WP-0015-T02 ships to production"
|
||||
embargo_since: "2026-08-19"
|
||||
embargo_review: "2026-08-26"
|
||||
```
|
||||
|
||||
`embargo_condition` must be an event someone can observe, not a mood. "Until
|
||||
it is safer" is not a condition. `embargo_review` follows the finding's
|
||||
severity interval from `docs/method/review.md`; when it passes, the embargo is
|
||||
re-decided, not extended by default.
|
||||
|
||||
An embargo that has outlived two consecutive reviews without its condition
|
||||
moving is itself a finding — the remediation has stalled, and the hold is now
|
||||
doing the work the fix was supposed to do.
|
||||
|
||||
## The build-mode deferral, re-taken
|
||||
|
||||
`INTENT.md` recorded controlled disclosure as deferred to production, reasoning
|
||||
that build mode has no users to expose. `RISK-F-0001` arrived and tested it: a
|
||||
live authorization bypass in the service every other service trusts, with
|
||||
publish-or-forget as the only available choice.
|
||||
|
||||
**The deferral is narrowed, not kept and not abandoned.**
|
||||
|
||||
What was right about it: build mode does have no consumers to protect, and
|
||||
building an embargo *mechanism* — timed release, staged notification,
|
||||
coordinated disclosure with third parties — before there is anyone to
|
||||
coordinate with would be machinery for its own sake.
|
||||
|
||||
What was wrong about it: it conflated the mechanism with the decision. The
|
||||
argument for publishing in build mode is that there are no users to expose.
|
||||
That argument says nothing about attackers, and `RISK-F-0001` is exactly the
|
||||
class where the two come apart — the finding names an unauthenticated
|
||||
decision surface and the service that carries it. Publishing that while it is
|
||||
live helps precisely one kind of reader.
|
||||
|
||||
So the ruling is:
|
||||
|
||||
1. **Build-mode default stays publish.** Architecture, method, fixed findings,
|
||||
and findings whose exposure is already bounded go out. The estate publishing
|
||||
what it knows is wrong remains the norm and does not need a case made for it
|
||||
each time.
|
||||
2. **Live-and-reachable is the exception, and it exists now.** A finding that
|
||||
is unfixed *and* whose text shortens the path to the defect is `embargoed`
|
||||
until the fix lands. That is the missing middle `INTENT.md` said did not
|
||||
exist. It costs one front-matter field and a line in `REGISTER.md`.
|
||||
3. **The mechanism stays deferred.** No timed release, no coordinated
|
||||
disclosure protocol, no notification tiers. Those wait for real users, as
|
||||
originally reasoned. What is not deferred is the *decision*, because
|
||||
`RISK-F-0001` demonstrated the decision is needed before the machinery is.
|
||||
|
||||
This is a decision of this repo, taken 2026-08-19 with `RISK-F-0001`,
|
||||
`RISK-F-0002` and `RISK-F-0003` in hand rather than hypothetically. It is
|
||||
revisable, and the production transition is the scheduled moment to revisit it.
|
||||
|
||||
## Test for "shortens the path"
|
||||
|
||||
Ask: does the finding tell a reader something that materially reduces the work
|
||||
of reaching the defect, beyond what reading the repo would give them?
|
||||
|
||||
- A file path and line number in a private repo — no, that is already there.
|
||||
- "This surface authenticates nobody, here is its cluster address" — yes.
|
||||
- "These five named lanes vend real secret values without the boundary firing"
|
||||
— yes.
|
||||
- "This system had no backups configured" — no, once backups exist; yes, while
|
||||
they do not, because it names when destruction is unrecoverable.
|
||||
|
||||
When the answer is genuinely unclear, embargo and re-decide at the review. The
|
||||
cost of a wrong embargo is a delayed publication; the cost of a wrong publish
|
||||
is not recoverable.
|
||||
|
||||
## Publication happens elsewhere
|
||||
|
||||
A `public` finding is handed to `policy-nexus` under its publication contract
|
||||
and gets a permanent address there. This repo never serves it and never
|
||||
edits it after handover; corrections go through the same route as the original.
|
||||
148
docs/method/escalation.md
Normal file
148
docs/method/escalation.md
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
---
|
||||
id: RISK-METHOD-ESCALATION
|
||||
type: method
|
||||
title: "Escalation: what reaches the operator personally"
|
||||
status: proposed
|
||||
owner: the-custodian
|
||||
drafted_by: risk-nexus
|
||||
drafted: "2026-08-19"
|
||||
workplan: RISK-WP-0001-T03
|
||||
review_interval: 90d
|
||||
---
|
||||
|
||||
# Escalation
|
||||
|
||||
`INTENT.md` gives `the-custodian` the duty of deciding what must reach the
|
||||
operator personally rather than sitting in a register, and says the rule is not
|
||||
yet written. This is the rule, drafted by `risk-nexus`.
|
||||
|
||||
**Status: `proposed`.** The custodian adopts it. It is not in force until the
|
||||
front-matter says `adopted`, and an unadopted rule is worse than an unwritten
|
||||
one because it looks like coverage.
|
||||
|
||||
Getting this 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.
|
||||
|
||||
## What escalation is
|
||||
|
||||
A message to the operator personally — inbox message to `the-custodian`, and
|
||||
said out loud in whatever session is running — containing exactly four things:
|
||||
|
||||
1. the finding id and one sentence of what is true;
|
||||
2. the decision being asked for;
|
||||
3. what happens if no answer comes;
|
||||
4. by when.
|
||||
|
||||
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
|
||||
anything, it was not an escalation.
|
||||
|
||||
The operator is expected to rule, or to defer explicitly with a date. Silence
|
||||
is not resolution: an unanswered escalation past its date goes back into the
|
||||
register as an open item on this repo, visible in `REGISTER.md`, and is raised
|
||||
again once. It is never quietly dropped, and it is never repeated weekly until
|
||||
someone answers to make it stop.
|
||||
|
||||
## The triggers
|
||||
|
||||
Each of the five candidates from `INTENT.md` is adopted, dropped, or bounded.
|
||||
A trigger without a threshold is not a rule.
|
||||
|
||||
### 1. Real tenant data — adopted, bounded
|
||||
|
||||
Escalate when a finding exposes real data belonging to a real counterparty, or
|
||||
**the decision that governs access to it**, while live and unfixed.
|
||||
|
||||
The bound matters: `INTENT.md` asks whether governing the access counts as
|
||||
exposing the data. It does. An authorization oracle that can be forged is not
|
||||
one step removed from the data; it is the step. Test data and empty tenants do
|
||||
not trigger it — the word is *real*.
|
||||
|
||||
### 2. Legal or regulatory obligation — adopted, unbounded
|
||||
|
||||
Escalate when a finding creates or reveals an obligation with an outside
|
||||
counterparty: a notification duty, a retention or erasure requirement, a
|
||||
contractual commitment, an in-scope determination under a regime.
|
||||
|
||||
No threshold. The estate cannot decide unilaterally that an obligation is
|
||||
small, and this repo is explicitly not the place where legal advice is given.
|
||||
|
||||
### 3. Spend — adopted, bounded
|
||||
|
||||
Escalate when remediation needs money that is not already committed:
|
||||
**recurring above €50/month, or one-off above €500.**
|
||||
|
||||
Below those, the owning repo decides and records it. The numbers are a
|
||||
starting proposal from this repo; the operator owns them and should overwrite
|
||||
them on adoption if they are wrong.
|
||||
|
||||
### 4. Ownership disagreement — adopted, bounded by one exchange
|
||||
|
||||
Escalate when two repos disagree about who owns a fix **and one routing
|
||||
exchange has already failed to settle it.**
|
||||
|
||||
Disagreement itself is normal and is the register's job to route. What needs
|
||||
the operator is a *stuck* disagreement, because only the operator can assign
|
||||
work across repos that will not take it. One exchange, then escalate — not
|
||||
three, and not zero.
|
||||
|
||||
### 5. Stalled remediation — adopted, bounded by interval
|
||||
|
||||
Escalate when a finding's fix has not moved for **twice its review interval**
|
||||
(`docs/method/review.md`): 14 days for `critical`, 60 for `high`, 180 for
|
||||
`medium`. `low` findings do not escalate on staleness; they age out through
|
||||
review.
|
||||
|
||||
"Not moved" means the fix owner's tracking record has not changed state and no
|
||||
new evidence has arrived. A deliberate, stated deferral by the owner is
|
||||
movement. Silence is not.
|
||||
|
||||
### 6. Ordering hazard across repos — added
|
||||
|
||||
Escalate once when remediating finding A in the wrong order relative to
|
||||
finding B would create a **false attestation** — a control that starts
|
||||
claiming a check happened when it did not.
|
||||
|
||||
This trigger is not in `INTENT.md`'s list. It is added because `RISK-F-0002`
|
||||
produced the case: enabling the `ops-warden` signing gate against a forgeable
|
||||
`flex-auth` would convert an absent control into a signed audit record
|
||||
asserting an authorization that was never made. Ordering hazards are cheap to
|
||||
avoid before the fact and expensive to detect afterwards, because the evidence
|
||||
is what lies.
|
||||
|
||||
The escalation is a single acknowledgement of the ordering, not a standing
|
||||
supervision request. Once the operator has the constraint, the register carries
|
||||
it.
|
||||
|
||||
## What does not escalate
|
||||
|
||||
Stated so the rule bites in both directions.
|
||||
|
||||
- **Known, owned, and moving.** However bad. A `critical` finding with an
|
||||
active fix and a responsive owner is register work.
|
||||
- **Severity alone.** There is deliberately no "escalate everything
|
||||
`critical`" trigger. Severity drives review cadence, not the operator's
|
||||
attention. `RISK-F-0002` argued its own case for not escalating and was
|
||||
right on triggers 1-5; it reaches the operator only through trigger 6, and
|
||||
only once.
|
||||
- **The reporter asking for it.** A repo can flag that it thinks something
|
||||
needs the operator. That is input, not a decision. This repo rules.
|
||||
- **Anything this repo can decide itself.** Severity, disclosure, filing
|
||||
shape, review dates. Asking the operator to confirm a judgement that is this
|
||||
repo's to make is how the operator becomes the queue.
|
||||
|
||||
## 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`.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
109
docs/method/review.md
Normal file
109
docs/method/review.md
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
---
|
||||
id: RISK-METHOD-REVIEW
|
||||
type: method
|
||||
title: "Review and expiry: what happens when nobody looks"
|
||||
status: adopted
|
||||
owner: risk-nexus
|
||||
adopted: "2026-08-19"
|
||||
workplan: RISK-WP-0001-T04
|
||||
review_interval: 180d
|
||||
---
|
||||
|
||||
# Review and expiry
|
||||
|
||||
`INTENT.md`: a finding that has sat untouched past its review date is itself a
|
||||
finding. Silence is not resolution. This document makes that operable.
|
||||
|
||||
## Intervals
|
||||
|
||||
Set from the headline severity at grading time, and reset at each review.
|
||||
|
||||
| Severity | Interval | Stale (2×, escalation trigger 5) |
|
||||
| --- | --- | --- |
|
||||
| `critical` | 7 days | 14 days |
|
||||
| `high` | 30 days | 60 days |
|
||||
| `medium` | 90 days | 180 days |
|
||||
| `low` | 180 days | — (ages out through review) |
|
||||
|
||||
A finding graded `critical` is being looked at weekly or it is not being
|
||||
managed. If weekly is unbearable, the honest response is to re-grade it, not
|
||||
to let the date slide.
|
||||
|
||||
## What a review is
|
||||
|
||||
Four questions, answered in writing on the finding. It takes minutes; it is not
|
||||
an investigation.
|
||||
|
||||
1. **Is the grade still right?** Re-read impact and likelihood against what has
|
||||
changed. New facts move the grade in both directions.
|
||||
2. **Is the blocker still true?** This is the one `RISK-F-0002` bought with
|
||||
evidence: *a blocker is a claim about the world at a date*. Its own stated
|
||||
blocker — "`flex-auth` is not deployed yet" — was invalidated within a day
|
||||
by `RISK-F-0001`, and nothing would have re-checked it. Every review
|
||||
re-checks every stated blocker.
|
||||
3. **Has the fix moved?** Read the owner's tracking record, not our memory of
|
||||
it. Confirm the record still exists and still refers to this defect.
|
||||
4. **Is the disclosure state still right?** An embargo whose condition has
|
||||
been met is published; an embargo whose condition has not moved in two
|
||||
reviews is a stall.
|
||||
|
||||
The finding gets a dated line under `## Reviews`, `last_reviewed` is updated,
|
||||
and `review_by` is pushed by one interval. A review that changes nothing still
|
||||
writes the line — "checked, nothing moved" is the evidence that the silence was
|
||||
observed rather than accidental.
|
||||
|
||||
## When a review is missed
|
||||
|
||||
Overdue is not a status change on the finding. It is a fact about *this repo*,
|
||||
and it surfaces in three places:
|
||||
|
||||
- `make check` reports it (`tools/register_check.py`), always, unconditionally.
|
||||
- `REGISTER.md` shows the finding as overdue with the day count.
|
||||
- At **twice** the interval, escalation trigger 5 fires for `critical`,
|
||||
`high` and `medium`. That is the point at which the register's own silence
|
||||
reaches the operator.
|
||||
|
||||
The register does not auto-escalate severity for lateness, and it does not
|
||||
auto-close anything. Both would be the register lying about its own state to
|
||||
make a number look better.
|
||||
|
||||
## The production re-score
|
||||
|
||||
Every finding carries `severity_at_production` alongside `severity`
|
||||
(`docs/method/severity.md`). Where the two differ, the finding is flagged
|
||||
`production_rescore: true`.
|
||||
|
||||
On the day any part of the estate declares production readiness, every flagged
|
||||
finding is re-scored before that declaration completes. This is not a review
|
||||
date — it is an event, and it fires regardless of where the review dates
|
||||
happen to sit.
|
||||
|
||||
Until then, `make check` lists the flagged findings so the size of that
|
||||
obligation is visible rather than discovered on the day.
|
||||
|
||||
## Front-matter this adds
|
||||
|
||||
```yaml
|
||||
last_reviewed: "2026-08-19"
|
||||
review_by: "2026-08-26"
|
||||
production_rescore: true
|
||||
```
|
||||
|
||||
`review_by` is what the nag reads. It is a date, never a duration, so that
|
||||
nothing has to recompute an interval to know whether a finding is late.
|
||||
|
||||
## Closing a finding
|
||||
|
||||
A finding leaves `open` for exactly one of:
|
||||
|
||||
- `fixed` — the owner's record shows the defect gone, and this repo has read
|
||||
something concrete rather than been told. Publication follows if the
|
||||
disclosure state was `embargoed`.
|
||||
- `accepted` — the estate is deliberately carrying it. Requires who accepted
|
||||
it, why, and a re-review date. `accepted` is not `closed`; it keeps a review
|
||||
interval forever.
|
||||
- `withdrawn` — the finding was wrong, or the defect never existed. Say which.
|
||||
|
||||
There is no `stale`, no `wontfix` and no silent expiry. A finding that nobody
|
||||
will fix and nobody will accept stays `open` and keeps arriving in the nag,
|
||||
because that is the true state.
|
||||
169
docs/method/severity.md
Normal file
169
docs/method/severity.md
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
---
|
||||
id: RISK-METHOD-SEVERITY
|
||||
type: method
|
||||
title: "Severity: how bad, how likely, and what is not a risk at all"
|
||||
status: adopted
|
||||
owner: risk-nexus
|
||||
adopted: "2026-08-19"
|
||||
workplan: RISK-WP-0001-T01
|
||||
review_interval: 180d
|
||||
---
|
||||
|
||||
# Severity
|
||||
|
||||
This is `risk-nexus`'s judgement instrument. It is not canon, it is not a
|
||||
standard, and it binds nobody else. It exists so that two findings graded a
|
||||
month apart are graded the same way, and so that a grade can be argued with.
|
||||
|
||||
It was written against three real findings (`RISK-F-0001`, `RISK-F-0002`,
|
||||
`RISK-F-0003`) and it must keep grading those three sensibly or it is wrong.
|
||||
|
||||
## The two axes
|
||||
|
||||
### Impact — what happens if it goes wrong once
|
||||
|
||||
| Band | Name | Test |
|
||||
| --- | --- | --- |
|
||||
| `I1` | negligible | Confined to one component. No data leaves it, no record is falsified, no recovery is lost. |
|
||||
| `I2` | limited | One system's data or availability. Recoverable. Confined to a single tenant, actor or lane. |
|
||||
| `I3` | serious | Crosses a boundary — tenant, system, or trust — or removes recoverability for one system. |
|
||||
| `I4` | severe | Crosses the estate. What is compromised here propagates to everything that trusts it, or the data loss is unbounded. |
|
||||
|
||||
Impact is scored at **one occurrence**, not at the worst imaginable campaign.
|
||||
"An attacker who already owns the cluster could do this too" is not an impact
|
||||
argument.
|
||||
|
||||
### Likelihood — how far anyone has to reach
|
||||
|
||||
| Band | Name | Test |
|
||||
| --- | --- | --- |
|
||||
| `L1` | remote | Requires access nobody currently holds and no ordinary process grants. |
|
||||
| `L2` | possible | Requires a foothold the estate does grant somewhere — an in-cluster workload, an agent session, a scoped token. |
|
||||
| `L3` | likely | Reachable from inside the normal working set with no additional step. |
|
||||
| `L4` | present | No barrier at all, or it is already happening. |
|
||||
|
||||
Likelihood is about **reach**, not about intent or about whether anyone has
|
||||
bothered. `risk-nexus` does not model attackers; it models what the system
|
||||
permits.
|
||||
|
||||
Where the reporter has not established exposure, the finding says so and the
|
||||
grade uses the band the *stated* facts support — not the worst case, and not
|
||||
zero. `RISK-F-0001` explicitly declines to assume a default-deny NetworkPolicy
|
||||
exists; the grade must decline with it, and the unverified fact becomes a
|
||||
review item rather than a silent assumption in either direction.
|
||||
|
||||
## The grid
|
||||
|
||||
| | `L1` | `L2` | `L3` | `L4` |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `I4` | medium | high | **critical** | **critical** |
|
||||
| `I3` | low | medium | high | **critical** |
|
||||
| `I2` | low | low | medium | high |
|
||||
| `I1` | note | low | low | medium |
|
||||
|
||||
Four severities: `low`, `medium`, `high`, `critical`. `note` is not a
|
||||
severity; see the floor.
|
||||
|
||||
## The fidelity modifier
|
||||
|
||||
**A control that lies is one impact band worse than the same control absent.**
|
||||
|
||||
Apply `+1` impact band (capped at `I4`) when the failure mode produces a
|
||||
*false record* rather than *no record*: an attestation that a check passed
|
||||
when nothing checked, an audit line asserting an authorization that was never
|
||||
made, a green signal derived from an unreachable test.
|
||||
|
||||
The reasoning is `RISK-F-0002`'s and the register adopts it: an absent control
|
||||
is a gap you can find by looking; a lying control is a gap that survives
|
||||
looking, because the evidence you would look at is the thing that is wrong.
|
||||
Only one of the two states misleads the person investigating afterwards.
|
||||
|
||||
The modifier applies to the state being scored. A finding that describes both
|
||||
states — control absent today, control lying if switched on in the wrong order —
|
||||
gets **two scores and one of them is the register's headline**; see
|
||||
"Which state is scored".
|
||||
|
||||
## Which state is scored
|
||||
|
||||
The headline `severity` is the state of the world **today**. A hazard that
|
||||
would be created by a *future* action is not the headline, because a register
|
||||
that scores hypotheticals stops describing the estate.
|
||||
|
||||
The hazard is not lost. It is recorded on the finding as a named
|
||||
**constraint** with its own grade, and it attaches to whatever action would
|
||||
trigger it — usually another finding's remediation. `RISK-F-0002` is the
|
||||
worked example: the gate being off is today (headline), the gate being
|
||||
switched on while the oracle is forgeable is a constraint on `RISK-F-0001`'s
|
||||
fix, graded separately and higher.
|
||||
|
||||
If the constraint's grade is higher than the headline, the finding says so in
|
||||
its ruling. A reader must not be able to come away with the low number and
|
||||
miss the high one.
|
||||
|
||||
## Build mode
|
||||
|
||||
Every finding is graded twice:
|
||||
|
||||
- `severity` — today, in build mode, with today's likelihood.
|
||||
- `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.
|
||||
|
||||
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.
|
||||
|
||||
## The floor
|
||||
|
||||
`INTENT.md`: if a finding would not change anyone's decision, it is a note,
|
||||
not a risk. Concretely, a register entry requires **both**:
|
||||
|
||||
1. **An owner who could act.** Some repo, or the operator, can do something
|
||||
about it. No actor, no entry.
|
||||
2. **A decision that changes.** Recording it alters what someone does, when
|
||||
they do it, or what they must not do first.
|
||||
|
||||
Fails either test → it is a note in `notes/`, not a finding in `findings/`.
|
||||
Notes are not graded, not reviewed, and not published. They exist so that
|
||||
"we saw it" survives without inflating the register.
|
||||
|
||||
An `I1`/`L1` cell is `note` in the grid for the same reason: something that
|
||||
is both negligible and unreachable is a thing we know, not a risk we carry.
|
||||
|
||||
Two things the floor does **not** exclude:
|
||||
|
||||
- **Known and deliberate.** `RISK-F-0002` is a decision somebody made on
|
||||
purpose. It still passes the floor, because it changes what may be switched
|
||||
on and in what order. Deliberate is not the same as tracked.
|
||||
- **Omission-shaped.** `RISK-F-0003` is a default that silently produces
|
||||
ungoverned lanes. The individual lane is small; the default is not.
|
||||
|
||||
## Provenance is a grading input
|
||||
|
||||
All four defects known to this register were found by repos reading their own
|
||||
code against a ladder, within days of each other. None was found by monitoring.
|
||||
|
||||
Where a finding's provenance is "we happened to look", the register does not
|
||||
get to assume that similar defects would have been caught. That raises
|
||||
likelihood for the class, not for the instance, and it belongs in the ruling's
|
||||
reasoning rather than in a modifier — the register grades what is filed, and
|
||||
notes when the filing was luck.
|
||||
|
||||
## Recording a grade
|
||||
|
||||
The finding's front-matter carries:
|
||||
|
||||
```yaml
|
||||
severity: critical # headline, today
|
||||
severity_at_production: critical
|
||||
impact: I4 # band, before modifiers
|
||||
likelihood: L3
|
||||
fidelity_modifier: false # true if +1 applied, with the reason in the ruling
|
||||
```
|
||||
|
||||
and the ruling section states impact, likelihood, any modifier, and the one
|
||||
sentence that would have to become false for the grade to change.
|
||||
Loading…
Add table
Add a link
Reference in a new issue