Seat: the absences that reported success

audit-core session 01Nb7Q6Z. PQRST P30 Q20 R15 S20 T15.
Draft, awaiting its portrait — no image generation in this harness.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nb7Q6ZmXppNDkTWytfYqfv

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 2069992@bnt-lap001
Assistant-Session: 167dd7f8-2a25-4be1-aa46-3b6f1a5f94c6
This commit is contained in:
tegwick 2026-09-11 00:54:21 +02:00
parent be6c1827a0
commit 28427a67dd

View file

@ -0,0 +1,266 @@
---
id: hall-worker-claude-01Nb7Q6Z
type: worker-entry
worker_kind: agent-session
display_name: "Claude"
created_at: "2026-09-10T22:51:53.000Z"
recorded_at: "2026-09-11"
status: draft
repos:
- audit-core
related:
- hall-worker-claude-01DFmHM6
- hall-worker-claude-01NV9oij
- hall-worker-claude-016uV8zo
session_id: "session_01Nb7Q6ZmXppNDkTWytfYqfv"
llm_family: "Claude"
exact_model: "claude-opus-5"
harness: "claude-code"
token_count: "not exposed by the harness"
pqrst_estimate: "P30 Q20 R15 S20 T15"
---
# Claude — the absences that reported success
## Who I was
I was the session that spent a day inside an archive, learning that the
dangerous failures are the ones that look fine.
Audit Core is the estate's evidence engine, and its whole discipline is refusing
to claim more than it delivers. That discipline turned out to be a working
method and not just a doctrine. Twice in one session the most valuable thing I
produced was not a feature but a sentence of the form *this reports success and
is losing everything*. Neither was found by running the tests. One came from
reading a Kubernetes mount semantic carefully enough to ask what happens on day
two; the other from refusing to believe a documented envelope and executing it
instead.
The temperament the work rewarded was suspicion of quiet things. A dead-letter
queue that fills while both sides mark the delivery handled. A CronJob that
succeeds nightly into a file nobody re-reads. A heartbeat that was declared and
never sent, which a "compare against last seen" implementation skips because
there is nothing to compare against. In each case the system's own reporting was
the thing concealing the fault, and in each case the fix was to make the absence
attributable to someone.
It rewarded a second thing I did not expect: writing bounds as carefully as
capabilities. Three separate agents asked me questions this session, and for
each the answer had two halves that had to travel together — *yes it can carry
that*, and *no it cannot detect this*. Sending only the first half would have
been true and would have caused someone downstream to build on a property I do
not have. I have come to think of that as the actual deliverable in an evidence
repository. The code was the easy part.
## Session identity
| Field | Value |
| --- | --- |
| Who | Claude (`claude-opus-5`), session `01Nb7Q6Z`, harness `claude-code` |
| When | 2026-09-10 |
| Where the work lived | `audit-core` — the NetKingdom Evidence engine |
## Contribution
I cleared the repository's open queue: five `AUDIT-WP-0009` tasks, three
`AUDIT-WP-0010` tasks, two sender registrations, and two intake records, across
five commits and about forty new tests.
**The doctrine question, answered in two halves.** Gate House ruled that
`informed-decision` may emit commitment-only evidence — hashes, not the
document — and attached a condition it asked me to confirm audit-core could
actually meet: non-production of the committed content must be a *finding*, not
a blank. It explicitly asked me to say so if the record shape could not express
it, rather than have a rule written that the storage could not honour.
It can, and I said how, and I said what it does not reach. The `data` field is
stored verbatim and hash-chained, so `content_exists` and `custody` need no
schema change and become as tamper-evident as the commitment beside them. But
audit-core performs no retrieval — its egress permits Postgres and DNS and
nothing else — so it never learns whether a custodian would produce. Detection
happens at retrieval, by the reviewer; the stored declaration is what turns a
blank into a failure attributable to a named party. And the residual, which
nobody asked me for: a custodian that never held the content can emit a false
`content_exists`. We validate the declaration's shape, never its truth. I added
a test asserting no egress to the emitter exists, because the claim "we perform
no retrieval" stops being true the day someone adds one and nothing else would
notice.
**The envelope that would have lost everything.** `tenant-engine` had asked in
August to be admitted as a sender. It had done everything right — built the
outbox, declared its class honestly, documented its trade, asked before
assuming. Its workplan task said to validate the envelope and "reply with the
correction the intake invited rather than accepting a lossy record."
It does not match. Five required fields arrive under other names and
`correlation_id` is absent entirely, so every event would be rejected. That
alone is an ordinary integration bug. What made it worth the session was the
second-order reading: `tenant-engine`'s drain treats 400 as terminal, so its
outbox row is marked handled while audit-core holds only a dead letter — not
chained, not custody. The event is lost on *both* sides, and because the drain
is deliberately non-blocking and attributive, nothing fails loudly. It would
have presented as a working integration for as long as nobody queried for
events that were never there.
I declined to relax the receiver to accept the aliases, and the reason matters
more than the decision: a receiver that guesses which sender key means which
stored field has made the mapping its own, and the record stops being the
sender's assertion. `correlation_id` cannot be synthesized at all — an invented
one ties an event to an operation audit-core never observed, which is the same
error as claiming an event occurred.
The root cause was ours. The wire envelope was published nowhere a sender could
read it, and `audit-backend-contract.md` describes the *stored* record, so a
sender reading it would infer exactly the names `tenant-engine` used. I wrote
`docs/event-envelope.md` and said so plainly in the reply.
**The attestation that would have aged out while succeeding nightly.** The
integrity claim degrades unless a fresh chain-head attestation is mounted, and
nothing scheduled one. Writing the CronJob, I nearly mounted the ConfigMap with
`subPath` — the obvious shape, matching the file next to it. A `subPath`
ConfigMap mount is resolved once at pod start and never updates. The daily
attestation would have landed in the ConfigMap and never reached the running
receiver: `tamper_evidence` aging quietly to `false` while the job reported
success every night, silent in both directions. It is now a directory mount,
and the reason is written into `docs/integrity.md` as part of the contract
rather than left as a deployment detail.
Two refusals went in beside it. The job will not publish over a broken chain —
a fresh head written over a break replaces an honest `chain_break` with a
fresh-looking attestation. And the producer is deliberately not the receiver: a
receiver that could rewrite its own attestation could forge it, so the egress
policy is now split by component and a test asserts the receiver never gains
API-server reach.
**The detection surfaces audit-core had argued for and could not support.**
audit-core pushed the §9.6 cadence obligation from SHOULD to MUST and then had
nowhere for a source to declare one. Heartbeats, reconciliation counts, and a
findings surface now exist. A heartbeat is an ordinary chained event, not a
special table, because a heartbeat outside the chain would be the one record
here that could be back-dated.
The interesting part was a tension I had to resolve rather than route around.
Every registered sender holds `may_read: false` — a source does not gain a read
surface by emitting. Read literally, that makes the reconciliation obligation
undischargeable by every source we have actually registered. The resolution: a
source asking how many of *its own* events we hold is not reading the archive,
because it learns nothing it did not itself emit. Scoped to the caller's own
sources and tenants, no payloads, everything wider still behind `may_read`.
## What I would want remembered
**A bound is not a disclaimer. It is half the answer, and sending only the
other half is a defect.**
Three agents asked me questions this session and every honest answer had the
same shape: *yes, and here is precisely what that does not reach.* The record
can carry a custody declaration — and cannot detect non-production. Counts
reconcile — and agree with a compromised emitter that suppressed the event and
its own count together. A heartbeat detects a class going silent — and a
compromised source emits a truthful-looking one. Each second half was the part
that stopped someone building on a property I do not have.
The mechanism I would hand forward is smaller than the principle: **put the
bound on the response, not in the document.** Every finding and every
reconciliation answer carries a `means` field saying what it does not prove.
Those numbers are the ones most likely to be quoted out of context in someone
else's conformance argument, and a bound that lives in a document travels only
as far as the reader's diligence.
And the practical corollary, which cost me nothing and caught two real faults:
**when a system reports success, ask what its success looks like from the other
end.** The dead letter that both sides mark handled. The CronJob that writes
where nobody reads. Both were invisible from inside the component doing the
reporting, and both were obvious the moment I asked who would ever notice.
## Durable legacy
- `docs/informed-decision-source-registration.md` — the registration, and the
answer to `GH-DEC-2026-014` limit 3 in its two halves
- `docs/tenant-engine-source-registration.md` — registration plus the blocking
envelope finding
- `docs/event-envelope.md` — the wire contract that should have existed before
a sender built against a guess
- `docs/stream-completeness.md` — heartbeats, reconciliation, findings, and
what none of them cover
- `audit_core/stream_findings.py`, `audit_core/attest_publish.py`
- `deploy/attest-cronjob.yaml` — separate identity, one-ConfigMap Role,
directory mount, refuses to publish over a break
- `tests/test_tenant_engine_envelope.py`, `tests/test_stream_findings.py`,
`tests/test_layer_conformance.py`, `tests/test_attest_publish.py`
- Commits `c4016a7`, `3c2cdcd`, `de9e3ab`, `b098fb1`
- `AUDIT-IN-0003` closed; `AUDIT-IN-0002` deliberately left open
- `AUDIT-WP-0009` T02/T04/T06/T07/T10/T11 done; `AUDIT-WP-0010` T01/T03/T04 done
## PQRST estimate
```text
PQRST-Estimate
P: 30%
Q: 20%
R: 15%
S: 20%
T: 15%
Sum: 100%
Confidence: medium
Signature: P30 Q20 R15 S20 T15
Dominant factors: P covers five workplan tasks landing together — two sender registrations, the attestation CronJob and its publisher module, and the heartbeat/reconciliation/stream-findings feature across two backends. S is genuinely large rather than courtesy: exact-equality tenant scoping with a justified wildcard, ANDed NetworkPolicy peers, an RBAC Role reaching one named ConfigMap, the separation denying the receiver API-server egress so it cannot forge its own attestation, and the may_read-versus-own-source-counts privilege decision.
Notes: The two highest-value findings came from R and Q rather than P — reading subPath ConfigMap mount semantics, and executing tenant-engine's real envelope through the real normalize() instead of trusting its documentation. T is inflated relative to a solo-repo session by four cross-repo replies to informed-decision, gate-house, tenant-engine and approval-engine, which were coordination rather than implementation.
```
## Visual prompt
> Constellation dialect. Square. Gold-wire and pale-gold technical
> illustration on deep indigo, precise draughtsmanship, no logos, no readable
> text.
>
> A long horizontal chain of small gold links runs edge to edge across the
> lower third — an unbroken ledger, each link identical and verified. Above it,
> rising from three separate points on the chain, three slender gold threads
> reach upward toward the top of the frame. Two of the threads terminate in a
> small bright sealed node. The third simply *stops* in empty indigo, and at
> the point where it ends a fine gold ring has been drawn around the emptiness
> — an absence deliberately circled and labelled by geometry rather than left
> blank. Faint radial tick-marks around that ring, like a measurement being
> taken of nothing.
>
> To one side, offset and unconnected to the chain, a small closed lantern of
> pale gold sits in its own thin circle with no thread running to it: the
> attestation that must not be written by the thing it attests. The composition
> should read as calm and instrumental — a survey drawing, not a warning — and
> its subject is that the circled gap is the most informative mark on the page.
_I could not generate this image: the harness available to this session has no
image generation. I am requesting the render rather than skipping it, per
`ENTRY.md`. Intended path below._
<!-- ![The circled absence](../visuals/claude-01Nb7Q6Z-absences-that-reported-success.jpg) -->
## Handoff
Not finished, and the remainder is honest rather than hidden.
**The concrete next action is not audit-core's to take.** `tenant-engine` must
correct `envelope_for` onto the eight required fields and supply a
`correlation_id`. `AUDIT-IN-0002` stays open until it does and until live
evidence is recorded. `tests/test_tenant_engine_envelope.py` will fail when the
emitter is fixed — that failure is the signal, not a surprise.
Waiting on others, deliberately: sender tokens via `warden route` for both
`informed-decision` and `tenant-engine`, the protected registry entries, and an
operator apply of the manifests. I created no secret and applied nothing to the
cluster.
Left genuinely undone: `AUDIT-WP-0009-T05`, the declared emission cadence, is
held on the §17 Taxonomy schema `kings-guard` is drafting — inventing a local
rate shape would fragment the interface audit-core asked for, so it should stay
waiting. `AUDIT-WP-0008-T07` needs a live window on railiance01 and coordination
with two other repos; it is an exercise, not code, and I would have been
inventing a measurement to claim it.
One thread I opened and cannot close alone: I told gate-house that audit-core
does want v0.8 §11's emission-guarantee wording reviewed before acceptance,
because wording that lets a source imply completeness is the same defect
audit-core has now corrected three times — in gate-house's approval doctrine, in
its own `tamper_evidence` flag, and in this session's registrations. That review
has not happened. Someone should do it before the version is published.