docs(canon): reconcile workload and tenant grouping semantics
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02929-244b-7391-b933-c04010e8eedb
This commit is contained in:
parent
ad2057acff
commit
bee22db620
21 changed files with 1118 additions and 59 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -83,6 +83,7 @@ instance/
|
|||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
docs/architecture/.ast_cache/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
| workplan | NK-WP-0024 | finished | — | workplans/NK-WP-0024-user-engine-portal-integration-expansion.md |
|
||||
| workplan | NK-WP-0025 | finished | — | workplans/NK-WP-0025-public-self-registration-and-application-jit.md |
|
||||
| workplan | NK-WP-0026 | finished | — | workplans/NK-WP-0026-flex-auth-caller-identity-rollout.md |
|
||||
| workplan | NK-WP-0027 | blocked | — | workplans/NK-WP-0027-reef-placement-reconciliation.md |
|
||||
| workplan | NK-WP-0028 | finished | — | workplans/NK-WP-0028-canon-publication-and-grouping-semantics.md |
|
||||
| task | ADHOC-2026-07-02-T01 | done | — | workplans/ADHOC-2026-07-02.md |
|
||||
| task | ADHOC-2026-07-02-T02 | done | — | workplans/ADHOC-2026-07-02.md |
|
||||
| task | ADHOC-2026-08-14-T01 | done | — | workplans/ADHOC-2026-08-14.md |
|
||||
|
|
@ -29,20 +31,20 @@
|
|||
| task | NET-WP-0020-T03 | done | — | workplans/NET-WP-0020-openbao-unseal-custody-and-ssh-automation.md |
|
||||
| task | NET-WP-0020-T04 | done | — | workplans/NET-WP-0020-openbao-unseal-custody-and-ssh-automation.md |
|
||||
| task | NET-WP-0020-T05 | done | — | workplans/NET-WP-0020-openbao-unseal-custody-and-ssh-automation.md |
|
||||
| task | NK-WP-0009-T1 | todo | — | workplans/NK-WP-0009-netkingdom-security-pattern-tutorials.md |
|
||||
| task | NK-WP-0009-T2 | todo | — | workplans/NK-WP-0009-netkingdom-security-pattern-tutorials.md |
|
||||
| task | NK-WP-0009-T3 | todo | — | workplans/NK-WP-0009-netkingdom-security-pattern-tutorials.md |
|
||||
| task | NK-WP-0009-T4 | todo | — | workplans/NK-WP-0009-netkingdom-security-pattern-tutorials.md |
|
||||
| task | NK-WP-0009-T5 | todo | — | workplans/NK-WP-0009-netkingdom-security-pattern-tutorials.md |
|
||||
| task | NK-WP-0009-T6 | todo | — | workplans/NK-WP-0009-netkingdom-security-pattern-tutorials.md |
|
||||
| task | NK-WP-0011-T1 | todo | — | workplans/NK-WP-0011-enterprise-federation-saml.md |
|
||||
| task | NK-WP-0011-T2 | todo | — | workplans/NK-WP-0011-enterprise-federation-saml.md |
|
||||
| task | NK-WP-0011-T3 | todo | — | workplans/NK-WP-0011-enterprise-federation-saml.md |
|
||||
| task | NK-WP-0011-T4 | todo | — | workplans/NK-WP-0011-enterprise-federation-saml.md |
|
||||
| task | NK-WP-0011-T5 | todo | — | workplans/NK-WP-0011-enterprise-federation-saml.md |
|
||||
| task | NK-WP-0011-T6 | todo | — | workplans/NK-WP-0011-enterprise-federation-saml.md |
|
||||
| task | NK-WP-0011-T7 | todo | — | workplans/NK-WP-0011-enterprise-federation-saml.md |
|
||||
| task | NK-WP-0011-T8 | todo | — | workplans/NK-WP-0011-enterprise-federation-saml.md |
|
||||
| task | NK-WP-0009-T01 | todo | — | workplans/NK-WP-0009-netkingdom-security-pattern-tutorials.md |
|
||||
| task | NK-WP-0009-T02 | todo | — | workplans/NK-WP-0009-netkingdom-security-pattern-tutorials.md |
|
||||
| task | NK-WP-0009-T03 | todo | — | workplans/NK-WP-0009-netkingdom-security-pattern-tutorials.md |
|
||||
| task | NK-WP-0009-T04 | todo | — | workplans/NK-WP-0009-netkingdom-security-pattern-tutorials.md |
|
||||
| task | NK-WP-0009-T05 | todo | — | workplans/NK-WP-0009-netkingdom-security-pattern-tutorials.md |
|
||||
| task | NK-WP-0009-T06 | todo | — | workplans/NK-WP-0009-netkingdom-security-pattern-tutorials.md |
|
||||
| task | NK-WP-0011-T01 | todo | — | workplans/NK-WP-0011-enterprise-federation-saml.md |
|
||||
| task | NK-WP-0011-T02 | todo | — | workplans/NK-WP-0011-enterprise-federation-saml.md |
|
||||
| task | NK-WP-0011-T03 | todo | — | workplans/NK-WP-0011-enterprise-federation-saml.md |
|
||||
| task | NK-WP-0011-T04 | todo | — | workplans/NK-WP-0011-enterprise-federation-saml.md |
|
||||
| task | NK-WP-0011-T05 | todo | — | workplans/NK-WP-0011-enterprise-federation-saml.md |
|
||||
| task | NK-WP-0011-T06 | todo | — | workplans/NK-WP-0011-enterprise-federation-saml.md |
|
||||
| task | NK-WP-0011-T07 | todo | — | workplans/NK-WP-0011-enterprise-federation-saml.md |
|
||||
| task | NK-WP-0011-T08 | todo | — | workplans/NK-WP-0011-enterprise-federation-saml.md |
|
||||
| task | NK-WP-0021-T01 | done | — | workplans/NK-WP-0021-activity-core-ops-sso-operators.md |
|
||||
| task | NK-WP-0021-T02 | done | — | workplans/NK-WP-0021-activity-core-ops-sso-operators.md |
|
||||
| task | NK-WP-0021-T03 | done | — | workplans/NK-WP-0021-activity-core-ops-sso-operators.md |
|
||||
|
|
@ -75,5 +77,15 @@
|
|||
| task | NK-WP-0025-T05 | done | — | workplans/NK-WP-0025-public-self-registration-and-application-jit.md |
|
||||
| task | NK-WP-0026-T01 | done | — | workplans/NK-WP-0026-flex-auth-caller-identity-rollout.md |
|
||||
| task | NK-WP-0026-T02 | done | — | workplans/NK-WP-0026-flex-auth-caller-identity-rollout.md |
|
||||
| task | NK-WP-0027-T01 | done | — | workplans/NK-WP-0027-reef-placement-reconciliation.md |
|
||||
| task | NK-WP-0027-T02 | wait | — | workplans/NK-WP-0027-reef-placement-reconciliation.md |
|
||||
| task | NK-WP-0027-T03 | wait | — | workplans/NK-WP-0027-reef-placement-reconciliation.md |
|
||||
| task | NK-WP-0027-T04 | done | — | workplans/NK-WP-0027-reef-placement-reconciliation.md |
|
||||
| task | NK-WP-0027-T05 | done | — | workplans/NK-WP-0027-reef-placement-reconciliation.md |
|
||||
| task | NK-WP-0027-T06 | wait | — | workplans/NK-WP-0027-reef-placement-reconciliation.md |
|
||||
| task | NK-WP-0028-T01 | done | — | workplans/NK-WP-0028-canon-publication-and-grouping-semantics.md |
|
||||
| task | NK-WP-0028-T02 | done | — | workplans/NK-WP-0028-canon-publication-and-grouping-semantics.md |
|
||||
| task | NK-WP-0028-T03 | done | — | workplans/NK-WP-0028-canon-publication-and-grouping-semantics.md |
|
||||
| task | NK-WP-0028-T04 | done | — | workplans/NK-WP-0028-canon-publication-and-grouping-semantics.md |
|
||||
| intake | NK-IN-0001 | closed | blue | docs/intakes/activity-core-ops-sso-operators.md |
|
||||
| intake | NK-IN-0002 | closed | blue | docs/intakes/activity-core-ops-sso-operators.md |
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@
|
|||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"workload_identity": {
|
||||
"$ref": "#/$defs/workloadIdentity"
|
||||
},
|
||||
"tenancy": {
|
||||
"$ref": "#/$defs/tenancy"
|
||||
},
|
||||
|
|
@ -28,7 +31,7 @@
|
|||
"$ref": "#/$defs/provider"
|
||||
},
|
||||
"zones": {
|
||||
"description": "Reserved for security-zone membership (tenancy-posture_v0.1 Decision 5.6). Its internal shape is defined by the NetKingdom security-zone standard drafted by zone-engine, not by this schema, and is deliberately unconstrained here until that standard lands. Present so a conformant combined declaration is not rejected by this validator."
|
||||
"$ref": "#/$defs/zoneDeclaration"
|
||||
},
|
||||
"evidence": {
|
||||
"$ref": "#/$defs/evidence"
|
||||
|
|
@ -83,6 +86,16 @@
|
|||
"provider"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"workload_identity"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"zones"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"evidence"
|
||||
|
|
@ -92,12 +105,30 @@
|
|||
}
|
||||
}
|
||||
],
|
||||
"allOf": [
|
||||
{
|
||||
"if": {
|
||||
"required": [
|
||||
"zones"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"required": [
|
||||
"workload_identity"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"additionalProperties": false,
|
||||
"$defs": {
|
||||
"serviceName": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-z0-9][a-z0-9._-]*$"
|
||||
},
|
||||
"repoName": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
|
||||
},
|
||||
"axisName": {
|
||||
"enum": [
|
||||
"I",
|
||||
|
|
@ -209,6 +240,183 @@
|
|||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"identityBinding": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"scheme",
|
||||
"authority",
|
||||
"subject",
|
||||
"principal_type"
|
||||
],
|
||||
"properties": {
|
||||
"scheme": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
|
||||
"description": "Identity mechanism, for example iam-profile, kubernetes-service-account, ssh-certificate, or openbao-auth-role."
|
||||
},
|
||||
"authority": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Authoritative issuer or registry for this principal."
|
||||
},
|
||||
"subject": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Exact principal value asserted by the authority."
|
||||
},
|
||||
"principal_type": {
|
||||
"enum": [
|
||||
"service",
|
||||
"agent"
|
||||
],
|
||||
"description": "IAM Profile principal type. A human identity is caller context and cannot be the sole workload identity."
|
||||
},
|
||||
"environment": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"evidence": {
|
||||
"$ref": "#/$defs/stringList"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"workloadIdentity": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"kind",
|
||||
"responsible_repo",
|
||||
"identity_bindings"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"$ref": "#/$defs/serviceName",
|
||||
"description": "Stable workload id. It must equal the containing service field."
|
||||
},
|
||||
"kind": {
|
||||
"enum": [
|
||||
"application",
|
||||
"platform-service",
|
||||
"automation",
|
||||
"operational-control-plane",
|
||||
"maintenance-job"
|
||||
]
|
||||
},
|
||||
"responsible_repo": {
|
||||
"$ref": "#/$defs/repoName",
|
||||
"description": "Repository accountable for the workload identity and zone declaration."
|
||||
},
|
||||
"declaration_ref": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Authoritative owner declaration. Required by RMGR-ADR-004 for a managed deployable, for example rapp-user-engine/declarations/rapp.yaml."
|
||||
},
|
||||
"identity_bindings": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"$ref": "#/$defs/identityBinding"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"zoneEvidence": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"ref",
|
||||
"supports"
|
||||
],
|
||||
"properties": {
|
||||
"ref": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"supports": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"uniqueItems": true,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"zoneDeclaration": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"standard",
|
||||
"membership",
|
||||
"responsible_party",
|
||||
"justification",
|
||||
"context",
|
||||
"evidence",
|
||||
"reviewed",
|
||||
"review_due"
|
||||
],
|
||||
"properties": {
|
||||
"standard": {
|
||||
"const": "security-zones_v0.1"
|
||||
},
|
||||
"membership": {
|
||||
"enum": [
|
||||
"z0-experimental",
|
||||
"z1-operational",
|
||||
"z2-protected",
|
||||
"z3-critical",
|
||||
"z2-continuity"
|
||||
]
|
||||
},
|
||||
"responsible_party": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"justification": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"context": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"maturity",
|
||||
"criticality",
|
||||
"data_classification"
|
||||
],
|
||||
"properties": {
|
||||
"maturity": {
|
||||
"enum": ["M0", "M1", "M2", "M3"]
|
||||
},
|
||||
"criticality": {
|
||||
"enum": ["low", "medium", "high", "critical", "n/a"]
|
||||
},
|
||||
"data_classification": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"evidence": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"$ref": "#/$defs/zoneEvidence"
|
||||
}
|
||||
},
|
||||
"reviewed": {
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
},
|
||||
"review_due": {
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"paths": {
|
||||
"type": "object",
|
||||
"propertyNames": {
|
||||
|
|
@ -408,6 +616,9 @@
|
|||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"workload_identity": {
|
||||
"$ref": "#/$defs/workloadIdentity"
|
||||
},
|
||||
"tenancy": {
|
||||
"$ref": "#/$defs/tenancy"
|
||||
},
|
||||
|
|
@ -419,8 +630,25 @@
|
|||
},
|
||||
"notes": {
|
||||
"$ref": "#/$defs/stringList"
|
||||
},
|
||||
"zones": {
|
||||
"$ref": "#/$defs/zoneDeclaration"
|
||||
}
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"if": {
|
||||
"required": [
|
||||
"zones"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"required": [
|
||||
"workload_identity"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ title: "NetKingdom IAM Profile v0.3"
|
|||
domain: netkingdom
|
||||
status: accepted
|
||||
owner: net-kingdom
|
||||
last_reviewed: "2026-07-23"
|
||||
last_reviewed: "2026-08-22"
|
||||
review_interval: 6m
|
||||
version: "0.3"
|
||||
created: "2026-07-23"
|
||||
updated: "2026-07-23"
|
||||
updated: "2026-08-22"
|
||||
scope: core-platform
|
||||
supersedes:
|
||||
- canon/standards/iam-profile_v0.2.md
|
||||
|
|
@ -236,7 +236,7 @@ flex-auth resource/action semantics.
|
|||
`tenant` is required for every token accepted by profile consumers.
|
||||
|
||||
Tenant identifiers follow `tenant:<grouping>:<name>`, where `<grouping>` is
|
||||
one of the taxonomy ratified by ADR-0013:
|
||||
one of the taxonomy ratified by ADR-0013 at identifier creation:
|
||||
|
||||
```text
|
||||
trial - test/trial/showcase tenants only
|
||||
|
|
@ -265,9 +265,14 @@ request MUST identify the tenant context for that request. If a client
|
|||
needs to switch tenant context, it obtains a new token or uses an
|
||||
approved token-exchange flow that records the target tenant.
|
||||
|
||||
The grouping segment is **onboarding-risk / entity-shape** classification
|
||||
only. It does not gate which capability roles (below) a tenant may hold —
|
||||
see Tenant Roles.
|
||||
The grouping segment is an immutable record of the tenant's
|
||||
**onboarding-time** onboarding-risk / entity-shape classification. It remains
|
||||
vocabulary-valid but becomes historical if the tenant's classification later
|
||||
changes. The authoritative current grouping is the `grouping` field held by
|
||||
`tenant-engine`; consumers MUST NOT split `tenant` and treat its middle segment
|
||||
as current policy input. Changing current grouping never renames the tenant.
|
||||
Neither the historical segment nor current grouping gates which capability
|
||||
roles (below) a tenant may hold — see Tenant Roles.
|
||||
|
||||
## Tenant Roles
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,21 @@
|
|||
---
|
||||
id: security-zones_v0.1
|
||||
id: netkingdom-security-zones-v0.1
|
||||
type: standard
|
||||
title: "NetKingdom Security Zones v0.1"
|
||||
domain: netkingdom
|
||||
status: proposed
|
||||
version: "0.1"
|
||||
owner: zone-engine
|
||||
publication_owner: net-kingdom
|
||||
date: "2026-08-22"
|
||||
created: "2026-08-22"
|
||||
updated: "2026-08-22"
|
||||
last_reviewed: "2026-08-22"
|
||||
review_interval: 3m
|
||||
source_revision: "zone-engine@a510393"
|
||||
standard_token: security-zones_v0.1
|
||||
related:
|
||||
- canon/standards/tenancy-posture_v0.1.md
|
||||
- repo-manager/docs/adr-004-authoritative-workload-declarations.md
|
||||
---
|
||||
|
||||
# NetKingdom Security Zones v0.1
|
||||
|
|
@ -313,8 +324,8 @@ conformant.
|
|||
|
||||
## 9. Time-boxed exceptions
|
||||
|
||||
The normative lifecycle is the T04 decision in
|
||||
`docs/exception-lifecycle-2026-08-22.md`: only the control owner's designated
|
||||
The normative lifecycle is the ZONE-WP-0001-T04 decision in
|
||||
`zone-engine/docs/exception-lifecycle-2026-08-22.md`: only the control owner's designated
|
||||
authority grants a named-workload, named-zone, named-control relaxation within a
|
||||
declared maximum duration. Enforcement applies it only for
|
||||
`not_before <= now < not_after`; invalid or unevaluable records are inactive,
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ domain: netkingdom
|
|||
status: proposed
|
||||
version: "0.1"
|
||||
created: "2026-08-17"
|
||||
updated: "2026-08-19"
|
||||
updated: "2026-08-22"
|
||||
scope: multi-tenancy-security-framework
|
||||
revision: "draft-9"
|
||||
revision: "draft-12"
|
||||
owner: net-kingdom
|
||||
last_reviewed: "2026-08-19"
|
||||
last_reviewed: "2026-08-22"
|
||||
review_interval: 6m
|
||||
declaration_schema: canon/schemas/tenancy-posture_v0.1.schema.json
|
||||
adr:
|
||||
|
|
@ -28,7 +28,7 @@ related:
|
|||
|
||||
## Status
|
||||
|
||||
**Proposed, draft-9; ratification-ready.** Relocated from
|
||||
**Proposed, draft-12; ratification-ready.** Relocated from
|
||||
`the-custodian/canon/architecture` on
|
||||
2026-08-17: multi-tenancy is part of the IT-security framework NetKingdom
|
||||
provides, so this framework belongs in NetKingdom canon beside the IAM Profile
|
||||
|
|
@ -64,6 +64,24 @@ and the tenant-engine boundary contract, not in the work-factory canon.
|
|||
`zones:` in `tenancy.yaml` so the estate keeps one declaration surface, and it
|
||||
records the reef/`P`/`V` reconciliation as an open defect of this document
|
||||
rather than of the repo that noticed it (Decision 8.4).
|
||||
- **draft-10** answers `zone-engine`'s `ZONE-WP-0001-T03`. It keeps the
|
||||
workload as the sole security-zone policy subject, makes operational and
|
||||
control-plane execution units part of that term, and requires unresolved
|
||||
workload identity or membership to remain `unknown` without zone inference
|
||||
(Decision 5.6.1). It also closes the textual reef/`P` boundary while leaving
|
||||
the substrate-provider declaration and mechanical `V` join as implementation
|
||||
work (Decision 8.4.2).
|
||||
- **draft-11** makes that ruling declarable. A `zones:` block now requires an
|
||||
authoritative `workload_identity` beside it, including for non-`rapp`
|
||||
operational workloads; multi-service files carry both per service. Missing
|
||||
identity remains absence rather than a guessed join (Decision 5.6.2).
|
||||
- **draft-12** reconciles that declaration with RMGR-ADR-004 and the published
|
||||
`security-zones_v0.1` proposal. Managed deployables use their authoritative
|
||||
rapp declaration and the exact Repo Manager reference tuple; independently
|
||||
governed operational execution units that are not managed deployables may
|
||||
declare locally. Native actions, actors, lanes, patterns, and resources are
|
||||
explicitly `not-applicable`, while omitted or unresolved workload references
|
||||
remain `unknown` (Decision 5.6.2).
|
||||
|
||||
**Reviewed by all six. The score:** six repos found three live defects in their
|
||||
own code by reading the ladders — `tenant-engine`'s unfiltered
|
||||
|
|
@ -650,6 +668,106 @@ joined by machine.
|
|||
repos. It is an *input* to stance selection and should be read by the zone
|
||||
model, not absorbed into a declaration.
|
||||
|
||||
**Decision 5.6.1 — the workload remains the sole zone policy subject, and
|
||||
absence resolves to `unknown`.** Here **workload** means an independently
|
||||
governed execution unit that performs application, automation, or operational
|
||||
control-plane work and can be attributed at enforcement time to both a
|
||||
responsible party and an authoritative workload identity. The independently
|
||||
governed executing unit behind operator-driven or automated SSH access, tunnel
|
||||
operation, credential brokering, policy compilation or enforcement, or
|
||||
maintenance is a workload when such a unit exists. The observed access, tunnel,
|
||||
grant, lane, pattern, or action is not itself a workload. A human or agent
|
||||
identity remains caller context; it does not replace the workload whose
|
||||
execution is being governed.
|
||||
|
||||
A repository, credential lane, grant template, pattern, or software package is
|
||||
not an alternative **zone** policy subject. A broker runtime is a workload; the
|
||||
grants and lanes it handles retain native resource identity and may explicitly
|
||||
be `not-applicable` to workload resolution. Every managed running deployable,
|
||||
including operational and tooling runtimes, has one authoritative
|
||||
`rapp-*/declarations/rapp.yaml` under RMGR-ADR-004. A pre-rapp managed runtime
|
||||
is migration debt and resolves `unknown`. An independently governed operational
|
||||
execution unit that is not a managed deployable may declare directly in its
|
||||
responsible repo's `tenancy.yaml`. The declaration surface broadens to cover
|
||||
real workloads; the subject model does not broaden merely to totalize an
|
||||
incomplete registry.
|
||||
|
||||
When a workload-applicable subject lacks an authoritative workload identity,
|
||||
when its reference is absent or ambiguous, or when that identity has no
|
||||
authoritative zone membership, the resolved membership MUST be `unknown`.
|
||||
It MUST NOT be inferred from a repository owner, credential path, lane type,
|
||||
actor class, environment, criticality, reef, organization posture, or a default
|
||||
zone. A control owner MAY define an explicit, reviewable fail-safe treatment for
|
||||
`unknown` — including denial, escalation, or a build-stage rule — but that
|
||||
treatment is stance, not membership. `unknown` never silently inherits a
|
||||
permissive zone or exception.
|
||||
|
||||
**Decision 5.6.2 — zone membership requires an authoritative workload binding
|
||||
in the same declaration entry.** A bare service name is a label, not identity
|
||||
evidence. Any single-service declaration carrying `zones:` MUST also carry
|
||||
`workload_identity`; in a layer repo using `services:`, both fields live on the
|
||||
same service entry. Top-level `zones:` is not valid for a multi-service file,
|
||||
because it would make membership ambiguous.
|
||||
|
||||
The binding states:
|
||||
|
||||
- `name` — the stable workload id, exactly equal to the declaration's
|
||||
`service`;
|
||||
- `kind` — application, platform service, automation, operational control
|
||||
plane, or maintenance job;
|
||||
- `responsible_repo` — the repository accountable for the identity and zone
|
||||
declaration;
|
||||
- one or more `identity_bindings`, each naming the identity scheme,
|
||||
authoritative issuer or registry, exact subject, IAM Profile principal type,
|
||||
and optional environment and evidence; and
|
||||
- for a managed deployable, a `declaration_ref` to its authoritative rapp
|
||||
declaration. Consuming catalogs reference it with the exact Repo Manager v1
|
||||
tuple `(rapp_id, workload_identity.name)` and optional `deployable`.
|
||||
|
||||
An identity binding uses `principal_type: service` or `agent`. A human identity
|
||||
may still be required as actor or delegation context, but cannot be the sole
|
||||
workload identity. A managed application, operational runtime, or tooling
|
||||
runtime references its rapp declaration. Only an independently governed
|
||||
operational execution unit that is not a managed deployable declares directly
|
||||
in its responsible repo's `tenancy.yaml`; native actions and resources do not
|
||||
acquire a fictional workload or rapp merely to enter policy.
|
||||
|
||||
The stable workload id is the join key. Credential lanes, grants, controls, and
|
||||
compiled policy resources reference that id explicitly; compilers MUST NOT
|
||||
recover it by parsing a credential path or repository name. Multiple runtime
|
||||
principals may bind to one workload when environments or mechanisms differ, but
|
||||
the bindings must be unique and remain owner-reviewed. If no authoritative
|
||||
binding matches the runtime principal, Decision 5.6.1 returns `unknown`.
|
||||
|
||||
```yaml
|
||||
service: ops-bridge-tunnel
|
||||
role: operational-access-path
|
||||
workload_identity:
|
||||
name: ops-bridge-tunnel
|
||||
kind: operational-control-plane
|
||||
responsible_repo: ops-bridge
|
||||
identity_bindings:
|
||||
- scheme: ssh-certificate
|
||||
authority: ops-warden
|
||||
subject: agt-ops-bridge
|
||||
principal_type: agent
|
||||
environment: prod
|
||||
zones:
|
||||
standard: security-zones_v0.1
|
||||
membership: z2-continuity
|
||||
responsible_party: ops-bridge
|
||||
justification: foundational tunnel path must retain availability under PDP loss
|
||||
context:
|
||||
maturity: M2
|
||||
criticality: high
|
||||
data_classification: confidential
|
||||
evidence:
|
||||
- ref: docs/evidence/ops-bridge-tunnel-zone.md
|
||||
supports: [M2, continuity-dependency, recovery]
|
||||
reviewed: "2026-08-22"
|
||||
review_due: "2026-11-22"
|
||||
```
|
||||
|
||||
Worked examples after applying the evidence rule and minimum-across-paths rule
|
||||
consistently:
|
||||
|
||||
|
|
@ -702,7 +820,8 @@ normative schema is
|
|||
declaration but do not replace it. The schema carries `current`, `implemented`,
|
||||
`target`, `reviewed`, `review_due`, `gap`, `placement_exceptions`,
|
||||
`service_class` (§8.3), per-path detail (§5.2), and provider reachability
|
||||
(§5.5). From the `net-kingdom` repo, owners validate one or more declarations
|
||||
(§5.5), plus the workload identity prerequisite for zone membership (§5.6.2).
|
||||
From the `net-kingdom` repo, owners validate one or more declarations
|
||||
with `uv run tools/tenancy-posture/validate.py <path>...`; the validator applies
|
||||
the JSON Schema and the evidence, date, implemented/current and provider-range
|
||||
rules that JSON Schema alone cannot express.
|
||||
|
|
@ -845,6 +964,14 @@ not. `P` grades **tenant data isolation within a datastore**; a reef is a named
|
|||
rung meaning "single node, shared control plane, risk accepted", and inventing
|
||||
one would be the fabrication §6 prohibits.
|
||||
|
||||
A reef binding therefore satisfies none of the `P` couplings in Decision 3.2
|
||||
by itself. It records the compute substrate and its accepted residual risk; it
|
||||
does not establish a database-per-consumer or database-per-tenant boundary, a
|
||||
per-tenant credential or encryption boundary, or an erasure horizon. Those
|
||||
remain properties of the workload and data provider declarations. The binding
|
||||
does participate in `V`, because availability composes across the complete
|
||||
critical path and the substrate can impose a ceiling.
|
||||
|
||||
The live consequence is on `V`, not `P`. §4.6 already warns that "a dedicated
|
||||
cluster can still be a single instance on a single node", and Decision 4.6.1
|
||||
makes `V` the minimum across the synchronous path. `reef-railiance` is
|
||||
|
|
@ -1265,12 +1392,10 @@ nothing about this availability fact; the new V axis carries it.
|
|||
See §8.3. The question asked whether to add a QoS dimension; the answer is
|
||||
no, and the reason is that we could not enforce one.
|
||||
|
||||
**Routed elsewhere, deliberately.** The tenant identifier
|
||||
`tenant:<grouping>:<name>` embeds headcount bands (`small`, `medium`, `large`)
|
||||
that change as a tenant grows, contradicting the consensus that identifiers
|
||||
should not encode mutable attributes. That is a critique of ADR-0013, not of
|
||||
this framework, and belongs to `tenant-engine` and NetKingdom canon. Folding it
|
||||
in here would overreach.
|
||||
**Tenant grouping ambiguity — resolved outside this framework.** ADR-0013
|
||||
revision 2 makes the identifier segment immutable onboarding-time history and
|
||||
the `tenant-engine` record authoritative for current grouping. Consumers do not
|
||||
parse current policy or spend-ceiling inputs from `tenant:<grouping>:<name>`.
|
||||
|
||||
## 20. Ratification path
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ domain: netkingdom
|
|||
status: accepted
|
||||
version: "0.1"
|
||||
created: "2026-07-23"
|
||||
updated: "2026-07-23"
|
||||
updated: "2026-08-22"
|
||||
scope: tenant-domain-boundaries
|
||||
adr:
|
||||
- docs/adr/ADR-0006-recursive-multi-tenant-identity-authorization.md
|
||||
|
|
@ -55,16 +55,22 @@ deployments.
|
|||
|
||||
| Resource kind | Source of truth | tenant-engine relation | Boundary rule |
|
||||
| --- | --- | --- | --- |
|
||||
| Tenant record (existence, grouping, name/slug) | `tenant-engine` | Canonical owner | Grouping value must be one of ADR-0013's taxonomy, or the reserved ungrouped `platform`/`coulomb` identifiers |
|
||||
| Tenant record (existence, current grouping, name/slug) | `tenant-engine` | Canonical owner | Current grouping must be one of ADR-0013's taxonomy, or the reserved ungrouped `platform`/`coulomb` classifications; the identifier segment is historical and must not be used as current grouping |
|
||||
| Tenant capability roles | `tenant-engine` | Canonical owner | Non-exclusive; grant/revoke are audited mutations (see Grant Contract below), never free-form field updates |
|
||||
| Plan/subscription assignment | `tenant-engine` | Canonical owner | References an `adaptive-pricing` plan id; does not define plan terms |
|
||||
| Pricing-model / plan definitions | `adaptive-pricing` | Consume by reference only | `tenant-engine` must not cache plan terms beyond what's needed to resolve which roles a plan currently grants |
|
||||
| Guardrail/quota policy (spend limits, entity/action counts) | `tenant-engine` (reserved) | Canonical owner once designed | Not implemented by this contract version — reserved namespace only, see Guardrail Policy section |
|
||||
| `tenant_roles` token claim | `tenant-engine` (live) / `key-cape` (cached copy) | `tenant-engine` is authoritative; the token claim is a point-in-time cache | Privileged/high-stakes decisions MUST re-query `tenant-engine` live — see IAM Profile v0.3, "Tenant Roles" section — never trust the cached claim alone |
|
||||
| Tenant identifier claim shape (`tenant`) | NetKingdom / IAM Profile contract | `tenant-engine` validates against it; does not mint the claim format | The wire format stays owned by the profile; `tenant-engine` owns which concrete tenant values currently exist |
|
||||
| Tenant identifier claim shape (`tenant`) | NetKingdom / IAM Profile contract | `tenant-engine` validates against it; does not mint the claim format | The wire format stays owned by the profile; the identifier is immutable, including its historical grouping segment; `tenant-engine` owns which concrete tenant values currently exist |
|
||||
| User/membership records scoped by a tenant | `user-engine` | No relation | `tenant_id` is the only key shared between the two services; `tenant-engine` never stores or reads user data |
|
||||
| Authorization decisions | `flex-auth` | Data source only | `tenant-engine` never enforces access itself; it answers queries `flex-auth`'s policy packages issue |
|
||||
|
||||
The tenant identifier and current grouping are intentionally independent after
|
||||
creation. `tenant-engine` MAY change the record's `grouping` through an audited
|
||||
mutation without renaming `tenant_id`. Reads and domain events expose current
|
||||
grouping explicitly. No API, guardrail, pricing, or authorization consumer may
|
||||
recover current grouping by parsing `tenant_id`.
|
||||
|
||||
## Tenant Role & Plan Grant Contract
|
||||
|
||||
Every role grant or revocation is an audited mutation, not a direct field
|
||||
|
|
|
|||
|
|
@ -1,3 +1,15 @@
|
|||
---
|
||||
id: NK-ADR-0006
|
||||
type: architecture-decision-record
|
||||
title: "Recursive Multi-Tenant Identity and Authorization Architecture"
|
||||
status: accepted
|
||||
owner: net-kingdom
|
||||
revision: "1"
|
||||
decided: "2026-05-17"
|
||||
last_reviewed: "2026-08-22"
|
||||
review_interval: 12m
|
||||
---
|
||||
|
||||
# ADR-0006 - Recursive Multi-Tenant Identity and Authorization Architecture
|
||||
|
||||
**Status:** Accepted
|
||||
|
|
|
|||
|
|
@ -1,3 +1,15 @@
|
|||
---
|
||||
id: NK-ADR-0007
|
||||
type: architecture-decision-record
|
||||
title: "Security Orchestration Boundary"
|
||||
status: accepted
|
||||
owner: net-kingdom
|
||||
revision: "1"
|
||||
decided: "2026-05-18"
|
||||
last_reviewed: "2026-08-22"
|
||||
review_interval: 12m
|
||||
---
|
||||
|
||||
# ADR-0007 - Security Orchestration Boundary
|
||||
|
||||
**Status:** Accepted
|
||||
|
|
|
|||
|
|
@ -1,3 +1,15 @@
|
|||
---
|
||||
id: NK-ADR-0008
|
||||
type: architecture-decision-record
|
||||
title: "Object Storage STS Credential Vending Boundary"
|
||||
status: accepted
|
||||
owner: net-kingdom
|
||||
revision: "1"
|
||||
decided: "2026-05-18"
|
||||
last_reviewed: "2026-08-22"
|
||||
review_interval: 12m
|
||||
---
|
||||
|
||||
# ADR-0008 - Object Storage STS Credential Vending Boundary
|
||||
|
||||
**Status:** Accepted
|
||||
|
|
|
|||
|
|
@ -1,3 +1,15 @@
|
|||
---
|
||||
id: NK-ADR-0010
|
||||
type: architecture-decision-record
|
||||
title: "Orchestration vs Dependency, and Self-Coherent Intent"
|
||||
status: accepted
|
||||
owner: net-kingdom
|
||||
revision: "1"
|
||||
decided: "2026-05-21"
|
||||
last_reviewed: "2026-08-22"
|
||||
review_interval: 12m
|
||||
---
|
||||
|
||||
# ADR-0010 - Orchestration vs Dependency, and Self-Coherent Intent
|
||||
|
||||
**Status:** Accepted (repo classification subject to ongoing refinement)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,15 @@
|
|||
---
|
||||
id: NK-ADR-0011
|
||||
type: architecture-decision-record
|
||||
title: "NetKingdom IAM Profile Ownership And Version Governance"
|
||||
status: accepted
|
||||
owner: net-kingdom
|
||||
revision: "1"
|
||||
decided: "2026-05-22"
|
||||
last_reviewed: "2026-08-22"
|
||||
review_interval: 12m
|
||||
---
|
||||
|
||||
# ADR-0011 - NetKingdom IAM Profile Ownership And Version Governance
|
||||
|
||||
**Status:** Accepted
|
||||
|
|
|
|||
|
|
@ -1,3 +1,15 @@
|
|||
---
|
||||
id: NK-ADR-0012
|
||||
type: architecture-decision-record
|
||||
title: "Playbook Capability Contract Ownership"
|
||||
status: accepted
|
||||
owner: net-kingdom
|
||||
revision: "1"
|
||||
decided: "2026-05-22"
|
||||
last_reviewed: "2026-08-22"
|
||||
review_interval: 12m
|
||||
---
|
||||
|
||||
# ADR-0012 - Playbook Capability Contract Ownership
|
||||
|
||||
**Status:** Accepted
|
||||
|
|
|
|||
|
|
@ -1,7 +1,20 @@
|
|||
---
|
||||
id: NK-ADR-0013
|
||||
type: architecture-decision-record
|
||||
title: "Tenant Onboarding Grouping Taxonomy"
|
||||
status: accepted
|
||||
owner: net-kingdom
|
||||
revision: "2"
|
||||
decided: "2026-07-23"
|
||||
last_reviewed: "2026-08-22"
|
||||
review_interval: 12m
|
||||
---
|
||||
|
||||
# ADR-0013 - Tenant Onboarding Grouping Taxonomy
|
||||
|
||||
**Status:** Accepted
|
||||
**Date:** 2026-07-23
|
||||
**Amended:** 2026-08-22 (current classification versus historical identifier segment)
|
||||
**Deciders:** Bernd Worsch, Codex
|
||||
|
||||
## Context
|
||||
|
|
@ -54,12 +67,26 @@ association - a legal association of people
|
|||
agentic - financially enabled AI entities
|
||||
```
|
||||
|
||||
This grouping is deliberately **orthogonal to capability role**
|
||||
(`PLTF`/`IAM`/`VEN`/`CUS`, still unratified): the grouping describes *what
|
||||
kind of entity a tenant is and how it was onboarded*; role describes *what
|
||||
it does on the platform*. Both may need to be carried as tenant metadata,
|
||||
but never conflated into one identifier segment — that conflation is exactly
|
||||
what this ADR avoids.
|
||||
The taxonomy has two deliberately different uses:
|
||||
|
||||
- At creation, the identifier's grouping segment records the tenant's
|
||||
onboarding-time classification. The complete identifier is immutable, so
|
||||
this segment is historical after creation.
|
||||
- The tenant record's `grouping` field records current classification. It may
|
||||
change as the entity changes and is authoritative for present-day policy,
|
||||
including guardrails and spend ceilings.
|
||||
|
||||
No consumer may parse the identifier's middle segment and treat it as current
|
||||
grouping. Consumers needing current grouping MUST read it from `tenant-engine`.
|
||||
Identifier creation still validates the segment against this vocabulary;
|
||||
historical does not mean free-form or optional.
|
||||
|
||||
Grouping is deliberately **orthogonal to capability role**
|
||||
(`PLTF`/`IAM`/`VEN`/`CUS`, subsequently ratified by ADR-0014): grouping
|
||||
describes *what kind of entity a tenant is and its current onboarding-risk
|
||||
classification*; role describes *what it does on the platform*. Both are
|
||||
carried as tenant metadata, but never conflated into the immutable identifier
|
||||
segment — that conflation is exactly what this ADR avoids.
|
||||
|
||||
`tenant:platform` and `tenant:coulomb` remain **reserved, ungrouped
|
||||
identifiers outside this taxonomy**: `tenant:platform` is the control-plane
|
||||
|
|
@ -101,10 +128,15 @@ section — not a new versioned profile document.
|
|||
already reflects this decision (`tenant:friendly:binky`).
|
||||
- Future tenant onboarding work should classify a tenant against this list
|
||||
before minting an identifier, rather than reaching for a role word.
|
||||
- The capability-role model (`PLTF`/`IAM`/`VEN`/`CUS`) remains a separate,
|
||||
still-unratified dimension; this ADR does not ratify that model, only
|
||||
avoids colliding with it. If/when it is ratified, role metadata should be
|
||||
carried alongside — not instead of — the grouping segment decided here.
|
||||
- Tenant identifiers never change when current grouping changes. The middle
|
||||
segment is creation-time history; `tenant-engine` is authoritative for the
|
||||
current grouping value.
|
||||
- Policy and commercial consumers, including spend-ceiling resolution, MUST
|
||||
query `tenant-engine` and MUST NOT derive current grouping by splitting a
|
||||
tenant identifier.
|
||||
- The capability-role model (`PLTF`/`IAM`/`VEN`/`CUS`) remains a separate
|
||||
dimension, now ratified by ADR-0014. Role metadata is carried alongside —
|
||||
not instead of — current grouping and the historical identifier segment.
|
||||
- `tenant:platform` and `tenant:coulomb` are reserved outside the taxonomy,
|
||||
pending Bernd's explicit confirmation (see Decision).
|
||||
|
||||
|
|
@ -138,6 +170,8 @@ resolved before the first non-Coulomb tenant goes live, not after.
|
|||
reviewable change).
|
||||
- Confirm the `tenant:platform`/`tenant:coulomb` reserved/ungrouped
|
||||
treatment explicitly.
|
||||
- If/when the `PLTF`/`IAM`/`VEN`/`CUS` capability-role model is ratified,
|
||||
define how role metadata is carried alongside the grouping segment
|
||||
decided here.
|
||||
- ADR-0014 and the Tenant Engine Boundary Contract define how capability-role
|
||||
metadata is carried alongside grouping.
|
||||
- Keep `tenant-engine`'s identifier parser vocabulary-validating for creation
|
||||
and lookup compatibility, but do not expose parsed grouping as current
|
||||
classification.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,15 @@
|
|||
---
|
||||
id: NK-ADR-0014
|
||||
type: architecture-decision-record
|
||||
title: "Tenant Capability Roles, Carrying Mechanism, and Tenant-Engine Ownership"
|
||||
status: accepted
|
||||
owner: net-kingdom
|
||||
revision: "1"
|
||||
decided: "2026-07-23"
|
||||
last_reviewed: "2026-08-22"
|
||||
review_interval: 12m
|
||||
---
|
||||
|
||||
# ADR-0014 - Tenant Capability Roles, Carrying Mechanism, and Tenant-Engine Ownership
|
||||
|
||||
**Status:** Accepted
|
||||
|
|
|
|||
|
|
@ -1,3 +1,15 @@
|
|||
---
|
||||
id: NK-ADR-0015
|
||||
type: architecture-decision-record
|
||||
title: "NetKingdom Railiance Workload Packaging and Relational Platform"
|
||||
status: accepted
|
||||
owner: net-kingdom
|
||||
revision: "1"
|
||||
decided: "2026-08-11"
|
||||
last_reviewed: "2026-08-22"
|
||||
review_interval: 12m
|
||||
---
|
||||
|
||||
# ADR-0015 - NetKingdom Railiance Workload Packaging and Relational Platform
|
||||
|
||||
**Status:** Accepted
|
||||
|
|
|
|||
109
docs/reef-posture-provider-contract.md
Normal file
109
docs/reef-posture-provider-contract.md
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
# Reef posture-provider contract
|
||||
|
||||
Status: proposal for `repo-manager` agreement under `NK-WP-0027-T02`
|
||||
|
||||
Date: 2026-08-22
|
||||
|
||||
Canon owner: `net-kingdom`
|
||||
|
||||
Reef vocabulary and declaration owner: `repo-manager` / `railiance-master`
|
||||
|
||||
## Purpose
|
||||
|
||||
A reef states where workloads may be placed and which residual substrate risk
|
||||
has been accepted. It is not a `P` level. It can nevertheless bound a posture
|
||||
axis: the current single-member `reef-railiance` can never make V2 failover
|
||||
reachable, regardless of how many replicas a workload declares.
|
||||
|
||||
This proposal extends Tenancy Posture Decision 5.5's provider shape to reefs
|
||||
without moving reef vocabulary into NetKingdom. The block belongs in the
|
||||
authoritative `declarations/reef.yaml`; it does not create a second reef file or
|
||||
duplicate the derived `bound_rapps` projection.
|
||||
|
||||
## Proposed declaration block
|
||||
|
||||
```yaml
|
||||
posture_provider:
|
||||
framework: netkingdom-tenancy-posture
|
||||
reviewed: "2026-08-22"
|
||||
review_due: "2027-02-22"
|
||||
axes:
|
||||
V:
|
||||
available: 0
|
||||
maximum: 1
|
||||
conditions:
|
||||
- A bound workload documents and exercises restart or recreation recovery in this failure domain.
|
||||
- The workload names every synchronous dependency used by the claimed operation.
|
||||
evidence:
|
||||
- evidence/verification/rail-runtime-2026-08-21.json
|
||||
- evidence/admission/rail-kubernetes-baseline.json
|
||||
reason: One observed member carries the control plane, etcd, and workloads; no automated failover is reachable.
|
||||
```
|
||||
|
||||
The `reef-railiance` values are deliberately conservative:
|
||||
|
||||
- `available: 0` means the reef offers no unconditional, reusable recovery
|
||||
guarantee to every bound workload today. A Ready node is not recovery
|
||||
evidence.
|
||||
- `maximum: 1` means a named workload can reach V1 by satisfying and evidencing
|
||||
the restart/recreate conditions. One failure domain makes V2 unreachable.
|
||||
|
||||
The owner may raise `available` when the reef publishes a reusable recovery
|
||||
guarantee that consumers can cite. Adding independent members and an exercised
|
||||
failover path may raise `maximum`; topology alone does not.
|
||||
|
||||
## Semantics
|
||||
|
||||
Each declared axis contains:
|
||||
|
||||
| Field | Meaning |
|
||||
| --- | --- |
|
||||
| `available` | Highest level the provider guarantees unconditionally to every binding in scope, with current evidence. |
|
||||
| `maximum` | Highest level a named consumer can reach after satisfying the listed conditions. |
|
||||
| `conditions` | Consumer or binding work required above `available`; empty only when `available == maximum`. |
|
||||
| `evidence` | Source-linked, current artifacts supporting the provider facts. |
|
||||
| `reason` | Why the ceiling exists, especially when structural or accepted. |
|
||||
|
||||
A reef declares only axes it materially bounds. A compute reef normally
|
||||
declares `V`; it does not declare `P` merely because data-bearing workloads sit
|
||||
on it. A provider-delegated storage reef may bound `P`, `R`, or `V`, but only
|
||||
where the substrate contract actually makes those properties reachable.
|
||||
|
||||
`available` and `maximum` use the axis vocabulary from
|
||||
`tenancy-posture_v0.1`. `available` MUST NOT exceed `maximum`. Review dates and
|
||||
evidence discipline follow Decisions 5.4, 5.5, and §13.
|
||||
|
||||
## Mechanical reconciliation
|
||||
|
||||
For each workload operation and each bound reef:
|
||||
|
||||
1. Resolve the reef from the workload's authoritative placement declaration.
|
||||
Missing or conflicting placement is `unknown`; do not select a default reef.
|
||||
2. Load the reef's `posture_provider` block from `declarations/reef.yaml`.
|
||||
3. Reject a workload claim above the reef's `maximum`.
|
||||
4. For a claim above `available`, require machine-readable evidence that every
|
||||
listed condition is satisfied for that workload and operation.
|
||||
5. Compose `V` with every synchronous provider using Decision 4.6.1's minimum
|
||||
rule. A reef ceiling is one input, not the whole availability claim.
|
||||
6. Emit the reef declaration revision and evidence references in the
|
||||
reconciliation result so the decision is reproducible.
|
||||
|
||||
The result is one of `satisfied`, `unsatisfied`, or `unknown`. `unknown` covers
|
||||
an absent provider block, unresolved reef binding, stale review, missing
|
||||
evidence, or an unrecognised axis value. It is never converted to a permissive
|
||||
ceiling.
|
||||
|
||||
## Ownership boundary
|
||||
|
||||
- `net-kingdom` owns the meaning of provider reachability and the `P`/`V`
|
||||
composition rules.
|
||||
- `repo-manager` / `railiance-master` owns whether and how this block is added
|
||||
to the reef schema.
|
||||
- Each `reef-*` repo owns its values, evidence, and review.
|
||||
- The workload owner owns its claim and evidence that provider conditions are
|
||||
met.
|
||||
- The reconciler reports; it does not manufacture acceptance or posture.
|
||||
|
||||
T03 may implement the join only after `repo-manager` agrees the authoritative
|
||||
field name and carrier. The semantics above are the canon-side acceptance
|
||||
criteria; the exact reef-schema spelling remains the reef owner's decision.
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import importlib.util
|
||||
import json
|
||||
import pathlib
|
||||
import unittest
|
||||
|
||||
|
|
@ -10,6 +11,7 @@ SPEC = importlib.util.spec_from_file_location("tenancy_posture_validate", MODULE
|
|||
assert SPEC and SPEC.loader
|
||||
VALIDATE = importlib.util.module_from_spec(SPEC)
|
||||
SPEC.loader.exec_module(VALIDATE)
|
||||
SCHEMA = json.loads(VALIDATE.SCHEMA.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
def declaration() -> dict:
|
||||
|
|
@ -30,10 +32,38 @@ def declaration() -> dict:
|
|||
}
|
||||
|
||||
|
||||
def zone_declaration() -> dict:
|
||||
return {
|
||||
"standard": "security-zones_v0.1",
|
||||
"membership": "z2-continuity",
|
||||
"responsible_party": "ops-warden",
|
||||
"justification": "foundational access path",
|
||||
"context": {
|
||||
"maturity": "M2",
|
||||
"criticality": "high",
|
||||
"data_classification": "confidential",
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"ref": "docs/evidence/example-zone.md",
|
||||
"supports": ["M2", "continuity-dependency"],
|
||||
}
|
||||
],
|
||||
"reviewed": "2026-08-22",
|
||||
"review_due": "2026-11-22",
|
||||
}
|
||||
|
||||
|
||||
class SemanticValidationTests(unittest.TestCase):
|
||||
def validate(self, document: dict) -> list[str]:
|
||||
return VALIDATE.validate_semantics(document, pathlib.Path("tenancy.yaml"))
|
||||
|
||||
def validate_full(self, document: dict, tmp_path: pathlib.Path) -> list[str]:
|
||||
import yaml
|
||||
|
||||
tmp_path.write_text(yaml.safe_dump(document), encoding="utf-8")
|
||||
return VALIDATE.validate(tmp_path, SCHEMA)
|
||||
|
||||
def test_floor_vector_with_reasons_is_valid(self) -> None:
|
||||
self.assertEqual([], self.validate(declaration()))
|
||||
|
||||
|
|
@ -68,6 +98,140 @@ class SemanticValidationTests(unittest.TestCase):
|
|||
}
|
||||
self.assertIn("service names must be unique", self.validate(document)[0])
|
||||
|
||||
def test_workload_identity_name_must_match_service(self) -> None:
|
||||
document = declaration()
|
||||
document["workload_identity"] = {
|
||||
"name": "different",
|
||||
"kind": "operational-control-plane",
|
||||
"responsible_repo": "example",
|
||||
"identity_bindings": [
|
||||
{
|
||||
"scheme": "iam-profile",
|
||||
"authority": "key-cape",
|
||||
"subject": "example-prod",
|
||||
"principal_type": "service",
|
||||
}
|
||||
],
|
||||
}
|
||||
self.assertIn(
|
||||
"workload_identity.name must equal service", self.validate(document)[0]
|
||||
)
|
||||
|
||||
def test_workload_identity_bindings_are_unique(self) -> None:
|
||||
document = declaration()
|
||||
binding = {
|
||||
"scheme": "iam-profile",
|
||||
"authority": "key-cape",
|
||||
"subject": "example-prod",
|
||||
"principal_type": "service",
|
||||
}
|
||||
document["workload_identity"] = {
|
||||
"name": "example",
|
||||
"kind": "platform-service",
|
||||
"responsible_repo": "example",
|
||||
"identity_bindings": [binding, binding],
|
||||
}
|
||||
self.assertIn(
|
||||
"workload identity bindings must be unique", self.validate(document)[0]
|
||||
)
|
||||
|
||||
def test_zones_require_authoritative_workload_identity(self) -> None:
|
||||
import tempfile
|
||||
|
||||
document = declaration()
|
||||
document["zones"] = zone_declaration()
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path = pathlib.Path(directory) / "tenancy.yaml"
|
||||
errors = self.validate_full(document, path)
|
||||
self.assertTrue(any("workload_identity" in error for error in errors))
|
||||
|
||||
def test_operational_workload_may_declare_zones(self) -> None:
|
||||
import tempfile
|
||||
|
||||
document = declaration()
|
||||
document["workload_identity"] = {
|
||||
"name": "example",
|
||||
"kind": "operational-control-plane",
|
||||
"responsible_repo": "ops-warden",
|
||||
"identity_bindings": [
|
||||
{
|
||||
"scheme": "ssh-certificate",
|
||||
"authority": "ops-warden",
|
||||
"subject": "agt-example",
|
||||
"principal_type": "agent",
|
||||
"environment": "prod",
|
||||
}
|
||||
],
|
||||
}
|
||||
document["zones"] = zone_declaration()
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path = pathlib.Path(directory) / "tenancy.yaml"
|
||||
self.assertEqual([], self.validate_full(document, path))
|
||||
|
||||
def test_zone_membership_uses_canonical_catalog(self) -> None:
|
||||
import tempfile
|
||||
|
||||
document = declaration()
|
||||
document["workload_identity"] = {
|
||||
"name": "example",
|
||||
"kind": "application",
|
||||
"responsible_repo": "example",
|
||||
"declaration_ref": "rapp-example/declarations/rapp.yaml",
|
||||
"identity_bindings": [
|
||||
{
|
||||
"scheme": "iam-profile",
|
||||
"authority": "key-cape",
|
||||
"subject": "example-prod",
|
||||
"principal_type": "service",
|
||||
}
|
||||
],
|
||||
}
|
||||
document["zones"] = zone_declaration()
|
||||
document["zones"]["membership"] = "permissive-default"
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path = pathlib.Path(directory) / "tenancy.yaml"
|
||||
errors = self.validate_full(document, path)
|
||||
self.assertTrue(any("membership" in error for error in errors))
|
||||
|
||||
def test_zone_review_due_must_be_after_reviewed(self) -> None:
|
||||
document = declaration()
|
||||
document["zones"] = zone_declaration()
|
||||
document["zones"]["review_due"] = document["zones"]["reviewed"]
|
||||
self.assertIn(
|
||||
"zones.review_due must be after zones.reviewed",
|
||||
self.validate(document)[0],
|
||||
)
|
||||
|
||||
def test_multi_service_zones_must_not_be_top_level(self) -> None:
|
||||
import tempfile
|
||||
|
||||
entry = declaration()
|
||||
document = {
|
||||
"schema_version": "0.1",
|
||||
"framework": "netkingdom-tenancy-posture",
|
||||
"services": [entry],
|
||||
"zones": zone_declaration(),
|
||||
}
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path = pathlib.Path(directory) / "tenancy.yaml"
|
||||
errors = self.validate_full(document, path)
|
||||
self.assertTrue(errors)
|
||||
|
||||
def test_multi_service_zone_requires_identity_on_same_entry(self) -> None:
|
||||
import tempfile
|
||||
|
||||
entry = declaration()
|
||||
entry["zones"] = zone_declaration()
|
||||
document = {
|
||||
"schema_version": "0.1",
|
||||
"framework": "netkingdom-tenancy-posture",
|
||||
"services": [entry],
|
||||
}
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path = pathlib.Path(directory) / "tenancy.yaml"
|
||||
errors = self.validate_full(document, path)
|
||||
self.assertTrue(any("workload_identity" in error for error in errors))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -38,6 +38,30 @@ def validate_semantics(document: dict[str, Any], path: pathlib.Path) -> list[str
|
|||
|
||||
for entry in entries:
|
||||
name = entry["service"]
|
||||
workload_identity = entry.get("workload_identity")
|
||||
if workload_identity:
|
||||
if workload_identity["name"] != name:
|
||||
errors.append(
|
||||
f"{name}: workload_identity.name must equal service"
|
||||
)
|
||||
bindings = workload_identity["identity_bindings"]
|
||||
binding_keys = [
|
||||
(
|
||||
binding["scheme"],
|
||||
binding["authority"],
|
||||
binding["subject"],
|
||||
binding.get("environment"),
|
||||
)
|
||||
for binding in bindings
|
||||
]
|
||||
if len(binding_keys) != len(set(binding_keys)):
|
||||
errors.append(f"{name}: workload identity bindings must be unique")
|
||||
zones = entry.get("zones")
|
||||
if zones:
|
||||
zone_reviewed = dt.date.fromisoformat(zones["reviewed"])
|
||||
zone_review_due = dt.date.fromisoformat(zones["review_due"])
|
||||
if zone_review_due <= zone_reviewed:
|
||||
errors.append(f"{name}: zones.review_due must be after zones.reviewed")
|
||||
posture = entry["tenancy"]
|
||||
current = posture["current"]
|
||||
reason = posture.get("reason", {})
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
---
|
||||
id: NK-WP-0027
|
||||
type: workplan
|
||||
title: "Reconcile the reef taxonomy with the P and V ladders"
|
||||
title: "Reconcile reef placement and security-zone canon dependencies"
|
||||
domain: infotech
|
||||
repo: net-kingdom
|
||||
status: proposed
|
||||
status: blocked
|
||||
owner: net-kingdom
|
||||
topic_slug: netkingdom
|
||||
planning_priority: P2
|
||||
planning_priority: P1
|
||||
created: "2026-08-19"
|
||||
updated: "2026-08-19"
|
||||
updated: "2026-08-22"
|
||||
state_hub_workstream_id: "a30a33e4-f980-4934-9efb-d61a75e6ae81"
|
||||
---
|
||||
|
||||
# NK-WP-0027 — Reefs, placement, and what a substrate makes reachable
|
||||
# NK-WP-0027 — Reefs, placement, and security-zone canon dependencies
|
||||
|
||||
Raised by answering `zone-engine`'s `ZONE-WP-0001-T01`. `zone-engine` asked
|
||||
whether canon should reconcile security zones with reefs, expecting the answer
|
||||
|
|
@ -37,20 +38,61 @@ accurately by its own reading and be wrong by the standard's own composition
|
|||
rule. This is Decision 5.5's provider-declaration finding one layer down: a
|
||||
reef is a provider with nowhere to say what it makes reachable.
|
||||
|
||||
## Activation review — 2026-08-22
|
||||
|
||||
The original reef finding remains valid and correctly owned. Review against
|
||||
draft-9 found T01 substantially written already in Decision 8.4.2, but the text
|
||||
did not explicitly say which Decision 3.2 couplings a reef binding fails to
|
||||
satisfy. Draft-10 now closes that textual gap. T02 and T03 remain real: the reef
|
||||
provider declaration and its mechanical join to consumer `V` do not yet exist.
|
||||
|
||||
The review also took in a second canon question handed over by
|
||||
`ZONE-WP-0001-T03`. Measured coverage is nine declared `rapp` workloads, one of
|
||||
27 credential lanes joinable, 13 plausible but undeclared consumers, and 13
|
||||
operational controls with no workload-shaped path. The ruling is recorded as
|
||||
Tenancy Posture Decision 5.6.1:
|
||||
|
||||
- the **workload remains the sole policy subject**;
|
||||
- workload includes independently governed application, automation, and
|
||||
operational/control-plane execution units behind SSH, tunnels, brokers,
|
||||
credential flows, policy machinery, and maintenance activity;
|
||||
- lanes, grants, patterns, repositories, actors, and packages do not become
|
||||
substitute policy subjects;
|
||||
- every managed deployable, including operational/tooling runtimes, resolves
|
||||
through its authoritative rapp declaration; a real operational execution
|
||||
unit that is not a managed deployable may declare locally; and
|
||||
- absent authoritative identity or membership resolves to `unknown`, never an
|
||||
inferred or silently permissive zone.
|
||||
|
||||
An explicit control rule may decide how to treat `unknown`; that is stance and
|
||||
does not manufacture membership. This preserves the build-stage flexibility
|
||||
already accepted by `ADR-0006` without encoding it as a false zone fact.
|
||||
|
||||
## T01 — Establish the reef and `P` boundary
|
||||
|
||||
```task
|
||||
id: NK-WP-0027-T01
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
state_hub_task_id: "a1dfa4ec-f946-425e-8183-782eef7763c4"
|
||||
```
|
||||
|
||||
**Establish the boundary between a reef and the `P` ladder in canon text.** Say
|
||||
what each answers, why a reef is not a `P` level, and which of `P`'s couplings
|
||||
(§3.2) a reef binding does and does not satisfy. Do not extend the `P` ladder.
|
||||
|
||||
**Done 2026-08-22.** Tenancy Posture Decision 8.4.2 now says explicitly that a
|
||||
reef binding records compute substrate and accepted residual risk, satisfies no
|
||||
`P` coupling by itself, and participates only as a possible `V` ceiling across
|
||||
the critical path.
|
||||
|
||||
## T02 — Extend provider declarations to reefs
|
||||
|
||||
```task
|
||||
id: NK-WP-0027-T02
|
||||
status: todo
|
||||
status: wait
|
||||
priority: medium
|
||||
state_hub_task_id: "601a0c5f-3f77-419f-9731-25e247424b31"
|
||||
```
|
||||
|
||||
**Extend Decision 5.5's provider declaration to substrate providers, and agree
|
||||
|
|
@ -60,10 +102,30 @@ sentence `apps-pg` now owes its consumers. `reef-railiance`'s first line is
|
|||
almost certainly a `V` ceiling. This is a proposal to `repo-manager`, not a
|
||||
canon fiat: it owns the reef vocabulary and the acceptance record.
|
||||
|
||||
**In progress 2026-08-22.** The canon-side boundary and proposed provider shape
|
||||
are ready. Agreement and the authoritative reef declaration surface remain with
|
||||
`repo-manager`.
|
||||
|
||||
**Contract proposal 2026-08-22.**
|
||||
`docs/reef-posture-provider-contract.md` now proposes a `posture_provider`
|
||||
block inside authoritative `declarations/reef.yaml`, reusing Decision 5.5's
|
||||
`available`/`maximum`/conditions/evidence semantics. For `reef-railiance` it
|
||||
proposes V0 available and V1 maximum: no unconditional reusable recovery
|
||||
guarantee exists, while a named workload can evidence restart/recreate recovery
|
||||
inside the one failure domain. The field name and reef-schema adoption remain
|
||||
subject to `repo-manager` agreement.
|
||||
|
||||
**Waiting:** `repo-manager` must confirm or amend the `reef.yaml` carrier,
|
||||
field name, and conservative V0/V1 values. NetKingdom cannot make that
|
||||
reef-vocabulary decision on its behalf.
|
||||
|
||||
## T03 — Reconcile reef ceilings mechanically
|
||||
|
||||
```task
|
||||
id: NK-WP-0027-T03
|
||||
status: wait
|
||||
priority: low
|
||||
state_hub_task_id: "b53bfb83-1df9-4548-a62f-628cb55ece4d"
|
||||
```
|
||||
|
||||
**Join reef ceilings to consumer `V` declarations mechanically.** Waits on T02.
|
||||
|
|
@ -72,6 +134,104 @@ a machine reconciles. Until then a consumer bound to a reef declares `V` with
|
|||
the reef named as a synchronous dependency, which is already required by
|
||||
Decision 4.6.1 and is not being done.
|
||||
|
||||
**Design advanced 2026-08-22.** The proposal defines a three-valued join:
|
||||
`satisfied`, `unsatisfied`, or `unknown`. It rejects claims above the reef
|
||||
maximum, requires condition evidence above its unconditional available level,
|
||||
and composes V across synchronous providers. Implementation still waits on the
|
||||
authoritative reef field name from T02.
|
||||
|
||||
## T04 — Rule on zone policy subject and absence
|
||||
|
||||
```task
|
||||
id: NK-WP-0027-T04
|
||||
status: done
|
||||
priority: high
|
||||
```
|
||||
|
||||
**Rule on the security-zone policy subject and absence semantics for
|
||||
`ZONE-WP-0001-T03`.** Keep workload as the sole subject, define it broadly
|
||||
enough to cover operational/control-plane execution, and state whether missing
|
||||
identity or membership may inherit a zone.
|
||||
|
||||
**Done 2026-08-22.** Decision 5.6.1 defines operational execution units as
|
||||
workloads, rejects lanes/actors/patterns as substitute subjects, and requires
|
||||
unresolved membership to return `unknown` without inference. A control may
|
||||
apply an explicit fail-safe stance to `unknown`; it may not relabel it.
|
||||
|
||||
## T05 — Broaden workload declaration coverage
|
||||
|
||||
```task
|
||||
id: NK-WP-0027-T05
|
||||
status: done
|
||||
priority: high
|
||||
```
|
||||
|
||||
**Broaden authoritative workload declaration coverage beyond managed `rapp`
|
||||
applications.** In the `security-zones_v0.1` publication review, require a
|
||||
stable workload identity and responsible party for operational/control-plane
|
||||
units, and a machine-readable join from credential/control resources to the
|
||||
workload they serve. Do not require `rapp` packaging merely to gain identity,
|
||||
and do not infer the join from path strings or repository ownership. Coordinate
|
||||
the declaration boundary with `zone-engine`, `repo-manager`, and the affected
|
||||
control owners.
|
||||
|
||||
**Done 2026-08-22.** Tenancy Posture draft-12 Decision 5.6.2 and its schema now
|
||||
require `workload_identity` whenever a `zones:` block is present. The binding
|
||||
names the stable workload id, kind, responsible repo, and one or more exact
|
||||
authority/subject/principal-type tuples. Multi-service declarations carry both
|
||||
fields per service; top-level multi-service membership is rejected. Following
|
||||
RMGR-ADR-004, every managed deployable uses its authoritative rapp declaration
|
||||
and consumer references use `(rapp_id, workload_identity.name)` plus optional
|
||||
`deployable`. Only a non-managed operational execution unit declares locally;
|
||||
native actions, actors, lanes, patterns, and resources are explicitly
|
||||
`not-applicable`, while omissions stay `unknown`. The published
|
||||
`canon/standards/security-zones_v0.1.md` proposal now has a closed schema shape
|
||||
for its five memberships, admission context, evidence, and review dates. The
|
||||
validator rejects service/id mismatch, duplicate bindings, and invalid review
|
||||
windows; tests cover missing identity and a valid operational workload.
|
||||
|
||||
## T06 — Resolve the `DataClassification` mismatch
|
||||
|
||||
```task
|
||||
id: NK-WP-0027-T06
|
||||
status: wait
|
||||
priority: high
|
||||
```
|
||||
|
||||
**Resolve the `DataClassification` vocabulary mismatch surfaced by
|
||||
`ZONE-WP-0001-T03`.** `rapp-policy-nexus` declares `public`, while ops-warden's
|
||||
`dataclass_floor` maps only `synthetic`, `internal`, `confidential`, and
|
||||
`restricted`. Do not alias `public` to `synthetic`: public describes disclosure
|
||||
policy, while synthetic describes data origin and whether values are real.
|
||||
Route the vocabulary decision to `info-tech-canon`, which owns
|
||||
`DataClassification`, and then update the workload-maturity mapping with its
|
||||
ruling. Until the mapping is authoritative, a compiler must report the maturity
|
||||
floor as unresolved rather than guess.
|
||||
|
||||
**Routed 2026-08-22.** The mismatch and non-equivalence are confirmed; owner
|
||||
consultation is sent and the downstream mapping is pending.
|
||||
|
||||
**Waiting:** `info-tech-canon` owns `DataClassification` and must rule its
|
||||
ordering relative to synthetic-data provenance. The proposed downstream
|
||||
`public -> M1` mapping remains explicitly non-authoritative until that answer.
|
||||
|
||||
## Current gate
|
||||
|
||||
The zone-engine publication candidate at `a510393` has been reviewed and
|
||||
published as the proposed NetKingdom `security-zones_v0.1` standard. All
|
||||
locally actionable canon and schema work is complete. The remaining chain
|
||||
is externally owned:
|
||||
|
||||
1. `repo-manager` agrees or amends the `reef.yaml` provider carrier (T02).
|
||||
2. NetKingdom implements the mechanical reef ceiling join against that accepted
|
||||
carrier (T03).
|
||||
3. `info-tech-canon` rules the `public`/synthetic relationship, after which
|
||||
ops-warden can update `dataclass_floor` (T06).
|
||||
|
||||
The workplan is `blocked` rather than left nominally active with every open task
|
||||
at `wait`. No human intervention is required yet; owner responses are the
|
||||
ordinary next input.
|
||||
|
||||
## Related
|
||||
|
||||
- `canon/standards/tenancy-posture_v0.1.md` Decisions 4.6.1, 5.5, 8.4.1, 8.4.2
|
||||
|
|
@ -80,3 +240,7 @@ Decision 4.6.1 and is not being done.
|
|||
is not readiness
|
||||
- `zone-engine/workplans/ZONE-WP-0001-security-zone-model.md` — where the
|
||||
question came from, and why it is not answered there
|
||||
- `zone-engine/docs/exception-lifecycle-2026-08-22.md` — already requires
|
||||
authoritative workload ids and fail-safe exception evaluation
|
||||
- `docs/reef-posture-provider-contract.md` — concrete T02/T03 carrier and join
|
||||
proposal awaiting reef-owner agreement
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
---
|
||||
id: NK-WP-0028
|
||||
type: workplan
|
||||
title: "Publish zone canon and clarify tenant grouping semantics"
|
||||
domain: infotech
|
||||
repo: net-kingdom
|
||||
status: finished
|
||||
owner: codex
|
||||
topic_slug: netkingdom
|
||||
planning_priority: P1
|
||||
created: "2026-08-22"
|
||||
updated: "2026-08-22"
|
||||
---
|
||||
|
||||
# NK-WP-0028 — Canon publication and grouping semantics
|
||||
|
||||
Authorized by the operator on 2026-08-22 after repository triage. This work
|
||||
publishes the zone-engine owner draft, reconciles its authoritative workload
|
||||
reference semantics with Tenancy Posture, resolves ADR-0013's now-load-bearing
|
||||
grouping ambiguity, and makes the existing ADR set publication-addressable.
|
||||
|
||||
## Publish and integrate Security Zones v0.1
|
||||
|
||||
```task
|
||||
id: NK-WP-0028-T01
|
||||
status: done
|
||||
priority: high
|
||||
```
|
||||
|
||||
Reviewed zone-engine revision `a510393` against Tenancy Posture Decisions 5.6.1
|
||||
and 5.6.2 and RMGR-ADR-004. Published it as proposed canon at
|
||||
`canon/standards/security-zones_v0.1.md`, retaining workload-only zone
|
||||
membership, explicit `not-applicable` for native non-workload subjects, and
|
||||
`unknown` for missing or ambiguous workload references. Replaced the tenancy
|
||||
schema's placeholder `zones:` object with the standard's five memberships,
|
||||
admission context, evidence, and review fields.
|
||||
|
||||
## Clarify current grouping versus historical identifier segment
|
||||
|
||||
```task
|
||||
id: NK-WP-0028-T02
|
||||
status: done
|
||||
priority: high
|
||||
```
|
||||
|
||||
Amended NK-ADR-0013 so the immutable tenant identifier retains its
|
||||
onboarding-time grouping segment as history while `tenant-engine.grouping` is
|
||||
the mutable, authoritative current classification. Consumers may not derive
|
||||
current policy, guardrail, or spend-ceiling inputs by splitting a tenant id.
|
||||
Propagated the ruling to IAM Profile v0.3 and the Tenant Engine Boundary
|
||||
Contract.
|
||||
|
||||
## Add publication metadata and ignore generated architecture cache
|
||||
|
||||
```task
|
||||
id: NK-WP-0028-T03
|
||||
status: done
|
||||
priority: medium
|
||||
```
|
||||
|
||||
Added unique `NK-ADR-*` identifiers plus owner, revision, review date, and
|
||||
review interval metadata to ADR-0006 through ADR-0015 that exist in this repo.
|
||||
Recorded the security-zone source revision and added the generated architecture
|
||||
AST cache to `.gitignore`.
|
||||
|
||||
## Verification
|
||||
|
||||
```task
|
||||
id: NK-WP-0028-T04
|
||||
status: done
|
||||
priority: medium
|
||||
```
|
||||
|
||||
Verified the JSON schema parses, all 14 tenancy-posture unit tests pass, and the
|
||||
repository diff has no whitespace errors. Seven estate declarations were also
|
||||
checked: five validate; the previously-routed flex-auth `implemented A2` drift
|
||||
and railiance-platform apps-pg R2/V1 evidence drift remain owner work and are
|
||||
not regressions from this change. Workplan state was reconciled with State Hub.
|
||||
Remaining external decisions stay tracked as waits in NK-WP-0027 and
|
||||
NK-WP-0022.
|
||||
Loading…
Add table
Add a link
Reference in a new issue