diff --git a/INTENT.md b/INTENT.md index 2259442..cf5b6e8 100644 --- a/INTENT.md +++ b/INTENT.md @@ -17,18 +17,6 @@ Audit Core must integrate cleanly with NetKingdom, Railiance, OpenBao, Kubernetes, identity providers, and application runtimes, but it must not depend on NetKingdom to exist or operate. -## Layer - -Audit Core is **Engine layer** under the NetKingdom security layer model -(`net-kingdom/canon/standards/security-layer-model_v0.3.md`): it exposes a -deterministic API contract and holds operational custody of the records it -accepts. - -It is explicitly **not a decision point**. Audit Core answers what was recorded; -it never answers whether an action is permitted, and it exposes no surface that -returns such a verdict. See `## Out Of Scope Initially` and -`history/2026-08-28-approval-evidence-assent.md`. - ## Problem Modern platforms generate audit-relevant events in many places: @@ -123,14 +111,9 @@ The data plane owns: 5. **Immutable archive and hot search are separate concerns.** Hot search can be short-lived and cost-tuned. Immutable archive is the evidence record. -6. **Tamper evidence is explicit, and bounded.** Audit Core should store - signed or hash-chained manifests for retained batches so operators can later - prove whether a record set was changed or truncated. The delivered bound is - narrower than that aspiration and `docs/integrity.md` is authoritative on it: - an in-database chain does not withstand a database owner without the external - chain-head attestation, and the chain proves nothing about an event that was - never emitted. Completeness at the boundary is the emitting source's - property, not the archive's. +6. **Tamper evidence is explicit.** Audit Core should store signed or + hash-chained manifests for retained batches so operators can later prove + whether a record set was changed, omitted, or truncated. 7. **Least-privilege access.** Tenants may access their own audit records according to policy. Platform operators may access cross-tenant records only @@ -242,33 +225,6 @@ NetKingdom must not be required for Audit Core's internal authorization model. Audit Core may accept NetKingdom OIDC claims when configured, but should also support a generic OIDC provider and local development auth mode. -## Approval Evidence - -Audit Core carries the **evidence half** of approvals as a distinct source, per -security layer model §9.4 and `AUDIT-IN-0001` (assented 2026-08-28). - -`approval-engine` owns the operative approval state — the durable object, atomic -supersession, single consumption, and revocation. Audit Core owns the record of -what happened to it: the four event classes **issuance, use, supersession, and -revocation**. - -Terms Audit Core accepts this under: - -- `approval-engine` is registered as a distinct source, with its own sender - registration, tenancy mapping, retention profile, and `secret_policy`, - onboarded under principle 4 like any other source; -- `approval-engine` guarantees **emission atomicity** — an approval cannot be - issued, consumed, superseded, or revoked without the corresponding event being - durably queued in the same transaction. Audit Core cannot detect a suppressed - emission and will not imply that what it received is everything that happened; -- Audit Core exposes **no approval-validity query**. Records, yes; a verdict - answering whether an approval is still valid, never. That would be deciding - early under §6.1 and would couple authorization to the audit fabric, which is - what §9.4 exists to prevent. Callers needing current state ask - `approval-engine`. - -Full reasoning: `history/2026-08-28-approval-evidence-assent.md`. - ## Tenant And Scope Model Audit Core should distinguish: diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 645d0dd..33214ce 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -55,4 +55,3 @@ | task | AUDIT-WP-0008-T06 | done | — | workplans/AUDIT-WP-0008-tenancy-posture-alignment.md | | task | AUDIT-WP-0008-T07 | progress | — | workplans/AUDIT-WP-0008-tenancy-posture-alignment.md | | task | AUDIT-WP-0008-T08 | done | — | workplans/AUDIT-WP-0008-tenancy-posture-alignment.md | -| intake | AUDIT-IN-0001 | open | — | intakes/intakes.md | diff --git a/history/2026-08-28-approval-evidence-assent.md b/history/2026-08-28-approval-evidence-assent.md deleted file mode 100644 index 2a21481..0000000 --- a/history/2026-08-28-approval-evidence-assent.md +++ /dev/null @@ -1,135 +0,0 @@ -# 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. diff --git a/intakes/intakes.md b/intakes/intakes.md index a83eac2..7db4949 100644 --- a/intakes/intakes.md +++ b/intakes/intakes.md @@ -7,7 +7,7 @@ id: AUDIT-IN-0001 kind: intake title: 'Proposed: audit-core takes the approval evidence half (security layer model v0.3 §9.4)' -status: closed +status: open origin: cross-repo origin_ref: net-kingdom security-layer-model_v0.3 §9.4 priority: medium @@ -30,26 +30,5 @@ description: 'gate-house proposes that audit-core own the tamper-evident record approval events as a distinct source, say so and gate-house will record the evidence half as unowned rather than assume it.' created: '2026-08-28T20:35:09.148892Z' -updated: '2026-08-28T21:10:00Z' -outcome: assent-with-conditions -closed: '2026-08-28T21:10:00Z' -resolution: 'Assent. The split is right: approval-engine owns the operative state, - audit-core owns the tamper-evident record of issuance, use, supersession, and - revocation as a distinct source. Two corrections to the rationale and one - condition. (1) INTENT principle 6 overstates 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. Approval events get exactly the guarantee every other source gets, - no more; anything stronger is an engine gap to declare under §5.3. (2) The chain - proves alteration and truncation, not omission at source. A suppressed - revocation leaves the chain intact and verify reports intact; completeness at - the boundary is the emitter''s property, not the archive''s. CONDITION: - approval-engine must guarantee emission atomicity (transactional outbox or - equivalent) so an approval cannot change state without the event being durably - queued in the same transaction — a requirement on approval-engine, not a task - audit-core can discharge for it. Boundary stated: no approval-validity query - will ever be exposed; a verdict surface would be deciding early under §6.1. - Also raised: audit-core declared no layer, contrary to §11 — now declared Engine - layer, explicitly not a decision point.' -recorded_in: history/2026-08-28-approval-evidence-assent.md +updated: '2026-08-28T20:35:09.148892Z' ```