Propose SecurityCaseTypes canon and add NK-WP-0048
security-case-types_v0.1 (proposed): types designed once with docs, tests and an informed-decision; known cases light (accept, ops-mason materializes, ops-warden follows through). Founder direction 2026-10-08. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 5457@bnt-lap001 Assistant-Session: 792bf84a-3783-4f5d-a811-cded61dd2012
This commit is contained in:
parent
d5dd19dfe2
commit
4b21f7bdee
2 changed files with 357 additions and 0 deletions
173
canon/standards/security-case-types_v0.1.md
Normal file
173
canon/standards/security-case-types_v0.1.md
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
---
|
||||
id: netkingdom-security-case-types-v0.1
|
||||
type: standard
|
||||
title: "NetKingdom Security Case Types v0.1"
|
||||
domain: netkingdom
|
||||
status: proposed
|
||||
version: "0.1"
|
||||
owner: net-kingdom
|
||||
created: "2026-10-08"
|
||||
updated: "2026-10-08"
|
||||
last_reviewed: "2026-10-08"
|
||||
review_interval: 3m
|
||||
scope: meta-orchestration
|
||||
related:
|
||||
- canon/standards/playbook-capability-contract_v0.2.md
|
||||
- canon/standards/security-scenario-composition_v0.1.md
|
||||
- canon/standards/credential-management_v0.2.md
|
||||
- docs/security-bootstrap-use-cases.md
|
||||
---
|
||||
|
||||
# NetKingdom Security Case Types v0.1
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
Most security work in the ecosystem repeats a small number of shapes: a browser
|
||||
service that signs users in through NetKingdom, a service that authenticates
|
||||
with its own credential, a workload that reads one KV path, an agent that needs
|
||||
a short-lived SSH certificate. Until now each occurrence was built by hand: a
|
||||
new helper script, a new custody path, a new founder checklist. That is slow,
|
||||
and every hand-built instance can drift from the last one.
|
||||
|
||||
This standard separates **designing a shape** from **using it**:
|
||||
|
||||
- A **SecurityCaseType** is designed once, with ample documentation and tests,
|
||||
and acknowledged as an informed-decision, because its shape is part of the
|
||||
security architecture as a whole.
|
||||
- A **SecurityCase** of an implemented type is light: the requester fills in the
|
||||
type's parameters, the case is accepted, ops-mason arranges it, and ops-warden
|
||||
carries it out on the authentication path the type provides.
|
||||
|
||||
Making a new type is deliberately harder than making a new case.
|
||||
|
||||
## 2. Terms
|
||||
|
||||
| Term | Meaning |
|
||||
| --- | --- |
|
||||
| **SecurityCaseType** | A reusable, versioned security pattern for one kind of use case. Defines parameters, composition, materialization, execution route, verification, rollback and threats. |
|
||||
| **SecurityCase** | One instance of a type, with concrete parameter values, an owner and an acceptance record. |
|
||||
| **KnownSecurityCase** | A SecurityCase whose type is `implemented` (section 5). Only known cases take the light path. |
|
||||
| **Type acknowledgment** | The informed-decision that admits a type, or a new major version of a type. |
|
||||
| **Case acceptance** | The record that the case's owner, and where the type requires it the founder, accepted this instance. |
|
||||
| **Materialization** | ops-mason building the structure a case needs: OpenBao policies, roles and KV path structure (never values), and catalog entries. |
|
||||
| **Follow-through** | ops-warden executing the case's declared entry points on the type's authentication path, and verifying it. |
|
||||
|
||||
A SecurityCaseType is not a new orchestration engine. It is a NetKingdom-owned
|
||||
**composition** of playbook capabilities that their owning repos declare under
|
||||
the Playbook Capability Contract, plus the guarantees in section 3. Execution
|
||||
stays with the declared entry points (ADR-0007, ADR-0012).
|
||||
|
||||
## 3. What a SecurityCaseType must define
|
||||
|
||||
A type is a directory `security-case-types/<type-id>/` in net-kingdom containing:
|
||||
|
||||
1. **`type.yaml`** (machine-readable, schema `canon/schemas/security-case-type_v0.1.schema.json`):
|
||||
- `id`, `version`, `status` (section 5), `title`, `purpose`
|
||||
- `parameters`: each with type, validation, allowed range and whether a case
|
||||
may set it. Secret values are never parameters, only custody references.
|
||||
- `composition`: required playbook capability ids with exact provider pins,
|
||||
in the security-scenario-composition form (fail-closed ordering, explicit
|
||||
initial trust, owner attribution)
|
||||
- `materialization`: the OpenBao structure ops-mason creates per case, as
|
||||
templates over the parameters: policy, role, KV path, catalog entry
|
||||
- `follow_through`: the ops-warden route for each step, `warden_executes`,
|
||||
the auth method and the entry point; which steps need an attended human
|
||||
login, if any, and why
|
||||
- `verification`: the checks that prove a case is live (positive and
|
||||
negative), runnable without reading a secret value
|
||||
- `rollback`: the exact inverse of each step
|
||||
- `acceptance`: who accepts a case (owner only, or owner and founder) and
|
||||
what risk class this type carries
|
||||
2. **`README.md`**: the threat model, what the type protects and from whom,
|
||||
design alternatives considered, and known limits.
|
||||
3. **Tests**: validation of `type.yaml`, a rendered example case, and the
|
||||
composer's output for that case. A type with no runnable tests cannot be
|
||||
acknowledged.
|
||||
4. **Reference instances**: existing hand-built instances this type replaces
|
||||
or adopts, so that the type is grounded in practice.
|
||||
|
||||
## 4. What a SecurityCase must define
|
||||
|
||||
A case is a file `security-cases/<case-id>.yaml`, in the requesting owner's
|
||||
repository or in net-kingdom when it has no other owner:
|
||||
|
||||
- `type`: `<type-id>@<version>`, which must be `implemented`
|
||||
- `parameters`: values for the type's parameters
|
||||
- `owner`: the repository and person accountable for the case
|
||||
- `acceptance`: who accepted it, when, and where (State Hub decision, or a
|
||||
record in the owner's repository)
|
||||
- `status`: `proposed` → `accepted` → `materialized` → `live` → `retired`
|
||||
|
||||
Nothing else. Everything a case needs beyond its parameters belongs in its type.
|
||||
If a case cannot be expressed in its type's parameters, it is not a case of that
|
||||
type: either change the case or propose a new type version (section 6).
|
||||
|
||||
## 5. Type lifecycle
|
||||
|
||||
| Status | Meaning | Who moves it |
|
||||
| --- | --- | --- |
|
||||
| `draft` | being written; not usable | type author |
|
||||
| `proposed` | complete per section 3, tests green, Decision Memo prepared | type author |
|
||||
| `acknowledged` | admitted by informed-decision | the founder, through informed-decision |
|
||||
| `implemented` | ops-mason can materialize it and ops-warden can follow through; one reference case is live and verified | net-kingdom, with ops-mason and ops-warden |
|
||||
| `deprecated` | no new cases; existing cases keep running | net-kingdom |
|
||||
| `retired` | no cases remain | net-kingdom |
|
||||
|
||||
Only `implemented` types accept new cases.
|
||||
|
||||
## 6. Changing a type
|
||||
|
||||
- **Patch** (documentation, tests, a stricter validation): a normal reviewed
|
||||
change; no decision.
|
||||
- **Minor** (a new optional parameter, an extra verification step): a
|
||||
reviewed change, recorded in the type's history; no new acknowledgment unless
|
||||
the risk class changes.
|
||||
- **Major** (a changed authentication path, materialization or trust
|
||||
transition; a looser validation; a higher risk class): a new informed-decision,
|
||||
as for a new type. Existing cases stay on their version until migrated.
|
||||
|
||||
## 7. The light path for known cases
|
||||
|
||||
For a case of an `implemented` type:
|
||||
|
||||
1. The requester writes the case file and validates it against the type.
|
||||
2. The accepter records acceptance (section 4). This is the only human step
|
||||
unless the type's `acceptance` requires an attended login for a specific
|
||||
step, which the type must justify.
|
||||
3. ops-mason materializes it from the type's templates. Its executive-summary
|
||||
gate collapses to the case acceptance, because the shape was decided when the
|
||||
type was acknowledged.
|
||||
4. ops-warden follows through on the type's route and runs the type's
|
||||
verification.
|
||||
5. The case moves to `live` with the verification receipt.
|
||||
|
||||
No case-specific helper script is written. If one seems necessary, the type is
|
||||
incomplete.
|
||||
|
||||
## 8. Roles
|
||||
|
||||
| Party | Responsibility |
|
||||
| --- | --- |
|
||||
| net-kingdom | owns this standard, the type directory, the schema and the composer; admits and retires types |
|
||||
| ops-mason | materializes OpenBao structure for cases from type templates; proposes the type's materialization section |
|
||||
| ops-warden | follows through on cases; owns the routing catalog entries a type defines; proposes the type's follow-through section |
|
||||
| owning repositories (key-cape, railiance-platform, ...) | declare the playbook capabilities that types compose; own execution |
|
||||
| informed-decision | presents the type's Decision Memo to the founder and records acknowledgment |
|
||||
| requesters | write cases, own them, retire them |
|
||||
|
||||
## 9. Boundaries
|
||||
|
||||
- No secret value in a type, a case, a test or a receipt.
|
||||
- This standard does not grant execution authority. Each step runs under its
|
||||
owner's declared entry point and its own authentication.
|
||||
- Existing hand-built instances keep working. They are adopted as cases when
|
||||
their type is implemented, not rewritten in place.
|
||||
|
||||
## 10. Open questions for v0.1 review
|
||||
|
||||
- Where should case files live by default: with the requester, or centrally in
|
||||
net-kingdom?
|
||||
- Is the informed-decision Decision Memo for a type rendered from `type.yaml`
|
||||
and `README.md`, or written separately?
|
||||
- Which steps of the first types genuinely need an attended human login (for
|
||||
example key-cape's live client configuration), and how is that minimised?
|
||||
184
workplans/NK-WP-0048-security-case-types.md
Normal file
184
workplans/NK-WP-0048-security-case-types.md
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
---
|
||||
id: NK-WP-0048
|
||||
type: workplan
|
||||
title: "Establish SecurityCaseTypes so that known security cases are light"
|
||||
domain: infotech
|
||||
repo: net-kingdom
|
||||
status: ready
|
||||
flavor: implementation
|
||||
owner: claude-code
|
||||
topic_slug: netkingdom
|
||||
created: "2026-10-08"
|
||||
updated: "2026-10-08"
|
||||
depends_on: []
|
||||
related_repos:
|
||||
- ops-mason
|
||||
- ops-warden
|
||||
- key-cape
|
||||
- railiance-platform
|
||||
- informed-decision
|
||||
---
|
||||
|
||||
# NK-WP-0048 - Establish SecurityCaseTypes so that known security cases are light
|
||||
|
||||
## Why
|
||||
|
||||
The founder's direction (2026-10-08): setting up a security integration of a
|
||||
kind that has been done before should be easy, meaning accept the case, then
|
||||
ops-mason arranges it and ops-warden follows through. Setting up a new kind
|
||||
needs ample documentation and tests and an informed-decision, because its shape
|
||||
is part of the security architecture.
|
||||
|
||||
Today every integration is hand-built: per-client helper scripts, per-lane
|
||||
custody, founder checklists. The trigger was KEY-WP-0038 (Forgejo as an OIDC
|
||||
client), whose next step was going to be yet another hand-written rollout
|
||||
script.
|
||||
|
||||
This plan continues the pattern work of NK-WP-0008 (pattern infospace),
|
||||
NK-WP-0009 (tutorials) and NK-WP-0030 (scenario composition). It turns patterns
|
||||
into **SecurityCaseTypes** that ops-mason and ops-warden can execute. Canon:
|
||||
`canon/standards/security-case-types_v0.1.md` (proposed).
|
||||
|
||||
Companion plans: ops-mason `MASON-WP-0010` (materialization) and ops-warden
|
||||
`WARDEN-WP-0044` (follow-through).
|
||||
|
||||
## Tasks
|
||||
|
||||
```task
|
||||
id: NK-WP-0048-T01
|
||||
status: wait
|
||||
needs_human: true
|
||||
blocking_reason: "The founder reviews and accepts the security-case-types_v0.1 canon proposal."
|
||||
priority: high
|
||||
```
|
||||
|
||||
### T01 — Accept the terminology and the canon
|
||||
|
||||
Founder review of `canon/standards/security-case-types_v0.1.md`, including its
|
||||
section 10 open questions. On acceptance the canon status goes from `proposed`
|
||||
to `accepted`.
|
||||
|
||||
```task
|
||||
id: NK-WP-0048-T02
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
### T02 — Inventory the de-facto types already built by hand
|
||||
|
||||
Read-only. List every security integration built so far and group them by shape.
|
||||
Known starting points:
|
||||
|
||||
- browser OIDC relying parties on key-cape: informed-decision-approver,
|
||||
coulomb-social, user-engine portal, openbao-admin, and Forgejo (pending)
|
||||
- confidential service clients with `client_credentials`: secrets-engine
|
||||
approval, requester and openbao clients, approval-engine operator
|
||||
- workload KV read lanes on OpenBao: the railiance-platform credential lane
|
||||
designs and CCRs, for example `railiance-backup-offsite-lane`
|
||||
- short-lived SSH certificates through ops-warden (`warden sign`)
|
||||
- tunnelled operator access (ops-bridge)
|
||||
|
||||
For each: the repositories involved, the hand-built steps, attended human steps,
|
||||
custody paths, verification evidence, and rollback (if any). Output
|
||||
`docs/security-case-type-inventory.md`, ranking candidate types by how often the
|
||||
shape recurs and how much manual work each instance costs today.
|
||||
|
||||
```task
|
||||
id: NK-WP-0048-T03
|
||||
status: wait
|
||||
depends_on: [NK-WP-0048-T01]
|
||||
blocking_reason: "The schema and template follow the accepted canon."
|
||||
priority: high
|
||||
```
|
||||
|
||||
### T03 — Schema, template and validator
|
||||
|
||||
- `canon/schemas/security-case-type_v0.1.schema.json` and
|
||||
`security-case_v0.1.schema.json`
|
||||
- `security-case-types/_template/` with `type.yaml`, `README.md` and tests to copy
|
||||
- a validator, extending `tools/security-scenario-composer/`, that checks a type,
|
||||
checks a case against its type, and renders the case into the composer's
|
||||
deterministic plan (still `execution.permitted: false`)
|
||||
|
||||
Acceptance: the validator rejects missing sections, secret-shaped parameter
|
||||
values, unpinned providers and cases against non-`implemented` types, with tests
|
||||
for each.
|
||||
|
||||
```task
|
||||
id: NK-WP-0048-T04
|
||||
status: wait
|
||||
depends_on: [NK-WP-0048-T02, NK-WP-0048-T03, MASON-WP-0010-T01, WARDEN-WP-0044-T01]
|
||||
blocking_reason: "The first type needs the inventory, the template, and ops-mason/ops-warden's sections."
|
||||
priority: high
|
||||
```
|
||||
|
||||
### T04 — Define the first type: browser OIDC relying party
|
||||
|
||||
`security-case-types/oidc-browser-relying-party/`, version 1.0:
|
||||
|
||||
- parameters: client id, display name, exact redirect URIs, scopes, client type
|
||||
(confidential or public), MFA pin, the groups the consuming service maps,
|
||||
custody path for the secret (confidential only), consuming service and its
|
||||
owner
|
||||
- composition: key-cape client registration (key-cape declares it as a playbook
|
||||
capability), secret minting into custody (railiance-platform), LLDAP group
|
||||
existence and membership (net-kingdom identity-provisioner), handover to the
|
||||
consuming service
|
||||
- materialization (ops-mason) and follow-through (ops-warden) sections
|
||||
- verification: discovery lists the redirect URI; a test sign-in returns the
|
||||
expected claims for one human; anonymous access to the custody path is denied
|
||||
- rollback: remove exactly this client and its custody path
|
||||
- README: threat model, MFA rationale, why redirect URIs are exact, which steps
|
||||
still need an attended login and how that is minimised
|
||||
- reference instances: informed-decision-approver, coulomb-social, user-engine
|
||||
portal, openbao-admin
|
||||
|
||||
Acceptance: complete per canon section 3, tests green, status `proposed`.
|
||||
|
||||
```task
|
||||
id: NK-WP-0048-T05
|
||||
status: wait
|
||||
depends_on: [NK-WP-0048-T04]
|
||||
needs_human: true
|
||||
blocking_reason: "A new SecurityCaseType is acknowledged as an informed-decision by the founder."
|
||||
priority: high
|
||||
```
|
||||
|
||||
### T05 — Acknowledge the type through informed-decision
|
||||
|
||||
Prepare the Decision Memo from the type's README and `type.yaml` and submit it
|
||||
through informed-decision's production intake. On acknowledgment the type
|
||||
moves to `acknowledged`.
|
||||
|
||||
```task
|
||||
id: NK-WP-0048-T06
|
||||
status: wait
|
||||
depends_on: [NK-WP-0048-T05, MASON-WP-0010-T03, WARDEN-WP-0044-T03]
|
||||
blocking_reason: "Implementation needs the acknowledged type and both executors' light paths."
|
||||
priority: high
|
||||
```
|
||||
|
||||
### T06 — First KnownSecurityCase: Forgejo
|
||||
|
||||
Write `security-cases/forgejo-netkingdom-oidc.yaml` from the parameters the
|
||||
founder accepted in KEY-WP-0038-T01 (`key-cape/docs/forgejo-oidc-client-request.yaml`),
|
||||
so that acceptance carries over as the case acceptance. ops-mason materializes it;
|
||||
ops-warden follows through and verifies it. The type becomes `implemented` once
|
||||
this reference case is live.
|
||||
|
||||
This replaces the hand-built path proposed for KEY-WP-0038-T02.
|
||||
|
||||
```task
|
||||
id: NK-WP-0048-T07
|
||||
status: wait
|
||||
depends_on: [NK-WP-0048-T06]
|
||||
blocking_reason: "The next types follow once the first one is proven end to end."
|
||||
priority: medium
|
||||
```
|
||||
|
||||
### T07 — Queue the next types
|
||||
|
||||
From the T02 ranking, open the next type drafts (likely the confidential service
|
||||
client and the workload KV read lane), each to be acknowledged on its own.
|
||||
Record which existing hand-built instances get adopted as cases, without
|
||||
rewriting them in place.
|
||||
Loading…
Add table
Add a link
Reference in a new issue