Declare the tenancy posture vector (AUDIT-WP-0008-T01).
Written against draft-7, which landed after the task was drafted and moved the
target. Decision 5.4 fixes the location at tenancy.yaml in the repo root rather
than docs/, and fixes the schema: current, target, reviewed, gap,
placement_exceptions, service_class, per-path detail, provider block.
Declares I1 A2 E1 P1 R1. E is quoted at 1 although T04 put the E2 mechanism on
both paths, because §13.2 states a passing CI run is not E2 evidence -- the
artifact is adversarial, compares separate tenant contexts and carries a review
date. Our cross-tenant tests are mechanical, so under §13.1 the level is not
claimable until T05. The mechanism is recorded in paths.E and the reason in
gap.E. Claiming E2 off unit tests would be the overclaim §6 prohibits, and
refusing that reasoning is what found the read-path defect.
R stays at 1: R2 needs backupRetentionDays in rapp-postgres's consumer file,
requested in T02 and not ours to declare.
Two additions draft-7 forced. A credentials gap under Decision 9.2 -- our own
finding, adopted as a rule, and it binds us: ingest credentials are static
long-lived bearer tokens, declared as a stated gap rather than a silent
exclusion. And a provides block under Decision 5.5, declaring what a sender can
reach through this service: E2 now, E3 pending ADR-0003, E4 and R4 unreachable.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 22:55:31 +02:00
|
|
|
# audit-core tenancy posture
|
|
|
|
|
#
|
2026-08-18 15:20:58 +02:00
|
|
|
# Declared per NetKingdom Tenancy Posture v0.1 (draft-8),
|
Declare the tenancy posture vector (AUDIT-WP-0008-T01).
Written against draft-7, which landed after the task was drafted and moved the
target. Decision 5.4 fixes the location at tenancy.yaml in the repo root rather
than docs/, and fixes the schema: current, target, reviewed, gap,
placement_exceptions, service_class, per-path detail, provider block.
Declares I1 A2 E1 P1 R1. E is quoted at 1 although T04 put the E2 mechanism on
both paths, because §13.2 states a passing CI run is not E2 evidence -- the
artifact is adversarial, compares separate tenant contexts and carries a review
date. Our cross-tenant tests are mechanical, so under §13.1 the level is not
claimable until T05. The mechanism is recorded in paths.E and the reason in
gap.E. Claiming E2 off unit tests would be the overclaim §6 prohibits, and
refusing that reasoning is what found the read-path defect.
R stays at 1: R2 needs backupRetentionDays in rapp-postgres's consumer file,
requested in T02 and not ours to declare.
Two additions draft-7 forced. A credentials gap under Decision 9.2 -- our own
finding, adopted as a rule, and it binds us: ingest credentials are static
long-lived bearer tokens, declared as a stated gap rather than a silent
exclusion. And a provides block under Decision 5.5, declaring what a sender can
reach through this service: E2 now, E3 pending ADR-0003, E4 and R4 unreachable.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 22:55:31 +02:00
|
|
|
# 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
|
2026-08-18 15:20:58 +02:00
|
|
|
# what this repo can evidence today. E is deliberately declared lower than the
|
|
|
|
|
# mechanism in place because the adversarial artifact is still absent.
|
|
|
|
|
|
|
|
|
|
schema_version: "0.1"
|
|
|
|
|
framework: netkingdom-tenancy-posture
|
|
|
|
|
service: audit-core
|
|
|
|
|
role: tenant-audit-service
|
Declare the tenancy posture vector (AUDIT-WP-0008-T01).
Written against draft-7, which landed after the task was drafted and moved the
target. Decision 5.4 fixes the location at tenancy.yaml in the repo root rather
than docs/, and fixes the schema: current, target, reviewed, gap,
placement_exceptions, service_class, per-path detail, provider block.
Declares I1 A2 E1 P1 R1. E is quoted at 1 although T04 put the E2 mechanism on
both paths, because §13.2 states a passing CI run is not E2 evidence -- the
artifact is adversarial, compares separate tenant contexts and carries a review
date. Our cross-tenant tests are mechanical, so under §13.1 the level is not
claimable until T05. The mechanism is recorded in paths.E and the reason in
gap.E. Claiming E2 off unit tests would be the overclaim §6 prohibits, and
refusing that reasoning is what found the read-path defect.
R stays at 1: R2 needs backupRetentionDays in rapp-postgres's consumer file,
requested in T02 and not ours to declare.
Two additions draft-7 forced. A credentials gap under Decision 9.2 -- our own
finding, adopted as a rule, and it binds us: ingest credentials are static
long-lived bearer tokens, declared as a stated gap rather than a silent
exclusion. And a provides block under Decision 5.5, declaring what a sender can
reach through this service: E2 now, E3 pending ADR-0003, E4 and R4 unreachable.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 22:55:31 +02:00
|
|
|
|
|
|
|
|
tenancy:
|
|
|
|
|
reviewed: "2026-08-17"
|
2026-08-18 15:20:58 +02:00
|
|
|
review_due: "2027-02-17"
|
Declare the tenancy posture vector (AUDIT-WP-0008-T01).
Written against draft-7, which landed after the task was drafted and moved the
target. Decision 5.4 fixes the location at tenancy.yaml in the repo root rather
than docs/, and fixes the schema: current, target, reviewed, gap,
placement_exceptions, service_class, per-path detail, provider block.
Declares I1 A2 E1 P1 R1. E is quoted at 1 although T04 put the E2 mechanism on
both paths, because §13.2 states a passing CI run is not E2 evidence -- the
artifact is adversarial, compares separate tenant contexts and carries a review
date. Our cross-tenant tests are mechanical, so under §13.1 the level is not
claimable until T05. The mechanism is recorded in paths.E and the reason in
gap.E. Claiming E2 off unit tests would be the overclaim §6 prohibits, and
refusing that reasoning is what found the read-path defect.
R stays at 1: R2 needs backupRetentionDays in rapp-postgres's consumer file,
requested in T02 and not ours to declare.
Two additions draft-7 forced. A credentials gap under Decision 9.2 -- our own
finding, adopted as a rule, and it binds us: ingest credentials are static
long-lived bearer tokens, declared as a stated gap rather than a silent
exclusion. And a provides block under Decision 5.5, declaring what a sender can
reach through this service: E2 now, E3 pending ADR-0003, E4 and R4 unreachable.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 22:55:31 +02:00
|
|
|
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.
|
|
|
|
|
|
2026-08-18 15:20:58 +02:00
|
|
|
current: { I: 1, A: 2, E: 1, P: 1, R: 2, V: 0 }
|
|
|
|
|
implemented: { E: 2 }
|
|
|
|
|
target: { I: 1, A: 2, E: 3, P: 1, R: 2, V: 1 }
|
Declare the tenancy posture vector (AUDIT-WP-0008-T01).
Written against draft-7, which landed after the task was drafted and moved the
target. Decision 5.4 fixes the location at tenancy.yaml in the repo root rather
than docs/, and fixes the schema: current, target, reviewed, gap,
placement_exceptions, service_class, per-path detail, provider block.
Declares I1 A2 E1 P1 R1. E is quoted at 1 although T04 put the E2 mechanism on
both paths, because §13.2 states a passing CI run is not E2 evidence -- the
artifact is adversarial, compares separate tenant contexts and carries a review
date. Our cross-tenant tests are mechanical, so under §13.1 the level is not
claimable until T05. The mechanism is recorded in paths.E and the reason in
gap.E. Claiming E2 off unit tests would be the overclaim §6 prohibits, and
refusing that reasoning is what found the read-path defect.
R stays at 1: R2 needs backupRetentionDays in rapp-postgres's consumer file,
requested in T02 and not ours to declare.
Two additions draft-7 forced. A credentials gap under Decision 9.2 -- our own
finding, adopted as a rule, and it binds us: ingest credentials are static
long-lived bearer tokens, declared as a stated gap rather than a silent
exclusion. And a provides block under Decision 5.5, declaring what a sender can
reach through this service: E2 now, E3 pending ADR-0003, E4 and R4 unreachable.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 22:55:31 +02:00
|
|
|
|
|
|
|
|
# §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 stays at 1 for the evidence reason in gap.E,
|
|
|
|
|
# not because a path is weaker.
|
|
|
|
|
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: >-
|
|
|
|
|
The E2 mechanism is in place on both paths as of AUDIT-WP-0008-T04, and
|
|
|
|
|
the quoted level is still 1. This is deliberate. §13.2 states that a
|
|
|
|
|
passing CI run is not E2 evidence: the E2 artifact is adversarial, needs
|
|
|
|
|
separate tenant contexts compared against each other, and carries a review
|
|
|
|
|
date rather than a green build. The repo's cross-tenant tests are
|
|
|
|
|
mechanical. Under §13.1 the level is not claimable until that artifact
|
|
|
|
|
exists, so E stays at 1 until AUDIT-WP-0008-T05 produces it with
|
|
|
|
|
whitehat-security. Declaring E2 on the strength of unit tests would be the
|
|
|
|
|
overclaim §6 prohibits, and the read-path defect this repo just fixed was
|
|
|
|
|
found precisely by refusing that kind of reasoning.
|
|
|
|
|
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.
|
2026-08-18 15:20:58 +02:00
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
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"
|
|
|
|
|
R:
|
|
|
|
|
available: 2
|
|
|
|
|
maximum: 2
|
|
|
|
|
conditions:
|
|
|
|
|
- "R4 is unreachable while the integrity chain commits to cleartext hashes."
|
|
|
|
|
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."
|
Declare the tenancy posture vector (AUDIT-WP-0008-T01).
Written against draft-7, which landed after the task was drafted and moved the
target. Decision 5.4 fixes the location at tenancy.yaml in the repo root rather
than docs/, and fixes the schema: current, target, reviewed, gap,
placement_exceptions, service_class, per-path detail, provider block.
Declares I1 A2 E1 P1 R1. E is quoted at 1 although T04 put the E2 mechanism on
both paths, because §13.2 states a passing CI run is not E2 evidence -- the
artifact is adversarial, compares separate tenant contexts and carries a review
date. Our cross-tenant tests are mechanical, so under §13.1 the level is not
claimable until T05. The mechanism is recorded in paths.E and the reason in
gap.E. Claiming E2 off unit tests would be the overclaim §6 prohibits, and
refusing that reasoning is what found the read-path defect.
R stays at 1: R2 needs backupRetentionDays in rapp-postgres's consumer file,
requested in T02 and not ours to declare.
Two additions draft-7 forced. A credentials gap under Decision 9.2 -- our own
finding, adopted as a rule, and it binds us: ingest credentials are static
long-lived bearer tokens, declared as a stated gap rather than a silent
exclusion. And a provides block under Decision 5.5, declaring what a sender can
reach through this service: E2 now, E3 pending ADR-0003, E4 and R4 unreachable.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 22:55:31 +02:00
|
|
|
|
2026-08-18 15:20:58 +02:00
|
|
|
evidence:
|
|
|
|
|
A2:
|
|
|
|
|
- "audit_core/ingestion.py"
|
|
|
|
|
- "tests/test_ingestion.py"
|
|
|
|
|
E1:
|
|
|
|
|
- "audit_core/postgres_backend.py"
|
|
|
|
|
- "tests/test_backend_conformance.py"
|
|
|
|
|
P1: "rapp-postgres/docs/evidence/isolation-2026-08-10.md"
|
|
|
|
|
R2:
|
|
|
|
|
- "rapp-postgres/consumers/audit-core.yaml"
|
|
|
|
|
- "tests/test_interface.py"
|