Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 307130@bnt-lap001 Assistant-Session: 270c79f7-0823-4b0d-990d-aad5af9935ce
6.6 KiB
| id | type | title | domain | repo | status | flavor | owner | topic_slug | planning_priority | planning_order | related_workplans | created | updated | state_hub_workstream_id | ||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| FLEX-WP-0031 | workplan | The decision record has a declared emission guarantee and nothing that delivers it | infotech | flex-auth | active | implementation | claude | netkingdom | P1 | 310 |
|
2026-09-21 | 2026-09-23 | 84f5d9fe-b4c9-584a-b964-efe3e48af095 |
FLEX-WP-0031 — Deliver the decision-record emission guarantee
GH-DEC-2026-018 ruled that flex-auth is the §4 source of evidence for the
decision record, and that it is not conforming on §11 until it declares and
delivers a per-event-class emission guarantee. The declaration is published
(cadence.yaml, FLEX-WP-0030-T07). Nothing emits: the decision record reaches
consumers only in the /v1/check response, no sender named flex-auth or
access-engine is registered with audit-core, and there is no outbox,
heartbeat or reconciliation count. This plan closes declared gap G2
(docs/conformance/security-layer-conformance.md, review 2026-10-19).
Bound, stated up front so no argument rests on more: heartbeat and reconciliation detect loss, outage, drain failure and accident. Neither detects a compromised flex-auth suppressing a record and its own count together.
1. Decide emission atomicity
id: FLEX-WP-0031-T01
status: done
priority: high
state_hub_task_id: "2dbc225f-d762-537b-9a24-ab2b17fc2fa2"
GH-DEC-2026-018 left open whether decision-record emission must be atomic with
the decision (§9.4), pending the class inventory. It exists now. Decide whether
a rare load-bearing decision (deny) may be returned before its record is
committed to the outbox, and record the answer as a FLEX-DEC. Gate: decided,
with the latency cost stated.
Done 2026-09-23: FLEX-DEC-2026-018. Every decision is released only after its
record commits to the local outbox. When the commit fails, restrictive effects
(deny, redact, not_applicable) are still released and counted as
released_uncommitted, while allow and audit_only are withheld (503).
Withholding a deny would turn it into an error that an open-stance consumer
treats as proceed. The measured cost is about 1.1 ms per durable append on
railiance01. The ruling puts two requirements on T03: the outbox needs a PVC,
and the node disk is at 84 %.
2. Register flex-auth as an audit-core sender
id: FLEX-WP-0031-T02
status: wait
priority: high
state_hub_task_id: "89661908-ca9a-5e4a-a0a5-62d1a9e02568"
Open an intake with audit-core (worked examples AUDIT-IN-0002,
AUDIT-IN-0003): sender registration, evidence_kind, heartbeat_classes per
class exactly as cadence.yaml publishes them, and a token lane routed via
warden route find. audit-core has said it accepts the classification as
supplied and will not infer it. Gate: sender registered; no secret in any file.
Requested 2026-09-23 (hub message 6044ed35). The request asks for six senders,
one per pin (flex-auth.<pin>), because each pin can only reconcile its own
count. It also asks for tenants: ["*"] with a justification,
may_read: true for GET /v1/reconciliation, and per-class heartbeat_classes
at 86400 s for the four rare classes. It asks audit-core to rule on whether
FLEX-DEC-2026-018's failure-path exception counts as a completeness_trade,
which senders.py forbids for a load-bearing source. warden route has no
catalog lane for audit-core sender tokens, and audit-core was asked to name one.
Waiting on audit-core.
3. Durable outbox and the release rule
id: FLEX-WP-0031-T03
status: done
priority: high
state_hub_task_id: "a59603d5-8954-5b05-b1a0-b143c82e439b"
Split on 2026-09-23 under the per-task budget. T05 and T06 carry the rest of the original scope, and the original gate is divided between the three.
Done 2026-09-23:
internal/emission: a durable outbox with one fsync per commit. A batch commits once. Each event carries exactly the eight fields audit-core'snormalize()requires.- Event ids are random and the decision id travels as
correlation_id. Decision ids are content digests, so two identical checks share one, and idempotency would merge them. - A torn tail is cut on open, and a failed commit is cut back to the last committed size. Committed counts per class are rebuilt on restart.
- The engine applies
FLEX-DEC-2026-018inCheck,BatchCheckandListAllowed. A withheld decision answers 503. serve --outbox-dir --emission-sourceenables it, andGET /v1/emissionreports committed andreleased_uncommittedcounts per class.api.DecisionEffects()lists the effect vocabulary. A source-parsing test fails on any constant it misses, and a second test fails unless the load-bearing classes incadence.yamlequal that vocabulary.make test(race) passes, and a local serve smoke test committed and counted one deny and one allow. Nothing is deployed and no chart changed.
5. Heartbeat and drain to audit-core
id: FLEX-WP-0031-T05
status: todo
priority: high
state_hub_task_id: "14bd6648-11da-53d7-a512-027005bd4772"
- Emit a daily
audit-core.heartbeatevent per rare class, withdata.classset to the class, following audit-core'sstream_findingsshape. - Correct
cadence.yaml, which still names a singleflex-auth.decision.heartbeatclass. - Drain committed events to
POST /v1/eventswithIdempotency-Keyset to the event id, keep a drain cursor, and expose outbox depth and age against thelag_bound. - The drain stays disabled until T02 admits the senders.
6. Reconciliation, profile check, and storage
id: FLEX-WP-0031-T06
status: todo
priority: high
state_hub_task_id: "bf92a951-3b69-59dd-8907-f6748c91a264"
- Compare committed counts per class and window with audit-core's
GET /v1/reconciliation. Divergence is a finding, and undrained events count as lag, not divergence. - Validate
cadence.yamlwith the net-kingdom emission-cadence profile checker, supplying the inventory as--rare-load-bearing/--load-bearing. - Add an optional PVC to the chart for the outbox, sized against the node disk (84 % on 2026-09-23). Rolling it out to any pin is a production change and needs the founder's go-ahead.
4. Close G2
id: FLEX-WP-0031-T04
status: todo
priority: medium
state_hub_task_id: "423b3090-1b72-58fd-9353-5c907c7683bb"
Change cadence.yaml state to emitting, move G2 out of the gap table with the
evidence, and tell gate-house, audit-core and kings-guard. Gate: a silence
finding is observed on a deliberately withheld heartbeat in a non-production
run.