79 lines
2.9 KiB
YAML
79 lines
2.9 KiB
YAML
|
|
# Canonical declaration: NetKingdom Tenancy Posture v0.1 draft-8.
|
||
|
|
schema_version: "0.1"
|
||
|
|
framework: netkingdom-tenancy-posture
|
||
|
|
service: tenant-engine
|
||
|
|
role: tenant-registry
|
||
|
|
|
||
|
|
tenancy:
|
||
|
|
current: { I: 1, A: 0, E: 1, P: "n/a", R: 0, V: 0 }
|
||
|
|
implemented: { A: 3, E: 2, P: 1 }
|
||
|
|
target: { I: 2, A: 3, E: 3, P: 1, R: 2, V: 1 }
|
||
|
|
reviewed: "2026-08-18"
|
||
|
|
review_due: "2027-02-17"
|
||
|
|
service_class: latency-critical
|
||
|
|
reason:
|
||
|
|
I: >-
|
||
|
|
Acting identity is supplied in request bodies; tenant-engine verifies no
|
||
|
|
inbound token. Canonical ownership of tenant records does not raise its
|
||
|
|
own inbound identity level.
|
||
|
|
A: >-
|
||
|
|
The running digest leaves GET tenant and role routes unprotected, so the
|
||
|
|
live minimum remains A0. Source now delegates every tenant/role read and
|
||
|
|
mutation to flex-auth before store access, implementing A3 without an
|
||
|
|
existence oracle; promotion and live endpoint evidence remain gated.
|
||
|
|
P: >-
|
||
|
|
Production still uses a dedicated SQLite PVC. It is a datastore, but it
|
||
|
|
is neither a shared database nor a PostgreSQL cluster described by P0-P4;
|
||
|
|
P1 is the accepted TEN-WP-0009 target.
|
||
|
|
R: >-
|
||
|
|
Tenant retirement is reversible and no hard-delete path exists; personal
|
||
|
|
fields therefore have no erasure position.
|
||
|
|
V: >-
|
||
|
|
The deployment has no exercised recovery objective or failover evidence.
|
||
|
|
gap:
|
||
|
|
I: "Bind actor and tenant to a verified inbound token."
|
||
|
|
A: "Authenticate and authorize every read path; then evidence endpoint denial."
|
||
|
|
E: >-
|
||
|
|
Child records are tenant-keyed, but E2 requires binding an authenticated
|
||
|
|
identity and adversarial evidence. Registry tables remain a named E3
|
||
|
|
exception because cross-tenant enumeration is their function.
|
||
|
|
P: "Complete TEN-WP-0009 and publish the P1 isolation evidence."
|
||
|
|
R: >-
|
||
|
|
docs/data-retention-policy.md now declares indefinite primary-record
|
||
|
|
retention and a 30-day copy horizon honestly. R2 still requires an
|
||
|
|
implemented and evidenced personal-field erasure/expiry workflow.
|
||
|
|
V: "Exercise restart recovery for tenant-engine and its critical path."
|
||
|
|
paths:
|
||
|
|
A:
|
||
|
|
mutations: 3
|
||
|
|
tenant_reads: 0
|
||
|
|
live_role_reads: 0
|
||
|
|
E:
|
||
|
|
tenant_keyed_children: 2
|
||
|
|
tenant_registry: 1
|
||
|
|
placement_exceptions: []
|
||
|
|
|
||
|
|
provider:
|
||
|
|
capability: tenant.registry
|
||
|
|
axes:
|
||
|
|
I:
|
||
|
|
available: 2
|
||
|
|
maximum: 3
|
||
|
|
conditions:
|
||
|
|
- "Consumers verify canonical tenant identifiers on their own inbound calls."
|
||
|
|
- "I3 consumers wire the live role lookup on high-stakes paths."
|
||
|
|
evidence:
|
||
|
|
- "net-kingdom/canon/standards/tenant-engine-boundary-contract_v0.1.md"
|
||
|
|
|
||
|
|
evidence:
|
||
|
|
E1:
|
||
|
|
- "src/tenant_engine/domain.py"
|
||
|
|
- "tests/test_store.py"
|
||
|
|
implemented_A3:
|
||
|
|
- "src/tenant_engine/app.py"
|
||
|
|
- "tests/test_api_reads.py"
|
||
|
|
implemented_P1:
|
||
|
|
- "src/tenant_engine/postgres_store.py"
|
||
|
|
- "tests/postgres_backend.py"
|
||
|
|
- "src/tenant_engine/transfer.py"
|