feat: prepare data-only Anthropic native delivery lane

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0726e-5232-73f2-aaca-2c05ceb62efb
This commit is contained in:
tegwick 2026-09-06 00:25:37 +02:00
parent ebdff586fe
commit 6a0daae437
7 changed files with 202 additions and 4 deletions

View file

@ -0,0 +1,60 @@
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

View file

@ -120,3 +120,10 @@ 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.

View file

@ -0,0 +1,53 @@
# 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.

View file

@ -284,6 +284,8 @@ def validate_entry(data: dict[str, Any], *, source: str = "<memory>") -> 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:

View file

@ -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}"
return {
data_path: ["read"],
meta_path: ["read"],
}
paths = {data_path: ["read"]}
if entry.delivery_auth.get("metadata_read", True):
paths[meta_path] = ["read"]
return paths
def render_policy_hcl(policy_name: str, paths: dict[str, list[str]]) -> str:

View file

@ -114,3 +114,20 @@ 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})

View file

@ -0,0 +1,59 @@
---
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"
---
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
```
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
```
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
```
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.