tenancy-posture draft-9: enforcement stance is not a seventh axis; reefs are canon's defect
Answers zone-engine ZONE-WP-0001-T01. Decision 5.6 — enforcement stance is a sibling standard, not an axis. The six ladders are monotone and the whole current/target/guard machinery depends on it; enforcement stance is not (ADR-0006 is the finding that the top rung is wrong for the SSH lane). And this framework is descriptive: an accurately declared exempt would be conformant and exempt. Membership is declared, stance belongs to the control owner. Zone membership rides tenancy.yaml under a reserved zones: key so the estate keeps one declaration surface; the schema permits it, unconstrained. Decisions 8.4.1/8.4.2 — 'substrate location is not evidence' stated once instead of three repo-local slogans, and the reef/P/V gap recorded as this document's defect rather than zone-engine's scope. NK-WP-0027 takes it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
4a915ce6c7
commit
9e041e3662
3 changed files with 512 additions and 86 deletions
|
|
@ -3,36 +3,93 @@
|
||||||
"$id": "https://policy.coulomb.social/schemas/tenancy-posture/v0.1",
|
"$id": "https://policy.coulomb.social/schemas/tenancy-posture/v0.1",
|
||||||
"title": "NetKingdom tenancy posture declaration v0.1",
|
"title": "NetKingdom tenancy posture declaration v0.1",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["schema_version", "framework"],
|
"required": [
|
||||||
|
"schema_version",
|
||||||
|
"framework"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"schema_version": {"const": "0.1"},
|
"schema_version": {
|
||||||
"framework": {"const": "netkingdom-tenancy-posture"},
|
"const": "0.1"
|
||||||
"service": {"$ref": "#/$defs/serviceName"},
|
},
|
||||||
"role": {"type": "string", "minLength": 1},
|
"framework": {
|
||||||
"tenancy": {"$ref": "#/$defs/tenancy"},
|
"const": "netkingdom-tenancy-posture"
|
||||||
"provider": {"$ref": "#/$defs/provider"},
|
},
|
||||||
"evidence": {"$ref": "#/$defs/evidence"},
|
"service": {
|
||||||
"notes": {"$ref": "#/$defs/stringList"},
|
"$ref": "#/$defs/serviceName"
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"tenancy": {
|
||||||
|
"$ref": "#/$defs/tenancy"
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"$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."
|
||||||
|
},
|
||||||
|
"evidence": {
|
||||||
|
"$ref": "#/$defs/evidence"
|
||||||
|
},
|
||||||
|
"notes": {
|
||||||
|
"$ref": "#/$defs/stringList"
|
||||||
|
},
|
||||||
"services": {
|
"services": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"minItems": 1,
|
"minItems": 1,
|
||||||
"items": {"$ref": "#/$defs/service"}
|
"items": {
|
||||||
|
"$ref": "#/$defs/service"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
{
|
{
|
||||||
"required": ["service", "role", "tenancy"],
|
"required": [
|
||||||
"not": {"required": ["services"]}
|
"service",
|
||||||
|
"role",
|
||||||
|
"tenancy"
|
||||||
|
],
|
||||||
|
"not": {
|
||||||
|
"required": [
|
||||||
|
"services"
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"required": ["services"],
|
"required": [
|
||||||
"not": {"anyOf": [
|
"services"
|
||||||
{"required": ["service"]},
|
],
|
||||||
{"required": ["role"]},
|
"not": {
|
||||||
{"required": ["tenancy"]},
|
"anyOf": [
|
||||||
{"required": ["provider"]},
|
{
|
||||||
{"required": ["evidence"]}
|
"required": [
|
||||||
]}
|
"service"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"role"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"tenancy"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"provider"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"evidence"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
|
@ -42,24 +99,65 @@
|
||||||
"pattern": "^[a-z0-9][a-z0-9._-]*$"
|
"pattern": "^[a-z0-9][a-z0-9._-]*$"
|
||||||
},
|
},
|
||||||
"axisName": {
|
"axisName": {
|
||||||
"enum": ["I", "A", "E", "P", "R", "V"]
|
"enum": [
|
||||||
|
"I",
|
||||||
|
"A",
|
||||||
|
"E",
|
||||||
|
"P",
|
||||||
|
"R",
|
||||||
|
"V"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"level": {
|
"level": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
{"type": "integer", "minimum": 0, "maximum": 4},
|
{
|
||||||
{"const": "n/a"}
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"const": "n/a"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"axisVector": {
|
"axisVector": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["I", "A", "E", "P", "R", "V"],
|
"required": [
|
||||||
|
"I",
|
||||||
|
"A",
|
||||||
|
"E",
|
||||||
|
"P",
|
||||||
|
"R",
|
||||||
|
"V"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"I": {"oneOf": [{"type": "integer", "minimum": 0, "maximum": 3}, {"const": "n/a"}]},
|
"I": {
|
||||||
"A": {"$ref": "#/$defs/level"},
|
"oneOf": [
|
||||||
"E": {"$ref": "#/$defs/level"},
|
{
|
||||||
"P": {"$ref": "#/$defs/level"},
|
"type": "integer",
|
||||||
"R": {"$ref": "#/$defs/level"},
|
"minimum": 0,
|
||||||
"V": {"$ref": "#/$defs/level"}
|
"maximum": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"const": "n/a"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"A": {
|
||||||
|
"$ref": "#/$defs/level"
|
||||||
|
},
|
||||||
|
"E": {
|
||||||
|
"$ref": "#/$defs/level"
|
||||||
|
},
|
||||||
|
"P": {
|
||||||
|
"$ref": "#/$defs/level"
|
||||||
|
},
|
||||||
|
"R": {
|
||||||
|
"$ref": "#/$defs/level"
|
||||||
|
},
|
||||||
|
"V": {
|
||||||
|
"$ref": "#/$defs/level"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
|
|
@ -67,97 +165,214 @@
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"minProperties": 1,
|
"minProperties": 1,
|
||||||
"properties": {
|
"properties": {
|
||||||
"I": {"oneOf": [{"type": "integer", "minimum": 0, "maximum": 3}, {"const": "n/a"}]},
|
"I": {
|
||||||
"A": {"$ref": "#/$defs/level"},
|
"oneOf": [
|
||||||
"E": {"$ref": "#/$defs/level"},
|
{
|
||||||
"P": {"$ref": "#/$defs/level"},
|
"type": "integer",
|
||||||
"R": {"$ref": "#/$defs/level"},
|
"minimum": 0,
|
||||||
"V": {"$ref": "#/$defs/level"}
|
"maximum": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"const": "n/a"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"A": {
|
||||||
|
"$ref": "#/$defs/level"
|
||||||
|
},
|
||||||
|
"E": {
|
||||||
|
"$ref": "#/$defs/level"
|
||||||
|
},
|
||||||
|
"P": {
|
||||||
|
"$ref": "#/$defs/level"
|
||||||
|
},
|
||||||
|
"R": {
|
||||||
|
"$ref": "#/$defs/level"
|
||||||
|
},
|
||||||
|
"V": {
|
||||||
|
"$ref": "#/$defs/level"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"stringMap": {
|
"stringMap": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": {"type": "string", "minLength": 1}
|
"additionalProperties": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"stringList": {
|
"stringList": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {"type": "string", "minLength": 1}
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"paths": {
|
"paths": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"propertyNames": {"$ref": "#/$defs/axisName"},
|
"propertyNames": {
|
||||||
|
"$ref": "#/$defs/axisName"
|
||||||
|
},
|
||||||
"additionalProperties": {
|
"additionalProperties": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"minProperties": 1,
|
"minProperties": 1,
|
||||||
"additionalProperties": {"$ref": "#/$defs/level"}
|
"additionalProperties": {
|
||||||
|
"$ref": "#/$defs/level"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"placementException": {
|
"placementException": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["tenants", "P", "reason"],
|
"required": [
|
||||||
|
"tenants",
|
||||||
|
"P",
|
||||||
|
"reason"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"tenants": {"$ref": "#/$defs/stringList"},
|
"tenants": {
|
||||||
"P": {"type": "integer", "minimum": 0, "maximum": 4},
|
"$ref": "#/$defs/stringList"
|
||||||
"reason": {"type": "string", "minLength": 1},
|
},
|
||||||
"tier_ref": {"type": "string", "minLength": 1}
|
"P": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 4
|
||||||
|
},
|
||||||
|
"reason": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"tier_ref": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"tenancy": {
|
"tenancy": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["current", "target", "reviewed", "review_due", "service_class"],
|
"required": [
|
||||||
|
"current",
|
||||||
|
"target",
|
||||||
|
"reviewed",
|
||||||
|
"review_due",
|
||||||
|
"service_class"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"current": {"$ref": "#/$defs/axisVector"},
|
"current": {
|
||||||
"implemented": {"$ref": "#/$defs/partialAxisVector"},
|
"$ref": "#/$defs/axisVector"
|
||||||
"target": {"$ref": "#/$defs/axisVector"},
|
},
|
||||||
"reviewed": {"type": "string", "format": "date"},
|
"implemented": {
|
||||||
"review_due": {"type": "string", "format": "date"},
|
"$ref": "#/$defs/partialAxisVector"
|
||||||
"service_class": {"enum": ["latency-critical", "interactive", "batch"]},
|
},
|
||||||
|
"target": {
|
||||||
|
"$ref": "#/$defs/axisVector"
|
||||||
|
},
|
||||||
|
"reviewed": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date"
|
||||||
|
},
|
||||||
|
"review_due": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date"
|
||||||
|
},
|
||||||
|
"service_class": {
|
||||||
|
"enum": [
|
||||||
|
"latency-critical",
|
||||||
|
"interactive",
|
||||||
|
"batch"
|
||||||
|
]
|
||||||
|
},
|
||||||
"permanent": {
|
"permanent": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"uniqueItems": true,
|
"uniqueItems": true,
|
||||||
"items": {"$ref": "#/$defs/axisName"}
|
"items": {
|
||||||
|
"$ref": "#/$defs/axisName"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"reason": {
|
||||||
|
"$ref": "#/$defs/stringMap"
|
||||||
|
},
|
||||||
|
"gap": {
|
||||||
|
"$ref": "#/$defs/stringMap"
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"$ref": "#/$defs/paths"
|
||||||
},
|
},
|
||||||
"reason": {"$ref": "#/$defs/stringMap"},
|
|
||||||
"gap": {"$ref": "#/$defs/stringMap"},
|
|
||||||
"paths": {"$ref": "#/$defs/paths"},
|
|
||||||
"placement_exceptions": {
|
"placement_exceptions": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {"$ref": "#/$defs/placementException"}
|
"items": {
|
||||||
|
"$ref": "#/$defs/placementException"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"secondary_stores": {"$ref": "#/$defs/stringList"}
|
"secondary_stores": {
|
||||||
|
"$ref": "#/$defs/stringList"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"providerAxis": {
|
"providerAxis": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["available", "maximum"],
|
"required": [
|
||||||
|
"available",
|
||||||
|
"maximum"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"available": {"$ref": "#/$defs/level"},
|
"available": {
|
||||||
"maximum": {"$ref": "#/$defs/level"},
|
"$ref": "#/$defs/level"
|
||||||
"conditions": {"$ref": "#/$defs/stringList"},
|
},
|
||||||
"evidence": {"$ref": "#/$defs/stringList"},
|
"maximum": {
|
||||||
"reason": {"type": "string", "minLength": 1}
|
"$ref": "#/$defs/level"
|
||||||
|
},
|
||||||
|
"conditions": {
|
||||||
|
"$ref": "#/$defs/stringList"
|
||||||
|
},
|
||||||
|
"evidence": {
|
||||||
|
"$ref": "#/$defs/stringList"
|
||||||
|
},
|
||||||
|
"reason": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"provider": {
|
"provider": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["axes"],
|
"required": [
|
||||||
|
"axes"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"capability": {"type": "string", "minLength": 1},
|
"capability": {
|
||||||
"profile": {"type": "string", "minLength": 1},
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
"axes": {
|
"axes": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"minProperties": 1,
|
"minProperties": 1,
|
||||||
"properties": {
|
"properties": {
|
||||||
"I": {"$ref": "#/$defs/providerAxis"},
|
"I": {
|
||||||
"A": {"$ref": "#/$defs/providerAxis"},
|
"$ref": "#/$defs/providerAxis"
|
||||||
"E": {"$ref": "#/$defs/providerAxis"},
|
},
|
||||||
"P": {"$ref": "#/$defs/providerAxis"},
|
"A": {
|
||||||
"R": {"$ref": "#/$defs/providerAxis"},
|
"$ref": "#/$defs/providerAxis"
|
||||||
"V": {"$ref": "#/$defs/providerAxis"}
|
},
|
||||||
|
"E": {
|
||||||
|
"$ref": "#/$defs/providerAxis"
|
||||||
|
},
|
||||||
|
"P": {
|
||||||
|
"$ref": "#/$defs/providerAxis"
|
||||||
|
},
|
||||||
|
"R": {
|
||||||
|
"$ref": "#/$defs/providerAxis"
|
||||||
|
},
|
||||||
|
"V": {
|
||||||
|
"$ref": "#/$defs/providerAxis"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
|
|
@ -168,21 +383,43 @@
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": {
|
"additionalProperties": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
{"type": "string", "minLength": 1},
|
{
|
||||||
{"$ref": "#/$defs/stringList"}
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/$defs/stringList"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"service": {
|
"service": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["service", "role", "tenancy"],
|
"required": [
|
||||||
|
"service",
|
||||||
|
"role",
|
||||||
|
"tenancy"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"service": {"$ref": "#/$defs/serviceName"},
|
"service": {
|
||||||
"role": {"type": "string", "minLength": 1},
|
"$ref": "#/$defs/serviceName"
|
||||||
"tenancy": {"$ref": "#/$defs/tenancy"},
|
},
|
||||||
"provider": {"$ref": "#/$defs/provider"},
|
"role": {
|
||||||
"evidence": {"$ref": "#/$defs/evidence"},
|
"type": "string",
|
||||||
"notes": {"$ref": "#/$defs/stringList"}
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"tenancy": {
|
||||||
|
"$ref": "#/$defs/tenancy"
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"$ref": "#/$defs/provider"
|
||||||
|
},
|
||||||
|
"evidence": {
|
||||||
|
"$ref": "#/$defs/evidence"
|
||||||
|
},
|
||||||
|
"notes": {
|
||||||
|
"$ref": "#/$defs/stringList"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,11 @@ domain: netkingdom
|
||||||
status: proposed
|
status: proposed
|
||||||
version: "0.1"
|
version: "0.1"
|
||||||
created: "2026-08-17"
|
created: "2026-08-17"
|
||||||
updated: "2026-08-17"
|
updated: "2026-08-19"
|
||||||
scope: multi-tenancy-security-framework
|
scope: multi-tenancy-security-framework
|
||||||
revision: "draft-8"
|
revision: "draft-9"
|
||||||
owner: net-kingdom
|
owner: net-kingdom
|
||||||
last_reviewed: "2026-08-17"
|
last_reviewed: "2026-08-19"
|
||||||
review_interval: 6m
|
review_interval: 6m
|
||||||
declaration_schema: canon/schemas/tenancy-posture_v0.1.schema.json
|
declaration_schema: canon/schemas/tenancy-posture_v0.1.schema.json
|
||||||
adr:
|
adr:
|
||||||
|
|
@ -28,7 +28,7 @@ related:
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
**Proposed, draft-8; ratification-ready.** Relocated from
|
**Proposed, draft-9; ratification-ready.** Relocated from
|
||||||
`the-custodian/canon/architecture` on
|
`the-custodian/canon/architecture` on
|
||||||
2026-08-17: multi-tenancy is part of the IT-security framework NetKingdom
|
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
|
provides, so this framework belongs in NetKingdom canon beside the IAM Profile
|
||||||
|
|
@ -59,6 +59,12 @@ and the tenant-engine boundary contract, not in the work-factory canon.
|
||||||
customer language. It also corrects the distinction between an implemented
|
customer language. It also corrects the distinction between an implemented
|
||||||
control and an evidenced current level.
|
control and an evidenced current level.
|
||||||
|
|
||||||
|
- **draft-9** answers `zone-engine`'s `ZONE-WP-0001-T01`. It rules that
|
||||||
|
enforcement stance is **not** a seventh axis (Decision 5.6) while reserving
|
||||||
|
`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).
|
||||||
|
|
||||||
**Reviewed by all six. The score:** six repos found three live defects in their
|
**Reviewed by all six. The score:** six repos found three live defects in their
|
||||||
own code by reading the ladders — `tenant-engine`'s unfiltered
|
own code by reading the ladders — `tenant-engine`'s unfiltered
|
||||||
event accessor, `audit-core`'s unfiltered read path, `flex-auth`'s
|
event accessor, `audit-core`'s unfiltered read path, `flex-auth`'s
|
||||||
|
|
@ -583,6 +589,67 @@ it.
|
||||||
A provider's own `P` is `n/a`, not a number. `apps-pg` *provides* `P1`; it is
|
A provider's own `P` is `n/a`, not a number. `apps-pg` *provides* `P1`; it is
|
||||||
not *at* `P1`, and writing `P: 1` there would later read as an isolation claim.
|
not *at* `P1`, and writing `P: 1` there would later read as an isolation claim.
|
||||||
|
|
||||||
|
**Decision 5.6 — enforcement stance is not a seventh axis, and `zones:` is
|
||||||
|
reserved in this file.** `zone-engine` asked whether *enforcement stance* —
|
||||||
|
whether a given control is enforced, advisory or exempt in a given band of the
|
||||||
|
estate — should fold in here rather than become a second standard. It should
|
||||||
|
not, for a reason that is structural rather than territorial.
|
||||||
|
|
||||||
|
**Every one of the six ladders is monotone: higher is stronger, and higher is
|
||||||
|
what a service wants.** That assumption is load-bearing throughout. §12's
|
||||||
|
*improve* step moves a service up. §12's *guard* checks that none is below what
|
||||||
|
it declared. §6 has to make a special allowance for a level that is
|
||||||
|
*permanently* low by design, and §12's guard is told not to nag it — the
|
||||||
|
allowance exists because low-is-normal is the exception here.
|
||||||
|
|
||||||
|
Enforcement stance is not monotone. The correct stance for a bootstrap lane is
|
||||||
|
deliberately and permanently *below* the top rung, and the top rung is
|
||||||
|
sometimes the wrong answer outright: `ops-warden`'s `ADR-0006` is exactly the
|
||||||
|
finding that a fail-closed authorization gate on the SSH lane the tunnels
|
||||||
|
depend on is not a stronger position, it is an outage. A ladder whose top is
|
||||||
|
sometimes wrong is an enumeration, not a ladder, and putting one inside this
|
||||||
|
vector would break `current`/`target`/`gap`, the guard, and §6 for the six that
|
||||||
|
are.
|
||||||
|
|
||||||
|
§8.3 already refused an axis for a weaker reason than this one — that a QoS
|
||||||
|
level would be an unenforced claim. Enforcement stance *is* enforced. It fails
|
||||||
|
the other half of the same test.
|
||||||
|
|
||||||
|
There is a second, sharper reason. §6's conformance rule is *accuracy, not
|
||||||
|
altitude*, and it works because this framework is **descriptive**: it never
|
||||||
|
blocks anything by itself. Prescription enters only through §11 and Decision
|
||||||
|
8.2, where a **requirer** — never the declaring repo — sets a minimum level and
|
||||||
|
the two are machine-reconciled. Enforcement stance is prescriptive by nature.
|
||||||
|
Fold it in as an axis and an accurately declared `exempt` becomes conformant
|
||||||
|
*and* exempt: a conformance rule that hands out the exemption it exists to
|
||||||
|
audit. The declarer must not be the party that sets the stance.
|
||||||
|
|
||||||
|
So the split is the one `flex-auth` already argued to `zone-engine`:
|
||||||
|
**membership is data and is declared; stance is a rule and belongs to the
|
||||||
|
control's owner.** Membership is posture-shaped and behaves like a level.
|
||||||
|
Stance behaves like a tier minimum under Decision 8.2 — asserted elsewhere,
|
||||||
|
joined by machine.
|
||||||
|
|
||||||
|
**What canon rules, and it is binding on the sibling standard:**
|
||||||
|
|
||||||
|
- A security-zone standard is a **separate document** in this family, drafted
|
||||||
|
by `zone-engine` and published in NetKingdom canon beside this one and the
|
||||||
|
`*-engine` boundary contracts. It carries over §6 verbatim and §13's evidence
|
||||||
|
discipline.
|
||||||
|
- **Zone membership is declared in `tenancy.yaml`**, under a reserved top-level
|
||||||
|
`zones:` key, sibling to `tenancy:` and `provider:` — *not* inside
|
||||||
|
`tenancy.current`. Decision 5.4 makes this file the repo's single posture
|
||||||
|
declaration surface, and a second root file would recreate the divergence
|
||||||
|
§5.4 was written to end. One file, one review cadence, one validator; two
|
||||||
|
standards, because the two have different owners and different conformance
|
||||||
|
semantics.
|
||||||
|
- `organization_posture` (`ops-warden` WP-0029) does **not** belong in this
|
||||||
|
file at all, under either key. It is a fleet-wide, time-varying scalar
|
||||||
|
describing the estate, not a property of the declaring service, and a
|
||||||
|
per-repo copy of a global would go stale in as many places as there are
|
||||||
|
repos. It is an *input* to stance selection and should be read by the zone
|
||||||
|
model, not absorbed into a declaration.
|
||||||
|
|
||||||
Worked examples after applying the evidence rule and minimum-across-paths rule
|
Worked examples after applying the evidence rule and minimum-across-paths rule
|
||||||
consistently:
|
consistently:
|
||||||
|
|
||||||
|
|
@ -752,6 +819,46 @@ things, none of which is priority:
|
||||||
classes are co-resident. An unenforceable risk that nobody can see is strictly
|
classes are co-resident. An unenforceable risk that nobody can see is strictly
|
||||||
worse than one that is stated.
|
worse than one that is stated.
|
||||||
|
|
||||||
|
### 8.4 Substrate location is not evidence — and reefs are not reconciled with `P` or `V`
|
||||||
|
|
||||||
|
**Decision 8.4.1 — location is not evidence of any property of the workload on
|
||||||
|
it.** Three repos have now written this rule locally in three vocabularies:
|
||||||
|
`railiance-master`'s *topology is not readiness*, `zone-engine`'s *placement is
|
||||||
|
not posture*, and §3.1 here, which requires every use of "isolation" to name
|
||||||
|
its axis. They are one rule. Stated once: **the substrate a workload sits on is
|
||||||
|
never, by itself, evidence for a level on any ladder in this framework.**
|
||||||
|
Binding to a reef, being on a dedicated instance, or naming a rail proves
|
||||||
|
placement and nothing else. Other repos should cite this rather than restate
|
||||||
|
it.
|
||||||
|
|
||||||
|
**Decision 8.4.2 — the reef taxonomy and this framework are not reconciled, and
|
||||||
|
that is this document's defect.** `zone-engine` asked whether canon should
|
||||||
|
reconcile reefs with the posture axes, on the assumption that this was a scope
|
||||||
|
question for the zone model. It is not: the unreconciled pair is not
|
||||||
|
zone ↔ reef, it is **reef ↔ `P` and `V`**, and it belongs to canon.
|
||||||
|
|
||||||
|
`repo-manager` owns substrate placement (`reef-railiance`, `reef-storage`) with
|
||||||
|
an explicit residual-risk acceptance attached to a binding. §7 and §8 of this
|
||||||
|
document presuppose that placement is fully described by the `P` ladder. It is
|
||||||
|
not. `P` grades **tenant data isolation within a datastore**; a reef is a named
|
||||||
|
**compute substrate carrying an accepted residual risk**. The `P` ladder has no
|
||||||
|
rung meaning "single node, shared control plane, risk accepted", and inventing
|
||||||
|
one would be the fabrication §6 prohibits.
|
||||||
|
|
||||||
|
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
|
||||||
|
single-node with a shared control plane, which **caps `V` for every workload
|
||||||
|
bound to it** regardless of that workload's own replica count — which Decision
|
||||||
|
4.6.1 already says is not evidence. Nothing today joins the reef's facts to a
|
||||||
|
consumer's `V` declaration, so a rapp can declare `V2` accurately by its own
|
||||||
|
reading and be wrong by this document's own composition rule.
|
||||||
|
|
||||||
|
This is `railiance-platform`'s provider-declaration finding (Decision 5.5)
|
||||||
|
generalised one layer down. A reef is a **provider** and has nowhere to state
|
||||||
|
what it makes reachable. Tracked as `NK-WP-0027`; the fix is canon's, and the
|
||||||
|
zone model is not blocked on it.
|
||||||
|
|
||||||
The known escalation short of P2 is gateway-level prioritisation — ordering
|
The known escalation short of P2 is gateway-level prioritisation — ordering
|
||||||
submissions in a connection proxy by the requesting tenant's current
|
submissions in a connection proxy by the requesting tenant's current
|
||||||
consumption. It is real, it is where the industry puts this when it must, and
|
consumption. It is real, it is where the industry puts this when it must, and
|
||||||
|
|
|
||||||
82
workplans/NK-WP-0027-reef-placement-reconciliation.md
Normal file
82
workplans/NK-WP-0027-reef-placement-reconciliation.md
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
---
|
||||||
|
id: NK-WP-0027
|
||||||
|
type: workplan
|
||||||
|
title: "Reconcile the reef taxonomy with the P and V ladders"
|
||||||
|
domain: infotech
|
||||||
|
repo: net-kingdom
|
||||||
|
status: proposed
|
||||||
|
owner: net-kingdom
|
||||||
|
topic_slug: netkingdom
|
||||||
|
planning_priority: P2
|
||||||
|
created: "2026-08-19"
|
||||||
|
updated: "2026-08-19"
|
||||||
|
---
|
||||||
|
|
||||||
|
# NK-WP-0027 — Reefs, placement, and what a substrate makes reachable
|
||||||
|
|
||||||
|
Raised by answering `zone-engine`'s `ZONE-WP-0001-T01`. `zone-engine` asked
|
||||||
|
whether canon should reconcile security zones with reefs, expecting the answer
|
||||||
|
to enlarge *its* scope. It does not: a zone is genuinely not a reef, and
|
||||||
|
`zone-engine` should keep *placement is not posture* and move on. The
|
||||||
|
unreconciled pair is **reef ↔ `P` and `V` in `tenancy-posture_v0.1`**, and it
|
||||||
|
is this repo's defect, recorded as Decision 8.4.2 in draft-9.
|
||||||
|
|
||||||
|
`repo-manager` owns substrate placement (`reef-railiance`, `reef-storage`) with
|
||||||
|
residual-risk acceptance attached to a binding. §7 and §8 of the standard
|
||||||
|
presuppose placement is fully described by the `P` ladder. `P` grades tenant
|
||||||
|
data isolation *within a datastore*; a reef is a named compute substrate
|
||||||
|
carrying an accepted residual risk. There is no rung for "single node, shared
|
||||||
|
control plane, risk accepted", and there should not be one — inventing it is
|
||||||
|
the fabrication §6 prohibits.
|
||||||
|
|
||||||
|
The live consequence is on `V`. Decision 4.6.1 makes `V` the minimum across the
|
||||||
|
synchronous path and says a replica count is not evidence. `reef-railiance` is
|
||||||
|
single-node with a shared control plane and therefore caps `V` for everything
|
||||||
|
bound to it. Nothing joins those facts today, so a rapp can declare `V2`
|
||||||
|
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.
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: NK-WP-0027-T01
|
||||||
|
status: todo
|
||||||
|
priority: medium
|
||||||
|
```
|
||||||
|
|
||||||
|
**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.
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: NK-WP-0027-T02
|
||||||
|
status: todo
|
||||||
|
priority: medium
|
||||||
|
```
|
||||||
|
|
||||||
|
**Extend Decision 5.5's provider declaration to substrate providers, and agree
|
||||||
|
it with `repo-manager`.** A reef should state, per axis it bounds, the maximum
|
||||||
|
level it makes reachable and what a consumer must do to reach it — the same
|
||||||
|
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.
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: NK-WP-0027-T03
|
||||||
|
status: wait
|
||||||
|
priority: low
|
||||||
|
```
|
||||||
|
|
||||||
|
**Join reef ceilings to consumer `V` declarations mechanically.** Waits on T02.
|
||||||
|
Decision 8.2's pattern applies — the requirer asserts, the declarer declares,
|
||||||
|
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.
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- `canon/standards/tenancy-posture_v0.1.md` Decisions 4.6.1, 5.5, 8.4.1, 8.4.2
|
||||||
|
- `repo-manager/docs/RailianceAppDeploymentGuide.md` — reefs, `bound_reefs`
|
||||||
|
- `railiance-master/docs/adr/ADR-0006-reef-production-admission.md` — topology
|
||||||
|
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
|
||||||
Loading…
Add table
Add a link
Reference in a new issue