Assistant: claude-code Assistant-Model: opus Assistant-Process: 2583210@bnt-lap001 Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
212 lines
11 KiB
Markdown
212 lines
11 KiB
Markdown
---
|
|
id: RISK-WP-0004
|
|
type: workplan
|
|
title: "Run the register: make the cadence actually happen, and close the gaps the first week found"
|
|
domain: infotech
|
|
repo: risk-nexus
|
|
status: finished
|
|
owner: the-custodian
|
|
topic_slug: risk-nexus
|
|
created: "2026-08-20"
|
|
updated: "2026-08-20"
|
|
depends_on_workplans:
|
|
- RISK-WP-0001
|
|
state_hub_workstream_id: "aeb4047e-6a43-5922-9a31-6de9bc79327a"
|
|
---
|
|
|
|
# RISK-WP-0004 — run the register
|
|
|
|
**Draft.** `RISK-WP-0001` built the instruments. This one is about the register
|
|
being *operated*, which is a different thing and the one that fails quietly.
|
|
|
|
## Goal
|
|
|
|
Nine findings, two notes, a regulatory record and an adaptive cadence exist.
|
|
**Nothing currently performs a check.** `make check` says what is due; a person
|
|
or an agent has to read the finding, ask the five questions, and record the
|
|
outcome. If that does not happen, every finding sits at `instant` forever and
|
|
the ladder becomes decoration.
|
|
|
|
Done means: checks happen on their own schedule without the operator
|
|
remembering, the register's own known gaps are closed, and the failure modes
|
|
found in the first week cannot recur silently.
|
|
|
|
## What the first week actually found
|
|
|
|
Every task below traces to something that happened, not something imagined.
|
|
|
|
| What happened | Task |
|
|
| --- | --- |
|
|
| Graded `RISK-F-0001` `critical` while its fix notice sat unread in the inbox | T02 |
|
|
| `RISK-F-0003` returned as `mitigated`, a word the tooling did not know, and vanished from the nag | fixed ad hoc; T03 generalises it |
|
|
| `ops-warden` and this register both used `RISK-F-0004` | fixed ad hoc; duplicate check now in `make check` |
|
|
| Two gradings rest on file comparison because an operator token is expired | T05 |
|
|
| `RISK-F-0007` accepted with an on-request path nobody has exercised | T04 |
|
|
|
|
## Tasks
|
|
|
|
### T01 — Something performs the checks
|
|
|
|
```task
|
|
id: RISK-WP-0004-T01
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "e8f5b149-48a5-5875-9ff6-23ba51880a84"
|
|
```
|
|
|
|
`tools/record_check.py` moves a finding along the ladder and writes the dated
|
|
line. What is missing is the thing that *calls* it on schedule.
|
|
|
|
Options, in ascending order of how much this repo should want them: a scheduled
|
|
agent session that runs `make check`, works the due list, and records outcomes;
|
|
a cron that only reports; a human habit. The first is the only one that
|
|
survives the operator being busy, which is the condition the whole ladder is
|
|
designed for.
|
|
|
|
Whatever it is, the check must remain a **judgement** — re-read the grade,
|
|
re-check every stated blocker, read the owner's tracking record. A job that
|
|
stamps `clean` without doing that is worse than no job, because it manufactures
|
|
a stability signal that is false. That is the `RISK-F-0002` failure mode
|
|
applied to this repo's own instruments.
|
|
|
|
Completed 2026-08-20, in two halves. The procedure exists (`docs/method/check-procedure.md`), `make due` prints the work list, and `make checked` records an outcome. **What does not exist is the thing that runs it on schedule**, and this register does not get to arm a standing compute commitment on the operator's behalf. The doc names the three options and says which survives the operator being busy. The operator chose the scheduled agent, on `activity-core`, and it is written:
|
|
|
|
- `activity-definitions/hourly-register-inbox-watch.md` — hourly at :05, fires
|
|
**only when an unread message is waiting for `risk-nexus`**. The inbox is the
|
|
trigger rather than the clock: an unread message is by construction a claim
|
|
that something in the register may have moved, and 2026-08-19 proved the
|
|
register will otherwise grade without looking.
|
|
- `activity-definitions/daily-register-check-sweep.md` — daily at 07:15,
|
|
unconditional. The floor that guarantees the question gets asked.
|
|
|
|
Both emit an **instruction to a session that can exercise judgement**. Neither
|
|
grades, closes, publishes, escalates nor records an outcome, and both say so in
|
|
their own text: stamping `clean` without doing the five questions produces a
|
|
`1q` rung that is a lie about stability — `RISK-F-0002`'s failure mode turned
|
|
on this register's own instruments.
|
|
|
|
Residual, routed rather than worked around: no context resolver knows what this
|
|
register has due, so the instruction says "run `make due`" instead of naming
|
|
findings. A `risk_register_due` query in `activity-core` would let the daily
|
|
sweep fire only when something is actually due. It works without it; it is
|
|
just louder than it needs to be.
|
|
|
|
The definitions are the ADR-001 source of truth. Live rows pick them up on the
|
|
next `make sync-activity-definitions`, which runs on the Railiance deployment
|
|
and not from this checkout.
|
|
|
|
### T02 — Inbox before grading, as a check rather than a habit
|
|
|
|
```task
|
|
id: RISK-WP-0004-T02
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "59196b2c-df84-5e35-abc3-a22ce18da882"
|
|
```
|
|
|
|
`RISK-WP-0001`'s residual says: if it slips again, make it a check. It has
|
|
slipped once, on the register's first day, and cost a wrong grade and a nearly
|
|
sent escalation.
|
|
|
|
`make check` should compare each finding's `last_checked` against the newest
|
|
message this repo has received about that system, and report any finding whose
|
|
inbox has spoken more recently than its register has. That is mechanical and
|
|
does not require the tooling to understand the message.
|
|
|
|
Completed 2026-08-20. `tools/inbox_check.py`, wired into `make check`. Compares each finding's `last_checked` against messages this repo has received about that system, and reports any finding whose inbox has spoken since the register last looked. Mechanical: it matches timestamps and names, reads nothing, decides nothing. Verified against the actual failure — replayed at the moment of the 2026-08-19 grading it surfaces all three flex-auth/rapp-postgres messages that were already waiting. An unreachable hub reports UNREACHABLE rather than silently passing, because a check that cannot see the inbox cannot be certified current.
|
|
|
|
### T03 — Fail loud everywhere else too
|
|
|
|
```task
|
|
id: RISK-WP-0004-T03
|
|
status: done
|
|
priority: medium
|
|
state_hub_task_id: "4cc53842-7221-5f25-89cc-d3916c18f212"
|
|
```
|
|
|
|
The `mitigated` defect was one instance of a class: the tooling quietly
|
|
tolerating something it did not expect. Sweep for the rest — unknown disclosure
|
|
states, unparseable dates, a `constraint_on` pointing at a finding that does
|
|
not exist, an `embargo_condition` on a finding that is not embargoed.
|
|
|
|
Every one of them should be reported by name and keep the finding watched.
|
|
|
|
Completed 2026-08-20. `make check` now reports, by name and without ever silently ignoring: unparseable dates, a cadence that is not a rung, an undefined disclosure state, a severity off the scale, a `constraint_on` or `related` pointing at a finding that does not exist, an embargo condition on a finding that is not embargoed, an embargo with no condition, and an escalation with no trigger. Nothing is malformed today, which is the answer that only means something because the check exists.
|
|
|
|
### T04 — Exercise the on-request verification path once
|
|
|
|
```task
|
|
id: RISK-WP-0004-T04
|
|
status: done
|
|
priority: medium
|
|
state_hub_task_id: "681e7bab-f645-5be4-a028-ec6f5b65923a"
|
|
```
|
|
|
|
`RISK-F-0007` is accepted until production on the strength of a path nobody has
|
|
used. A route that has never been walked is a plan, not a route.
|
|
|
|
Pick one named consumer boundary, request verification through the documented
|
|
path, and see what actually happens: who answers, what evidence comes back,
|
|
whether the finding's likelihood moves for that consumer, and what the record
|
|
looks like. The value is in the friction it exposes.
|
|
|
|
Completed 2026-08-20 as far as this repo can complete it. `RISK-V-0002`: verification of `user-engine`'s tenant boundary requested through the documented path. `user-engine` was chosen because they are a consumer with a boundary and *not* already carrying a finding about one — using `tenant-engine` or `audit-core` would have tested the path against systems already known to fail it. The outcome is pending and all three outcomes are useful, including silence, which would tell the estate that `RISK-F-0007` is being carried on an assumption that asking works.
|
|
|
|
### T05 — The verification credential
|
|
|
|
```task
|
|
id: RISK-WP-0004-T05
|
|
status: done
|
|
priority: medium
|
|
state_hub_task_id: "ffdfd3b3-a026-5705-8dad-a0aa3c07df33"
|
|
```
|
|
|
|
`RISK-F-0009` and `RISK-F-0003`'s mitigation both rest on comparing files
|
|
because `ops-warden`'s operator token is expired and `bao policy read` cannot
|
|
be run.
|
|
|
|
That is not a finding — nothing is wrong with the estate because a token
|
|
expired — but it means the register is grading deployed controls from their
|
|
source. Establish what this repo can legitimately verify itself, and what it
|
|
must always take from owners. **If the answer is "nothing", that is worth
|
|
knowing and writing down**, because it bounds every grade in the register.
|
|
|
|
Completed 2026-08-20, by trying rather than reasoning. `docs/method/verification.md`. **Cluster reads work from this host; OpenBao returns 403**, the same wall `ops-warden` hit. So the register can check what the cluster admits and cannot check what the secret store permits, and every grade touching an OpenBao policy is a grade on a document. That asymmetry is recorded rather than closed — a risk register holding production secret-store credentials would have traded a verification problem for a worse one. First use produced `RISK-V-0001`, which confirmed `RISK-F-0001`'s ingress claim against the live cluster, contradicted the `egress: []` claim in the same message, and surfaced a third NetworkPolicy with no ingress rules that bears on whether `ops-warden` enabling its gate would fail closed.
|
|
|
|
### T06 — Regulatory records on the same ladder
|
|
|
|
```task
|
|
id: RISK-WP-0004-T06
|
|
status: done
|
|
priority: low
|
|
state_hub_task_id: "bff86b2b-28ce-53fe-8417-dee92c94fd3f"
|
|
```
|
|
|
|
Duplicate of `RISK-WP-0003-T04`, kept here as a pointer rather than a second
|
|
copy. Whichever workplan reaches it first does it; the other closes with a
|
|
reference.
|
|
|
|
Completed 2026-08-20. Regulatory records ride the findings ladder rather than getting a second review mechanism: `RISK-REG-0001` carries `cadence`, `clean_streak`, `last_checked` and `next_check`, and `make check` reports regulatory records due exactly as it reports findings. `RISK-WP-0003-T04` closes by reference.
|
|
|
|
## Non-goals
|
|
|
|
- **No dashboard.** `REGISTER.md` and `make check` are the surface, and the
|
|
register is supposed to stay small enough to read.
|
|
- **No automated grading.** A machine may schedule, list and record. Severity,
|
|
disclosure and escalation stay judgements this repo makes.
|
|
- **No monitoring of other systems.** `RISK-N-0003` records that everything
|
|
here was found by reading rather than watching; this workplan does not
|
|
attempt to change that, and a register that grows probes becomes a second
|
|
engineering team.
|
|
|
|
## Risks
|
|
|
|
**A scheduled check becomes a rubber stamp.** The whole value of the ladder is
|
|
that a `1q` rung means something. Mitigation: T01 treats stamping without
|
|
judgement as a defect, and `clean_streak` makes a suspiciously smooth climb
|
|
visible.
|
|
|
|
**The register spends its attention on itself.** Six tasks about the register's
|
|
own machinery, none of which fix a defect in the estate. Mitigation: T01, T02
|
|
and T05 all exist because the register got something wrong in week one; if
|
|
week two produces no such items, this workplan should shrink rather than grow.
|