Keep review obligations visible and reconcile owner evidence (RISK-WP-0006, RISK-WP-0007)
check_all runs every check stage even when one fails; malformed dates are reported rather than aborting; accepted findings and closure evidence are shown; defer requires a valid future date. Adds SCOPE.md, the scope assessment, the open-findings source review and a unittest suite. Stops tracking __pycache__. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 6903@bnt-lap001 Assistant-Session: 8319e8a8-ffa6-4eb3-b8bf-b29945628f89
This commit is contained in:
parent
29f50d5143
commit
bbbede5f47
25 changed files with 1007 additions and 43 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
13
Makefile
13
Makefile
|
|
@ -1,7 +1,7 @@
|
||||||
PY := python3
|
PY := python3
|
||||||
TOOLS := tools
|
TOOLS := tools
|
||||||
|
|
||||||
.PHONY: help register check checked due fixes coverage
|
.PHONY: help register check checked due fixes coverage test
|
||||||
|
|
||||||
help:
|
help:
|
||||||
@echo "make register - rebuild REGISTER.md from findings/"
|
@echo "make register - rebuild REGISTER.md from findings/"
|
||||||
|
|
@ -15,18 +15,14 @@ register:
|
||||||
@$(PY) $(TOOLS)/register_index.py
|
@$(PY) $(TOOLS)/register_index.py
|
||||||
|
|
||||||
check:
|
check:
|
||||||
@$(PY) $(TOOLS)/register_index.py --check
|
@$(PY) $(TOOLS)/check_all.py
|
||||||
@echo
|
|
||||||
@$(PY) $(TOOLS)/register_check.py
|
|
||||||
@echo
|
|
||||||
@$(PY) $(TOOLS)/inbox_check.py
|
|
||||||
|
|
||||||
checked:
|
checked:
|
||||||
@$(PY) $(TOOLS)/record_check.py $(ARGS)
|
@$(PY) $(TOOLS)/record_check.py $(ARGS)
|
||||||
@$(PY) $(TOOLS)/register_index.py
|
@$(PY) $(TOOLS)/register_index.py
|
||||||
|
|
||||||
due:
|
due:
|
||||||
@$(PY) $(TOOLS)/register_check.py | sed -n '/Checks due/,/^$$/p'
|
@$(PY) $(TOOLS)/register_check.py
|
||||||
@$(PY) $(TOOLS)/inbox_check.py
|
@$(PY) $(TOOLS)/inbox_check.py
|
||||||
|
|
||||||
fixes:
|
fixes:
|
||||||
|
|
@ -34,3 +30,6 @@ fixes:
|
||||||
|
|
||||||
coverage:
|
coverage:
|
||||||
@$(PY) $(TOOLS)/coverage.py
|
@$(PY) $(TOOLS)/coverage.py
|
||||||
|
|
||||||
|
test:
|
||||||
|
@PYTHONDONTWRITEBYTECODE=1 $(PY) -m unittest discover -s tests -v
|
||||||
|
|
|
||||||
15
README.md
15
README.md
|
|
@ -40,4 +40,19 @@ make check # verify the index, then report what is going quiet
|
||||||
embargoes due for re-decision, escalations awaiting the operator, and what is
|
embargoes due for re-decision, escalations awaiting the operator, and what is
|
||||||
owed at the production transition. It changes nothing.
|
owed at the production transition. It changes nothing.
|
||||||
|
|
||||||
|
All check stages run even when the index is stale; the command still exits
|
||||||
|
nonzero for a failed stage. `make due` shows the full obligation report and
|
||||||
|
inbox freshness, including full regulatory policies, embargo review deadlines
|
||||||
|
and publication handovers that remain pending after a finding closes.
|
||||||
|
`make checked` accepts finding, regulatory determination and full policy IDs;
|
||||||
|
it records an actual review, not a repair for an overdue warning.
|
||||||
|
|
||||||
|
`make fixes` distinguishes owner workplans from recorded acceptance obligations.
|
||||||
|
`make check` and `make due` also show explicit `closure_condition` evidence still
|
||||||
|
owed by live findings, even when a source workplan has finished. Acceptance
|
||||||
|
terms and a finished workplan are not proof of runtime closure.
|
||||||
|
|
||||||
|
Run `make test` for isolated regression checks. Python 3 and PyYAML are required.
|
||||||
|
|
||||||
- Intent: `INTENT.md`
|
- Intent: `INTENT.md`
|
||||||
|
- Current capability: [SCOPE.md](SCOPE.md)
|
||||||
|
|
|
||||||
10
REGISTER.md
10
REGISTER.md
|
|
@ -1,6 +1,6 @@
|
||||||
# Register
|
# Register
|
||||||
|
|
||||||
Generated by `tools/register_index.py` from `findings/`. Do not edit by hand. Last built 2026-09-02.
|
Generated by `tools/register_index.py` from `findings/`. Do not edit by hand. Last built 2026-09-05.
|
||||||
|
|
||||||
3 live of 11 findings; 3 notes below the floor.
|
3 live of 11 findings; 3 notes below the floor.
|
||||||
|
|
||||||
|
|
@ -9,9 +9,9 @@ Generated by `tools/register_index.py` from `findings/`. Do not edit by hand. La
|
||||||
| ID | Finding | System | Severity | Disclosure | Escalation | Fix owner | Status | Cadence | Next check |
|
| ID | Finding | System | Severity | Disclosure | Escalation | Fix owner | Status | Cadence | Next check |
|
||||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||||
| [RISK-F-0011](findings/RISK-F-0011-qonto-audit-deny-stream-completeness.md) | qonto-assistant audit.deny stream completeness is not established | qonto-assistant | medium | public | none | qonto-assistant | open | instant (0) | **due** |
|
| [RISK-F-0011](findings/RISK-F-0011-qonto-audit-deny-stream-completeness.md) | qonto-assistant audit.deny stream completeness is not established | qonto-assistant | medium | public | none | qonto-assistant | open | instant (0) | **due** |
|
||||||
| [RISK-F-0010](findings/RISK-F-0010-embedded-backup-webdav-credential.md) | Forgejo backup source embeds a WebDAV credential default | railiance-platform | low | embargoed | none | railiance-platform | open | 1h (1) | 2026-09-02 09:11Z |
|
| [RISK-F-0010](findings/RISK-F-0010-embedded-backup-webdav-credential.md) | Forgejo backup source embeds a WebDAV credential default | railiance-platform | low | embargoed | none | railiance-platform | open | instant (0) | **due** |
|
||||||
| [RISK-F-0009](findings/RISK-F-0009-openbao-deny-set-covers-a-third-of-high-risk-lanes.md) | agent-high-risk-boundary denies 6 of 17 high-risk lanes; the direct bao path is unprotected for the rest | railiance-platform | **high** | public | none | railiance-platform | fixed | instant (0) | **due** |
|
| [RISK-F-0009](findings/RISK-F-0009-openbao-deny-set-covers-a-third-of-high-risk-lanes.md) | agent-high-risk-boundary denies 6 of 17 high-risk lanes; the direct bao path is unprotected for the rest | railiance-platform | **high** | public | none | railiance-platform | fixed | instant (0) | **due** |
|
||||||
| [RISK-F-0008](findings/RISK-F-0008-audit-retention-legal-basis-assumed.md) | The legal basis for retaining audit facts against an erasure request has been assumed, never established | audit-core | medium | public | **answered** (t2, answered) | risk-nexus | accepted | 1h (1) | 2026-09-02 09:11Z |
|
| [RISK-F-0008](findings/RISK-F-0008-audit-retention-legal-basis-assumed.md) | The legal basis for retaining audit facts against an erasure request has been assumed, never established | audit-core | medium | public | **answered** (t2, answered) | risk-nexus | accepted | 1h (1) | **due** |
|
||||||
| [RISK-F-0007](findings/RISK-F-0007-unverified-tenant-boundary.md) | No consumer's tenant boundary is verified anywhere | estate | **high** | public | **answered** (t4, assigned) | per-consumer, on request | fixed | instant (0) | **due** |
|
| [RISK-F-0007](findings/RISK-F-0007-unverified-tenant-boundary.md) | No consumer's tenant boundary is verified anywhere | estate | **high** | public | **answered** (t4, assigned) | per-consumer, on request | fixed | instant (0) | **due** |
|
||||||
| [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** | public | **answered** (t3, answered) | railiance-platform | fixed | instant (0) | **due** |
|
| [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** | public | **answered** (t3, answered) | railiance-platform | fixed | instant (0) | **due** |
|
||||||
| [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 | public | none | audit-core | fixed | instant (0) | **due** |
|
| [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 | public | none | audit-core | fixed | instant (0) | **due** |
|
||||||
|
|
@ -35,8 +35,8 @@ Silence never buys a softer grade — see `docs/method/dependencies.md`.
|
||||||
|
|
||||||
| Finding | Who | What would change | Default if silent | On |
|
| Finding | Who | What would change | Default if silent | On |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| RISK-F-0011 | qonto-assistant | a published cadence plus a reconciliation view would let a later observation support completeness; a rejection keeps the grade and records that estate observation must not treat the stream as complete | the medium grade stands; missing cadence is recorded as a stalled remediation, and observation remains staffed with completeness pending | 2026-09-16 |
|
| RISK-F-0011 | qonto-assistant | accepted deployed-instance evidence supports bounded stream completeness and permits closure; source-only evidence keeps the finding open | the medium grade stands; missing deployed acceptance is recorded as a stalled remediation, and observation remains staffed with completeness pending | 2026-09-16 |
|
||||||
| RISK-F-0010 | railiance-platform | the finding becomes fixed and the embargo lifts | the low grade and embargo stand; missing fix tracking is recorded as a stalled remediation | 2026-09-15 |
|
| RISK-F-0010 | railiance-platform | the finding becomes fixed and the embargo lifts | the low grade and embargo stand; absent provider invalidation and recovery evidence is recorded as a stalled remediation | 2026-09-15 |
|
||||||
| RISK-F-0008 | audit-core | a working keyed commitment narrows RISK-REG-0001 to retained-by-obligation categories only | encrypt-then-hash recorded as the only known route, and the retention period recorded as unstateable | 2026-11-17 |
|
| RISK-F-0008 | audit-core | a working keyed commitment narrows RISK-REG-0001 to retained-by-obligation categories only | encrypt-then-hash recorded as the only known route, and the retention period recorded as unstateable | 2026-11-17 |
|
||||||
|
|
||||||
## Embargoes
|
## Embargoes
|
||||||
|
|
|
||||||
71
SCOPE.md
Normal file
71
SCOPE.md
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
# SCOPE — risk-nexus
|
||||||
|
|
||||||
|
Updated 2026-09-05 (Europe/Berlin), including RISK-WP-0006 and RISK-WP-0007. This describes the checked-in capabilities;
|
||||||
|
[INTENT.md](INTENT.md) remains the intended remit. Evidence and remaining gaps
|
||||||
|
are in the [dated assessment](history/2026-09-05-014333-scope-intent-assessment.md).
|
||||||
|
|
||||||
|
`risk-nexus` is a file-based risk register and regulatory reference collection,
|
||||||
|
owned by `the-custodian`, with Python command-line tools for indexing, review
|
||||||
|
bookkeeping and reports. Humans or agent sessions make the judgements and act
|
||||||
|
on the reports. This repository contains no web service, intake API, deployment
|
||||||
|
or independent scheduler, and does not itself serve `risk.coulomb.social`.
|
||||||
|
|
||||||
|
## What it can do
|
||||||
|
|
||||||
|
| Capability | Implemented scope and evidence |
|
||||||
|
| --- | --- |
|
||||||
|
| Record findings and notes | YAML front-matter and Markdown in `findings/` and `notes/`; [filing contract](findings/README.md) separates reporter facts from register grading. Research, review and observation have produced records. Incident intake is a written procedure; external-report contact provisioning remains routed elsewhere. |
|
||||||
|
| Grade and explain decisions | [Method instruments](docs/method/) define severity, disclosure, escalation, review, dependencies and verification. Dated rulings and finding histories record applied decisions. Scoring and acceptance are judgements, not computed decisions. |
|
||||||
|
| Generate a readable register | `make register` builds `REGISTER.md` from findings and notes, including constraints, finding waits, embargoes and cadence. It is an index, not the source of truth. |
|
||||||
|
| Report review work | `tools/register_check.py` reports due checks, missing grades, selected malformed fields, unknown statuses, waits/defaults, tracked fix state, embargo conditions and review dates, pending handovers and escalations, production re-score flags and regulatory reviews including full policies. `fixed` and `withdrawn` leave the ordinary watch list, but disclosure obligations remain visible; accepted, mitigated and unknown statuses remain watched. |
|
||||||
|
| Record review outcomes | `make checked ARGS="<id> clean\|moved\|defer ..."` updates an eligible record's timestamps, checker, cadence and review history, then regenerates the index. Clean climbs one rung from `instant` toward `1q`; moved resets; defer records a supplied date and reason. Completion of the review procedure and operator authorization for deferral are not enforced by the tool. |
|
||||||
|
| Read remediation records | `make fixes` resolves supported workplan/task IDs in live findings against sibling checkout files under `/home/worsch`, including an archive convention. It reports status, missing tracking and severity-based inactivity windows using the workplan file's last commit date. This is a proxy for recorded activity, not proof of task progress or a deployed fix. |
|
||||||
|
| Keep closure obligations visible | Live findings can state `closure_condition`, reported independently of source workplan completion. An accepted finding without fix tracking reports its recorded accepter, ending condition, resolvable regulatory determination and review date; missing fields still produce an incomplete-acceptance/missing-tracking warning. This does not verify that acceptance remains valid. |
|
||||||
|
| Check inbox freshness | `tools/inbox_check.py` reads up to 100 State Hub messages and matches names/IDs against live findings checked earlier. It reports potentially newer evidence; it neither interprets nor acknowledges messages. |
|
||||||
|
| Count reporting coverage | `make coverage` counts names appearing as system, fix owner or reporter and compares them with State Hub repo slugs when available. It measures mention coverage, not assessment coverage or assurance. |
|
||||||
|
| Retain regulatory research | One determination in `docs/regulatory/`, a thirteen-entry policy catalogue, and four full policy records. Sources, dates and activation conditions are stored for retrieval. Review discovery includes nested full policies; catalogues are excluded. All discovered records accept recorded outcomes. |
|
||||||
|
| Record disclosure and handover | Public, embargoed and restricted states express disclosure decisions. Finding metadata records publication status and addresses supplied by `policy-nexus`. Publication and access control are external; a `public` decision does not prove a completed handover. |
|
||||||
|
| Describe scheduled work | Two `activity-definitions/` files describe an hourly inbox watch and a daily 07:15 Europe/Berlin sweep. They ask an external activity system to instruct a session. They do not execute reviews or guarantee that a session acts. |
|
||||||
|
|
||||||
|
## Operating dependencies and limits
|
||||||
|
|
||||||
|
- Python 3, PyYAML, Make and Git are required for the relevant local commands;
|
||||||
|
no dependency manifest is checked in. `make test` runs isolated regression tests.
|
||||||
|
- State Hub reads use hard-coded `http://127.0.0.1:8000` endpoints. Fix tracking
|
||||||
|
assumes local sibling repositories and specific workplan naming/formatting.
|
||||||
|
- `make check` verifies the index and runs register and inbox reports even if a
|
||||||
|
prior stage fails, returning nonzero for any failed stage. Rendering includes the
|
||||||
|
current date and time-dependent due labels, so staleness need not mean source
|
||||||
|
records changed. `make due` runs the full obligation report and inbox check directly,
|
||||||
|
including nested policies, due embargo reviews and pending publication handovers
|
||||||
|
across closed as well as live findings.
|
||||||
|
- Reports do not send escalations, apply defaults, expire acceptances, lift
|
||||||
|
embargoes, close findings or block delivery. Operational warnings generally
|
||||||
|
return exit code zero. Selected validation exists, not comprehensive schema
|
||||||
|
enforcement; invalid date strings are tolerated by parsing and selected fields
|
||||||
|
are reported for repair. Deferrals require valid future dates.
|
||||||
|
- Incident deadlines and production-transition events
|
||||||
|
are procedural obligations without dedicated automated deadline/event handling.
|
||||||
|
The production-transition definition remains `proposed`.
|
||||||
|
- Historical verification records distinguish owner evidence, checkout evidence
|
||||||
|
and live reads. They do not establish current infrastructure access or health.
|
||||||
|
|
||||||
|
## Current recorded footprint
|
||||||
|
|
||||||
|
The checkout contains eleven findings: eight fixed, two open and one accepted;
|
||||||
|
three notes; one regulatory determination; four full policies out of thirteen
|
||||||
|
catalogue entries; and three verification records. Both open findings now carry
|
||||||
|
owner workplan tracking and explicit pending runtime/provider evidence. The
|
||||||
|
accepted finding carries a resolvable determination and an overdue substantive
|
||||||
|
review, displayed as a recorded acceptance obligation. Two findings are marked
|
||||||
|
published, eight pending handover, and one embargoed. These are repository
|
||||||
|
records, not a fresh verification of the affected systems or published sites.
|
||||||
|
|
||||||
|
## Ownership boundary
|
||||||
|
|
||||||
|
The repo owns risk intake records, grading, disclosure decisions, regulatory
|
||||||
|
research retention and escalation/review procedures. Fixes and incident response
|
||||||
|
belong to system owners; publication belongs to `policy-nexus`; canon and
|
||||||
|
estate-level decisions belong to the custodian/operator. It provides neither
|
||||||
|
legal advice nor compliance certification, estate-wide detection, or a delivery
|
||||||
|
gate. Completing the intended remit does not require taking over those roles.
|
||||||
42
STATE.md
42
STATE.md
|
|
@ -1,6 +1,6 @@
|
||||||
# STATE — risk-nexus
|
# STATE — risk-nexus
|
||||||
|
|
||||||
**Updated:** 2026-09-02
|
**Updated:** 2026-09-05
|
||||||
**Domain:** infotech · **Repo:** risk-nexus · **Owner:** the-custodian
|
**Domain:** infotech · **Repo:** risk-nexus · **Owner:** the-custodian
|
||||||
|
|
||||||
## One-line posture
|
## One-line posture
|
||||||
|
|
@ -20,13 +20,41 @@ backup credential, and an accepted medium on audit retention.
|
||||||
| `RISK-WP-0003` | **finished** | Regulatory intake; the legal policy set |
|
| `RISK-WP-0003` | **finished** | Regulatory intake; the legal policy set |
|
||||||
| `RISK-WP-0004` | **finished** | Running the register: cadence, verification, inbox-before-grading |
|
| `RISK-WP-0004` | **finished** | Running the register: cadence, verification, inbox-before-grading |
|
||||||
| `RISK-WP-0005` | **finished** | The seven gaps from `history/2026-08-21-intent-gap-analysis.md` |
|
| `RISK-WP-0005` | **finished** | The seven gaps from `history/2026-08-21-intent-gap-analysis.md` |
|
||||||
|
| `RISK-WP-0006` | **finished** | Reporting survives a stale index; full policies, embargo deadlines and closed-finding handovers stay visible; regression coverage and State Hub registration. |
|
||||||
|
| `RISK-WP-0007` | **finished** | Owner evidence reconciled, runtime/provider closure conditions recorded, and accepted obligations distinguished from missing engineering fixes. |
|
||||||
|
|
||||||
|
## Scope correction and reporting repair — 2026-09-05
|
||||||
|
|
||||||
|
`SCOPE.md` now describes the checked-in capability. The timestamped assessment
|
||||||
|
in `history/2026-09-05-014333-scope-intent-assessment.md` records the remaining
|
||||||
|
gaps behind the earlier claim that WP-0005 closed them all.
|
||||||
|
|
||||||
|
WP-0006 repairs the reporting path: `make check` runs every stage even after
|
||||||
|
failure; `make due` exposes regulatory policies and disclosure obligations;
|
||||||
|
malformed date strings no longer abort reporting; invalid deferrals cannot
|
||||||
|
write; archived completed workplans no longer trigger false inactivity alarms.
|
||||||
|
Eight regression tests pass. The live report now exposes four overdue policies,
|
||||||
|
eight pending publication handovers, and the existing overdue findings.
|
||||||
|
These are visibility repairs, not substantive reviews or evidence of closure.
|
||||||
|
|
||||||
|
The daily activity source includes those obligations. Its live synchronization
|
||||||
|
and end-to-end delivery remain unverified. External intake, incident clocks,
|
||||||
|
production-transition decisions and estate assessment coverage remain open.
|
||||||
|
|
||||||
|
WP-0007 then reconciled the owner evidence in RISK-V-0003. Qonto's source
|
||||||
|
cadence/reconciliation exists; KG-WP-0005-T03 waits for deployed acceptance.
|
||||||
|
RPF-WP-0029 removed the backup fallback; T02 waits for provider invalidation
|
||||||
|
and recovery receipts. Both findings were recorded as moved and remain open
|
||||||
|
at `instant`; F-0010 remains embargoed. F-0008's substantive review remains
|
||||||
|
overdue and its existing acceptance terms are displayed explicitly. Ten tests
|
||||||
|
pass. WP-0007 and four tasks are registered in State Hub.
|
||||||
|
|
||||||
## The register
|
## The register
|
||||||
|
|
||||||
| ID | Sev | Status | Disclosure | Cadence | System |
|
| ID | Sev | Status | Disclosure | Cadence | System |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| `RISK-F-0011` | medium | open | public | instant | qonto-assistant |
|
| `RISK-F-0011` | medium | open | public | instant | qonto-assistant |
|
||||||
| `RISK-F-0010` | low | open | embargoed | 1h | railiance-platform |
|
| `RISK-F-0010` | low | open | embargoed | instant | railiance-platform |
|
||||||
| `RISK-F-0009` | high | fixed | public | instant | railiance-platform |
|
| `RISK-F-0009` | high | fixed | public | instant | railiance-platform |
|
||||||
| `RISK-F-0008` | medium | accepted | public | 1h | audit-core |
|
| `RISK-F-0008` | medium | accepted | public | 1h | audit-core |
|
||||||
| `RISK-F-0007` | high | fixed | public | instant | estate |
|
| `RISK-F-0007` | high | fixed | public | instant | estate |
|
||||||
|
|
@ -76,8 +104,8 @@ outcome.
|
||||||
|
|
||||||
| Who | On | Defaults |
|
| Who | On | Defaults |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| qonto-assistant | heartbeat / emission-cadence and a reconciliation view for `audit.deny` (`F-0011`) | 2026-09-16 |
|
| qonto-assistant | deployed-instance capture and King's Guard acceptance under `KG-WP-0005-T03`; source cadence/reconciliation now exist (`F-0011`) | 2026-09-16 |
|
||||||
| railiance-platform | revoke or invalidate the provider credential, remove the source default, name fix tracking (`F-0010`) | 2026-09-15 |
|
| railiance-platform | provider invalidation and recovery receipts under `RPF-WP-0029-T02`; source fallback removed (`F-0010`) | 2026-09-15 |
|
||||||
| the-custodian | canon kinds packet | 2026-09-17 |
|
| the-custodian | canon kinds packet | 2026-09-17 |
|
||||||
| audit-core | keyed commitment; `platform-pg` co-residency horizon | 2026-11-17 |
|
| audit-core | keyed commitment; `platform-pg` co-residency horizon | 2026-11-17 |
|
||||||
|
|
||||||
|
|
@ -107,10 +135,10 @@ statehub fix-consistency --repo risk-nexus
|
||||||
|
|
||||||
## Known conditions
|
## Known conditions
|
||||||
|
|
||||||
- **Workplans are not indexed in the hub.** C-06 on all four: this instance is
|
- **Earlier workplans were not indexed in the hub.** C-06 on the earlier set: this instance was
|
||||||
not the identifier registrar. Needs a run with `STATEHUB_REGISTRAR=1` on the
|
not the identifier registrar. Needs a run with `STATEHUB_REGISTRAR=1` on the
|
||||||
production instance. The estate's read model cannot see any `risk-nexus`
|
production instance. WP-0006 now has a registered Hub workplan and five task
|
||||||
workplan.
|
UUIDs; this implementation did not repair historical workplan registration.
|
||||||
- **C-31** fires on `RISK-F-` ids until canon registers the kinds. Packet sent.
|
- **C-31** fires on `RISK-F-` ids until canon registers the kinds. Packet sent.
|
||||||
Defaults 2026-09-17.
|
Defaults 2026-09-17.
|
||||||
- **OpenBao is unverifiable from here** (403). Every grade touching an OpenBao
|
- **OpenBao is unverifiable from here** (403). Every grade touching an OpenBao
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@
|
||||||
| workplan | RISK-WP-0003 | finished | — | workplans/RISK-WP-0003-regulatory-intake.md |
|
| workplan | RISK-WP-0003 | finished | — | workplans/RISK-WP-0003-regulatory-intake.md |
|
||||||
| workplan | RISK-WP-0004 | finished | — | workplans/RISK-WP-0004-run-the-register.md |
|
| workplan | RISK-WP-0004 | finished | — | workplans/RISK-WP-0004-run-the-register.md |
|
||||||
| workplan | RISK-WP-0005 | finished | — | workplans/RISK-WP-0005-close-the-intent-gaps.md |
|
| workplan | RISK-WP-0005 | finished | — | workplans/RISK-WP-0005-close-the-intent-gaps.md |
|
||||||
|
| workplan | RISK-WP-0006 | finished | — | workplans/RISK-WP-0006-keep-review-obligations-visible.md |
|
||||||
|
| workplan | RISK-WP-0007 | finished | — | workplans/RISK-WP-0007-reconcile-owner-evidence.md |
|
||||||
| task | RISK-WP-0001-T01 | done | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
| task | RISK-WP-0001-T01 | done | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
||||||
| task | RISK-WP-0001-T02 | done | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
| task | RISK-WP-0001-T02 | done | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
||||||
| task | RISK-WP-0001-T03 | done | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
| task | RISK-WP-0001-T03 | done | — | workplans/RISK-WP-0001-make-the-register-decidable.md |
|
||||||
|
|
@ -41,3 +43,12 @@
|
||||||
| task | RISK-WP-0005-T05 | done | — | workplans/RISK-WP-0005-close-the-intent-gaps.md |
|
| task | RISK-WP-0005-T05 | done | — | workplans/RISK-WP-0005-close-the-intent-gaps.md |
|
||||||
| task | RISK-WP-0005-T06 | done | — | workplans/RISK-WP-0005-close-the-intent-gaps.md |
|
| task | RISK-WP-0005-T06 | done | — | workplans/RISK-WP-0005-close-the-intent-gaps.md |
|
||||||
| task | RISK-WP-0005-T07 | done | — | workplans/RISK-WP-0005-close-the-intent-gaps.md |
|
| task | RISK-WP-0005-T07 | done | — | workplans/RISK-WP-0005-close-the-intent-gaps.md |
|
||||||
|
| task | RISK-WP-0006-T01 | done | — | workplans/RISK-WP-0006-keep-review-obligations-visible.md |
|
||||||
|
| task | RISK-WP-0006-T02 | done | — | workplans/RISK-WP-0006-keep-review-obligations-visible.md |
|
||||||
|
| task | RISK-WP-0006-T03 | done | — | workplans/RISK-WP-0006-keep-review-obligations-visible.md |
|
||||||
|
| task | RISK-WP-0006-T04 | done | — | workplans/RISK-WP-0006-keep-review-obligations-visible.md |
|
||||||
|
| task | RISK-WP-0006-T05 | done | — | workplans/RISK-WP-0006-keep-review-obligations-visible.md |
|
||||||
|
| task | RISK-WP-0007-T01 | done | — | workplans/RISK-WP-0007-reconcile-owner-evidence.md |
|
||||||
|
| task | RISK-WP-0007-T02 | done | — | workplans/RISK-WP-0007-reconcile-owner-evidence.md |
|
||||||
|
| task | RISK-WP-0007-T03 | done | — | workplans/RISK-WP-0007-reconcile-owner-evidence.md |
|
||||||
|
| task | RISK-WP-0007-T04 | done | — | workplans/RISK-WP-0007-reconcile-owner-evidence.md |
|
||||||
|
|
|
||||||
|
|
@ -77,9 +77,12 @@ condition: 'true'
|
||||||
action:
|
action:
|
||||||
task_template: 'risk-nexus: work the register due list'
|
task_template: 'risk-nexus: work the register due list'
|
||||||
description: >-
|
description: >-
|
||||||
Run `make due` in risk-nexus, then work each listed finding through the five
|
Run `make due` in risk-nexus, then work each due finding through the five
|
||||||
questions in docs/method/check-procedure.md and record the outcome with
|
questions in docs/method/check-procedure.md and record the outcome with
|
||||||
`make checked`. Findings at the `instant` rung are due immediately; the
|
`make checked`. Also review due regulatory records and full policies,
|
||||||
|
re-decide due embargoes, and reconcile pending publication handovers,
|
||||||
|
including closed findings, per docs/method/check-procedure.md.
|
||||||
|
Findings at the `instant` rung are due immediately; the
|
||||||
ladder climbs only on a clean check. Escalate only what
|
ladder climbs only on a clean check. Escalate only what
|
||||||
docs/method/escalation.md says to escalate, batched into one operator
|
docs/method/escalation.md says to escalate, batched into one operator
|
||||||
conversation. If nothing is due, that is a complete run and worth nothing
|
conversation. If nothing is due, that is a complete run and worth nothing
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,18 @@ Then, per due finding:
|
||||||
be met while the embargo still holds, if a sibling finding would be exposed
|
be met while the embargo still holds, if a sibling finding would be exposed
|
||||||
by publishing (`RISK-F-0003`).
|
by publishing (`RISK-F-0003`).
|
||||||
|
|
||||||
|
Also work the non-finding obligations printed by `make due`: review the sources
|
||||||
|
and activation context for each due regulatory determination or full policy;
|
||||||
|
re-decide due embargoes; and reconcile pending publication handovers with the
|
||||||
|
publication owner's evidence, including for closed findings. Regulatory reviews
|
||||||
|
use `make checked ARGS="<RISK-REG-or-RISK-POL-id> clean|moved ..."` after the
|
||||||
|
review. A handover report is not authorization to publish embargoed content.
|
||||||
|
|
||||||
|
Index validation failure does not suppress later `make check` stages. Read the
|
||||||
|
reports before regenerating the index. A successful regeneration is not a
|
||||||
|
review outcome. Invalid date fields remain work to repair rather than evidence
|
||||||
|
that a check is current.
|
||||||
|
|
||||||
Then record it, in the same sitting:
|
Then record it, in the same sitting:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
||||||
104
docs/verifications/2026-09-05-open-findings-source-review.md
Normal file
104
docs/verifications/2026-09-05-open-findings-source-review.md
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
---
|
||||||
|
id: RISK-V-0003
|
||||||
|
type: verification
|
||||||
|
title: "Owner-source progress and outstanding runtime evidence"
|
||||||
|
date: "2026-09-05"
|
||||||
|
owner: risk-nexus
|
||||||
|
workplan: RISK-WP-0007
|
||||||
|
findings: [RISK-F-0011, RISK-F-0010, RISK-F-0008]
|
||||||
|
---
|
||||||
|
|
||||||
|
# Owner-source review — 2026-09-05
|
||||||
|
|
||||||
|
This is a checkout and inbox review, not a runtime probe. No credentials were
|
||||||
|
used or reproduced, no system was changed and no legal determination was renewed.
|
||||||
|
Files can include uncommitted owner work; repository HEAD is context, not proof
|
||||||
|
that every inspected change is in that commit.
|
||||||
|
|
||||||
|
## Qonto deny-stream completeness
|
||||||
|
|
||||||
|
Read State Hub notice `c6442eef-34fc-46a7-9639-10f2cd6120fc` (2026-09-04),
|
||||||
|
QONTO-WP-0005, `specs/audit-emission-cadence.yaml`, `src/qonto_assistant/audit.py`,
|
||||||
|
the application lifespan/reconciliation endpoint, and KG-WP-0005.
|
||||||
|
|
||||||
|
The source now declares process instance/sequence semantics, a 24-hour default
|
||||||
|
active-process heartbeat, startup and best-effort shutdown, and reconciliation
|
||||||
|
counts. AuditLogger serializes emission and exposes source counters; the app
|
||||||
|
wires the heartbeat lifecycle and identity-checked snapshot route. Qonto records
|
||||||
|
88 passing tests on its latest review; that suite was not rerun by risk-nexus.
|
||||||
|
King's Guard records local source-path validation and explicitly leaves
|
||||||
|
KG-WP-0005-T03 waiting for authorized deployed evidence.
|
||||||
|
|
||||||
|
**Conclusion:** the old statement that no source cadence/reconciliation exists
|
||||||
|
is obsolete. Runtime completeness remains unestablished. F-0011 stays open,
|
||||||
|
medium and public, with QONTO-WP-0005 and KG-WP-0005-T03 as tracking.
|
||||||
|
|
||||||
|
**Closure evidence owed:** qonto's runtime owner supplies a bounded capture from
|
||||||
|
one deployed instance, naming the deployed revision, configured heartbeat
|
||||||
|
interval and observation window. It covers startup, a request transition,
|
||||||
|
periodic heartbeat timing, sequence/instance continuity and a same-instance
|
||||||
|
reconciliation snapshot. King's Guard compares received counts and source counts,
|
||||||
|
records any gaps and the acceptance decision. Evidence may support only the
|
||||||
|
observed instance/window, never an unbounded all-time completeness claim.
|
||||||
|
The original 2026-09-16 default remains; a completed source plan does not close
|
||||||
|
the runtime finding. This narrows the existing evidence request; no new request
|
||||||
|
or message was sent in this sitting.
|
||||||
|
|
||||||
|
## Backup credential
|
||||||
|
|
||||||
|
Read RPF-WP-0029 and inspected `tools/cmd/forgejo-backup` in memory for the
|
||||||
|
named shell fallback without outputting credential-bearing lines. No nonempty
|
||||||
|
literal fallback for `RAILIANCE_BACKUP_NC_TOKEN` remains in that script.
|
||||||
|
The owner records fail-closed input tests as complete under T01. T02 is `wait`:
|
||||||
|
provider-side invalidation and encrypted upload/restore receipts are absent.
|
||||||
|
|
||||||
|
**Conclusion:** source removal is established in the checkout; predecessor
|
||||||
|
invalidation is not. F-0010 stays open, low and embargoed. RPF-WP-0029-T02 names
|
||||||
|
the remaining provider/recovery work. The 2026-09-15 embargo review/default
|
||||||
|
stands. No inference is made about whether the predecessor is still valid.
|
||||||
|
Only non-secret invalidation, governed ciphertext upload and restore receipts
|
||||||
|
can complete the remaining evidence; source removal alone cannot lift the hold.
|
||||||
|
|
||||||
|
## Accepted retention obligation
|
||||||
|
|
||||||
|
Read the existing acceptance and determination references in F-0008 and
|
||||||
|
`audit-core/docs/erasure-and-audit.md`. Audit Core still documents the
|
||||||
|
cleartext-hash confirmation problem and says keyed commitments are not built.
|
||||||
|
No new answer to the co-residency horizon or keyed-commitment wait was present
|
||||||
|
in the fetched risk-nexus inbox. This is not proof that no answer exists elsewhere.
|
||||||
|
|
||||||
|
F-0008 already has a named accepter, an ending condition, a real determination
|
||||||
|
and a next check. The reporting problem is classifying that accepted obligation
|
||||||
|
as an untracked fix. The report should expose its existing acceptance terms
|
||||||
|
without inventing engineering work or treating acceptance as closure. Its
|
||||||
|
substantive review remains due: this sitting does not establish that the
|
||||||
|
real-person/counterparty trigger has not fired and does not renew the legal basis.
|
||||||
|
|
||||||
|
## External intake and scheduled reviews
|
||||||
|
|
||||||
|
Searched policy-nexus publication configuration, workplans and deployment files
|
||||||
|
for a security contact/security.txt or delivered external-report route. None
|
||||||
|
was found in those inspected sources. The existing intake proposal remains the
|
||||||
|
available evidence; current public endpoints and estate-wide contact availability
|
||||||
|
were not verified. Publishing a new contact requires its actual receiving owner.
|
||||||
|
|
||||||
|
Searched activity-core's local definitions and evidence for the two risk register
|
||||||
|
activities. No matching execution receipt was found in those paths. The two
|
||||||
|
definitions in risk-nexus remain source instructions. Their live registration,
|
||||||
|
execution and completed-session chain are unverified; this search is not proof
|
||||||
|
that the activities do not run. No deployment or synchronization was attempted.
|
||||||
|
|
||||||
|
## Source provenance
|
||||||
|
|
||||||
|
| Inspected source | SHA-256 of the non-secret document |
|
||||||
|
| --- | --- |
|
||||||
|
| qonto-assistant QONTO-WP-0005 | `f3b21ed7d046e7a4e5e8eee1397dcdcf1a17211f75786da3a0a2258b44802c3a` |
|
||||||
|
| qonto-assistant cadence declaration | `69db6068b2e262f6b9108903cf7c5a7764efba5c981344c50df496018bc98ed9` |
|
||||||
|
| qonto-assistant audit.py | `573e669914ae2ae77dfbf0a0929ef080cfbcb7dd4e0ba79e9408dd401fd74437` |
|
||||||
|
| railiance-platform RPF-WP-0029 | `396d2e167b8bd1141671fadd864660a1e8bc6efb1ea3a09be3465e841ce33144` |
|
||||||
|
| audit-core erasure-and-audit.md | `40d0f86ad401c3fb413fb21346a77210b6840d52f05093b31143a11b8a3a878b` |
|
||||||
|
|
||||||
|
Observed HEADs: qonto `e5611147fd72a23e58618b87b0c3b96c807d0043`,
|
||||||
|
railiance-platform `f637989a6911a7a13812cba223ffc007d78d6302`,
|
||||||
|
audit-core `95dcb78e17d46889c17b55e3ba1aadbcceec6a99`,
|
||||||
|
policy-nexus `c1b60f322e3bcddff3cece618ece2bd3686169e1`.
|
||||||
|
|
@ -365,3 +365,17 @@ achievable. An accepted risk still gets checked.
|
||||||
- **2026-08-20** — not clean: Trigger list ruled: no external determination in build mode; accepted with the legal policy set as the compensating control. Cadence instant → instant; checked again immediately.
|
- **2026-08-20** — not clean: Trigger list ruled: no external determination in build mode; accepted with the legal policy set as the compensating control. Cadence instant → instant; checked again immediately.
|
||||||
- **2026-09-01** — not clean: the regulatory record now states target periods per category; the remaining gap is whether platform-pg co-residency can achieve them, while the keyed-commitment question is unchanged. Grade and acceptance hold. Cadence instant → instant; checked again immediately.
|
- **2026-09-01** — not clean: the regulatory record now states target periods per category; the remaining gap is whether platform-pg co-residency can achieve them, while the keyed-commitment question is unchanged. Grade and acceptance hold. Cadence instant → instant; checked again immediately.
|
||||||
- **2026-09-02** — clean check: acceptance, RISK-REG-0001, and the audit-core keyed-commitment wait unchanged. Cadence instant → 1h (1 clean in a row); next check 2026-09-02 09:11Z.
|
- **2026-09-02** — clean check: acceptance, RISK-REG-0001, and the audit-core keyed-commitment wait unchanged. Cadence instant → 1h (1 clean in a row); next check 2026-09-02 09:11Z.
|
||||||
|
|
||||||
|
## Evidence inspection — 2026-09-05 (review remains due)
|
||||||
|
|
||||||
|
[RISK-V-0003](../docs/verifications/2026-09-05-open-findings-source-review.md)
|
||||||
|
records a source/inbox inspection. The technical owner still documents the
|
||||||
|
cleartext-hash limitation; no new answer to the existing wait appeared in the
|
||||||
|
fetched risk-nexus inbox. The report now displays this record's existing
|
||||||
|
accepter, ending condition, determination and review date as a recorded
|
||||||
|
acceptance obligation, rather than inventing a fix plan to fill `fix_tracking`.
|
||||||
|
|
||||||
|
This is not a clean check or a renewed acceptance. Whether the real-person or
|
||||||
|
counterparty condition has fired, and the substantive regulatory review, remain
|
||||||
|
unestablished here. The overdue review, existing grade and acceptance terms are
|
||||||
|
preserved; absence of a new inbox answer cannot certify the condition false.
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ date_filed: "2026-08-23"
|
||||||
system: railiance-platform
|
system: railiance-platform
|
||||||
environment: production
|
environment: production
|
||||||
fix_owner: railiance-platform
|
fix_owner: railiance-platform
|
||||||
fix_tracking: unset
|
fix_tracking: RPF-WP-0029-T02
|
||||||
|
closure_condition: "provider invalidation plus governed ciphertext upload and restore receipts; source fallback removal alone does not lift the embargo"
|
||||||
|
verification: RISK-V-0003
|
||||||
# Graded by risk-nexus 2026-09-01 — docs/rulings/2026-09-01-inbox-sweep.md
|
# Graded by risk-nexus 2026-09-01 — docs/rulings/2026-09-01-inbox-sweep.md
|
||||||
severity: low
|
severity: low
|
||||||
severity_at_production: low
|
severity_at_production: low
|
||||||
|
|
@ -25,20 +27,20 @@ embargo_condition: "the provider credential is revoked or invalidated and the li
|
||||||
embargo_since: "2026-09-01"
|
embargo_since: "2026-09-01"
|
||||||
embargo_review: "2026-09-15"
|
embargo_review: "2026-09-15"
|
||||||
escalation: none
|
escalation: none
|
||||||
last_checked: "2026-09-02T08:11:17Z"
|
last_checked: "2026-09-05T00:05:51Z"
|
||||||
next_check: "2026-09-02T09:11:17Z"
|
next_check: "2026-09-05T00:05:51Z"
|
||||||
cadence: 1h
|
cadence: instant
|
||||||
clean_streak: 1
|
clean_streak: 0
|
||||||
waiting_on:
|
waiting_on:
|
||||||
- who: railiance-platform
|
- who: railiance-platform
|
||||||
what: "revoke or invalidate the provider credential, remove the source default, name fix tracking, and demonstrate governed ciphertext upload plus restore"
|
what: "complete RPF-WP-0029-T02: revoke or invalidate the provider credential and demonstrate governed ciphertext upload plus restore; source fallback removal is established"
|
||||||
since: "2026-09-01"
|
since: "2026-09-01"
|
||||||
would_change: "the finding becomes fixed and the embargo lifts"
|
would_change: "the finding becomes fixed and the embargo lifts"
|
||||||
default: "the low grade and embargo stand; missing fix tracking is recorded as a stalled remediation"
|
default: "the low grade and embargo stand; absent provider invalidation and recovery evidence is recorded as a stalled remediation"
|
||||||
default_at: "2026-09-15"
|
default_at: "2026-09-15"
|
||||||
graded_by: risk-nexus
|
graded_by: risk-nexus
|
||||||
ruling: RISK-RULING-2026-09-01-A
|
ruling: RISK-RULING-2026-09-01-A
|
||||||
checked_by: "grok/risk-nexus"
|
checked_by: "codex/risk-nexus"
|
||||||
---
|
---
|
||||||
|
|
||||||
# RISK-F-0010 — Forgejo backup source embeds a WebDAV credential default
|
# RISK-F-0010 — Forgejo backup source embeds a WebDAV credential default
|
||||||
|
|
@ -118,7 +120,21 @@ does not soften the assessment.
|
||||||
|
|
||||||
Reasoning: `docs/rulings/2026-09-01-inbox-sweep.md`.
|
Reasoning: `docs/rulings/2026-09-01-inbox-sweep.md`.
|
||||||
|
|
||||||
|
## Source remediation reconciled — 2026-09-05
|
||||||
|
|
||||||
|
RPF-WP-0029-T01 records source fallback removal and fail-closed input checks.
|
||||||
|
This register confirmed the named fallback is absent in the current script
|
||||||
|
without displaying or testing any credential. RPF-WP-0029-T02 remains `wait`
|
||||||
|
for provider invalidation and governed encrypted upload/restore receipts.
|
||||||
|
|
||||||
|
[RISK-V-0003](../docs/verifications/2026-09-05-open-findings-source-review.md)
|
||||||
|
records the boundary: source removal does not establish invalidation of the
|
||||||
|
predecessor. Open, low, embargoed and no escalation remain appropriate on the
|
||||||
|
available evidence. The 2026-09-15 review/default is unchanged. The historical
|
||||||
|
source-default statements above describe the earlier assessments.
|
||||||
|
|
||||||
## Reviews
|
## Reviews
|
||||||
|
|
||||||
- **2026-09-01** — graded from the filed report and a redacted current-source check. The literal default remains; no fix record was found. Cadence starts at instant.
|
- **2026-09-01** — graded from the filed report and a redacted current-source check. The literal default remains; no fix record was found. Cadence starts at instant.
|
||||||
- **2026-09-02** — clean check: literal source default remains; no fix tracking; embargo and 2026-09-15 wait unchanged. Cadence instant → 1h (1 clean in a row); next check 2026-09-02 09:11Z.
|
- **2026-09-02** — clean check: literal source default remains; no fix tracking; embargo and 2026-09-15 wait unchanged. Cadence instant → 1h (1 clean in a row); next check 2026-09-02 09:11Z.
|
||||||
|
- **2026-09-05** — not clean: Confirmed source fallback removal and RPF-WP-0029 tracking; provider invalidation and encrypted upload/restore receipts remain pending. Low grade and embargo retained; see RISK-V-0003. Cadence 1h → instant; checked again immediately.
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ date_filed: "2026-09-02"
|
||||||
system: qonto-assistant
|
system: qonto-assistant
|
||||||
environment: production
|
environment: production
|
||||||
fix_owner: qonto-assistant
|
fix_owner: qonto-assistant
|
||||||
fix_tracking: unset
|
fix_tracking: QONTO-WP-0005 / KG-WP-0005-T03
|
||||||
|
closure_condition: "authorized deployed-instance capture accepted by kings-guard: heartbeat timing, sequence continuity and same-instance reconciliation"
|
||||||
|
verification: RISK-V-0003
|
||||||
# Graded by risk-nexus 2026-09-02 — docs/rulings/2026-09-02-qonto-deny-stream.md
|
# Graded by risk-nexus 2026-09-02 — docs/rulings/2026-09-02-qonto-deny-stream.md
|
||||||
severity: medium
|
severity: medium
|
||||||
severity_at_production: medium
|
severity_at_production: medium
|
||||||
|
|
@ -29,20 +31,20 @@ revision: "graded-1"
|
||||||
last_reviewed: "2026-09-02"
|
last_reviewed: "2026-09-02"
|
||||||
review_interval: 6m
|
review_interval: 6m
|
||||||
escalation: none
|
escalation: none
|
||||||
last_checked: "2026-09-02T07:20:00Z"
|
last_checked: "2026-09-05T00:05:51Z"
|
||||||
next_check: "2026-09-02T07:20:00Z"
|
next_check: "2026-09-05T00:05:51Z"
|
||||||
cadence: instant
|
cadence: instant
|
||||||
clean_streak: 0
|
clean_streak: 0
|
||||||
waiting_on:
|
waiting_on:
|
||||||
- who: qonto-assistant
|
- who: qonto-assistant
|
||||||
what: "publish a heartbeat or emission-cadence declaration and a reconciliation view for the audit.deny stream, or reject that obligation"
|
what: "supply runtime-owner deployed-instance capture for kings-guard acceptance under KG-WP-0005-T03; source cadence and reconciliation now exist"
|
||||||
since: "2026-09-02"
|
since: "2026-09-02"
|
||||||
would_change: "a published cadence plus a reconciliation view would let a later observation support completeness; a rejection keeps the grade and records that estate observation must not treat the stream as complete"
|
would_change: "accepted deployed-instance evidence supports bounded stream completeness and permits closure; source-only evidence keeps the finding open"
|
||||||
default: "the medium grade stands; missing cadence is recorded as a stalled remediation, and observation remains staffed with completeness pending"
|
default: "the medium grade stands; missing deployed acceptance is recorded as a stalled remediation, and observation remains staffed with completeness pending"
|
||||||
default_at: "2026-09-16"
|
default_at: "2026-09-16"
|
||||||
graded_by: risk-nexus
|
graded_by: risk-nexus
|
||||||
ruling: RISK-RULING-2026-09-02-A
|
ruling: RISK-RULING-2026-09-02-A
|
||||||
checked_by: "grok/risk-nexus"
|
checked_by: "codex/risk-nexus"
|
||||||
---
|
---
|
||||||
|
|
||||||
# RISK-F-0011 — qonto-assistant audit.deny stream completeness is not established
|
# RISK-F-0011 — qonto-assistant audit.deny stream completeness is not established
|
||||||
|
|
@ -141,6 +143,22 @@ wait makes that last statement expire.
|
||||||
|
|
||||||
Reasoning: `docs/rulings/2026-09-02-qonto-deny-stream.md`.
|
Reasoning: `docs/rulings/2026-09-02-qonto-deny-stream.md`.
|
||||||
|
|
||||||
|
## Source remediation reconciled — 2026-09-05
|
||||||
|
|
||||||
|
The missing-source statements above describe intake, not the current checkout.
|
||||||
|
QONTO-WP-0005 is finished: cadence, heartbeat lifecycle, instance/sequence fields
|
||||||
|
and an identity-checked reconciliation view now exist. King's Guard's local
|
||||||
|
source-path checks are recorded complete, but KG-WP-0005-T03 waits for an
|
||||||
|
authorized deployed capture. Notice `c6442eef-34fc-46a7-9639-10f2cd6120fc`
|
||||||
|
explicitly requests independent deployed-stream acceptance before closure.
|
||||||
|
|
||||||
|
[RISK-V-0003](../docs/verifications/2026-09-05-open-findings-source-review.md)
|
||||||
|
records the inspected evidence and bounded acceptance requirements. Status
|
||||||
|
remains open, medium, public, no escalation: deployed completeness is still
|
||||||
|
unknown, with no evidence of suppression or an authorization bypass. The
|
||||||
|
2026-09-16 default is retained, now describing the actual remaining obligation.
|
||||||
|
|
||||||
## Reviews
|
## Reviews
|
||||||
|
|
||||||
- **2026-09-02** — graded from the Gate House intake, the named conformance review, and a current-source check of qonto-assistant. Local lockout is in-process; the emitted deny stream still has no cadence or reconciliation view. Cadence starts at instant.
|
- **2026-09-02** — graded from the Gate House intake, the named conformance review, and a current-source check of qonto-assistant. Local lockout is in-process; the emitted deny stream still has no cadence or reconciliation view. Cadence starts at instant.
|
||||||
|
- **2026-09-05** — not clean: Reviewed owner notice, cadence/logger/endpoint and KG-WP-0005; source remediation exists, deployed-instance acceptance remains pending under KG-WP-0005-T03. See RISK-V-0003. Cadence instant → instant; checked again immediately.
|
||||||
|
|
|
||||||
192
history/2026-09-05-014333-scope-intent-assessment.md
Normal file
192
history/2026-09-05-014333-scope-intent-assessment.md
Normal file
|
|
@ -0,0 +1,192 @@
|
||||||
|
---
|
||||||
|
type: history
|
||||||
|
title: "Repository scope against INTENT: capabilities and remaining gaps"
|
||||||
|
date: "2026-09-05"
|
||||||
|
assessed_at: "2026-09-05T01:43:33+02:00"
|
||||||
|
author: codex
|
||||||
|
repo: risk-nexus
|
||||||
|
source_revision: "29f50d5143afc8c9d9884810dc34e39adf6edd43"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Scope against intent
|
||||||
|
|
||||||
|
The repository implements a usable, manually operated risk register with
|
||||||
|
reporting aids. It does not yet deliver the full intended assurance that known
|
||||||
|
risks cannot go quiet, regulation stays current, or reports can arrive from any
|
||||||
|
source. [SCOPE.md](../SCOPE.md) was absent and has been created to describe the
|
||||||
|
actual capability and its dependencies.
|
||||||
|
|
||||||
|
This assessment reads the local implementation, records and workplans, and runs
|
||||||
|
read-only reports. It does not re-grade findings, verify external fixes, check
|
||||||
|
publication endpoints, or reassess the legal correctness of regulatory texts.
|
||||||
|
External operational claims below are identified as recorded or unverified.
|
||||||
|
The timestamp prefix uses Europe/Berlin; the inspection timestamp is
|
||||||
|
2026-09-04 23:43:33 UTC. The existing modified Python bytecode file was left alone.
|
||||||
|
|
||||||
|
## INTENT ownership claims
|
||||||
|
|
||||||
|
| INTENT claim | Assessment | Evidence and boundary |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Finding intake from research, review, incident and external report | Partial | [Filing contract](../findings/README.md), eleven finding files and observation-sourced F-0011 demonstrate internal intake. [Incident/external method](../docs/method/intake.md) supplies a procedure but records the external contact as only routed. No intake service or incident clock is implemented here. |
|
||||||
|
| Severity and triage | Implemented as a judgement workflow | [Severity method](../docs/method/severity.md), dated rulings and all three live records carry grades. Tools surface absent grades but do not compute or independently verify them. |
|
||||||
|
| Remediation tracking: owner, state and stalls | Partial | [Fix tracker](../tools/fix_tracker.py) reads supported owner workplans and flags inactivity. All three live findings currently report no fix tracking; local workplan commits are only a progress proxy. |
|
||||||
|
| Disclosure timing and deliberate holds | Implemented records; partial follow-through | [Disclosure method](../docs/method/disclosure.md) and F-0010 record a conditional embargo. Public/pending/published metadata distinguishes decisions from delivery, but embargo review deadlines and pending publication are not actively checked. |
|
||||||
|
| Regulatory intake and retained research | Partial | [Regulatory collection](../docs/regulatory/README.md) retains one determination; the [policy catalogue](../docs/regulatory/policies/README.md) names thirteen positions, four written in full. Policy review dates are outside tool discovery. |
|
||||||
|
| Written escalation rule and operator attention | Rule implemented; delivery procedural | [Escalation method](../docs/method/escalation.md) defines triggers and delivery states. The checker prints pending and seven-day-unacknowledged items; it does not send, retry, acknowledge or apply defaults. |
|
||||||
|
|
||||||
|
The intended boundaries are substantially preserved: no remediation service,
|
||||||
|
publication host, legal-advice service or canon authority has been added.
|
||||||
|
Verification is bounded by the [verification method](../docs/method/verification.md).
|
||||||
|
There is a wording conflict to resolve: the adopted review method says re-scoring
|
||||||
|
occurs before a production declaration completes, while INTENT excludes delivery
|
||||||
|
blocking and the proposed transition method says it does not gate the event.
|
||||||
|
No delivery gate is implemented.
|
||||||
|
|
||||||
|
## Gaps and concrete completion criteria
|
||||||
|
|
||||||
|
### 1. The review entry point can suppress the overdue reports
|
||||||
|
|
||||||
|
**Priority: high. Owner: risk-nexus.** `make check` fails on stale `REGISTER.md`
|
||||||
|
before running the register or inbox checker. The index embeds today's date and
|
||||||
|
time-dependent due labels ([generator](../tools/register_index.py)), so the
|
||||||
|
passage of time alone can stop the operational report. The direct checker
|
||||||
|
currently reports all three live findings overdue and a two-day heartbeat gap.
|
||||||
|
|
||||||
|
Separate index validation from report execution so a stale index still exposes
|
||||||
|
due work, heartbeat and inbox evidence. Completion means the stale-index case
|
||||||
|
reports both the failure and the operational work list. Actual overdue reviews
|
||||||
|
must be performed with evidence; regenerating the index cannot satisfy them.
|
||||||
|
|
||||||
|
### 2. Regulatory policies can silently expire outside the review loop
|
||||||
|
|
||||||
|
**Priority: high. Owner: risk-nexus.** `register_lib.regulatory()` uses a
|
||||||
|
non-recursive `docs/regulatory/*.md` scan. All four full policies are nested in
|
||||||
|
`policies/`, have `next_check: 2026-08-20T21:30:00Z`, and are omitted from both
|
||||||
|
the due report and `record_check.py`'s eligible records. Method review intervals
|
||||||
|
likewise have no general due-date reporting. This contradicts INTENT's retained,
|
||||||
|
non-silently-expiring regulatory knowledge requirement.
|
||||||
|
|
||||||
|
Discover and review the full policy records, make them eligible for recorded
|
||||||
|
outcomes, and define how method review dates are maintained. Distinguish the
|
||||||
|
nine catalogue-only entries from sourced determinations, with owners and dates
|
||||||
|
for elaboration when activation approaches. Completion means an overdue nested
|
||||||
|
policy appears in the work list and can receive a recorded review.
|
||||||
|
|
||||||
|
### 3. External and incident intake remain incomplete in operation
|
||||||
|
|
||||||
|
**Priority: high. Owners: risk-nexus; policy-nexus and the-custodian for contact delivery.**
|
||||||
|
The intake method still says no external contact exists and describes a routed
|
||||||
|
proposal. Local evidence establishes neither a delivered contact nor a tested
|
||||||
|
external-to-register path; it does not establish the current state of the whole
|
||||||
|
estate. Incident fields and urgent timing are prose only: the tools do not
|
||||||
|
process `incident` or `first_observed`, enforce incident cadence, or report the
|
||||||
|
notification deadline described by the method. No incident-marked finding was
|
||||||
|
found in this checkout.
|
||||||
|
|
||||||
|
Obtain evidence of a discoverable contact and a report reaching triage. Add
|
||||||
|
deadline handling for incident records and demonstrate an urgent intake exercise
|
||||||
|
with an owner and escalation record. The legal basis for any deadline remains
|
||||||
|
subject to the regulatory record's own review; this assessment does not validate it.
|
||||||
|
|
||||||
|
### 4. Remediation visibility is incomplete for the live register
|
||||||
|
|
||||||
|
**Priority: high. Owners: risk-nexus and the named system owners.** F-0010,
|
||||||
|
F-0011 and accepted F-0008 all have unset tracking. The inbox check finds a newer
|
||||||
|
F-0011 remediation notice naming QONTO-WP-0005, so the register is demonstrably
|
||||||
|
behind incoming evidence. The notice is not proof the defect is fixed.
|
||||||
|
|
||||||
|
Read and reconcile that evidence, obtain the applicable tracking records, and
|
||||||
|
record an explicit reviewable acceptance obligation where a fix plan is not
|
||||||
|
appropriate. The tracker resolves only a workplan ID syntax and expected file
|
||||||
|
layout, uses whole-file commit time rather than task transitions, and does not
|
||||||
|
verify deployed state. Completion means every live finding has an actionable
|
||||||
|
tracking or acceptance record and inactivity remains visible independently of
|
||||||
|
register check frequency. Task shorthand and archived completed-status handling
|
||||||
|
also need care: the parser requires full IDs, and the appended `[archived]`
|
||||||
|
suffix prevents the current exact completed-state comparison from matching.
|
||||||
|
|
||||||
|
### 5. Expiry, escalation and execution still depend on an attending session
|
||||||
|
|
||||||
|
**Priority: high. Owners: risk-nexus; activity-core for execution evidence.**
|
||||||
|
The tools report lateness and suggested actions but do not apply them. A heartbeat
|
||||||
|
printed by the same command nobody runs cannot provide independent delivery
|
||||||
|
assurance. The two activity definitions request work; their presence does not
|
||||||
|
prove scheduler registration, execution, session completion or operator receipt.
|
||||||
|
The observed overdue records show the intended cadence is not currently reflected
|
||||||
|
in recorded outcomes. No escalation is presently reported as awaiting an answer.
|
||||||
|
|
||||||
|
Demonstrate scheduled instruction delivery through to a completed review, and an
|
||||||
|
independently visible missed-run condition. Demonstrate acknowledgement and the
|
||||||
|
single permitted re-raise/default path for an escalation. Human judgement should
|
||||||
|
remain required; reliable delivery need not automate grading or send repeated nags.
|
||||||
|
|
||||||
|
### 6. Disclosure and production obligations are recorded but not fully followed
|
||||||
|
|
||||||
|
**Priority: medium. Owners: risk-nexus, policy-nexus and the-custodian.**
|
||||||
|
The checker lists embargo conditions but never compares `embargo_review` with
|
||||||
|
the clock. It does not list pending publication handovers; eight findings have
|
||||||
|
that state, including fixed records outside the normal live watch list. Two
|
||||||
|
findings are marked published; those metadata were not verified against a site.
|
||||||
|
|
||||||
|
The [production definition](../docs/method/production-transition.md) remains
|
||||||
|
`proposed`, contains historical counts and refers to F-0007's former acceptance
|
||||||
|
although that finding is now fixed. The checker reports only live flagged
|
||||||
|
findings (currently F-0008), not an event-driven acceptance expiry or policy
|
||||||
|
activation process.
|
||||||
|
|
||||||
|
Completion means due embargo decisions and pending handovers remain actionable
|
||||||
|
independently of closure; the custodian settles the transition definition and
|
||||||
|
conflicting declaration wording; an event record identifies the applicable
|
||||||
|
re-scores, acceptance decisions and policy activations without silently adding a gate.
|
||||||
|
|
||||||
|
### 7. Coverage measures mentions, not whether systems have been assessed
|
||||||
|
|
||||||
|
**Priority: medium. Owners: risk-nexus with estate inventory owners.**
|
||||||
|
[coverage.py](../tools/coverage.py) combines system, owner and reporter strings,
|
||||||
|
including values such as `estate` and `per-consumer, on request`. It has no
|
||||||
|
last-assessed date, assessment scope or evidence for a clean assessment. Thus a
|
||||||
|
mentioned repo is not necessarily assessed, and an unmentioned repo is unknown.
|
||||||
|
The current inventory request did not yield a denominator; the historical
|
||||||
|
7-of-117 count must not be presented as current coverage.
|
||||||
|
|
||||||
|
Record assessment provenance and dates against canonical repo identities, with
|
||||||
|
explicit unknowns. Completion means a clean assessment, a reported defect and
|
||||||
|
an unassessed system can be distinguished without turning this repo into the
|
||||||
|
estate's scanner or remediation team.
|
||||||
|
|
||||||
|
## What good looks like: current result
|
||||||
|
|
||||||
|
- **Known gaps have severity and owner:** met for the recorded live findings;
|
||||||
|
completeness across the estate is unproven.
|
||||||
|
- **Applicable regulation is found before needed:** not established. The
|
||||||
|
[previous assessment](2026-08-21-intent-gap-analysis.md) records retrospective
|
||||||
|
discovery of already-live obligations. A catalogue improves retrieval but
|
||||||
|
does not erase that history or provide ongoing horizon scanning.
|
||||||
|
- **Stalled fixes are visible while stalled:** partially supported by a local
|
||||||
|
file reader, presently limited by missing tracking and overdue reviews.
|
||||||
|
- **Necessary operator judgement is reached without noise:** procedures and
|
||||||
|
historical rulings exist; current end-to-end delivery assurance is unverified.
|
||||||
|
- **Findings expire or escalate; the register stays readable:** the small
|
||||||
|
register and note floor are implemented. Timely follow-through remains a
|
||||||
|
process requirement rather than a guaranteed outcome.
|
||||||
|
|
||||||
|
[WP-0005](../workplans/RISK-WP-0005-close-the-intent-gaps.md) and STATE.md call the
|
||||||
|
previous seven gaps closed. The delivered tools and procedures are real progress,
|
||||||
|
but routing a contact request, drafting a transition definition, printing a
|
||||||
|
heartbeat and counting mentions do not establish those end-to-end outcomes.
|
||||||
|
Historical completion records were preserved; this assessment records the
|
||||||
|
remaining capability gaps rather than rewriting their history.
|
||||||
|
|
||||||
|
## Verification results
|
||||||
|
|
||||||
|
| Read-only check | Observed result |
|
||||||
|
| --- | --- |
|
||||||
|
| `PYTHONDONTWRITEBYTECODE=1 make check` | Failed at stale index, Make exit 2; subsequent report stages did not execute. |
|
||||||
|
| `PYTHONDONTWRITEBYTECODE=1 python3 tools/register_check.py` | Exit 0; three live findings, all overdue by about 62–64 hours; two-day heartbeat warning; three missing fix trackers; one overdue top-level regulatory record; no pending operator escalations. |
|
||||||
|
| `PYTHONDONTWRITEBYTECODE=1 make fixes` | Exit 0; all three live findings report `NO FIX TRACKING`. |
|
||||||
|
| `PYTHONDONTWRITEBYTECODE=1 python3 tools/inbox_check.py` | Exit 0; nine messages returned, including a newer F-0011 remediation notice dated 2026-09-04. No messages were acknowledged or sent. |
|
||||||
|
| `PYTHONDONTWRITEBYTECODE=1 make coverage` | Exit 0; eleven distinct mention strings; inventory endpoint unavailable within the tool's attempts, so current denominator unknown. The separate inbox request succeeded. |
|
||||||
|
|
||||||
|
Warnings returning zero are advisory output, not a clean bill of health. The
|
||||||
|
review tools were run directly after the stale-index failure to inspect their
|
||||||
|
results without regenerating unrelated files or claiming reviews had happened.
|
||||||
157
tests/test_review_workflow.py
Normal file
157
tests/test_review_workflow.py
Normal file
|
|
@ -0,0 +1,157 @@
|
||||||
|
import contextlib
|
||||||
|
import datetime as dt
|
||||||
|
import io
|
||||||
|
import pathlib
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1] / "tools"))
|
||||||
|
import check_all
|
||||||
|
import fix_tracker
|
||||||
|
import record_check
|
||||||
|
import register_check
|
||||||
|
import register_lib as lib
|
||||||
|
|
||||||
|
NOW = dt.datetime(2026, 9, 5, tzinfo=dt.timezone.utc)
|
||||||
|
|
||||||
|
|
||||||
|
class ReviewWorkflowTests(unittest.TestCase):
|
||||||
|
def report(self, findings=(), regulatory=()):
|
||||||
|
output = io.StringIO()
|
||||||
|
with patch.object(lib, "findings", return_value=list(findings)), \
|
||||||
|
patch.object(lib, "regulatory", return_value=list(regulatory)), \
|
||||||
|
patch.object(lib, "records_with_waits", return_value=[]), \
|
||||||
|
patch.object(fix_tracker, "report", return_value=[]), \
|
||||||
|
patch.object(register_check, "NOW", NOW), contextlib.redirect_stdout(output):
|
||||||
|
self.assertEqual(register_check.main(), 0)
|
||||||
|
return output.getvalue()
|
||||||
|
|
||||||
|
def test_all_stages_run_after_failure(self):
|
||||||
|
for failed_stage in range(3):
|
||||||
|
results = [subprocess.CompletedProcess([], int(i == failed_stage)) for i in range(3)]
|
||||||
|
with patch.object(check_all.subprocess, "run", side_effect=results) as run, \
|
||||||
|
contextlib.redirect_stdout(io.StringIO()):
|
||||||
|
self.assertEqual(check_all.main(), 1)
|
||||||
|
self.assertEqual(run.call_count, 3)
|
||||||
|
self.assertTrue(run.call_args_list[-1].args[0][1].endswith("inbox_check.py"))
|
||||||
|
|
||||||
|
def test_all_success_and_spawn_failure(self):
|
||||||
|
with patch.object(check_all.subprocess, "run", return_value=subprocess.CompletedProcess([], 0)), \
|
||||||
|
contextlib.redirect_stdout(io.StringIO()):
|
||||||
|
self.assertEqual(check_all.main(), 0)
|
||||||
|
with patch.object(check_all.subprocess, "run", side_effect=[OSError("unavailable"),
|
||||||
|
subprocess.CompletedProcess([], 0), subprocess.CompletedProcess([], 0)]) as run, \
|
||||||
|
contextlib.redirect_stdout(io.StringIO()):
|
||||||
|
self.assertEqual(check_all.main(), 1)
|
||||||
|
self.assertEqual(run.call_count, 3)
|
||||||
|
|
||||||
|
def test_nested_policy_discovered_reported_and_reviewable(self):
|
||||||
|
with tempfile.TemporaryDirectory() as directory:
|
||||||
|
root = pathlib.Path(directory)
|
||||||
|
policies = root / "docs/regulatory/policies"
|
||||||
|
policies.mkdir(parents=True)
|
||||||
|
(policies / "README.md").write_text("Catalogue without front-matter")
|
||||||
|
policy = policies / "example.md"
|
||||||
|
policy.write_text('---\nid: RISK-POL-9999\nnext_check: "2026-08-20"\n'
|
||||||
|
'cadence: instant\n---\n\n# Policy\n')
|
||||||
|
with patch.object(lib, "REPO", root):
|
||||||
|
records = lib.regulatory()
|
||||||
|
self.assertEqual([r["id"] for r in records], ["RISK-POL-9999"])
|
||||||
|
self.assertIn("RISK-POL-9999 — due", self.report(regulatory=records))
|
||||||
|
with patch.object(lib, "findings", return_value=[]), patch.object(lib, "now", return_value=NOW), \
|
||||||
|
contextlib.redirect_stdout(io.StringIO()):
|
||||||
|
self.assertEqual(record_check.main(["RISK-POL-9999", "clean", "review evidence"]), 0)
|
||||||
|
reviewed = lib.load(policy)
|
||||||
|
self.assertEqual(reviewed["cadence"], "1h")
|
||||||
|
self.assertIn("review evidence", policy.read_text())
|
||||||
|
|
||||||
|
def test_invalid_dates_do_not_abort_reports(self):
|
||||||
|
finding = dict(id="RISK-F-9999", _path=pathlib.Path("test.md"), status="open",
|
||||||
|
next_check="not-a-date", severity="high", cadence="instant")
|
||||||
|
report = self.report([finding], [dict(id="RISK-POL-9999", next_check="bad")])
|
||||||
|
self.assertIn("next_check is not a date", report)
|
||||||
|
self.assertIn("RISK-POL-9999 — invalid date", report)
|
||||||
|
self.assertIn("Publication handovers pending", report)
|
||||||
|
self.assertIsNone(lib.moment("2026-99-99"))
|
||||||
|
self.assertEqual(lib.moment("2026-09-05T00:00:00"), NOW)
|
||||||
|
|
||||||
|
def test_regulatory_deferral_expires_and_bad_date_stays_visible(self):
|
||||||
|
policy = dict(id="RISK-POL-9999", next_check="2026-08-20", deferred_to="2026-09-06")
|
||||||
|
self.assertIn("Regulatory records due:\n none", self.report(regulatory=[policy]))
|
||||||
|
policy["deferred_to"] = "2026-09-04"
|
||||||
|
self.assertIn("RISK-POL-9999 — due", self.report(regulatory=[policy]))
|
||||||
|
policy["deferred_to"] = "bad"
|
||||||
|
self.assertIn("invalid date: deferred_to", self.report(regulatory=[policy]))
|
||||||
|
|
||||||
|
def test_disclosure_obligations_survive_closure(self):
|
||||||
|
findings = [dict(id="RISK-F-9998", _path=pathlib.Path("a.md"), status="fixed",
|
||||||
|
disclosure="embargoed", embargo_condition="owner verifies", embargo_review="2026-09-01"),
|
||||||
|
dict(id="RISK-F-9999", _path=pathlib.Path("b.md"), status="fixed",
|
||||||
|
disclosure="public", publication="pending-handover")]
|
||||||
|
report = self.report(findings)
|
||||||
|
self.assertIn("RISK-F-9998 — embargo review due", report)
|
||||||
|
self.assertIn("RISK-F-9999 (fixed) — pending policy-nexus", report)
|
||||||
|
findings[0].pop("embargo_review")
|
||||||
|
self.assertIn("missing or invalid embargo_review", self.report(findings))
|
||||||
|
findings[0]["embargo_review"] = "2027-01-01"
|
||||||
|
self.assertIn("Embargo reviews due:\n none", self.report(findings))
|
||||||
|
|
||||||
|
def test_bad_deferral_does_not_write_and_review_clears_old_deferral(self):
|
||||||
|
with tempfile.TemporaryDirectory() as directory:
|
||||||
|
path = pathlib.Path(directory) / "record.md"
|
||||||
|
original = '---\nid: RISK-F-9999\ncadence: instant\ndeferred_to: "2027-01-01"\n---\n'
|
||||||
|
path.write_text(original)
|
||||||
|
with patch.object(lib, "findings", side_effect=lambda: [lib.load(path)]), \
|
||||||
|
patch.object(lib, "regulatory", return_value=[]), patch.object(lib, "now", return_value=NOW), \
|
||||||
|
contextlib.redirect_stdout(io.StringIO()):
|
||||||
|
for value in ("bad", "2020-01-01"):
|
||||||
|
with self.assertRaises(SystemExit):
|
||||||
|
record_check.main(["RISK-F-9999", "defer", value, "operator reason"])
|
||||||
|
self.assertEqual(path.read_text(), original)
|
||||||
|
record_check.main(["RISK-F-9999", "moved", "new evidence"])
|
||||||
|
self.assertNotIn("deferred_to", lib.load(path))
|
||||||
|
|
||||||
|
def test_archived_completed_fix_is_not_stalled(self):
|
||||||
|
with tempfile.TemporaryDirectory() as directory:
|
||||||
|
root = pathlib.Path(directory)
|
||||||
|
archive = root / "owner/workplans/archived"
|
||||||
|
archive.mkdir(parents=True)
|
||||||
|
(archive / "260901-TEST-WP-0001-fix.md").write_text(
|
||||||
|
'---\nid: TEST-WP-0001\nstatus: finished\nrepo: owner\n---\n')
|
||||||
|
finding = dict(id="RISK-F-9999", status="open", severity="high", fix_tracking="TEST-WP-0001")
|
||||||
|
with patch.object(fix_tracker, "ESTATE", root), patch.object(lib, "findings", return_value=[finding]), \
|
||||||
|
patch.object(lib, "now", return_value=NOW), \
|
||||||
|
patch.object(fix_tracker, "last_commit", return_value=NOW - dt.timedelta(days=100)):
|
||||||
|
report = "\n".join(fix_tracker.report())
|
||||||
|
self.assertIn("finished [archived]", report)
|
||||||
|
self.assertNotIn("UNCHANGED", report)
|
||||||
|
|
||||||
|
def test_accepted_obligation_requires_a_resolvable_basis_and_review(self):
|
||||||
|
finding = dict(id="RISK-F-9999", status="accepted", fix_tracking="unset",
|
||||||
|
accepted_by="operator", accepted_until="real data arrives",
|
||||||
|
determination="RISK-REG-9999", next_check="2026-08-01")
|
||||||
|
with patch.object(lib, "findings", return_value=[finding]), \
|
||||||
|
patch.object(lib, "regulatory", return_value=[dict(id="RISK-REG-9999")]):
|
||||||
|
report = "\n".join(fix_tracker.report())
|
||||||
|
self.assertIn("RECORDED ACCEPTANCE", report)
|
||||||
|
self.assertIn("not a fix or renewed acceptance", report)
|
||||||
|
self.assertNotIn("NO FIX TRACKING", report)
|
||||||
|
finding["next_check"] = "bad"
|
||||||
|
self.assertIn("ACCEPTANCE INCOMPLETE: next_check", "\n".join(fix_tracker.report()))
|
||||||
|
self.assertIn("NO FIX TRACKING", "\n".join(fix_tracker.report()))
|
||||||
|
finding["next_check"] = "2026-08-01"
|
||||||
|
with patch.object(lib, "findings", return_value=[finding]), patch.object(lib, "regulatory", return_value=[]):
|
||||||
|
self.assertIn("resolvable determination", "\n".join(fix_tracker.report()))
|
||||||
|
|
||||||
|
def test_completed_source_does_not_hide_closure_evidence(self):
|
||||||
|
finding = dict(id="RISK-F-9999", _path=pathlib.Path("test.md"), status="open",
|
||||||
|
fix_tracking="TEST-WP-0001 (finished)", closure_condition="runtime acceptance receipt")
|
||||||
|
report = self.report([finding])
|
||||||
|
self.assertIn("Closure evidence pending:\n RISK-F-9999 — runtime acceptance receipt", report)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
25
tools/check_all.py
Normal file
25
tools/check_all.py
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Run all read-only checks, retaining failures without hiding later reports."""
|
||||||
|
import pathlib
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
TOOLS = pathlib.Path(__file__).resolve().parent
|
||||||
|
STAGES = (("register_index.py", "--check"), ("register_check.py",), ("inbox_check.py",))
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
failed = False
|
||||||
|
for stage in STAGES:
|
||||||
|
try:
|
||||||
|
result = subprocess.run([sys.executable, str(TOOLS / stage[0]), *stage[1:]])
|
||||||
|
failed = result.returncode != 0 or failed
|
||||||
|
except OSError as exc:
|
||||||
|
print(f"{stage[0]}: could not run: {exc}", flush=True)
|
||||||
|
failed = True
|
||||||
|
print(flush=True)
|
||||||
|
return int(failed)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
|
|
@ -68,6 +68,7 @@ def resolve(fix_tracking: str) -> list[dict]:
|
||||||
"id": full,
|
"id": full,
|
||||||
"repo": fm.get("repo", path.parent.parent.name),
|
"repo": fm.get("repo", path.parent.parent.name),
|
||||||
"state": (state or "unreadable") + (" [archived]" if archived else ""),
|
"state": (state or "unreadable") + (" [archived]" if archived else ""),
|
||||||
|
"completed": str(state).lower() in ("done", "finished", "cancel"),
|
||||||
"workplan_status": fm.get("status"),
|
"workplan_status": fm.get("status"),
|
||||||
"moved": last_commit(path),
|
"moved": last_commit(path),
|
||||||
})
|
})
|
||||||
|
|
@ -81,6 +82,22 @@ def report() -> list[str]:
|
||||||
continue
|
continue
|
||||||
tracking = f.get("fix_tracking")
|
tracking = f.get("fix_tracking")
|
||||||
if not tracking or str(tracking).startswith("unset"):
|
if not tracking or str(tracking).startswith("unset"):
|
||||||
|
if f.get("status") == "accepted":
|
||||||
|
missing = [key for key in ("accepted_by", "accepted_until", "determination")
|
||||||
|
if not f.get(key) or str(f[key]) == "unset"]
|
||||||
|
if lib.moment(f.get("next_check")) is None:
|
||||||
|
missing.append("next_check")
|
||||||
|
determinations = {r.get("id") for r in lib.regulatory()}
|
||||||
|
if f.get("determination") and f["determination"] not in determinations:
|
||||||
|
missing.append("resolvable determination")
|
||||||
|
if not missing:
|
||||||
|
lines.append(
|
||||||
|
f"{f['id']} — RECORDED ACCEPTANCE by {f['accepted_by']}; "
|
||||||
|
f"ends when: {f['accepted_until']}; basis {f['determination']}; "
|
||||||
|
f"review {f['next_check']} (not a fix or renewed acceptance)"
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
lines.append(f"{f['id']} — ACCEPTANCE INCOMPLETE: {', '.join(missing)}")
|
||||||
lines.append(f"{f['id']} ({f.get('severity')}) — NO FIX TRACKING; owner {f.get('fix_owner')}")
|
lines.append(f"{f['id']} ({f.get('severity')}) — NO FIX TRACKING; owner {f.get('fix_owner')}")
|
||||||
continue
|
continue
|
||||||
resolved = resolve(tracking)
|
resolved = resolve(tracking)
|
||||||
|
|
@ -93,7 +110,7 @@ def report() -> list[str]:
|
||||||
if r["moved"]:
|
if r["moved"]:
|
||||||
age = (now - r["moved"]).days
|
age = (now - r["moved"]).days
|
||||||
window = STALL_DAYS.get(f.get("severity"), 30)
|
window = STALL_DAYS.get(f.get("severity"), 30)
|
||||||
done = str(r["state"]).lower() in ("done", "finished", "cancel")
|
done = r.get("completed", False)
|
||||||
flag = "" if done or age <= window else f" ← UNCHANGED {age}d (window {window}d)"
|
flag = "" if done or age <= window else f" ← UNCHANGED {age}d (window {window}d)"
|
||||||
lines.append(f"{f['id']} — {r['id']}: {r['state']}, last changed {r['moved']:%Y-%m-%d}{flag}")
|
lines.append(f"{f['id']} — {r['id']}: {r['state']}, last changed {r['moved']:%Y-%m-%d}{flag}")
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,8 @@ def main(argv: list[str]) -> int:
|
||||||
fail("`defer` needs a date and the operator's reason")
|
fail("`defer` needs a date and the operator's reason")
|
||||||
until, why = rest[0], rest[1]
|
until, why = rest[0], rest[1]
|
||||||
new_rung, streak, nxt = rung, int(f.get("clean_streak", 0)), lib.moment(until)
|
new_rung, streak, nxt = rung, int(f.get("clean_streak", 0)), lib.moment(until)
|
||||||
|
if nxt is None or nxt <= now:
|
||||||
|
fail("`defer` needs a valid future date")
|
||||||
line = f"- **{now:%Y-%m-%d}** — deferred to {until} by explicit operator decision: {why}"
|
line = f"- **{now:%Y-%m-%d}** — deferred to {until} by explicit operator decision: {why}"
|
||||||
defer = until
|
defer = until
|
||||||
else:
|
else:
|
||||||
|
|
@ -71,6 +73,8 @@ def main(argv: list[str]) -> int:
|
||||||
}
|
}
|
||||||
if defer:
|
if defer:
|
||||||
subs["deferred_to"] = defer
|
subs["deferred_to"] = defer
|
||||||
|
else:
|
||||||
|
text = re.sub(r"(?m)^deferred_to:.*\n", "", text)
|
||||||
for key, value in subs.items():
|
for key, value in subs.items():
|
||||||
quoted = f'"{value}"' if key not in ("cadence", "clean_streak") else value
|
quoted = f'"{value}"' if key not in ("cadence", "clean_streak") else value
|
||||||
if re.search(rf"(?m)^{key}:", text):
|
if re.search(rf"(?m)^{key}:", text):
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ NOW = lib.now()
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
fs = [f for f in lib.findings() if lib.watched(f.get("status"))]
|
all_findings = lib.findings()
|
||||||
|
fs = [f for f in all_findings if lib.watched(f.get("status"))]
|
||||||
lines: list[str] = []
|
lines: list[str] = []
|
||||||
|
|
||||||
def section(title: str, rows: list[str], quiet: str) -> None:
|
def section(title: str, rows: list[str], quiet: str) -> None:
|
||||||
|
|
@ -50,9 +51,9 @@ def main() -> int:
|
||||||
# reported by name, and never silently ignored.
|
# reported by name, and never silently ignored.
|
||||||
ids = {f["id"] for f in lib.findings()}
|
ids = {f["id"] for f in lib.findings()}
|
||||||
malformed: list[str] = []
|
malformed: list[str] = []
|
||||||
for f in fs:
|
for f in all_findings:
|
||||||
fid = f["id"]
|
fid = f["id"]
|
||||||
for field in ("last_checked", "next_check", "embargo_since", "deferred_to"):
|
for field in ("last_checked", "next_check", "embargo_since", "embargo_review", "deferred_to", "escalation_sent"):
|
||||||
if f.get(field) and lib.moment(f[field]) is None:
|
if f.get(field) and lib.moment(f[field]) is None:
|
||||||
malformed.append(f"{fid} — {field} is not a date: {f[field]!r}")
|
malformed.append(f"{fid} — {field} is not a date: {f[field]!r}")
|
||||||
if (c := f.get("cadence")) and c not in lib.CADENCE_NAMES:
|
if (c := f.get("cadence")) and c not in lib.CADENCE_NAMES:
|
||||||
|
|
@ -147,6 +148,10 @@ def main() -> int:
|
||||||
# RISK-WP-0005-T01: the fix's own state, read from the owner's workplan
|
# RISK-WP-0005-T01: the fix's own state, read from the owner's workplan
|
||||||
# file rather than from our memory of what they told us.
|
# file rather than from our memory of what they told us.
|
||||||
section("Fix state", fix_tracker.report(), "no finding claims a tracked fix")
|
section("Fix state", fix_tracker.report(), "no finding claims a tracked fix")
|
||||||
|
section("Closure evidence pending", [
|
||||||
|
f"{f['id']} — {f['closure_condition']}"
|
||||||
|
for f in fs if f.get("closure_condition")
|
||||||
|
], "none recorded")
|
||||||
if due_defaults:
|
if due_defaults:
|
||||||
section("Defaults now due — apply them", due_defaults, "none")
|
section("Defaults now due — apply them", due_defaults, "none")
|
||||||
if deep:
|
if deep:
|
||||||
|
|
@ -154,11 +159,26 @@ def main() -> int:
|
||||||
|
|
||||||
embargo = [
|
embargo = [
|
||||||
f"{f['id']} — lifts when: {f.get('embargo_condition')}"
|
f"{f['id']} — lifts when: {f.get('embargo_condition')}"
|
||||||
for f in fs
|
for f in all_findings
|
||||||
if f.get("disclosure") == "embargoed"
|
if f.get("disclosure") == "embargoed"
|
||||||
]
|
]
|
||||||
section("Embargoed", embargo, "none")
|
section("Embargoed", embargo, "none")
|
||||||
|
|
||||||
|
embargo_due = []
|
||||||
|
for f in all_findings:
|
||||||
|
if f.get("disclosure") != "embargoed":
|
||||||
|
continue
|
||||||
|
when = lib.moment(f.get("embargo_review"))
|
||||||
|
if when is None:
|
||||||
|
embargo_due.append(f"{f['id']} — missing or invalid embargo_review; re-decide the hold")
|
||||||
|
elif NOW >= when:
|
||||||
|
embargo_due.append(f"{f['id']} — embargo review due {f['embargo_review']}; re-decide the hold")
|
||||||
|
section("Embargo reviews due", embargo_due, "none")
|
||||||
|
section("Publication handovers pending", [
|
||||||
|
f"{f['id']} ({f.get('status')}) — pending policy-nexus handover: {f.get('publication_id', 'no publication id')}"
|
||||||
|
for f in all_findings if f.get("publication") == "pending-handover"
|
||||||
|
], "none")
|
||||||
|
|
||||||
# T05 — an escalation nobody acknowledged is indistinguishable from one
|
# T05 — an escalation nobody acknowledged is indistinguishable from one
|
||||||
# never sent, which is the failure this register fixed for its own inbox
|
# never sent, which is the failure this register fixed for its own inbox
|
||||||
# and not, until now, for the path that matters more.
|
# and not, until now, for the path that matters more.
|
||||||
|
|
@ -184,6 +204,14 @@ def main() -> int:
|
||||||
|
|
||||||
reg = []
|
reg = []
|
||||||
for r in lib.regulatory():
|
for r in lib.regulatory():
|
||||||
|
invalid = [field for field in ("last_checked", "next_check", "review_by", "deferred_to")
|
||||||
|
if r.get(field) and lib.moment(r[field]) is None]
|
||||||
|
if invalid:
|
||||||
|
reg.append(f"{r.get('id')} — invalid date: {', '.join(invalid)}; review required")
|
||||||
|
continue
|
||||||
|
until = lib.moment(r.get("deferred_to"))
|
||||||
|
if until and NOW < until:
|
||||||
|
continue
|
||||||
when = lib.moment(r.get("next_check")) or lib.moment(r.get("review_by"))
|
when = lib.moment(r.get("next_check")) or lib.moment(r.get("review_by"))
|
||||||
if when is None:
|
if when is None:
|
||||||
reg.append(f"{r.get('id')} — no next_check set")
|
reg.append(f"{r.get('id')} — no next_check set")
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ def regulatory() -> list[dict]:
|
||||||
d = REPO / "docs" / "regulatory"
|
d = REPO / "docs" / "regulatory"
|
||||||
if not d.exists():
|
if not d.exists():
|
||||||
return []
|
return []
|
||||||
return sorted((load(p) for p in d.glob("*.md") if p.name != "README.md"),
|
return sorted((load(p) for p in d.rglob("*.md") if p.name != "README.md"),
|
||||||
key=lambda r: r.get("id", ""))
|
key=lambda r: r.get("id", ""))
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -112,7 +112,12 @@ def moment(value) -> dt.datetime | None:
|
||||||
if isinstance(value, dt.date):
|
if isinstance(value, dt.date):
|
||||||
return dt.datetime.combine(value, dt.time(0, 0), tzinfo=dt.timezone.utc)
|
return dt.datetime.combine(value, dt.time(0, 0), tzinfo=dt.timezone.utc)
|
||||||
if isinstance(value, str) and value not in ("", "unset"):
|
if isinstance(value, str) and value not in ("", "unset"):
|
||||||
return dt.datetime.fromisoformat(value.replace("Z", "+00:00")).astimezone(dt.timezone.utc)
|
try:
|
||||||
|
parsed = dt.datetime.fromisoformat(value.replace("Z", "+00:00"))
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
return (parsed.replace(tzinfo=dt.timezone.utc) if parsed.tzinfo is None
|
||||||
|
else parsed.astimezone(dt.timezone.utc))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
130
workplans/RISK-WP-0006-keep-review-obligations-visible.md
Normal file
130
workplans/RISK-WP-0006-keep-review-obligations-visible.md
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
---
|
||||||
|
id: RISK-WP-0006
|
||||||
|
type: workplan
|
||||||
|
title: "Keep review obligations visible when the index or records are stale"
|
||||||
|
domain: infotech
|
||||||
|
repo: risk-nexus
|
||||||
|
status: finished
|
||||||
|
owner: the-custodian
|
||||||
|
topic_slug: risk-nexus
|
||||||
|
created: "2026-09-05"
|
||||||
|
updated: "2026-09-05"
|
||||||
|
depends_on_workplans:
|
||||||
|
- RISK-WP-0005
|
||||||
|
state_hub_workstream_id: "900ba790-c5b8-523c-947f-5cd743fa1d58"
|
||||||
|
---
|
||||||
|
|
||||||
|
# RISK-WP-0006 — keep review obligations visible
|
||||||
|
|
||||||
|
## Problem and priority
|
||||||
|
|
||||||
|
The [scope assessment](../history/2026-09-05-014333-scope-intent-assessment.md)
|
||||||
|
found that `make check` stops before showing overdue work, all four full legal
|
||||||
|
policies are outside review discovery, and disclosure obligations disappear
|
||||||
|
from the work list. These are the first priorities: they hide known obligations
|
||||||
|
and can be corrected within this repository without a new service or mandate.
|
||||||
|
Malformed dates must not defeat the repaired reporting path.
|
||||||
|
|
||||||
|
## Tasks and acceptance
|
||||||
|
|
||||||
|
### T01 — Run every check stage even if another fails
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: RISK-WP-0006-T01
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
state_hub_task_id: "44f58905-fc81-571f-b112-e37001b02ed9"
|
||||||
|
```
|
||||||
|
|
||||||
|
Run index, register and inbox checks independently, preserving a nonzero result
|
||||||
|
if any stage fails. A stale index and a broken register stage must still allow
|
||||||
|
the inbox stage to run. No regeneration or grading as a side effect.
|
||||||
|
|
||||||
|
### T02 — Include full policies in the review workflow
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: RISK-WP-0006-T02
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
state_hub_task_id: "4a9cd603-7722-5e3b-833e-b65109f33d8a"
|
||||||
|
```
|
||||||
|
|
||||||
|
Discover nested regulatory records, excluding README catalogues. Full policies
|
||||||
|
must appear when due and accept recorded outcomes. `make due` must expose these
|
||||||
|
obligations to existing scheduled sessions, not filter them out. Invalid dates
|
||||||
|
must be reported without aborting the report; invalid deferrals must not write.
|
||||||
|
|
||||||
|
### T03 — Keep disclosure obligations visible after closure
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: RISK-WP-0006-T03
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
state_hub_task_id: "3d250ebe-1d06-55f2-a4cc-8a716b12414f"
|
||||||
|
```
|
||||||
|
|
||||||
|
Report due or missing embargo review dates and pending publication handovers
|
||||||
|
across all findings, including fixed findings. Surface them through `make due`.
|
||||||
|
Do not publish, lift embargoes or change finding statuses automatically.
|
||||||
|
|
||||||
|
### T04 — Correct the archived fix completion signal
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: RISK-WP-0006-T04
|
||||||
|
status: done
|
||||||
|
priority: medium
|
||||||
|
state_hub_task_id: "79b0c627-9fff-59e2-a400-8d3e9585504b"
|
||||||
|
```
|
||||||
|
|
||||||
|
An archived completed workplan must not be reported as an unchanged unfinished
|
||||||
|
fix just because its display status carries an archive suffix. Preserve the
|
||||||
|
archive label and the documented whole-file timestamp limitation.
|
||||||
|
|
||||||
|
### T05 — Verify, document and reconcile registration
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: RISK-WP-0006-T05
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
state_hub_task_id: "96d06e61-84e7-5c3a-9d79-b700408afaf7"
|
||||||
|
```
|
||||||
|
|
||||||
|
Add focused regression tests for the failures above using isolated files and
|
||||||
|
mocked external reads. Run them and the live read-only reporting path. Update
|
||||||
|
SCOPE, usage and the operational instructions, and reconcile the workplan and
|
||||||
|
task records with State Hub. Record actual registration results and residuals.
|
||||||
|
|
||||||
|
## Scope boundary and next priorities
|
||||||
|
|
||||||
|
This plan repairs visibility, not the overdue substantive reviews themselves.
|
||||||
|
External intake delivery, urgent incident handling, scheduler-to-session delivery
|
||||||
|
proof and the production declaration require separate operational decisions or
|
||||||
|
cross-repository work. They remain open in the assessment. Missing fix records
|
||||||
|
and the F-0011 notice require evidence reconciliation, not automatic closure.
|
||||||
|
No legal conclusions, grades, acknowledgements or messages are generated here.
|
||||||
|
|
||||||
|
## Verification and completion evidence
|
||||||
|
|
||||||
|
Implementation complete for T01–T04. Eight isolated regression tests pass via
|
||||||
|
`make test`, covering stage failures, nested policy discovery and recorded
|
||||||
|
reviews, invalid dates and deferrals, disclosure after closure, and archived
|
||||||
|
completed fixes. `git diff --check` passes.
|
||||||
|
|
||||||
|
Live validation first ran with a stale index: every report still executed and
|
||||||
|
Make returned nonzero. After `make register`, `make check` and `make due` both
|
||||||
|
returned zero while exposing all four overdue policies, eight pending handovers,
|
||||||
|
three overdue findings and the newer F-0011 inbox notice. No finding or policy
|
||||||
|
was stamped reviewed, re-graded or closed.
|
||||||
|
|
||||||
|
Registration: the normal CLI and an outside-sandbox retry timed out on State Hub
|
||||||
|
reads. A longer-timeout full reconciliation was stopped after prolonged API
|
||||||
|
reads without a completion result. Targeted registration succeeded
|
||||||
|
through the same workplan/task API and deterministic IDs used by the reconciler.
|
||||||
|
The workplan UUID is `900ba790-c5b8-523c-947f-5cd743fa1d58`; all five task
|
||||||
|
UUIDs are recorded beside their source blocks. Completion and the file binding
|
||||||
|
are synchronized through the API; the local index uses the reconciler renderer.
|
||||||
|
|
||||||
|
Residuals: external contact delivery, incident clocks, independent execution
|
||||||
|
assurance, substantive overdue reviews, method review scheduling and production
|
||||||
|
transition decisions remain open. The updated activity definition is local
|
||||||
|
source; deployment/synchronization to activity-core was not performed.
|
||||||
113
workplans/RISK-WP-0007-reconcile-owner-evidence.md
Normal file
113
workplans/RISK-WP-0007-reconcile-owner-evidence.md
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
---
|
||||||
|
id: RISK-WP-0007
|
||||||
|
type: workplan
|
||||||
|
title: "Reconcile owner evidence and keep runtime closure obligations visible"
|
||||||
|
domain: infotech
|
||||||
|
repo: risk-nexus
|
||||||
|
status: finished
|
||||||
|
owner: the-custodian
|
||||||
|
topic_slug: custodian
|
||||||
|
created: "2026-09-05"
|
||||||
|
updated: "2026-09-05"
|
||||||
|
depends_on_workplans:
|
||||||
|
- RISK-WP-0006
|
||||||
|
state_hub_workstream_id: "ac12733f-3f4b-5c7b-aee7-7115b9c4db72"
|
||||||
|
---
|
||||||
|
|
||||||
|
# RISK-WP-0007 — reconcile owner evidence
|
||||||
|
|
||||||
|
The repaired reports expose work the register had not read. Reconcile it before
|
||||||
|
building another mechanism. Source remediation is progress; deployed acceptance
|
||||||
|
and credential invalidation require their own evidence.
|
||||||
|
|
||||||
|
## T01 — Reconcile the qonto return
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: RISK-WP-0007-T01
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
state_hub_task_id: "d3f0a9b7-4374-5350-b0b4-d7ac4f782acb"
|
||||||
|
```
|
||||||
|
|
||||||
|
Read the newer inbox notice, source cadence/logger/endpoint and observer workplan.
|
||||||
|
Link QONTO-WP-0005 and KG-WP-0005-T03 to F-0011; replace the stale missing-source
|
||||||
|
claim with the concrete runtime acceptance obligation. Keep the medium grade
|
||||||
|
and open status until that obligation is demonstrated. Record a moved check.
|
||||||
|
|
||||||
|
## T02 — Reconcile backup source remediation
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: RISK-WP-0007-T02
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
state_hub_task_id: "215b8b0b-aef0-5575-bf12-b08dc2941cbe"
|
||||||
|
```
|
||||||
|
|
||||||
|
Read RPF-WP-0029 and verify source fallback removal without displaying, testing
|
||||||
|
or copying credential material. Link provider invalidation/recovery tracking;
|
||||||
|
keep the low grade, open status and embargo until the original conditions hold.
|
||||||
|
Record a moved check, retaining the existing deadline.
|
||||||
|
|
||||||
|
## T03 — Distinguish accepted obligations from missing fixes
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: RISK-WP-0007-T03
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
state_hub_task_id: "a17feb05-2c2c-5372-adbb-9d2c095f55fd"
|
||||||
|
```
|
||||||
|
|
||||||
|
Report an accepted record's accepter, expiry condition, determination and review
|
||||||
|
date when those fields resolve to a real record. Do not invent a fix workplan
|
||||||
|
for F-0008 or suppress incomplete acceptance records. Surface closure conditions
|
||||||
|
even when the source workplan is completed. Cover both paths with regression
|
||||||
|
tests. Inspect F-0008's technical evidence without renewing legal conclusions
|
||||||
|
or certifying that its real-data trigger remains false.
|
||||||
|
|
||||||
|
## T04 — Record verification boundaries and register the result
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: RISK-WP-0007-T04
|
||||||
|
status: done
|
||||||
|
priority: medium
|
||||||
|
state_hub_task_id: "ebf1edad-6e0e-5fdc-9781-5e79cff8b117"
|
||||||
|
```
|
||||||
|
|
||||||
|
Retain dated source evidence, explicit next evidence and owners. Inspect local
|
||||||
|
external-intake/publication and activity evidence; state exactly what remains
|
||||||
|
unverified. Update scope/state/index, run tests and reports, register this
|
||||||
|
workplan and its tasks, and verify completion in State Hub.
|
||||||
|
|
||||||
|
## Boundaries
|
||||||
|
|
||||||
|
No messages, acknowledgements, deployments, credential actions, publication,
|
||||||
|
new spending or automatic finding closure. Existing source-owner workplans
|
||||||
|
remain authoritative. This plan closes the register's reconciliation work,
|
||||||
|
not the owners' unresolved runtime obligations or the substantive legal reviews.
|
||||||
|
|
||||||
|
## Completion evidence
|
||||||
|
|
||||||
|
Completed 2026-09-05. RISK-V-0003 retains the inspected source evidence,
|
||||||
|
provenance and runtime/provider acceptance requirements. F-0011 now tracks
|
||||||
|
QONTO-WP-0005 and KG-WP-0005-T03; F-0010 tracks RPF-WP-0029-T02. Both received
|
||||||
|
`moved` outcomes and remain at `instant`; no same-sitting clean check was made.
|
||||||
|
Grades, open statuses, the credential embargo and original default dates remain.
|
||||||
|
|
||||||
|
F-0008's technical inspection is explicitly not a completed substantive review.
|
||||||
|
Its existing acceptance is now reported with its determination and due date;
|
||||||
|
invalid/incomplete acceptances still produce missing-tracking warnings. The
|
||||||
|
closure-evidence section survives completed source workplans.
|
||||||
|
|
||||||
|
Ten isolated tests pass via `make test`; document links and `git diff --check`
|
||||||
|
pass. The generated register and live checker expose the two waiting owner tasks,
|
||||||
|
recorded acceptance, four overdue full policies and eight publication handovers.
|
||||||
|
|
||||||
|
State Hub registration succeeded for workplan
|
||||||
|
`ac12733f-3f4b-5c7b-aee7-7115b9c4db72` and all four tasks (UUIDs in source).
|
||||||
|
Completion status and backing-file binding are reconciled through the same API;
|
||||||
|
the local WORK-RECORDS index is regenerated with the State Hub renderer.
|
||||||
|
|
||||||
|
Still external or unverified: runtime capture/observer acceptance, provider
|
||||||
|
invalidation/recovery receipts, acceptance-trigger facts and legal reviews,
|
||||||
|
external contact delivery and scheduled-session completion. Source searches
|
||||||
|
establish no stronger conclusion. No messages or acknowledgements were sent.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue