Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02991-be07-7bb3-8b6d-e9701b5621de
168 lines
8.3 KiB
YAML
168 lines
8.3 KiB
YAML
# audit-core tenancy posture
|
|
#
|
|
# Declared per NetKingdom Tenancy Posture v0.1 (draft-8),
|
|
# net-kingdom/canon/standards/tenancy-posture_v0.1.md.
|
|
# Location and schema per Decision 5.4; per-path detail per Decision 5.2;
|
|
# provider block per Decision 5.5.
|
|
#
|
|
# Conformance is accuracy, not altitude (§6). Nothing here is claimed above
|
|
# what this repo can evidence today. E2 is backed by a bounded adversarial
|
|
# target run; its scope and freshness limit are recorded below.
|
|
|
|
schema_version: "0.1"
|
|
framework: netkingdom-tenancy-posture
|
|
service: audit-core
|
|
role: tenant-audit-service
|
|
|
|
tenancy:
|
|
reviewed: "2026-08-22"
|
|
review_due: "2026-08-23"
|
|
service_class: batch # §8.3.2. Co-resident with latency-critical
|
|
# tenant-engine on platform-pg; the mixture is
|
|
# reported by the platform, not hidden.
|
|
|
|
current: { I: 1, A: 2, E: 2, P: 1, R: 2, V: 0 }
|
|
target: { I: 1, A: 2, E: 3, P: 1, R: 2, V: 1 }
|
|
|
|
# §5.2 — declare per path, quote the minimum. The quoted E above is the
|
|
# minimum across paths. As of AUDIT-WP-0008-T04 both paths carry the same
|
|
# mechanism. The quoted level is now 2 because the adversarial target artifact
|
|
# required by §13.2 exists for this revision.
|
|
paths:
|
|
E:
|
|
write: 2 # Sender credential bound to the sources and tenants it may
|
|
# claim; checked at one choke point (audit_core/ingestion.py).
|
|
read: 2 # Event reads filtered to permitted tenants; surfaces with no
|
|
# tenant key require full scope. Cross-tenant fetch returns
|
|
# 404, not 403, so the surface is not an existence oracle.
|
|
|
|
placement_exceptions: [] # No tenant is on dedicated substrate. All
|
|
# tenants share database audit_core on
|
|
# platform-pg.
|
|
|
|
gap:
|
|
I: >-
|
|
I1 is accurate and is not currently a target. Senders authenticate with
|
|
bearer tokens and the tenant arrives in the request body, checked against
|
|
an allowlist bound to the credential (§4.1 places request-supplied tenant
|
|
identifiers at I1 however canonical the string). The allowlist is a real
|
|
control, but it is an A-axis control; it does not make the identity
|
|
verified. Moving to I2 means senders carrying a verified token with a
|
|
tenant claim, which is a change to every sender and not audit-core's to
|
|
make alone. Recorded as accurate, not as ambition.
|
|
|
|
A: >-
|
|
A2 is accurate. Authorization is a single local boundary — permitted
|
|
sources, permitted tenants, may_write, may_read — bound once and centrally.
|
|
No flex-auth delegation. A3 is not a near-term target: flex-auth is itself
|
|
at A0 on its own self-report (/v1/check authenticates no caller), so
|
|
delegating to it today would lower this service's assurance, not raise it.
|
|
|
|
E: >-
|
|
E2 is implemented on both paths by AUDIT-WP-0008-T04 and evidenced by the
|
|
bounded whitehat-security target run WH-ENG-20260822-AUDIT-E2-03. An
|
|
ordinary tenant-A identity could not fetch tenant B's event by id, observe
|
|
tenant B's correlation fixture, or append as tenant B across ten attempted
|
|
operations. The run ended 2026-08-22T22:10:25Z with no limitations;
|
|
receipt-bound cleanup removed both temporary identities, both exact KV
|
|
paths, all projection resources and the runner. This says only that the
|
|
attempted attacks did not work, not that the boundary always holds. The
|
|
24-hour facility baseline makes review or replacement due at
|
|
2026-08-23T22:10:25Z, and relevant boundary changes require a
|
|
pre-promotion run.
|
|
E_target: >-
|
|
E3 (row-level security per rapp-postgres ADR-0003) targeted 2027-03-31.
|
|
Blocked behind the E2 artifact — §4.3 requires E2 evidence alongside any
|
|
E3 claim — and needs the EXPLAIN comparison first, since RLS disables
|
|
functional indexes built on non-leakproof functions. E4 is unreachable at
|
|
P1 by the §3.2 coupling and is not a target.
|
|
|
|
R_ceiling: >-
|
|
R4 is unreachable under the current design and is not a target. Per
|
|
Decision 4.5.3 — which this repo found — the hash chain commits to a
|
|
SHA-256 of the cleartext record, which survives key destruction as a
|
|
confirmation oracle over low-entropy fields. A fleet R4 target must exempt
|
|
this service explicitly. See docs/erasure-and-audit.md (AUDIT-WP-0008-T03).
|
|
|
|
credentials: >-
|
|
Stated gap against Decision 9.2 rather than a silent exclusion. Database
|
|
credentials comply with 9.1: dynamic leases re-read from a mounted Secret
|
|
at connection time, no restart on rotation. Ingest credentials do not:
|
|
they are static long-lived bearer tokens, rotated overlap-first by
|
|
publishing a replacement alongside the incumbent and then dropping the
|
|
predecessor. audit-core raised this omission during review and is not
|
|
exempting itself from the rule it asked for. No dated remedy yet; leasing
|
|
consumer-facing credentials needs a broker path that does not exist.
|
|
|
|
retention_placement: >-
|
|
audit-core's INTENT wants unbounded WORM archive. That is data.archive in
|
|
ITC-CAP terms, recorded as an unmet requirement in
|
|
data/capability/audit-core-operational.json, and it is deliberately not a
|
|
backup-window question: a 30-day WAL window is not an archive, is not
|
|
searchable, and restores instance-wide. Reviewed 2026-12-31. If no
|
|
data.archive provision is procured by then, audit-core reopens placement
|
|
under the §4.5 retention trigger, with P2 as the fallback — a worse answer
|
|
than archive, named now so it is not improvised later.
|
|
V: >-
|
|
No exercise establishes restart recovery for the complete audit path.
|
|
V1 is the target; replica count or Kubernetes restart policy is not
|
|
treated as evidence. Dependencies enumerated and the exercise specified in
|
|
docs/availability-recovery.md (AUDIT-WP-0008-T07); the exercise itself
|
|
awaits a live window on railiance01. V2 is not reachable at P1 as built:
|
|
platform-pg runs instances 1, and Decision 4.6.1 makes V the minimum across
|
|
synchronous providers, so V1 is the ceiling here rather than the next step.
|
|
|
|
provider:
|
|
capability: operations.audit
|
|
profile: administrative
|
|
axes:
|
|
E:
|
|
available: 2
|
|
maximum: 3
|
|
conditions:
|
|
- "E3 requires rapp-postgres ADR-0003 applied to audit_core and its EXPLAIN probe."
|
|
- "E4 is unreachable at P1 with one runtime credential."
|
|
evidence:
|
|
- "audit_core/ingestion.py"
|
|
- "tests/test_ingestion.py"
|
|
- "docs/evidence/AUDIT-WP-0008-T05-whitehat-e2-03-pass-2026-08-22.md"
|
|
R:
|
|
available: 2
|
|
maximum: 2
|
|
conditions:
|
|
- "R4 is unreachable while the integrity chain commits to cleartext hashes."
|
|
- >-
|
|
The 30-day horizon is declared but NOT solely ours to hold. audit-core
|
|
is at P1, and on shared substrate the erasure horizon is the instance
|
|
maximum across co-residents (§4.5), not the value this consumer
|
|
declares. A co-resident on platform-pg declaring a longer window
|
|
extends what a sender's audit records remain recoverable for, without
|
|
any change here and without notice to the sender. Decision 4.5.4 names
|
|
this as why a bare R2 is insufficient for a retention promise; we are
|
|
not a tier, but we are a provider quoting a number we do not control
|
|
alone, and a sender relying on 30 days should read it as a floor on
|
|
our side and a platform-derived maximum in practice.
|
|
- >-
|
|
A sender needing a horizon it can actually rely on needs audit-core at
|
|
P2. That is the §4.5 retention trigger and it is recorded in
|
|
gap.retention_placement with a 2026-12-31 review.
|
|
evidence:
|
|
- "rapp-postgres/consumers/audit-core.yaml"
|
|
- "audit_core/interface.py"
|
|
V:
|
|
available: 0
|
|
maximum: 1
|
|
conditions:
|
|
- "Exercise restart recovery across audit-core, platform-pg and OpenBao."
|
|
|
|
evidence:
|
|
A2:
|
|
- "audit_core/ingestion.py"
|
|
- "tests/test_ingestion.py"
|
|
E2:
|
|
- "docs/evidence/AUDIT-WP-0008-T05-whitehat-e2-03-pass-2026-08-22.md"
|
|
- "docs/evidence/AUDIT-WP-0008-T05-whitehat-e2-03-final-report.json"
|
|
P1: "rapp-postgres/docs/evidence/isolation-2026-08-10.md"
|
|
R2:
|
|
- "rapp-postgres/consumers/audit-core.yaml"
|
|
- "tests/test_interface.py"
|