FLEX-WP-0031-T03: durable decision outbox and the FLEX-DEC-2026-018 release rule
internal/emission commits one audit-core-shaped event per decision with fsync before release (one sync per batch), random event ids with the decision id as correlation_id, torn-tail and failed-commit truncation, and per-class committed/released_uncommitted counts at GET /v1/emission. The engine releases restrictions whose record failed to commit and withholds allow/audit_only (503). api.DecisionEffects() is pinned by a source-parsing test and cadence.yaml must classify exactly it. T03 split under the task budget: heartbeat+drain is T05, reconciliation, profile check and PVC are T06. Nothing deployed. 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
This commit is contained in:
parent
7f0e2e37f9
commit
cd14a34e33
9 changed files with 842 additions and 23 deletions
|
|
@ -61,7 +61,7 @@ and the node disk is at 84 %.
|
|||
|
||||
```task
|
||||
id: FLEX-WP-0031-T02
|
||||
status: todo
|
||||
status: wait
|
||||
priority: high
|
||||
state_hub_task_id: "89661908-ca9a-5e4a-a0a5-62d1a9e02568"
|
||||
```
|
||||
|
|
@ -72,22 +72,81 @@ 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.
|
||||
|
||||
## 3. Transactional outbox, heartbeat and reconciliation counts
|
||||
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
|
||||
|
||||
```task
|
||||
id: FLEX-WP-0031-T03
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "a59603d5-8954-5b05-b1a0-b143c82e439b"
|
||||
```
|
||||
|
||||
Emit one event per decision into a local outbox, drained to `audit-core`
|
||||
`POST /v1/events`; a daily `flex-auth.decision.heartbeat`; committed counts per
|
||||
class exposed for `GET /v1/reconciliation`; lag bound per `cadence.yaml`.
|
||||
Gate: `cadence.yaml` validates under the net-kingdom emission-cadence profile
|
||||
checker with the inventory supplied as `--rare-load-bearing`/`--load-bearing`
|
||||
assertions; tests assert the declared classes equal the `DecisionEffect`
|
||||
vocabulary so a new effect cannot ship unclassified.
|
||||
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's
|
||||
`normalize()` 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-018` in `Check`, `BatchCheck` and
|
||||
`ListAllowed`. A withheld decision answers 503.
|
||||
- `serve --outbox-dir --emission-source` enables it, and `GET /v1/emission`
|
||||
reports committed and `released_uncommitted` counts 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 in `cadence.yaml` equal 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
|
||||
|
||||
```task
|
||||
id: FLEX-WP-0031-T05
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
- Emit a daily `audit-core.heartbeat` event per rare class, with `data.class`
|
||||
set to the class, following audit-core's `stream_findings` shape.
|
||||
- Correct `cadence.yaml`, which still names a single
|
||||
`flex-auth.decision.heartbeat` class.
|
||||
- Drain committed events to `POST /v1/events` with `Idempotency-Key` set to the
|
||||
event id, keep a drain cursor, and expose outbox depth and age against the
|
||||
`lag_bound`.
|
||||
- The drain stays disabled until T02 admits the senders.
|
||||
|
||||
## 6. Reconciliation, profile check, and storage
|
||||
|
||||
```task
|
||||
id: FLEX-WP-0031-T06
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
- 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.yaml` with 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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue