Bound durable outbox storage and enforce process writer exclusion
Some checks failed
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 3s
Build and Publish Container Image / build-and-push (push) Failing after 1m1s

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a140c4-354a-7823-8f0d-8f717397f786
This commit is contained in:
tegwick 2026-10-16 18:43:52 +02:00
parent 2b064eee51
commit 0a05383195
14 changed files with 733 additions and 26 deletions

View file

@ -68,3 +68,56 @@ 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`.
## 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.