secrets-engine/workplans/SECRETS-WP-0008-layer-model-lifecycle-conformance.md
tegwick 3cd9955ac9
Some checks are pending
CI Smoke / host-smoke (push) Waiting to run
CI Smoke / container-smoke (push) Waiting to run
Implement SECRETS-WP-0008 unblocked layer-model obligations
Load pep-stance.yaml as the live unreachable-engine gate and record named
stance fields on privileged evidence. Classify evidence, queue load-bearing
records in a local outbox, and add heartbeat/drain commands that never sit
on a mutation path. Publish proposed SSH-CA and secret-use evidence
contracts without adding an OpenBao SSH-CA write.

T02 (access-engine decision records) and T06 (no standing credential) stay
wait on external endpoints.

Assistant: grok
Assistant-Session: 01a04cea-cb33-7c63-bad7-c1b0f9f0076b
2026-08-29 12:52:55 +02:00

9.5 KiB

id type title domain repo status owner topic_slug created updated state_hub_workstream_id
SECRETS-WP-0008 workplan Evolve the Lifecycle engine to the accepted security layer model infotech secrets-engine active grok custodian 2026-08-29 2026-08-29 9c9e5164-b2f5-5ea2-a557-5368d65e9fe0

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

id: SECRETS-WP-0008-T01
status: done
priority: high
state_hub_task_id: "945735c6-2d3d-5f72-baf0-692e6b210889"

Completed 2026-08-29. _require_lane_approval loads pep-stance.yaml. SHIPPED_STANCE is pinned equal to the published map. Fail-closed production evidence records stance_stage, stance_failure_mode, and omits stance_decision_id unless a decision was rendered.

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

id: SECRETS-WP-0008-T02
status: wait
priority: high
state_hub_task_id: "3eb9cff8-1441-5437-9e92-a2b655c82d04"

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

id: SECRETS-WP-0008-T03
status: done
priority: high
state_hub_task_id: "0b54cedf-9335-5fa0-bdcb-1efa9a9cd98d"

Completed 2026-08-29. evidence-classification.yaml is the declaration. Load-bearing records are queued in evidence_dir/outbox/ before JSONL. secrets-engine evidence heartbeat emits a positive claim. Drain never sits on a mutation path and an audit-core outage leaves the queue in place.

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

id: SECRETS-WP-0008-T04
status: done
priority: medium
state_hub_task_id: "581aeee3-3d99-5034-992b-7d42e6542a19"

Completed 2026-08-29. Contract published at docs/ssh-ca-signing-contract.md. No OpenBao SSH-CA write was added. layer.yaml owner_status remains proposed.

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

id: SECRETS-WP-0008-T05
status: done
priority: medium
state_hub_task_id: "3100d28c-9494-5b21-9d5a-af583cd8aa55"

Completed 2026-08-29. Contract published at docs/secret-use-evidence-contract.md. layer.yaml owner_status remains proposed. route/audit are still not this surface.

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

id: SECRETS-WP-0008-T06
status: wait
priority: medium
state_hub_task_id: "d7bc8bdc-a0f8-5058-a640-374ef9859148"

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.