Compare commits
No commits in common. "3177d2cee01c37186d6d893c343d9a17b3ef996c" and "d623f239d35ba04221686fc8631af83a41e01975" have entirely different histories.
3177d2cee0
...
d623f239d3
4 changed files with 5 additions and 206 deletions
50
INTENT.md
50
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
|
Kubernetes, identity providers, and application runtimes, but it must not depend
|
||||||
on NetKingdom to exist or operate.
|
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
|
## Problem
|
||||||
|
|
||||||
Modern platforms generate audit-relevant events in many places:
|
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
|
5. **Immutable archive and hot search are separate concerns.** Hot search can
|
||||||
be short-lived and cost-tuned. Immutable archive is the evidence record.
|
be short-lived and cost-tuned. Immutable archive is the evidence record.
|
||||||
|
|
||||||
6. **Tamper evidence is explicit, and bounded.** Audit Core should store
|
6. **Tamper evidence is explicit.** Audit Core should store signed or
|
||||||
signed or hash-chained manifests for retained batches so operators can later
|
hash-chained manifests for retained batches so operators can later prove
|
||||||
prove whether a record set was changed or truncated. The delivered bound is
|
whether a record set was changed, omitted, or truncated.
|
||||||
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.
|
|
||||||
|
|
||||||
7. **Least-privilege access.** Tenants may access their own audit records
|
7. **Least-privilege access.** Tenants may access their own audit records
|
||||||
according to policy. Platform operators may access cross-tenant records only
|
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
|
Audit Core may accept NetKingdom OIDC claims when configured, but should also
|
||||||
support a generic OIDC provider and local development auth mode.
|
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
|
## Tenant And Scope Model
|
||||||
|
|
||||||
Audit Core should distinguish:
|
Audit Core should distinguish:
|
||||||
|
|
|
||||||
|
|
@ -55,4 +55,3 @@
|
||||||
| task | AUDIT-WP-0008-T06 | done | — | workplans/AUDIT-WP-0008-tenancy-posture-alignment.md |
|
| 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-T07 | progress | — | workplans/AUDIT-WP-0008-tenancy-posture-alignment.md |
|
||||||
| task | AUDIT-WP-0008-T08 | done | — | 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 |
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
|
||||||
|
|
@ -7,7 +7,7 @@ id: AUDIT-IN-0001
|
||||||
kind: intake
|
kind: intake
|
||||||
title: 'Proposed: audit-core takes the approval evidence half (security layer model
|
title: 'Proposed: audit-core takes the approval evidence half (security layer model
|
||||||
v0.3 §9.4)'
|
v0.3 §9.4)'
|
||||||
status: closed
|
status: open
|
||||||
origin: cross-repo
|
origin: cross-repo
|
||||||
origin_ref: net-kingdom security-layer-model_v0.3 §9.4
|
origin_ref: net-kingdom security-layer-model_v0.3 §9.4
|
||||||
priority: medium
|
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
|
approval events as a distinct source, say so and gate-house will record the evidence
|
||||||
half as unowned rather than assume it.'
|
half as unowned rather than assume it.'
|
||||||
created: '2026-08-28T20:35:09.148892Z'
|
created: '2026-08-28T20:35:09.148892Z'
|
||||||
updated: '2026-08-28T21:10:00Z'
|
updated: '2026-08-28T20:35:09.148892Z'
|
||||||
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
|
|
||||||
```
|
```
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue