2026-10-04 11:40:37 +02:00
|
|
|
# Decision emission preparation
|
|
|
|
|
|
|
|
|
|
FLEX-WP-0031 implements a durable local outbox, daily per-class heartbeats,
|
|
|
|
|
asynchronous delivery and optional PVC. Every pin still defaults to no outbox
|
|
|
|
|
and no delivery worker. `cadence.yaml` remains declared-not-yet-emitting; G2
|
|
|
|
|
does not close on local tests or chart rendering.
|
|
|
|
|
|
|
|
|
|
After sender admission and the exact approved rollout, enable the chart's
|
|
|
|
|
`outbox.enabled`, choose a unique `outbox.source` for the pin, and set
|
|
|
|
|
`outbox.size` against measured capacity and expected cumulative log growth.
|
|
|
|
|
`outbox.existingClaim` can reuse its own retained claim. New claims carry Helm's keep policy so uninstall does not remove the
|
|
|
|
|
evidence log; any eventual claim cleanup needs its own reviewed action.
|
|
|
|
|
The chart enforces one
|
|
|
|
|
replica and Recreate; each source requires its own outbox. Never run two
|
|
|
|
|
processes against one outbox directory. The fsGroup permits the non-root
|
|
|
|
|
process to write the mount while keeping its root filesystem read-only.
|
|
|
|
|
|
|
|
|
|
Delivery requires explicit serve flags:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
--audit-url <admitted audit-core http(s) /v1/events endpoint>
|
|
|
|
|
--audit-token-file <governed mounted sender token path>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Neither flag is enabled by the chart or any checked-in production pin. These
|
|
|
|
|
flags require `--outbox-dir`; the source is supplied by `--emission-source`.
|
|
|
|
|
The worker reads the token file per event to support rotation, refuses HTTP
|
|
|
|
|
redirects, and does not log tokens or receiver response bodies. Receiver
|
|
|
|
|
authentication/network admission and token mounts remain owner dependencies.
|
|
|
|
|
|
|
|
|
|
The worker commits due heartbeats into the same log as decisions, then drains
|
|
|
|
|
bounded batches in order. The daily timestamp is recovered from the committed
|
|
|
|
|
log after restart. Each heartbeat has its own event/correlation ID and carries
|
|
|
|
|
`data.class`, committed count and the process's released-uncommitted count.
|
|
|
|
|
Known uncommitted releases produce `released-uncommitted-finding` instead of a
|
|
|
|
|
nothing-to-report assertion. This count is volatile across restart, as the
|
|
|
|
|
existing atomicity ruling states; the heartbeat does not strengthen that bound.
|
|
|
|
|
|
|
|
|
|
Only documented 200 (duplicate) and 202 (accepted) responses advance
|
|
|
|
|
`drain.json`. The cursor is fsynced, atomically replaced and its directory
|
|
|
|
|
synced. A rejection, timeout or cursor-write failure retains the event and
|
|
|
|
|
replays its original idempotency key. A failing head event blocks subsequent
|
|
|
|
|
delivery rather than being dropped. HTTP occurs outside the decision lock.
|
|
|
|
|
|
|
|
|
|
`GET /v1/emission` reports committed and released-uncommitted decision counts,
|
|
|
|
|
pending event depth, oldest pending commit time and `lag_exceeded` when depth
|
|
|
|
|
exceeds 100 or age exceeds 1h. Counts include no record payload. The drain
|
|
|
|
|
cursor advances over heartbeats as well as decisions; pending depth includes
|
|
|
|
|
both. Acknowledged entries are retained in the append-only log. There is no
|
|
|
|
|
compaction/retention worker, so operators must plan storage and monitoring for
|
|
|
|
|
cumulative log growth before rollout.
|
|
|
|
|
|
|
|
|
|
`docs/contracts/decision-emission-cadence.json` is the schema-valid wire
|
|
|
|
|
declaration for receiver registration. It names all five classes explicitly;
|
|
|
|
|
allow's additional reconciliation obligation is in a source extension because
|
|
|
|
|
the generic expected-rate form prohibits a reconciliation block and the
|
|
|
|
|
security profile prohibits duplicate classes. audit-core's parser accepts the
|
|
|
|
|
declaration; that does not prove native sender admission or evaluation of the
|
|
|
|
|
source extension.
|
|
|
|
|
|
|
|
|
|
Run `make verify-emission-cadence` against the sibling InfoTechCanon schema and
|
|
|
|
|
NetKingdom profile checker. The declaration pins the schema SHA-256 and the
|
|
|
|
|
check rejects drift. Go tests check inventory/heartbeat parity; chart checks
|
|
|
|
|
exercise auth on/off, existing/new PVCs and refusal of multiple replicas.
|
|
|
|
|
|
|
|
|
|
A valid remote comparator remains blocked: audit-core windows use receiver
|
|
|
|
|
accepted_at, and local windows would use commit time. The current ingest
|
|
|
|
|
receipt contains no acceptance timestamp. Comparing these directly would
|
|
|
|
|
manufacture divergence after delayed delivery. Requirements and native
|
|
|
|
|
acceptance gates are in `blocked-task-dependencies-2026-10-04.md`.
|
2026-10-16 18:43:52 +02:00
|
|
|
|
|
|
|
|
## Bounded single writer for native signer admission
|
|
|
|
|
|
|
|
|
|
`Open` now requires the admitted Linux filesystem locking semantics. It obtains
|
|
|
|
|
an exclusive nonblocking OS `flock` on owner/current-group regular `writer.lock` before
|
|
|
|
|
reading the cursor or inspecting/recovering the journal. The FD remains open for
|
|
|
|
|
the outbox lifetime; another process refuses before journal mutation. Close waits
|
|
|
|
|
for an in-flight drain/cursor commit, closes the journal and releases the lock;
|
|
|
|
|
process death also releases it. The lock file is retained, never unlinked. It is created 0600; writable-PVC
|
|
|
|
|
fsGroup reconciliation may widen it to 0660 for the same admitted UID/GID, which
|
|
|
|
|
is supported. The lock, journal and cursor refuse foreign ownership/group, other-access,
|
|
|
|
|
hardlinks, symlinks and nonregular files. The lock is nonsecret; private seed permissions remain separately strict. This
|
|
|
|
|
protects competing admitted producers, not hostile same-UID unlink/rename or
|
|
|
|
|
privileged host tampering. Native PVC admission must prove actual filesystem
|
|
|
|
|
locking semantics; RWO and Recreate with one replica alone are insufficient.
|
|
|
|
|
|
|
|
|
|
`serve --outbox-max-bytes` and chart `outbox.maxBytes` select a positive integer
|
|
|
|
|
at most **67108864** (64MiB), also the default and source hard ceiling. Each
|
|
|
|
|
newline-terminated record and each atomic aggregate batch is capped at **2MiB**.
|
|
|
|
|
The cap is checked before any write; a rejected batch cannot partially commit.
|
|
|
|
|
`GET /v1/emission` reports max/committed/remaining bytes and byte-cap exhaustion
|
|
|
|
|
and `writer_fenced` without payloads. The requested PVC capacity is not a filesystem quota. The
|
|
|
|
|
initial retained Secrets pin proposes a new 1Gi local-path claim; no existing
|
|
|
|
|
claim was observed. Reclaim/retention, permissions, volume identity and native
|
|
|
|
|
filesystem semantics require separate owner admission.
|
|
|
|
|
|
|
|
|
|
Startup refuses files above the selected ceiling and streams records with a
|
|
|
|
|
2MiB line bound, rather than loading the whole log. The cursor is bounded to
|
|
|
|
|
4KiB. A newline-terminated corrupt/oversized entry is preserved and refused;
|
|
|
|
|
only the existing bounded unterminated final write repair truncates uncommitted
|
|
|
|
|
bytes. Initial journal directory entries and successful repair truncation are
|
|
|
|
|
synced. Startup failure releases the OS lock. Existing oversized committed
|
|
|
|
|
state is never automatically deleted, compacted, rotated or accepted by raising
|
|
|
|
|
a runtime cap above the hard maximum.
|
|
|
|
|
|
|
|
|
|
Write/fsync errors withhold all effects under current GH-DEC-2026-024, including
|
|
|
|
|
DENY. A partial append is truncated back to the committed prefix and synced;
|
|
|
|
|
if that rollback cannot be confirmed, the writer is fenced for its lifetime
|
|
|
|
|
until Close/restart and independent recovery. Capacity refusal touches no prior
|
|
|
|
|
bytes. Actual `/dev/full` ENOSPC and `/dev/null` fsync failure tests exercise
|
|
|
|
|
closed failure/fencing. A filled bounded journal remains full across restart;
|
|
|
|
|
acknowledged entries are still retained. At 75% capacity request an exact reviewed
|
|
|
|
|
export/retention action, and at 90% stop initiating protected work. These are
|
|
|
|
|
operator thresholds, not an invented automated retention worker or audit-core
|
|
|
|
|
admission. No underlying disk-full condition is repaired by retrying a protected
|
|
|
|
|
operation or deleting evidence.
|
|
|
|
|
|
|
|
|
|
The retained lifecycle signer rollout must use a new immutable CI candidate
|
|
|
|
|
containing reviewed hardening. Native admission includes actual competing-process
|
|
|
|
|
exclusion, capacity/failure/restart and response/original-record checks. Local
|
|
|
|
|
source tests, Helm keep annotation and a volume request do not prove node-loss
|
|
|
|
|
recovery, receiver custody or complete emission adoption. FLEX-WP-0031's remaining
|
|
|
|
|
native/G2 obligations stay open.
|