audit-core/history/2026-08-28-approval-evidence-assent.md
tegwick 3177d2cee0
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Assent to AUDIT-IN-0001 — approval evidence half, with conditions
gate-house proposed (security layer model v0.3 §9.4) that audit-core own
the tamper-evident record of approvals while approval-engine owns the
operative state. Assented, with two corrections and one condition.

Correction 1: INTENT principle 6 overstated the delivered guarantee.
docs/integrity.md is authoritative — an in-database chain does not
withstand a database owner without the external chain-head attestation,
and even then it is not WORM. Principle 6 now points at that bound.

Correction 2: the chain proves alteration and truncation, not omission
at source. A suppressed revocation leaves the chain intact.

Condition: approval-engine must guarantee emission atomicity, so an
approval cannot change state without the event being durably queued in
the same transaction. Not a task audit-core can discharge for it.

Boundary: no approval-validity query will be exposed — that would be
deciding early under §6.1.

Also declares audit-core's layer (Engine, not a decision point), which
§11 requires and INTENT.md was missing.

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

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4040362@bnt-lap001
Assistant-Session: 4fd0fd24-2ee8-4413-bd67-43bd79ca73f1
2026-08-28 22:46:13 +02:00

6.2 KiB

Approval evidence — audit-core's assent (AUDIT-IN-0001)

Date: 2026-08-28 Intake: AUDIT-IN-0001 Requested by: gate-house Standard: net-kingdom/canon/standards/security-layer-model_v0.3.md §9.4 (proposed) Outcome: assent, with two corrections to the rationale and one condition on the emitting engine.


What was asked

gate-house proposed that audit-core own the evidence half of approvals — issuance, use, supersession, and revocation, emitted as audit events — while a new approval-engine owns the operative state: the durable object, atomic supersession, single consumption, and revocation without holder cooperation.

The two reasons given for keeping the operative state out of audit-core are correct and audit-core does not contest them:

  • operational custody is append-only Postgres by design (docs/audit-backend-contract.md), and an approval needs mutable current-state semantics with compare-and-swap supersession; and
  • access-engine must read approval state in-path, so putting it behind the audit fabric would make an audit outage an authorization outage.

The answer

Assent. The split is the right one. Approval evidence is a record of what happened, not the authoritative answer to whether an approval is still valid, and that distinction is what keeps this inside INTENT.md's "policy decision making" exclusion rather than a violation of it.

Two corrections and one condition follow. None of them reject the split; they state what audit-core actually delivers so the standard does not rest on a stronger claim than the implementation supports.


Correction 1 — principle 6 is an aspiration, and the delivered bound is weaker

gate-house's rationale cites INTENT.md principle 6 — signed or hash-chained manifests so operators can later prove whether a record set was changed, omitted, or truncated — as already being what authenticated approval entries need forensically.

docs/integrity.md is more careful than principle 6, and it is the contract that ships. In its own words: a chain inside the same database detects a rewritten payload_hash only if the attacker does not also recompute the suffix — and a database owner can. Tamper evidence against that class of attacker requires the external chain-head attestation, and even with it:

It still does not mean WORM, object lock, or ITC-CAP data.archive.

tamper_evidence=True is conditional on two preconditions being live (verify failing on a rewritten row, and verify-against-attestation reporting a missing cited head as a break). It is not a property of the store at rest.

So: approval events get exactly the guarantee every other audit source gets — no more. That guarantee is real and it is useful, but it is bounded by the attestation being taken and stored outside platform-pg. If §9.4 needs a stronger property for approvals specifically — WORM, object lock, or a transparency log — that is an engine gap to declare under §5.3, not a setting audit-core can turn on.

Correction 2 — the chain proves alteration, not omission at source

This is the more consequential one, and it is the reason for the condition below.

The hash chain proves that accepted records were not altered or truncated. It cannot prove anything about an approval event that was never emitted. For an approval object the omission case is not a corner: a suppressed revocation is precisely the event an attacker most wants missing, and it leaves the chain perfectly intact. Verify would report intact.

Principle 6 claims audit-core can prove a record set was "omitted". Against a compromised or buggy sender, it cannot, and neither can any append-only archive. Completeness at the boundary is the emitter's property, not the archive's.

The condition — approval-engine owns emission atomicity

audit-core accepts the evidence half on the condition that approval-engine guarantees emission is atomic with the state change — a transactional outbox or equivalent, such that an approval cannot be issued, consumed, superseded, or revoked without the corresponding event being durably queued in the same transaction.

Without that, the evidence half is silently incomplete and audit-core has no mechanism to detect the gap. audit-core will report what it received; it will not imply that what it received is everything that happened.

This is a requirement on approval-engine, not a task audit-core can discharge on its behalf. It should appear in approval-engine's contract before the evidence half is treated as load-bearing.

Boundary audit-core states explicitly

approval-engine will be registered as a distinct source, with its own sender registration, tenancy mapping, retention profile, and secret_policy under the existing onboarding rules (principle 4: a source is onboarded when ownership, retention, access, export, and evidence policy are declared and validated — not when events start arriving).

audit-core will not expose an approval-validity query. No read surface will answer "is this approval still valid". Records, yes; a verdict, never. Such a surface would be deciding early under §6.1, and a consumer branching on an audit-core answer would be routing an authorization decision through the audit fabric — the exact coupling §9.4 exists to prevent. Callers who need current state ask approval-engine.

The four event classes accepted as a distinct source: issuance, use, supersession, revocation, per §9.4.

Conformance note raised in passing

§11 requires that every repository in §4 declare its layer in INTENT.md. audit-core declares none today. It is corrected in the same change: audit-core is Engine layer — it exposes a deterministic API contract and holds operational custody — and it is explicitly not a decision point, per the boundary stated above.


What changed in this repository

File Change
INTENT.md layer declared; approval evidence named as a source; principle 6 cross-referenced to the docs/integrity.md bound
intakes/intakes.md AUDIT-IN-0001 closed, outcome assent-with-conditions
history/ this record

Reply sent to gate-house on the State Hub inbox thread.