RISK-WP-0004: five of six tasks done; the executor is the operator's call
T02 inbox check, wired into make check and verified against the actual 2026-08-19 failure — replayed at that moment it surfaces all three messages that were already waiting. T03 sweeps the rest of the quietly-tolerated class: bad dates, cadence off the ladder, undefined disclosure states, dangling constraint_on and related refs, embargoes without conditions, escalations without triggers. T04 requests verification of user-engine's tenant boundary — the first walk down the on-request path, chosen as a consumer not already known to fail it. T05 established by trying what this register can verify: cluster yes, OpenBao 403. T06 puts regulatory records on the findings ladder. T01 stays in progress: the procedure, make due and make checked exist, but arming something that runs them on schedule is a standing compute commitment and the operator's to make. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
97fcc56a4d
commit
36b707f0c3
10 changed files with 296 additions and 9 deletions
BIN
tools/__pycache__/inbox_check.cpython-312.pyc
Normal file
BIN
tools/__pycache__/inbox_check.cpython-312.pyc
Normal file
Binary file not shown.
Binary file not shown.
72
tools/inbox_check.py
Normal file
72
tools/inbox_check.py
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Has the inbox spoken more recently than the register has looked?
|
||||
|
||||
RISK-WP-0004-T02. On 2026-08-19 this register graded RISK-F-0001 `critical`
|
||||
while its fix notice sat unread in the inbox. The residual said: if it slips
|
||||
again, make it a check. It slipped once, so here is the check.
|
||||
|
||||
Mechanical only. It compares timestamps and matches on the system name; it does
|
||||
not read the message and does not decide anything. It reports findings whose
|
||||
inbox has spoken since the register last looked.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
|
||||
import register_lib as lib
|
||||
|
||||
HUB = "http://127.0.0.1:8000/messages/?to_agent=risk-nexus&limit=100"
|
||||
|
||||
|
||||
def fetch() -> list[dict] | None:
|
||||
try:
|
||||
with urllib.request.urlopen(HUB, timeout=6) as r:
|
||||
return json.load(r)
|
||||
except (urllib.error.URLError, TimeoutError, json.JSONDecodeError, OSError):
|
||||
return None
|
||||
|
||||
|
||||
def main() -> int:
|
||||
msgs = fetch()
|
||||
if msgs is None:
|
||||
# Fail loud: an unreachable inbox means no check can be certified current.
|
||||
print("Inbox: UNREACHABLE — the hub did not answer.")
|
||||
print(" No check can be certified current while this is true.")
|
||||
print(" Findings may have moved without the register hearing about it.")
|
||||
return 0
|
||||
|
||||
fs = [f for f in lib.findings() if lib.watched(f.get("status"))]
|
||||
rows = []
|
||||
for f in fs:
|
||||
looked = lib.moment(f.get("last_checked"))
|
||||
system = str(f.get("system", "")).lower()
|
||||
owner = str(f.get("fix_owner", "")).lower()
|
||||
if not looked or not system:
|
||||
continue
|
||||
for m in msgs:
|
||||
said = lib.moment(m.get("created_at"))
|
||||
if not said or said <= looked:
|
||||
continue
|
||||
blob = f"{m.get('subject','')} {m.get('body','')} {m.get('from_agent','')}".lower()
|
||||
if system in blob or (owner and owner in blob) or f["id"].lower() in blob:
|
||||
rows.append(
|
||||
f"{f['id']} — last looked {looked:%Y-%m-%d %H:%MZ}; "
|
||||
f"{m.get('from_agent')} wrote {said:%Y-%m-%d %H:%MZ}: {m.get('subject','')[:70]}"
|
||||
)
|
||||
break
|
||||
|
||||
print(f"Inbox: {len(msgs)} message(s) addressed to risk-nexus\n")
|
||||
if rows:
|
||||
print("Findings whose inbox has spoken since the register last looked:")
|
||||
for r in rows:
|
||||
print(f" {r}")
|
||||
print("\n Read those before grading or checking. This is question zero.")
|
||||
else:
|
||||
print("No finding has an inbox message newer than its last check.")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
|
|
@ -44,6 +44,36 @@ def main() -> int:
|
|||
if unknown:
|
||||
section("Unrecognised status", unknown, "none")
|
||||
|
||||
# T03 — the `mitigated` defect was one instance of a class: the tooling
|
||||
# quietly tolerating something it did not expect. Everything below is
|
||||
# reported by name, and never silently ignored.
|
||||
ids = {f["id"] for f in lib.findings()}
|
||||
malformed: list[str] = []
|
||||
for f in fs:
|
||||
fid = f["id"]
|
||||
for field in ("last_checked", "next_check", "embargo_since", "deferred_to"):
|
||||
if f.get(field) and lib.moment(f[field]) is None:
|
||||
malformed.append(f"{fid} — {field} is not a date: {f[field]!r}")
|
||||
if (c := f.get("cadence")) and c not in lib.CADENCE_NAMES:
|
||||
malformed.append(f"{fid} — cadence '{c}' is not a rung on the ladder")
|
||||
if (d := f.get("disclosure")) and d not in ("public", "embargoed", "restricted", "unset"):
|
||||
malformed.append(f"{fid} — disclosure '{d}' is not a defined state")
|
||||
if (s := f.get("severity")) and s not in lib.SEVERITIES + ["unset"]:
|
||||
malformed.append(f"{fid} — severity '{s}' is not on the scale")
|
||||
if (on := f.get("constraint_on")) and on not in ids:
|
||||
malformed.append(f"{fid} — constraint_on points at {on}, which does not exist")
|
||||
for ref in (f.get("related") or []):
|
||||
if ref not in ids:
|
||||
malformed.append(f"{fid} — related names {ref}, which does not exist")
|
||||
if f.get("embargo_condition") and f.get("disclosure") != "embargoed":
|
||||
malformed.append(f"{fid} — carries an embargo_condition but disclosure is '{f.get('disclosure')}'")
|
||||
if f.get("disclosure") == "embargoed" and not f.get("embargo_condition"):
|
||||
malformed.append(f"{fid} — embargoed with no condition; a hold with no lift is a silence")
|
||||
if f.get("escalation") == "required" and not f.get("escalation_trigger"):
|
||||
malformed.append(f"{fid} — escalated with no trigger named")
|
||||
if malformed:
|
||||
section("Malformed", malformed, "none")
|
||||
|
||||
ungraded = [
|
||||
f"{f['id']} — {', '.join(k for k in lib.GRADED_FIELDS if str(f.get(k, 'unset')) == 'unset')}"
|
||||
for f in fs
|
||||
|
|
@ -112,6 +142,15 @@ def main() -> int:
|
|||
]
|
||||
section("Owed at the production transition", rescore, "none — no finding is graded lower for build mode")
|
||||
|
||||
reg = []
|
||||
for r in lib.regulatory():
|
||||
when = lib.moment(r.get("next_check")) or lib.moment(r.get("review_by"))
|
||||
if when is None:
|
||||
reg.append(f"{r.get('id')} — no next_check set")
|
||||
elif NOW >= when:
|
||||
reg.append(f"{r.get('id')} — due {when:%Y-%m-%d}: {str(r.get('title','')).strip()}")
|
||||
section("Regulatory records due", reg, "none")
|
||||
|
||||
print(f"Register check — {NOW:%Y-%m-%d %H:%MZ}\n{len(fs)} live finding(s)\n")
|
||||
print("\n".join(lines).rstrip())
|
||||
return 0
|
||||
|
|
|
|||
|
|
@ -77,6 +77,15 @@ def findings() -> list[dict]:
|
|||
return sorted(items, key=lambda f: f["id"], reverse=True)
|
||||
|
||||
|
||||
def regulatory() -> list[dict]:
|
||||
"""Regulatory records expire, so they ride the same ladder as findings."""
|
||||
d = REPO / "docs" / "regulatory"
|
||||
if not d.exists():
|
||||
return []
|
||||
return sorted((load(p) for p in d.glob("*.md") if p.name != "README.md"),
|
||||
key=lambda r: r.get("id", ""))
|
||||
|
||||
|
||||
def notes() -> list[dict]:
|
||||
if not NOTES.exists():
|
||||
return []
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue