223 lines
8.3 KiB
Markdown
223 lines
8.3 KiB
Markdown
|
|
---
|
||
|
|
id: SECRETS-WP-0008
|
||
|
|
type: workplan
|
||
|
|
title: "Evolve the Lifecycle engine to the accepted security layer model"
|
||
|
|
domain: infotech
|
||
|
|
repo: secrets-engine
|
||
|
|
status: ready
|
||
|
|
owner: grok
|
||
|
|
topic_slug: custodian
|
||
|
|
created: "2026-08-29"
|
||
|
|
updated: "2026-08-29"
|
||
|
|
---
|
||
|
|
|
||
|
|
# SECRETS-WP-0008 - Evolve the Lifecycle engine to the accepted security layer model
|
||
|
|
|
||
|
|
## Goal
|
||
|
|
|
||
|
|
Close the gaps between the 2026-08-29 layer declaration (Engine / Lifecycle)
|
||
|
|
and the obligations the accepted NetKingdom Security Layer Model v0.7 places on
|
||
|
|
a PEP-shaped Lifecycle engine.
|
||
|
|
|
||
|
|
Source review: `history/2026-08-29-layer-model-scope-intent-review.md`.
|
||
|
|
Declaration surface already landed this session: `INTENT.md` frontmatter,
|
||
|
|
`layer.yaml`, `pep-stance.yaml`, and `tests/test_layer_conformance.py`.
|
||
|
|
|
||
|
|
This workplan does **not** restart CLI hardening owned by `SECRETS-WP-0007`.
|
||
|
|
It adds the layer-model remainder: stance binding, decision-record consumption,
|
||
|
|
`audit-core` evidence, and the two proposed engine surfaces.
|
||
|
|
|
||
|
|
## Non-goals
|
||
|
|
|
||
|
|
- Taking ops-warden's SSH access lane or becoming a credential broker.
|
||
|
|
- Rendering or caching authorization decisions.
|
||
|
|
- Observation in production or automatic containment (companion §10: both are
|
||
|
|
at zero estate-wide).
|
||
|
|
- Service mode, runtime tenancy, or a second custody backend.
|
||
|
|
- Reopening live production on State Hub status or local fixtures.
|
||
|
|
|
||
|
|
## Coordination
|
||
|
|
|
||
|
|
- `SECRETS-WP-0007-T04` owns the consumer validator and the fail-closed
|
||
|
|
production gate until a durable ActionAuthorization object is served.
|
||
|
|
- `SECRETS-WP-0007-T05` owns delivery-session self-revocation and the KeyCape
|
||
|
|
scaffold; this workplan owns the layer-model "no standing credential" bar.
|
||
|
|
- railiance-platform owns production OpenBao and the JWT role.
|
||
|
|
- `access-engine` / State Hub own serving the decision record.
|
||
|
|
- `audit-core` owns evidence custody.
|
||
|
|
- ops-warden owns the SSH Staff PEP and must assent any SSH-CA API contract.
|
||
|
|
- kings-guard owns secret-abuse posture and must assent the evidence surface.
|
||
|
|
- gate-house owns statute §13.1 inventory of PEP stance maps.
|
||
|
|
|
||
|
|
## Tasks
|
||
|
|
|
||
|
|
## Publish stance application as shipped behaviour
|
||
|
|
|
||
|
|
```task
|
||
|
|
id: SECRETS-WP-0008-T01
|
||
|
|
status: todo
|
||
|
|
priority: high
|
||
|
|
```
|
||
|
|
|
||
|
|
`pep-stance.yaml` is published and tests pin `prod: fail_closed` to
|
||
|
|
`_require_lane_approval`. The gate is still hardcoded, and a refusal is
|
||
|
|
recorded as a `DecisionError` rather than named stance fields.
|
||
|
|
|
||
|
|
Load the published map as the source of shipped defaults. When the
|
||
|
|
unreachable-engine residue is applied, record at least stage, failure mode, and
|
||
|
|
decision id present only where a decision was rendered. Keep the three-factor
|
||
|
|
unsafe-demo exception out of the stance table. Assert map equality in
|
||
|
|
`tests/test_layer_conformance.py` the way ops-warden's stance test does.
|
||
|
|
|
||
|
|
Acceptance:
|
||
|
|
|
||
|
|
- `_require_lane_approval` (or its successor) reads `pep-stance.yaml`.
|
||
|
|
- Changing the YAML without changing the code fails the test, and the reverse.
|
||
|
|
- Fail-closed production evidence includes named stance fields, never a secret.
|
||
|
|
- Build/test remain fail-open *relative to access-engine* and still require
|
||
|
|
the existing lane-approval check; that residue stays documented as a gap
|
||
|
|
until T02.
|
||
|
|
|
||
|
|
## Consume access-engine decision records
|
||
|
|
|
||
|
|
```task
|
||
|
|
id: SECRETS-WP-0008-T02
|
||
|
|
status: wait
|
||
|
|
priority: high
|
||
|
|
```
|
||
|
|
|
||
|
|
Blocked on the durable ActionAuthorization serving path owned with
|
||
|
|
`SECRETS-WP-0007-T04` / State Hub / `access-engine`.
|
||
|
|
|
||
|
|
Once that object is served, a protected side effect holds a decision record
|
||
|
|
identifying the request it was rendered for. Replay is permitted iff the
|
||
|
|
canonical request digest matches and the lifetime holds. Do not cache the
|
||
|
|
verdict. Do not treat State Hub status, a local fixture, or catalog admission
|
||
|
|
as the decision.
|
||
|
|
|
||
|
|
Acceptance:
|
||
|
|
|
||
|
|
- Every live privileged production handler passes one shared consume function.
|
||
|
|
- Wrong digest, expired lifetime, superseded status, or missing record fail
|
||
|
|
closed before OpenBao.
|
||
|
|
- Evidence carries the decision id; a fail-closed residue still records the
|
||
|
|
stance instead.
|
||
|
|
- Local fixtures cannot authorize steady-state production.
|
||
|
|
|
||
|
|
## Emit evidence under the §9.6 bound
|
||
|
|
|
||
|
|
```task
|
||
|
|
id: SECRETS-WP-0008-T03
|
||
|
|
status: todo
|
||
|
|
priority: high
|
||
|
|
```
|
||
|
|
|
||
|
|
Classify each privileged action as load-bearing or attributive. Today's trail
|
||
|
|
is attributive local JSONL plus best-effort State Hub notes; completeness is
|
||
|
|
already not claimed and must stay that way until the destination is
|
||
|
|
`audit-core`.
|
||
|
|
|
||
|
|
Load-bearing classes (at least live destroy, production revoke/suspend of a
|
||
|
|
control, and dual-control provision once those are enabled) require atomic
|
||
|
|
emission via a **local** outbox and a declared cadence or heartbeat. Do not
|
||
|
|
place a synchronous `audit-core` dependency inside the state-change
|
||
|
|
transaction. Attributive classes may keep the current non-blocking trade if
|
||
|
|
that trade stays declared.
|
||
|
|
|
||
|
|
Acceptance:
|
||
|
|
|
||
|
|
- A machine-readable classification exists next to the declaration.
|
||
|
|
- No control in this repository branches on presence or absence of a local
|
||
|
|
evidence record.
|
||
|
|
- Load-bearing emission is queued locally; an `audit-core` outage does not
|
||
|
|
block a revocation.
|
||
|
|
- Documentation uses the sound claim: the archive proves records it holds were
|
||
|
|
not altered or truncated after arrival.
|
||
|
|
|
||
|
|
## Accept the SSH-CA signing engine surface
|
||
|
|
|
||
|
|
```task
|
||
|
|
id: SECRETS-WP-0008-T04
|
||
|
|
status: todo
|
||
|
|
priority: medium
|
||
|
|
```
|
||
|
|
|
||
|
|
ops-warden's `ssh-ca-signing-write` gap names this engine as intended owner.
|
||
|
|
Accept the **engine API**, decline the Staff lane. Publish a contract
|
||
|
|
ops-warden can call after an `access-engine` decision: sign a short-lived
|
||
|
|
certificate for an `adm`/`agt`/`atm` actor under the caller's request, present
|
||
|
|
no additional authority, reconstruct as the caller's action.
|
||
|
|
|
||
|
|
Do not implement a replacement client until ops-warden assents the contract.
|
||
|
|
Do not unpark the standalone `warden-sign` AppRole as break-glass.
|
||
|
|
|
||
|
|
Acceptance:
|
||
|
|
|
||
|
|
- A non-secret contract document in `docs/` states request, decision binding,
|
||
|
|
lifetime, evidence, and non-responsibilities.
|
||
|
|
- ops-warden has a recorded chance to assent or contest.
|
||
|
|
- No OpenBao SSH-CA write is added to this CLI ahead of that assent.
|
||
|
|
- `layer.yaml` owner_status remains `proposed` until the surface ships.
|
||
|
|
|
||
|
|
## Accept the secret-use evidence surface
|
||
|
|
|
||
|
|
```task
|
||
|
|
id: SECRETS-WP-0008-T05
|
||
|
|
status: todo
|
||
|
|
priority: medium
|
||
|
|
```
|
||
|
|
|
||
|
|
kings-guard's secret-abuse posture is fixture-driven because no engine exposes
|
||
|
|
lease, revocation, mount, rotation, and delivery-session metadata. `route` and
|
||
|
|
`audit` are operator summaries over local JSONL and are not that surface.
|
||
|
|
|
||
|
|
Publish a read-only engine contract of non-secret metadata, bounded by §9.6:
|
||
|
|
it cannot prove omission at source. Coordinate destination with `audit-core`.
|
||
|
|
Do not give kings-guard a vault client, and do not return values.
|
||
|
|
|
||
|
|
Acceptance:
|
||
|
|
|
||
|
|
- Contract lists fields, freshness, and the evidence bound.
|
||
|
|
- kings-guard has a recorded chance to assent or contest.
|
||
|
|
- No secret material, token, or accessor is in the surface.
|
||
|
|
- `layer.yaml` owner_status remains `proposed` until the surface ships.
|
||
|
|
|
||
|
|
## No standing engine credential
|
||
|
|
|
||
|
|
```task
|
||
|
|
id: SECRETS-WP-0008-T06
|
||
|
|
status: wait
|
||
|
|
priority: medium
|
||
|
|
```
|
||
|
|
|
||
|
|
Blocked on the platform-owned OpenBao JWT mount/role (railiance-platform) and
|
||
|
|
on `SECRETS-WP-0007-T05` wiring. Companion §7 / statute §3.4: an agent holds
|
||
|
|
no long-lived credential of its own. Authority is per task, time-bounded, and
|
||
|
|
attributable to the principal it acts for.
|
||
|
|
|
||
|
|
Bootstrap token files remain break-glass, heavily evidenced, never an implicit
|
||
|
|
fallback from service identity.
|
||
|
|
|
||
|
|
Acceptance:
|
||
|
|
|
||
|
|
- Steady-state CLI/API auth is the reviewed service identity, not
|
||
|
|
`--bootstrap-token-file`.
|
||
|
|
- Bootstrap is a named break-glass provider with distinct evidence.
|
||
|
|
- No fallback from JWT/service-auth failure into bootstrap or AppRole.
|
||
|
|
- Issued delivery sessions continue to self-revoke as in WP-0007-T05.
|
||
|
|
|
||
|
|
## Exit criteria
|
||
|
|
|
||
|
|
- The published PEP stance is the shipped default and stance application is
|
||
|
|
recorded by name.
|
||
|
|
- Production live side effects require an access-engine decision record, or
|
||
|
|
remain fail-closed with a recorded stance.
|
||
|
|
- Evidence classification and destination match §9.6; completeness is not
|
||
|
|
claimed.
|
||
|
|
- SSH-CA and secret-use surfaces are either contracted with the declaring
|
||
|
|
repositories or explicitly declined in this repository's own voice.
|
||
|
|
- Bootstrap is not the steady-state engine credential.
|
||
|
|
- `layer.yaml` / `pep-stance.yaml` / INTENT frontmatter stay in one voice.
|
||
|
|
- No raw secret values in Git, State Hub, chat, prompts, workplans, evidence,
|
||
|
|
or argv.
|