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:
parent
ebdff586fe
commit
6a0daae437
7 changed files with 202 additions and 4 deletions
60
catalog/glas-claude-agent-dev-anthropic.yaml
Normal file
60
catalog/glas-claude-agent-dev-anthropic.yaml
Normal 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
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
53
docs/glas-claude-delivery.md
Normal file
53
docs/glas-claude-delivery.md
Normal 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.
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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})
|
||||
|
|
|
|||
59
workplans/SECRETS-WP-0009-glas-claude-native-delivery.md
Normal file
59
workplans/SECRETS-WP-0009-glas-claude-native-delivery.md
Normal 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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue