issue-core flagged the installed `warden` lacked the `route` subcommand. Two causes:
1. uv reused a cached wheel (version stayed 0.1.0) so the installed warden.cli was
stale. Documented the cache-clean + --reinstall fix in ADHOC-2026-06-27.
2. Even rebuilt, route/access/policy were unusable outside a checkout because the
routing catalog + posture descriptors live in registry/ at repo root, outside the
package. Bundle registry/ into the wheel (hatch force-include -> warden/_registry)
and add a packaged-data fallback in find_catalog_path / find_posture_path after the
repo walk, so source runs still prefer the repo's registry/ (single source of truth).
Verified `warden route list` / `warden policy list` work from /tmp. 200 tests, lint clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Finish the Workload Security Posture workplan (all five tasks done).
T3 — scripts/check_secret_posture_conformance.py: read-only checker that asserts
env-posture conformance (backend/unseal/real_values per tier) and evaluates the
secret-flow lattice via posture.can_deliver. Metadata-only manifest, no secret
values, exit 0/1/2. examples/posture-conformance.example.yaml as the reference.
T4 — src/warden/doubles.py: generalizes "fake bao" into materialize_doubles() —
hermetic, synthetic-only (synthetic- prefix) stand-ins for bao/key-cape honoring
each argv/stdout/exit contract, for fully offline dev/test access flows. Documented
as the sanctioned dev backend in WorkloadSecurityPosture.md R1.
T5 — INTENT/SCOPE/wiki aligned; canon landing in net-kingdom/info-tech-canon left
owner-driven (tracked via coordination messages).
16 new tests, 200 passing, ruff clean. Archived WP-0012/0014/0015 to
workplans/archived/ with 260627- prefix.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a lane: secret|login field to RouteEntry. The login lane is an
interactive auth bootstrap: it skips the caller-auth precheck (no token
yet — that's the point) and the secret-read gate (it establishes the
identity the gate needs), runs the owner's login command interactively
as the caller via inherited stdio, and rejects --exec. The token stays
in the caller's own store; warden never captures it (G2 holds). Audited
as action: login. key-cape-oidc-login populated as the reference login
entry. Advisory proxy hint updated now that T3 has shipped.
172 passed, lint clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds transparent, policy-gated, audited proxy of a non-SSH credential
through `warden access`, for exec_capable lanes. Three guardrails in code:
- G1 caller identity: runs the owner's tool with the caller's own env;
warden injects no token of its own (caller_auth_present check).
- G2 transit-only: --fetch inherits stdout (never PIPE) so the value
never enters warden's memory or any log; --exec injects into the child
env only. Audit (access-audit.log) is metadata-only.
- G3 policy gate: check_fetch_policy runs before any fetch; with
policy.enabled=false the proxy refuses unless --no-policy is given.
resolve_fetch_command refuses unresolved <…> placeholders rather than
guess owner-side names. New warden/proxy.py + policy.check_fetch_policy;
tests/test_proxy.py asserts all three guardrails. 168 passed, lint clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds `warden access <need> [--domain X] [--json]`: resolves a credential
need against the routing catalog and renders the structured handoff
(owner, auth method, path template, command skeleton, policy gate
status, proxy hint). SSH lane points at `warden sign`; routed lanes end
"warden advises, the owner vends". New pure warden/access.py module
(expand_handoff, policy_gate_status) reused by the T3 proxy lane. JSON
output is stable and secret-free. tests/test_access.py added.
157 passed, lint clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds optional assist-layer fields (auth_method, path_template,
fetch_command, exec_capable, policy_ref) to RouteEntry, parsed and
secret-screened in catalog.py. Handoff fields are templates/pointers
only — _assert_no_secret_material rejects known token prefixes and
high-entropy runs, and exec_capable requires a fetch_command. The
openbao-api-key entry is populated as the reference example (covers the
coulomb_social npm shape).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add platform-secret playbooks for issue-core ingestion, OpenRouter llm-connect,
object-storage STS, and database dynamic credentials. Extend the routing catalog
with draft entries and implement `warden route list --stale` for quarterly drift
review. Document the review cadence in AccessRouting and mark the workplan finished.
Add a read-only `warden route` command group (list/show/find) that reads
registry/routing/catalog.yaml and tells a worker which subsystem owns a need
and which wiki/canon doc to follow. ops-warden still executes exactly one lane
(SSH); routed entries return a pointer and never call any subsystem.
- src/warden/routing/: models.py + catalog.py loader; enforces the
no-double-source rule (non-SSH entries with steps/cert_command fail validation),
dup-id and schema checks.
- route list (active-only unless --all, --tag), route show (SSH appends steps +
cert pattern; routed ends with "next action on <owner> — see <wiki_ref>"),
route find (keyword ranking, --json).
- tests/test_routing.py: load/validation, find ranking, CLI JSON shapes, plus a
drift guard (every wiki_ref anchor resolves; every entry has a reviewed date).
- Docs: wiki/AccessRouting.md CLI section, README quick reference, SCOPE A3 -> A4.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add policy.py client that calls flex-auth /v1/check before sign/issue when
policy.enabled is true. Record policy_decision_id in signatures.log. Default
off preserves existing inventory-only behavior. Document production OpenBao
health probe and update config/wiki references.
T1 — TTL max enforcement:
- models.py: MAX_TTL_HOURS policy constant
- ca.py: _enforce_ttl() raises CAError when spec.ttl_hours > type max
- Called at top of LocalCA.sign() and VaultCA.sign()
- scorecard.py: check_ttl_policy() — flags certs with issued TTL > type max
- run_scorecard() now returns 5 checks
T2 — Stale cert cleanup:
- ca.py: _evict_cert() removes existing cert before writing new one (no accumulation)
- cli.py: warden cleanup [actor] [--dry-run] command
- check_no_stale_certs detail suggests 'warden cleanup' when stale certs found
T3 — Outgoing signatures log:
- ca.py: _append_signature_log() writes JSONL to state_dir/signatures.log
- Called after every successful sign() in LocalCA and VaultCA
- cli.py: warden log [actor] [--last N] [--json] command
- parse_cert_metadata now also returns valid_from (needed for TTL policy check)
61 tests passing, ruff clean.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>