From 26e3490c9bb0ac4c0c9524cd50bb74e4116f4cc4 Mon Sep 17 00:00:00 2001 From: tegwick Date: Thu, 20 Aug 2026 07:17:04 +0200 Subject: [PATCH] Correct T02's "no join key": the workload side exists in rapp declarations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit T02 concluded no registry carries a lane-to-workload join key. Too strong — it was derived from ops-warden's catalog alone, which is the one place a workload declaration would not live. rapp-*/declarations/rapp.yaml declares workload_identity with data_classification, criticality, readiness_state and bound_reefs for nine workloads. ops-warden's dataclass_floor already maps synthetic/internal/ confidential/restricted to M0-M3. So workload -> classification -> minimum maturity is a shared vocabulary spanning two repos already, and it is the operator's maturity-derived default half-implemented by accident. criticality is the other half and no control reads it yet. Three real defects replace the blocking unknown: the lane-to-workload key is only derivable by parsing path_template, whose convention is inconsistent (rapp-qonto/keycape-client parses a bundle as a workload) and whose names disagree with workload_identity.name; rapps declare "public" which dataclass_floor does not map; and nine declared workloads do not cover ~17 catalog path identities. Consequence for ownership: zone-engine does not need to build a workload registry. It consumes rapp declarations plus dataclass_floor, and asks ops-warden for one explicit field. Co-Authored-By: Claude Opus 5 --- docs/estate-partition-2026-08-19.md | 13 ++++-- workplans/ZONE-WP-0001-security-zone-model.md | 43 +++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/docs/estate-partition-2026-08-19.md b/docs/estate-partition-2026-08-19.md index 684932d..d46646f 100644 --- a/docs/estate-partition-2026-08-19.md +++ b/docs/estate-partition-2026-08-19.md @@ -212,9 +212,16 @@ still predict where danger concentrates. What they cannot do is name the entity policy applies to, because ops-warden's catalog contains no workloads. The missing join found in §4 is therefore not a tidy-up. **It is the model.** -Until something declares which workload consumes which lane, there is no subject -to attach a standard to — and `M0`–`M3` already grades workloads, which is the -side of the join that exists. + +> **Corrected 2026-08-20.** "No registry carries a join key" was too strong — it +> was concluded from ops-warden's catalog alone, the one place a *workload* +> declaration would not live. `rapp-*/declarations/rapp.yaml` declares +> `workload_identity` with `data_classification` and `criticality` for nine +> workloads, and ops-warden's `dataclass_floor` already maps classification to +> `M0`–`M3`. The chain exists and spans two repos. What is genuinely missing is +> an explicit `workload:` field on catalog entries — the key is currently only +> derivable by parsing `path_template`, whose convention is inconsistent. See +> `ZONE-WP-0001-T03`. ### Build stage diff --git a/workplans/ZONE-WP-0001-security-zone-model.md b/workplans/ZONE-WP-0001-security-zone-model.md index 05f3341..0d79012 100644 --- a/workplans/ZONE-WP-0001-security-zone-model.md +++ b/workplans/ZONE-WP-0001-security-zone-model.md @@ -332,6 +332,49 @@ anything declaring which workload consumes which lane. T03 cannot produce a usable stance model until that is answered, and the honest answer may be that it belongs to whatever declares workloads — not to this repo. +**Corrected 2026-08-20 — the workload side exists, and most of the join with +it.** T02 concluded no registry carries a join key. That was too strong; it was +derived from ops-warden's catalog alone, which is the one place a workload +declaration would *not* live. + +`rapp-*/declarations/rapp.yaml` is the workload declaration surface. **Nine** +rapps declare `workload_identity` (`name`, `principal`, `service_account`, +`tenant`) together with `data_classification`, `criticality` +(`low`/`medium`/`high`/`critical`), `readiness_state`, and `bound_reefs`. + +And the chain to maturity is already complete: ops-warden's +`registry/policy/security-posture.yaml` carries `dataclass_floor`, mapping +`synthetic→M0, internal→M1, confidential→M2, restricted→M3`. So +**workload → `data_classification` → minimum maturity** is a shared vocabulary +that spans two repos today, with nobody having built it for this purpose. That +is the operator's maturity-derived default, already half-implemented. + +`criticality` is the other half — it is exactly the "critical if the context is +critical" axis, declared per workload, and untouched by any control so far. + +Three defects in the join, which are now T03's actual work rather than a +blocking unknown: + +1. **The lane→workload key is derivable but fragile.** `path_template` encodes + `platform/workloads///` for most lanes — but the + convention is inconsistent: `platform/workloads/rapp-qonto/keycape-client` + has one level fewer, so parsing yields `keycape-client` as a "workload" when + it is a bundle. And the names do not agree: that path says `rapp-qonto` while + the rapp declares `workload_identity.name: qonto`. **Recommendation: add an + explicit `workload:` field to catalog entries.** Inferring identity by + parsing a path string is precisely the implicit coupling that breaks quietly. +2. **Vocabulary mismatch.** rapps declare `public`, which `dataclass_floor` does + not map. `rapp-policy-nexus` is `public` today, so the floor cannot grade it. + One of the two vocabularies must move; canon owns `DataClassification`. +3. **Coverage is partial.** Nine workloads are declared; ops-warden's catalog + yields ~17 distinct path identities. The unmatched remainder is the + interesting set — it is where a lane exists for something that is not a + declared workload at all. + +This reopens the ownership question favourably: zone-engine does **not** need to +build a workload registry. It needs to consume `rapp` declarations and ops-warden's +`dataclass_floor`, and to ask ops-warden for one explicit field. + **Build stage is a positional fact, not a concession.** The organization is in `build`; the default stance is permissive and zones tighten by *admission*, rather than by raising a global floor. That is what makes this model compatible