Eleven findings (R1-R11) on net-kingdom's proposed SecurityCaseType oidc-service-client 0.1 for request f61cc81e: type changes R3, R4, R6, R7, R8; ops-mason builder follow-ups R10; rollback addition R11. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 5502@bnt-lap001 Assistant-Session: 68b3b02f-5d0f-4e71-8421-796f62e50196
389 lines
22 KiB
Markdown
389 lines
22 KiB
Markdown
---
|
|
id: MASON-WP-0010
|
|
type: workplan
|
|
title: "Materialize SecurityCases from their type, with acceptance as the only gate"
|
|
domain: infotech
|
|
repo: ops-mason
|
|
status: blocked
|
|
flavor: implementation
|
|
owner: claude-code
|
|
topic_slug: netkingdom
|
|
created: "2026-10-08"
|
|
updated: "2026-10-31"
|
|
depends_on: []
|
|
related_repos:
|
|
- net-kingdom
|
|
- ops-warden
|
|
- railiance-platform
|
|
state_hub_workstream_id: "eabf2c39-94bd-5a11-8f2e-76d7a95d1583"
|
|
---
|
|
|
|
# MASON-WP-0010 — Materialize SecurityCases from their type, with acceptance as the only gate
|
|
|
|
## Why
|
|
|
|
NetKingdom is introducing SecurityCaseTypes (net-kingdom `NK-WP-0048`, canon
|
|
`security-case-types_v0.1`, proposed). A type is designed once, with
|
|
documentation, tests and an informed-decision. Each case of an implemented type
|
|
is then light: it is accepted, ops-mason arranges it, and ops-warden follows
|
|
through.
|
|
|
|
ops-mason's four phases (construction plan, review, executive summary, build)
|
|
stay exactly as they are for **new types and for structure that no type
|
|
covers**. For a **KnownSecurityCase**, the construction plan is rendered from
|
|
the type's materialization templates, and the executive-summary gate collapses
|
|
to the case acceptance, because the shape was decided when the type was
|
|
acknowledged.
|
|
|
|
MASON-WP-0009 (a hand-built placement of a key-cape client secret) is the kind
|
|
of work this replaces. It becomes a reference instance for the first type.
|
|
|
|
## Tasks
|
|
|
|
```task
|
|
id: MASON-WP-0010-T01
|
|
status: done
|
|
depends_on: [NK-WP-0048-T03]
|
|
priority: high
|
|
state_hub_task_id: "3382ea7b-65ca-59a9-97ae-273455af44c2"
|
|
```
|
|
|
|
### T01 — Define the type's materialization section
|
|
|
|
Propose the `materialization` part of the SecurityCaseType schema together with
|
|
net-kingdom: policy, role, KV path structure and catalog-entry templates over
|
|
case parameters, with naming rules. These must respect ops-mason's existing
|
|
"respect, extend or compact before adding" review, so that a type cannot
|
|
template sprawl. Write it for the first type, `oidc-browser-relying-party`, from
|
|
MASON-WP-0009 and the existing key-cape client custody paths.
|
|
|
|
**Review (2026-10-08) of net-kingdom `security-case-types/oidc-browser-relying-party/type.yaml` 1.0.**
|
|
The structure (four items, all but the catalog entry conditional on
|
|
`confidential`) is right. The names add three new families where existing ones
|
|
cover the need, so they fail "respect, extend or compact before adding".
|
|
Requested refinements, each from the live CCR-2026-0033 placement
|
|
(`plans/keycape-secrets-engine-openbao-client-custody.md`):
|
|
|
|
1. **Fix the path in the type.** `secret_ref` should not be case-settable; a
|
|
free pattern under `platform/workloads/` lets every case pick its own layout.
|
|
Derive it: `platform/workloads/keycape/{client_id}` (field `CLIENT_SECRET`),
|
|
as for `secrets-engine-openbao`.
|
|
2. **Reuse the policy family.** Existing readers are
|
|
`workload-kv-read-keycape-<client>-<reader>`. Rename
|
|
`keycape-client-{client_id}-read` to `workload-kv-read-keycape-{client_id}-eso`
|
|
(KeyCape reads its client secret only through ESO), and
|
|
`{consuming_service}-oidc-client-{client_id}-read` to
|
|
`workload-kv-read-keycape-{client_id}-{consuming_service}`. Update
|
|
verification `custody-allowed-to-consumer` and rollback to match.
|
|
3. **Template the policy body, not just its name.** An `openbao_policy` item
|
|
needs its rules (`read` on `platform/data/workloads/keycape/{client_id}`,
|
|
nothing else: no metadata, list, parent or sibling), or the review cannot
|
|
check invariant (ii) and a rendered plan is not buildable.
|
|
4. **Add the missing ESO role.** `deliver-secret` needs a Kubernetes-auth role
|
|
`external-secrets-keycape-{client_id}` (kind `openbao_role`, bound to the
|
|
ESO service account, policy from item 2, 15m TTL, no default policy), as
|
|
the reference placement has.
|
|
5. **Catalog naming.** The one existing entry is `rapp-qonto-keycape-client`;
|
|
prefer `{consuming_service}-keycape-client` over `oidc-client-{client_id}`.
|
|
6. **Rollback order.** `mint-secret` "destroy" and `client-secret-path`
|
|
"remove" act on the same KV path; collapse to one step (metadata delete
|
|
after the ExternalSecret is gone) so rollback cannot fail on a missing path.
|
|
|
|
With 1-4 applied, the section is acceptable to ops-mason for NK-WP-0048-T05.
|
|
|
|
2026-10-08: net-kingdom folded in all six (net-kingdom `074b3a0`, message
|
|
`508e2a12`); its schema/validator now require a body on policy and role items.
|
|
NK-WP-0048-T05 still waits on WARDEN-WP-0044-T01 and a founder answer.
|
|
|
|
2026-10-09: the founder accepted memo r4; hub decision `e418263e` resolved and
|
|
the type is `acknowledged` (net-kingdom `0e86f95`). T02 is unblocked.
|
|
|
|
**Review (2026-10-31) of net-kingdom `security-case-types/oidc-service-client/type.yaml` 0.1**
|
|
(proposed, net-kingdom `5d5f15d`, memo `nk-wp-0056-t14-oidc-service-client-r1`,
|
|
hub decision `f8044f81`, request message `f61cc81e`). Checked against the
|
|
browser type 1.1, the live CCR-2026-0041/0042 placement and the bounded
|
|
executor's native lanes CCR-2026-0058/0059, and by a trial render of
|
|
`examples/nk-bind-executor-approval.yaml` through `case_plan.render` and
|
|
`case_build` on a scratch copy marked `acknowledged` (no live survey, no
|
|
OpenBao). All six items render; names come out as
|
|
`workload-kv-read-keycape-nk-bind-executor-approval-{eso,bounded-executor}`,
|
|
`external-secrets-keycape-nk-bind-executor-approval` and catalog entry
|
|
`bounded-executor-keycape-nk-bind-executor-approval`.
|
|
|
|
Verdict: **acceptable with changes.** The structure is right and reuses the
|
|
browser type's custody, ESO and policy families. R3, R4, R6, R7 and R8 change
|
|
the type (so memo r2 replaces r1); R10 is ops-mason's own builder work and does
|
|
not block acknowledgment, but must land before the first case is built.
|
|
|
|
- **R1 — client-secret-path: ok.** Derived, not case-settable, same
|
|
`platform/workloads/keycape/{client_id}` / `CLIENT_SECRET` as the browser type
|
|
and CCR-2026-0033. Unconditional (the type is always confidential), so no
|
|
`when`. `client_id` is unique in KeyCape, so browser and service clients
|
|
cannot collide in the one `keycape/` subtree.
|
|
- **R2 — keycape-reader-policy and naming family: ok.** Unchanged from the
|
|
browser type; `workload-kv-read-keycape-<client>-<reader>` is respected for
|
|
both readers. Longest rendered name is 68 characters, within OpenBao limits.
|
|
- **R3 — eso-role: change needed (small).** Bound to
|
|
`external-secrets/external-secrets`, one policy, 15m, no default policy:
|
|
right. But the body omits `audience: openbao` and `token_explicit_max_ttl:
|
|
15m`, which the consumer role states and the live
|
|
`external-secrets-keycape-forgejo` role has; ops-mason's builder fills them
|
|
in silently today. Add both so the template is what gets built, and the two
|
|
roles read the same.
|
|
- **R4 — consumer-reader-policy self-lifecycle stanzas: change needed.** The
|
|
`auth/token/lookup-self` (read) and `auth/token/revoke-self` (update) stanzas
|
|
are correct and needed (a native per-call reader should revoke its token
|
|
after the read, and the platform applier refuses a `token_self_lifecycle:
|
|
true` policy without them, see T04 2026-10-10). But only the consumer policy
|
|
declares them, while the ESO policy needs them equally. Declare them in
|
|
**both** policy bodies, so each body is the complete policy the review
|
|
checks (item 3 of the 1.0 review). ops-mason then stops appending them (R10).
|
|
- **R5 — consumer-reader-role (native Kubernetes auth): ok.** One
|
|
ServiceAccount, one namespace, audience `openbao`, 15m ttl/max/explicit max,
|
|
one policy, no default policy: this is exactly the CCR-2026-0058/0059 shape
|
|
that is live and verified for `sso/nk-bind-executor`, and "policies are never
|
|
combined in one role" holds (the executor gets a third separate role). Role
|
|
name equal to the policy name matches the native-lane convention. Dropping
|
|
ESO delivery to the consumer removes a Secret copy and a SecretStore per
|
|
case; ops-mason prefers it.
|
|
- **R6 — consumer binding parameters: change needed.** The patterns admit
|
|
`consumer_service_account: default` and namespaces such as
|
|
`external-secrets`, `openbao` or `kube-system`. Refuse `default` (any pod in
|
|
the namespace would read the client secret; CCR-2026-0059 verifies the
|
|
default SA is denied), and refuse the `external-secrets` and `openbao`
|
|
namespaces, in the type's constraints or the validator.
|
|
- **R7 — shared namespace with KeyCape's copy: change needed.** The first case
|
|
binds `sso/nk-bind-executor`, and `sso` is where `deliver-secret` writes
|
|
`keycape-{client_id}-client`. So "no Secret copy in the consumer's namespace"
|
|
(README, purpose) is false for this case; isolation rests on the consumer SA
|
|
having no Secret read in its namespace (true today: rapp-bounded-executor
|
|
`manifests/rbac.yaml` grants no Secret access). Add a verification:
|
|
`{consumer_namespace}/{consumer_service_account}` cannot get Secrets in its
|
|
namespace (in particular `sso/keycape-{client_id}-client`), `can-i` denial as
|
|
proof; and reword the README claim to "the type creates no Secret copy for
|
|
the consumer".
|
|
- **R8 — verification wording: change needed (small).**
|
|
`custody-allowed-to-consumer` says the policy grants read on the path "and
|
|
nothing else"; with R4 it also grants token self-lookup/revoke. Say "and no
|
|
other path under `platform/`, apart from token self-lifecycle". Optionally
|
|
add the same allow check for the ESO policy.
|
|
- **R9 — catalog-entry: ok, one question.** `{consuming_service}-keycape-{client_id}`
|
|
instead of the browser type's `{consuming_service}-keycape-client` is right:
|
|
a service holds one client per audience, so the browser form would collide.
|
|
Question: `consuming_service: bounded-executor` differs from the workload name
|
|
the platform already uses for this executor (`net-kingdom-bind-executor` in
|
|
CCR-2026-0058/0059 and their catalog ids). The case should use the
|
|
established name, or the type README should say which one `workload_ref`
|
|
carries.
|
|
- **R10 — ops-mason builder (ours, not a type change).** The trial build shows
|
|
four defects to fix before the first service-client case is built:
|
|
(a) `_policy_hcl` always appends the self-lifecycle stanzas, so the consumer
|
|
policy gets them twice; append only when absent. (b) A policy with a role is
|
|
treated as ESO: the consumer CCR gets `access_frontdoor.type:
|
|
external-secrets`; for a native role it must be `platform-owner` (as
|
|
CCR-2026-0059) with a `delivery: {surface: native-workload-login, namespace,
|
|
service_account}` block. (c) `catalog_id` is hard-coded to
|
|
`{consuming_service}-keycape-client`; take it from the catalog item.
|
|
(d) `audience` and `token_explicit_max_ttl` are hard-coded / copied from
|
|
`token_max_ttl`; take them from the role body (with R3). The consumer CCR is
|
|
no longer `in_flight`: with the role in the type it is complete `proposed`,
|
|
`bound_claims_confirmed: false` until the platform owner confirms the SA.
|
|
- **R11 — rollback order: ok, with one addition.** Consumer configuration,
|
|
registration, env binding, delivery, then custody (one metadata delete, after
|
|
the ExternalSecret is gone, per item 6 of the 1.0 review), roles before their
|
|
policies, catalog last: consistent with the browser type. Addition: deleting
|
|
the consumer role does not revoke issued tokens; state that rollback is
|
|
complete only after the consumer's last token has expired (at most 15m after
|
|
the role is deleted) or was revoked, as the T03 deactivate note does.
|
|
Suggested, not required: remove `consumer-reader-role` directly after
|
|
`hand-over` is reversed, so consumer access ends first. (ops-mason's own
|
|
`rollback.yaml` lists `removes_exactly` in plain reverse order, which differs
|
|
from the type's steps; fixed with R10.)
|
|
|
|
T04 is unchanged by this type: `secrets-engine-openbao`'s second reader is an
|
|
attended OIDC operator, not a ServiceAccount, so it fits neither type.
|
|
|
|
```task
|
|
id: MASON-WP-0010-T02
|
|
status: done
|
|
depends_on: [MASON-WP-0010-T01, NK-WP-0048-T05]
|
|
priority: high
|
|
state_hub_task_id: "fd385537-7378-5539-8a6e-f45851296f42"
|
|
```
|
|
|
|
### T02 — Render a construction plan from a case
|
|
|
|
`mason plan --case <case.yaml>` validates the case against its `implemented`
|
|
type, renders the construction plan from the type's templates, and runs the
|
|
existing consistency review against current OpenBao structure (read-only, no
|
|
values). The output is the usual plan, marked `derived-from-type`, plus the
|
|
case-acceptance reference in place of a fresh executive summary.
|
|
|
|
Tests: render the reference case; refuse a case whose type is not
|
|
`implemented`; refuse parameter values outside the type's validation; flag a
|
|
collision with existing structure.
|
|
|
|
2026-10-09 done: `ops-mason plan --case <case.yaml> [--out F] [--no-live]`
|
|
(`src/ops_mason/case_plan.py`). Validation and rendering are net-kingdom's own
|
|
`security_case_validator.py` (imported, not copied), with provider declarations
|
|
loaded through its composer. ops-mason adds the review against existing
|
|
structure: a read-only live survey (policy list, role lists, KV metadata,
|
|
ops-warden catalog ids) that fails loudly instead of returning an empty
|
|
structure, and flags each collision as a finding. Output is a construction
|
|
plan with `derived_from_type` and `render_digest`, and section 5 is the case
|
|
acceptance; status `reviewed` only when accepted and collision-free. Exit 0
|
|
clean, 1 collisions, 2 refused. `tests/test_case_plan.py` (8, on a copy of the
|
|
type marked `implemented`); suite 167 passed. The live Forgejo case is refused
|
|
today, correctly: the type is `acknowledged`, not yet `implemented`.
|
|
|
|
2026-10-09: net-kingdom accepted the Forgejo case
|
|
(`net-kingdom/security-cases/forgejo-netkingdom-oidc.yaml`, message `d1bbcb44`).
|
|
As the reference case it renders with `--allow-unimplemented`, mirroring the
|
|
validator's flag: allowed only for an `acknowledged` type, marked
|
|
`reference_case: true`; and `reviewed` now requires a live survey. Rendered
|
|
live into `plans/case-forgejo-netkingdom-oidc.md`: status `reviewed`, no
|
|
collision, digest `sha256:fb8b114d…`.
|
|
|
|
```task
|
|
id: MASON-WP-0010-T03
|
|
status: progress
|
|
depends_on: [MASON-WP-0010-T02]
|
|
blocked_on: message-from:railiance-platform
|
|
blocking_reason: "Typed exact structural evidence request is prepared. Native materialization waits on independently authenticated policy/role/layout/catalog observations and CCR42 consumer binding/application. Mint, delivery and first live verification are follow-through, not structural prerequisites."
|
|
priority: high
|
|
state_hub_task_id: "56cea6be-c613-586c-80cd-125340b374da"
|
|
```
|
|
|
|
### T03 — Build from an accepted case
|
|
|
|
`mason build --case <case.yaml>` builds a rendered plan when the case's
|
|
acceptance record is present, with no separate executive-summary approval. Its
|
|
audit trail names the case, the type version and the acceptance. It proposes the
|
|
pointer-only ops-warden catalog entries the type defines, as today. Rollback
|
|
removes exactly what this case created.
|
|
|
|
Acceptance: the Forgejo reference case (NK-WP-0048-T06) materializes through this
|
|
path.
|
|
|
|
2026-10-09: implemented. `ops-mason build --case <case> --plan <plan> [--out]
|
|
[--allow-unimplemented]` (`src/ops_mason/case_build.py`) refuses unless the
|
|
case is accepted, the plan is `reviewed` and its render digest equals a fresh
|
|
render. It writes a bundle and never touches OpenBao: one workload-kv-read CCR
|
|
draft per policy (ESO policy + Kubernetes role, mirroring CCR-2026-0033; the
|
|
consumer policy `in_flight` with `openbao.auth` missing until the consumer owner
|
|
binds it), the policy HCL, an ops-warden catalog proposal, `rollback.yaml`
|
|
(exactly what the case creates, reverse order) and a manifest with file hashes.
|
|
Every file names the case, type version, render digest and acceptance record;
|
|
the audit log gets a `case-build-prepared` record with the case acceptance as
|
|
approver. The drafts are checked with railiance-platform's own
|
|
`credential-change.py validate`. `tests/test_case_build.py` (6); suite 175
|
|
passed. Forgejo bundle built into `builds/case-forgejo-netkingdom-oidc/`,
|
|
platform validation pass; handed to railiance-platform (message `2c409503`).
|
|
|
|
```task
|
|
id: MASON-WP-0010-T04
|
|
status: wait
|
|
depends_on: [MASON-WP-0010-T03]
|
|
blocking_reason: "After T03, and only once a type fits: secrets-engine-openbao is a service (JWT) client, which oidc-browser-relying-party does not cover."
|
|
priority: medium
|
|
state_hub_task_id: "f6ad0d3c-8f47-5fdf-8115-6ca9d8a1fead"
|
|
```
|
|
|
|
### T04 — Adopt MASON-WP-0009 as a case
|
|
|
|
Once `oidc-browser-relying-party` (or the confidential service client type) is
|
|
implemented, express MASON-WP-0009's placement as a case of that type without
|
|
changing the live structure, and close the hand-built path.
|
|
|
|
2026-10-10 (T03): railiance-platform filed the drafts as CCR-2026-0041 (ESO
|
|
reader) and CCR-2026-0042 (consumer reader, in_flight until railiance-apps binds
|
|
it), messages `83465dcd`/`be3a762d`; the founder applied CCR-2026-0041 at
|
|
2026-10-09T18:09Z. Its review found a render defect: the CCRs declare
|
|
`token_self_lifecycle: true` but the policies lacked the lookup-self/revoke-self
|
|
stanzas, so the applier refused them. Fixed in `case_build.py` (test asserts
|
|
the three stanzas; output now equals the platform-generated policy apart from
|
|
comments) and in the committed bundle. Two follow-ups for the next render:
|
|
net-kingdom changed the type to `KEYCAPE_{client_id:env}_CLIENT_SECRET`
|
|
(ops-warden `23ba584`), so the render digest will change; and a live re-render
|
|
of a partly applied case will report its own objects as collisions. The KV
|
|
value waits on mint-secret (RPF-WP-0054).
|
|
|
|
2026-10-10 (T03 follow-up): `plan --case` now recognises objects listed in the
|
|
case's own committed bundle (`builds/case-<id>/rollback.yaml`, same case id) as
|
|
"already present from this case's own build", not collisions; anything else
|
|
existing still collides (2 tests, suite 177 passed). The committed Forgejo plan
|
|
is stale: net-kingdom's `{client_id:env}` change moves the render digest from
|
|
`fb8b114d…` to `5e97931e…`. Re-render it live under the next survey grant.
|
|
|
|
2026-10-10: Forgejo plan re-rendered live: `reviewed`, no collision, digest
|
|
`af1f4f81…`; policy `workload-kv-read-keycape-forgejo-eso` shown as already
|
|
present from this case's own bundle. The ESO role did not appear as present;
|
|
check on the next grant.
|
|
|
|
2026-10-10: checked. `auth/kubernetes/role/external-secrets-keycape-forgejo`
|
|
exists as applied (external-secrets/external-secrets, audience openbao, 15m,
|
|
policy `workload-kv-read-keycape-forgejo-eso`, no default policy). Why the plan's
|
|
"already present" list omitted it is not yet confirmed (the survey should list
|
|
`auth/kubernetes/role`); reproduce under the next grant. The collision review
|
|
is unaffected: it never flagged the role.
|
|
|
|
2026-10-10: type 1.1 (net-kingdom `e2174ce`, message `af66538c`) adds the
|
|
consumer-enforces-groups verification and tightens redirect URIs; the case is
|
|
re-pinned to @1.1. The live re-render above was already 1.1. Bundle rebuilt
|
|
from it (`builds/case-forgejo-netkingdom-oidc/`, platform validation pass);
|
|
the ESO policy is unchanged against the applied CCR-2026-0041, so 1.1 changes
|
|
no OpenBao object.
|
|
|
|
|
|
2026-10-11 accepted-architecture source implementation: materialization is
|
|
structure only under the already accepted canon; the stale mint-before-
|
|
materialization blocker is removed, not replaced by a fake status label.
|
|
`src/ops_mason/case_structure.py` and read-only `ops-mason structure-request`
|
|
validate a separate current structural projection against the hashed bundle
|
|
and prepare typed per-owner observations. Full execution drift remains visible:
|
|
35880bb adds --check-config to register-client, changing full render af1f4f81
|
|
→ e64b56e4 while materialization/composition/verification/rollback remain equal.
|
|
No prior execution approval is carried forward. Candidate receipt verification
|
|
requires independent owner/manual provenance and derives undo only from
|
|
verified creation receipts; planned rollback identities are not ownership.
|
|
Thirty-three relevant tests and ruff pass. Status-only raw-hash binding previews
|
|
accepted→materialized only after independent observations, preserving every
|
|
parameter/acceptance field; it writes and signs nothing. Details and exact native owner seams:
|
|
`docs/forgejo-structural-materialization-source-v1.md`. T03 remains progress;
|
|
case remains accepted@1.1, not materialized/live. CCR42 consumer auth remains
|
|
in_flight, and native owner evidence is not manufactured by source preparation.
|
|
|
|
2026-10-16 (T03 source compatibility): `plan`, `build` and
|
|
`structure-request` now expose explicit `--types-root`, passing it to the existing
|
|
exact-version NetKingdom API. Actual acknowledged 1.2 source renders the proposed
|
|
Forgejo case into a six-object **draft**, preserving its absent acceptance.
|
|
Six actual-source integration checks prove the root selection, dedicated consumer
|
|
namespace/SA, ordinary unimplemented refusal, proposed build refusal, historical
|
|
1.1 bundle refusal and malformed namespace refusal. Existing 44 plan/build/
|
|
structure tests pass. No live survey, execution, case/type status, acceptance,
|
|
native owner evidence or CCR was changed. T03 remains progress; actual accepted
|
|
1.2 case/reviewed source and authenticated native owner evidence remain required.
|
|
|
|
2026-10-17 (T03 source review): ops-mason source is complete for T03.
|
|
`structure-request` prepares the typed request; `case_structure.verify` and
|
|
`bind_status_transition` take an owner-supplied authenticating verifier by
|
|
design, so no CLI that trusts observation JSON is added. Every remaining step
|
|
is an owner observation or an attended native run.
|
|
|
|
Attended checklist (in order; none may be simulated):
|
|
1. net-kingdom: accept the Forgejo case at type 1.2 (acceptance record in the
|
|
case); ops-mason then re-renders `plan --case ... --types-root <1.2>` to
|
|
`reviewed` and rebuilds the bundle (source-only, worker may run).
|
|
2. railiance-platform: supply independently authenticated metadata-only
|
|
observations for ESO policy, `external-secrets-keycape-forgejo` role and
|
|
KV layout, each marked created (with change receipt) or preexisting-matched,
|
|
against the `structure-request` digest. No values.
|
|
3. railiance-apps + railiance-platform: bind CCR-2026-0042 consumer
|
|
`openbao.auth` (namespace/SA), reconcile it from @1.0 to the current type,
|
|
review and apply; supply its receipt.
|
|
4. ops-warden: authenticate the pointer-only catalog entry observation.
|
|
5. Owner (railiance-platform) supplies the authenticating verifier seam and,
|
|
with founder go, runs `bind_status_transition` to preview
|
|
accepted -> materialized; Warden accepts the new raw case digest.
|
|
6. Follow-through after materialization, not prerequisites: mint in custody,
|
|
ESO delivery, first live verification (NK-WP-0048-T06).
|