diff --git a/catalog/glas-claude-agent-dev-anthropic.yaml b/catalog/glas-claude-agent-dev-anthropic.yaml deleted file mode 100644 index 149009a..0000000 --- a/catalog/glas-claude-agent-dev-anthropic.yaml +++ /dev/null @@ -1,60 +0,0 @@ -id: glas-claude-agent-dev-anthropic -kind: kv -org: coulomb -repo: sand-boxer -stage: prod -description: Proposed native exec-env delivery for CCR-2026-0016. KV custody exists; - no runtime grant or activation yet. -mount: platform -path: workloads/glas-harness/claude-agent-dev -mount_management: existing -fields: -- ANTHROPIC_API_KEY -consumers: -- name: sand-boxer-glas-agent-dev - auth: approle - claim: catalog:glas-claude-agent-dev-anthropic - purpose: Owner-admitted glas-harness agt run through the reviewed local profile; - no caller-facing key fetch -workload_delivery: [] -delivery_modes: -- exec-env -- read-check -delivery_auth: - method: approle - management: engine - policy_name: se-prod-glas-claude-agent-dev-anthropic - role_name: se-prod-glas-claude-agent-dev-anthropic - metadata_read: false - token_ttl: 5m - token_max_ttl: 15m - secret_id_ttl: 5m - secret_id_num_uses: 1 - token_num_uses: 8 -approval: - model: ccr - decision_ref: CCR-2026-0016 - notes: Custody only has been completed. Native apply and exec require durable exact-action - authorization, engine consume, scoped backend authority and verified delivery - state. This entry is not authorization. -verification: - positive: Exact scoped AppRole reads only ANTHROPIC_API_KEY into the approved child; - owner binding and redaction pass. - negative: Wrong owner profile/project/actor, direct caller fetch, sibling KV, metadata, - listing and writes denied. -risk: - classification: high - notes: API spend; provider expiry 2027-01-31T21:00:00Z is not enforced by Bao token - TTL. Workspace scope and budget unverified. -rotation: - owner: railiance-platform + sand-boxer - expectation: Provider replacement, versioned CAS custody, stop old runs, verify - replacement then revoke predecessor at Anthropic and prove denial. - ttl: provider-defined -deactivation: - owner: railiance-platform + sand-boxer - expectation: Disable lane, stop affected runs, revoke Bao sessions and provider - key. Preserve custody history. -audit: - evidence: CCR id, actor, exact path, field name, provider key identifier if non-secret, - timestamps, and pass/fail only diff --git a/docs/catalog-admission.md b/docs/catalog-admission.md index 7b31c9f..e91c1d5 100644 --- a/docs/catalog-admission.md +++ b/docs/catalog-admission.md @@ -120,10 +120,3 @@ Before accepting an existing production lane: that approval cannot be resolved. 8. Preserve the interim route until native positive and negative verification passes without exposing a value. - -### Optional data-only KV read policy - -`delivery_auth.metadata_read` is a boolean, defaulting to `true` for existing -lanes. Set `false` when the consumer needs only the KV data GET; generated -policy omits the metadata endpoint. Owner metadata verification then needs -separate operator authority, not broader consumer access. diff --git a/docs/glas-claude-delivery.md b/docs/glas-claude-delivery.md deleted file mode 100644 index 2876967..0000000 --- a/docs/glas-claude-delivery.md +++ /dev/null @@ -1,53 +0,0 @@ -# Glas Claude exec delivery - -Proposed native lane `glas-claude-agent-dev-anthropic`, provenance -railiance-platform CCR-2026-0016; implementation/activation record SECRETS-WP-0009. -KV custody is already confirmed at version 2. Do not provision or rotate it as -part of native read-lane adoption. - -The generated plan checks existing mount `platform`, creates policy and AppRole -`se-prod-glas-claude-agent-dev-anthropic`, and grants read only on -`platform/data/workloads/glas-harness/claude-agent-dev`. Field ANTHROPIC_API_KEY -is selected by the exec adapter; KV policies scope entries, not fields. -`delivery_auth.metadata_read: false` excludes the metadata endpoint; existing -lanes retain their previous metadata access by default. Token TTL 5m, maximum -15m, SecretID TTL 5m and single use, token use budget 8. No wildcard, listing, -workload writes, mount mutation, provider creation or default-policy change is -included in this plan. Verify effective token identity policies at activation. - -Sand-boxer's owner-configured credential route binds profile, project, actor and -nonempty run id before invoking secrets-engine's exec-env interface. The -provider injects the key into a private host helper that directly forwards it to -the namespace broker. The broker injects only ANTHROPIC_API_KEY into the command -and redacts exact values before truncating output. No OpenBao token crosses -into the sandbox; no key is returned through Glas's API. Values are available -to the trusted workload and descendants; encoding/exfiltration by hostile -workload code is not prevented by an output redactor. Existing sandbox, egress, -artifact verification and profile admission boundaries remain required. - -A synthetic provider proves the transport only. It does not stand in for native -approval, OpenBao access, provider authentication or production readiness. - -## Activation requirements - -The current engine's production stance refuses before opening the backend: -`production action 'exec' requires a durable access-engine decision record; -live production remains disabled`. This refusal was exercised with the proposed -catalog and service-jwt selection. No real value was requested. - -Activation depends on SECRETS-WP-0007-T04 (exact production actions) and -SECRETS-WP-0008-T02/T06 (decision consumption and service authority). Require -canonical ActionAuthorization for each protected action, successful consume, -and exact scoped backend authority. This draft cannot authorize itself; an -operator browser token or unsafe-demo flag is not a runtime substitute. - -Once those services exist: obtain the reviewed apply authorization, apply this -exact policy/AppRole with scoped authority, verify positive read and denied -metadata/sibling/write access without exposing values, and record delivery-ready -state. Bind approved exec authorization and named engine service authentication -to the sand-boxer owner route. Prove actual provider authentication and a bounded -Glas task, then activate routing and only the validated profile. - -Rotation: store replacement with CAS, stop old runs, verify replacement, revoke -predecessor at Anthropic and prove denial. Bao session expiration does not revoke -the provider key. Compromise disables the provider key and affected runs first. diff --git a/src/secrets_engine/catalog.py b/src/secrets_engine/catalog.py index 0b063e9..736c214 100644 --- a/src/secrets_engine/catalog.py +++ b/src/secrets_engine/catalog.py @@ -284,8 +284,6 @@ def validate_entry(data: dict[str, Any], *, source: str = "") -> Catalog delivery_auth = data["delivery_auth"] if not isinstance(delivery_auth, dict): raise CatalogError(f"{source}: delivery_auth must be a mapping") - if "metadata_read" in delivery_auth and not isinstance(delivery_auth["metadata_read"], bool): - raise CatalogError(f"{source}: delivery_auth.metadata_read must be boolean") auth_method = delivery_auth.get("method", "approle") auth_management = delivery_auth.get("management", "engine") if auth_method not in VALID_DELIVERY_AUTH_METHODS: diff --git a/src/secrets_engine/roles.py b/src/secrets_engine/roles.py index fb93dd4..35d0500 100644 --- a/src/secrets_engine/roles.py +++ b/src/secrets_engine/roles.py @@ -175,10 +175,10 @@ def lane_policy_paths(entry: CatalogEntry) -> dict[str, list[str]]: """The minimal KV v2 paths + capabilities a consumer policy needs for a lane.""" data_path = f"{entry.mount}/data/{entry.path}" meta_path = f"{entry.mount}/metadata/{entry.path}" - paths = {data_path: ["read"]} - if entry.delivery_auth.get("metadata_read", True): - paths[meta_path] = ["read"] - return paths + return { + data_path: ["read"], + meta_path: ["read"], + } def render_policy_hcl(policy_name: str, paths: dict[str, list[str]]) -> str: diff --git a/tests/test_guards.py b/tests/test_guards.py index 1a41687..437d221 100644 --- a/tests/test_guards.py +++ b/tests/test_guards.py @@ -114,20 +114,3 @@ def test_every_admitted_lane_renders_existing_mount_check_and_exact_policy(): assert f'path "{entry.kv_data_path}"' in plan.policy_hcl assert "*" not in entry.kv_data_path assert plan.role_name.startswith("se-prod-") - - -def test_metadata_read_can_be_excluded_without_changing_default(): - from secrets_engine.roles import lane_policy_paths - default = _entry(stage="test", path="test/team/thing") - assert "secret/metadata/test/team/thing" in lane_policy_paths(default) - narrow = _entry(stage="test", path="test/team/thing", delivery_auth={ - "method":"approle", "management":"engine", "metadata_read":False}) - assert lane_policy_paths(narrow) == {"secret/data/test/team/thing":["read"]} - assert "metadata/" not in build_plan(narrow, "test").policy_hcl - - -@pytest.mark.parametrize("invalid", ["false", None, 0, [], {}]) -def test_metadata_read_setting_requires_boolean(invalid): - from secrets_engine.errors import CatalogError - with pytest.raises(CatalogError, match="metadata_read must be boolean"): - _entry(delivery_auth={"metadata_read":invalid}) diff --git a/workplans/SECRETS-WP-0009-glas-claude-native-delivery.md b/workplans/SECRETS-WP-0009-glas-claude-native-delivery.md deleted file mode 100644 index 5123d78..0000000 --- a/workplans/SECRETS-WP-0009-glas-claude-native-delivery.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -id: SECRETS-WP-0009 -type: workplan -title: "Activate native Claude credential delivery for Glas" -domain: infotech -repo: secrets-engine -status: blocked -owner: codex -created: "2026-09-05" -updated: "2026-09-05" -state_hub_workstream_id: "40ccc3b4-d046-5a58-8649-e7935f45c974" ---- - -Demand: GLAS-WP-0012-T02 / SAND-WP-0015-T04, custody CCR-2026-0016. -The user authorized continuing credential delivery after storing the key in Bao. -This record tracks native read-lane adoption, not a new provider key or rotation. - -## Define the exact native read lane - -```task -id: SECRETS-WP-0009-T01 -status: done -priority: high -state_hub_task_id: "4f1cf242-3aec-56a8-b958-5d53823875e0" -``` - -Added catalog glas-claude-agent-dev-anthropic; plan checks existing platform -mount and proposes one data-only read policy/AppRole. Token TTL5m/max15m, -single-use SecretID5m, token use budget8. See docs/glas-claude-delivery.md. -No metadata, sibling, listing or write capability is proposed. - -## Support data-only delivery policies - -```task -id: SECRETS-WP-0009-T02 -status: done -priority: high -state_hub_task_id: "fa4a3e87-0854-5e2b-af44-facd5b25f443" -``` - -Added boolean delivery_auth.metadata_read with compatible default true and -explicit false for this lane. Validation refuses non-booleans; generated plan -omits metadata permissions when disabled. Full owner suite passes. Sand-boxer -synthetic exec-env transport proof passed; no real secret was read. - -## Activate the approved native lane and verify real owner delivery - -```task -id: SECRETS-WP-0009-T03 -status: wait -priority: high -state_hub_task_id: "f8069c8a-ad6b-5d0b-9a36-c2326699437d" -``` - -Depends on SECRETS-WP-0007-T04 and SECRETS-WP-0008-T02/T06: canonical production -authorization, successful consume and scoped service authority must exist. -Current production exec refuses before OpenBao because durable access-engine -decision records are not served. Do not bypass this with unsafe-demo or a human -operator runtime token. Then apply the exact read policy/AppRole, prove positive -and negative access, register delivery-ready evidence, bind owner exec with -service authentication, and return verified pins/evidence to SAND-WP-0015 and -GLAS-WP-0012. Provider scope/budget and expiry remain explicit acceptance inputs. -Keep the catalog route inactive until real verification passes.