From b386b796e330d7e4a47b93054074de05d6e22ce1 Mon Sep 17 00:00:00 2001 From: tegwick Date: Sat, 24 Oct 2026 23:49:27 +0200 Subject: [PATCH] GLAS-WP-0018: assess session-scoped agent identity and tool boundary; propose workplan Co-Authored-By: Claude Sonnet 5.5 Assistant: claude-code Assistant-Model: sonnet Assistant-Process: 328925@bnt-lap001 Assistant-Session: 14b795fd-c632-4c01-8d28-e7e490c7b0ed --- WORK-RECORDS.md | 7 + ...n-identity-and-tool-boundary-assessment.md | 165 ++++++++++++++++++ ...ession-agent-identity-and-tool-boundary.md | 101 +++++++++++ 3 files changed, 273 insertions(+) create mode 100644 history/2026-10-24-agent-session-identity-and-tool-boundary-assessment.md create mode 100644 workplans/GLAS-WP-0018-session-agent-identity-and-tool-boundary.md diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index ffe8d74..e56f9b5 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -26,6 +26,7 @@ | workplan | GLAS-WP-0015 | blocked | — | workplans/GLAS-WP-0015-production-dependency-coordination.md | | workplan | GLAS-WP-0016 | blocked | — | workplans/GLAS-WP-0016-fi-research-brief-profile.md | | workplan | GLAS-WP-0017 | blocked | — | workplans/GLAS-WP-0017-assembly-checkpoint-governed-route.md | +| workplan | GLAS-WP-0018 | proposed | — | workplans/GLAS-WP-0018-session-agent-identity-and-tool-boundary.md | | task | ADHOC-2026-09-06-T01 | done | — | workplans/ADHOC-2026-09-06.md | | task | ADHOC-2026-09-06-T02 | done | — | workplans/ADHOC-2026-09-06.md | | task | ADHOC-2026-09-06-T03 | done | — | workplans/ADHOC-2026-09-06.md | @@ -90,6 +91,12 @@ | task | GLAS-WP-0016-T06 | done | — | workplans/GLAS-WP-0016-fi-research-brief-profile.md | | task | GLAS-WP-0017-T01 | done | — | workplans/GLAS-WP-0017-assembly-checkpoint-governed-route.md | | task | GLAS-WP-0017-T02 | wait | — | workplans/GLAS-WP-0017-assembly-checkpoint-governed-route.md | +| task | GLAS-WP-0018-T01 | todo | — | workplans/GLAS-WP-0018-session-agent-identity-and-tool-boundary.md | +| task | GLAS-WP-0018-T02 | todo | — | workplans/GLAS-WP-0018-session-agent-identity-and-tool-boundary.md | +| task | GLAS-WP-0018-T03 | todo | — | workplans/GLAS-WP-0018-session-agent-identity-and-tool-boundary.md | +| task | GLAS-WP-0018-T04 | wait | — | workplans/GLAS-WP-0018-session-agent-identity-and-tool-boundary.md | +| task | GLAS-WP-0018-T05 | todo | — | workplans/GLAS-WP-0018-session-agent-identity-and-tool-boundary.md | +| task | GLAS-WP-0018-T06 | todo | — | workplans/GLAS-WP-0018-session-agent-identity-and-tool-boundary.md | | intake | GLAS-IN-0001 | done | blue | docs/intakes/residuals.md | | intake | GLAS-IN-0002 | todo | red | docs/intakes/residuals.md | | intake | GLAS-IN-0003 | todo | green | docs/intakes/residuals.md | diff --git a/history/2026-10-24-agent-session-identity-and-tool-boundary-assessment.md b/history/2026-10-24-agent-session-identity-and-tool-boundary-assessment.md new file mode 100644 index 0000000..6ce9137 --- /dev/null +++ b/history/2026-10-24-agent-session-identity-and-tool-boundary-assessment.md @@ -0,0 +1,165 @@ +# Assessment: session-scoped agent identity and tool boundary + +Date: 2026-10-24. Status: assessment only; no harness behavior changed. +Request: net-kingdom hub message 14ea093a (standard +`service-identity-privilege_v0.1.md` draft-3 SI-14, SI-15; companion section 7; +SEC-DSM DSM-AGENT-002, -007, -008). key-cape assesses the issuing side in parallel. +Plan: `workplans/GLAS-WP-0018-session-agent-identity-and-tool-boundary.md`. + +## Verdict + +Feasible for the sessions glas-harness actually launches, in three separable steps. +Glas is the right place for (a) carriage and (b) attribution, and for *declaring* +(c); enforcement of (c) belongs to the rein, the sandbox and the token's audience. +Glas cannot control a person's interactive Claude Code, Codex or Grok terminal +session; for those it can only offer a shared contract and helper. Be explicit in +the declaration that such sessions stay at SI-14's "holds the person's reach". + +## What exists today + +Evidence is from `src/glas_harness/{gateway,contract,hub}.py`, the reins and profiles. + +| Need | Today | Gap | +|---|---|---| +| Actor type | `ExecutionRequest.actor` is `adm`/`agt`/`atm`, validated into sand-boxer `Consumer`; `run_id` is the request id. Docs state attribution is "not caller authentication". | A label, not an IAM principal. No `principal_type=agent`, no `act.sub`, no token. | +| Per-run identity | `request_id` (uuid) names the run and the sandbox consumer. Sandbox is per run and destroyed after. | Nothing binds `request_id` to an issuer-signed subject. | +| Credentials | `credential_route_refs` are labels passed to the sandbox owner (`SandboxExecRequest.credential_route_refs`), applied only to the workload command; secret-looking values are refused in profiles. | A KeyCape agent token is a new credential class with no route. The owner (sand-boxer / credential owner) must deliver it. | +| Tool boundary | Profile field `tool_profile` (for example `green-commit-only`) is passed as `--tool-profile` to rein-aharness / rein-openweights; the rein enforces it. Sandbox profile (bwrap, egress deny-by-default) bounds filesystem and network. | Glas does not know what a tool profile allows; it is an opaque string. No Glas-side check that the profile is narrower than the person's reach. Tool profiles do not name credentials or hub write scope. | +| Attribution record | `ExecutionEvidence` (actor, project, profile, rein, model, sandbox_id, commit_sha, timings, tool_events_count and completeness, refs to assignment/role/duty). Posted to the Hub as a `gateway_run` progress event with hard-coded `author: agt-glas-harness`. | Aggregate per run, not per state-changing action. Tool events are `complete` only when the rein streams them, parsed after the subprocess ends; `unavailable` for open-weight. No `on_behalf_of`, no session identity, no evidence location/hash. Hub author is unauthenticated free text (the declared net-kingdom gap). Hub post is best-effort, no outbox. | +| Commit trailers | Commits inside the sandbox are made by the rein. | Glas neither requires nor verifies `Assistant`, `Assistant-Session`, `Assistant-Process`. | +| Limits | Token, turn, USD budgets and per-command timeout passed to reins that support them. | No aggregate wall clock; nothing ties session lifetime to token lifetime (60 minute ceiling). | +| Readiness | No committed profile is `ready`. | Any identity feature starts on unverified/blocked profiles, so it cannot yet claim production assurance. | + +## (a) Per-session agent identity + +Design sketch (not implemented): + +1. Add an optional `identity` section to `ExecutionRequest` / profile: required + `on_behalf_of` (the person, becomes `act.sub`), `mode` (`agent`), requested + `ttl_seconds` (profile ceiling 3600), `audience` list. +2. Before `rein.start_session`, the gateway asks a pluggable `AgentIdentityIssuer` + (interface in Glas, KeyCape-backed adapter) for a token whose subject is the run + (`agent:`), `principal_type=agent`, `act.sub` the person, expiry + `min(profile ttl, remaining timeout, 3600)`. Fail closed: no token, no + identity-requiring profile run (new `failure_stage` such as `identity`). +3. Deliver the token to the workload as a sandbox credential (stdin or a + sandbox-owner delivery route), never in argv, task file, evidence, Hub detail + or logs; never in the person's password safe (SI-9). Redaction of the token + pattern in tool output before it enters `ToolResult`. +4. Carry through tool calls: Glas passes a token handle; the rein presents it to + downstream services. Reins must accept and use it (a rein change), and + downstream services must verify it (their change). Glas alone can only guarantee + issue, scoped delivery, expiry and revocation at teardown. +5. Teardown: discard the token, request revocation if the issuer supports it + (dependency on key-cape), record issuance and revocation in evidence by + token id (`jti`) only. + +Dependencies: KeyCape agent-token issuance (principal_type claim, `act`, +60 minute cap, per-run subject, revocation) and the sandbox/credential owner for +delivery. Without them Glas can stub the issuer for tests but must not claim +identity. + +Effort: contract + issuer interface + fail-closed gateway wiring + tests, +roughly 3 to 5 days in Glas; real issuer adapter and delivery 3 to 5 days after +key-cape and sand-boxer land their sides; rein acceptance of the token is a +separate rein-aharness task. + +## (b) Attribution per state-changing action + +Today's evidence answers "which run, profile, model, sandbox, outcome, commit". +SI-15 also wants "on whose authority" and "where the evidence is kept" per action. + +Proposal: + +- Add `identity_ref` (subject, `act.sub`, token `jti`, issuer, expiry; no token), + `session_id` and `authority_ref` (assignment/role/duty already exist as refs) to + `ExecutionEvidence`. +- Define an `ActionRecord` (actor, on_behalf_of, session, operation, target, + result, evidence_location, evidence_sha256, timestamp). Glas emits one per + commit it can see and one per tool event when the rein streams events; where + the rein cannot report, the record says `events_completeness: unavailable` + rather than implying coverage. This honestly keeps SI-15's "reconstructable" + as partial. +- Write a hashed evidence receipt file (sandbox-external, append-only + location chosen with the custodian), and put its hash in the Hub event. Use a + durable local outbox so the Hub post is not best-effort only. +- Require and verify commit trailers (`Assistant`, `Assistant-Session`, + `Assistant-Process`) on sandbox commits; refuse or flag a run whose commits + lack them. +- Replace the hard-coded Hub author with the run identity once the Hub can + authenticate it; until then record it in `detail` and keep the gap stated. + +Effort: 4 to 6 days. Risk: tool-event coverage is rein-dependent; ActionRecords +from parsed streams are after-the-fact, not tamper-evident, unless the receipt is +stored outside the agent's reach. + +## (c) Session-scoped tool boundary + +Facts: the boundary today is sandbox profile (filesystem, egress) plus rein +`tool_profile`. For a harness-launched session the person's ambient reach is +already mostly absent: the run is in a bwrap sandbox with a deny-by-default +network and no person credentials; `credential_route_refs: []` in the local +profile. The risk SI-14 names is the *interactive* terminal session, which Glas +does not launch. + +Proposal for launched sessions: + +- Make the boundary declarative and checkable: a `boundary` block in the profile + (tool profile id and hash, sandbox profile, egress hosts, credential route refs, + hub write scope, max lifetime) that Glas records in evidence, and a catalog + validation that every profile with a non-empty credential route or + identity requirement names a non-default tool profile. +- Resolve `tool_profile` against a rein-published manifest (rein-aharness + `profiles.py` registry) so Glas can state, not just forward, what the tools + can reach, and fail when the rein reports a different profile than requested + (the rein already echoes `tool_profile` in its result; Glas currently does not + compare). +- Effective authority statement: tools reachable x token audience x sandbox + egress. Emit it per run as evidence (DSM-AGENT-008). +- Bind token audience and scopes to the boundary, so a tool that is callable but + outside the boundary is rejected by the downstream service, not by the model's + good manners (companion section 7 rule 2). + +Effort: 3 to 4 days in Glas plus a rein-aharness manifest export. Risk: a tool +profile that allows shell lets the agent reach whatever the sandbox network and +credentials allow; the sandbox, not the profile name, is the real boundary. + +## Claude Code, Codex and Grok + +| Session type | Glas control | Identity | Tool boundary | Attribution | +|---|---|---|---|---| +| Harness-launched via rein-aharness (Claude CLI inside sandbox) | Full outer lifecycle | Feasible once KeyCape + delivery exist; rein must present the token | Sandbox + tool profile, enforced by sand-boxer and the rein | Run evidence now; per-action partial via streamed events | +| Harness-launched via rein-openweights | Full outer lifecycle | Same, if the rein accepts it | Same | Weaker: tool events unavailable | +| Interactive Claude Code in a person's terminal | None | Could use a helper script that requests a token at session start; person must run it | Claude Code permission and hook settings, set by the person; not Glas | Commit trailers and hub notes only | +| Codex | No rein exists. Needs a new rein (CLI adapter) to be harness-launched | As above once a rein exists | Codex sandbox/approval modes, outside Glas | Trailers already used by Codex commits (`Assistant: codex`) | +| Grok | No rein exists | Same | Not known; unverified | Not verified | + +Honest scope: Glas can only deliver SI-14 conformance for sessions it launches. +For the rest it can publish a small, provider-neutral "session identity +contract" (what a session must obtain, carry, record) that the person or a +wrapper implements. Whether Codex and Grok expose hooks sufficient for per-call +attribution is not established here and needs checking before any claim. + +## Risks and open questions + +1. Token in the sandbox: the agent can read and exfiltrate its own token within + its lifetime. Mitigation is narrow audience, short TTL, egress deny-by-default, + revocation at teardown; it is not eliminated. +2. Identity over a still-blocked runtime: all profiles are non-ready, so this + should be built behind unverified profiles and proven in isolation first. +3. Evidence that the agent can write is not independent evidence; the receipt + location must be outside the sandbox and the verifier independent (SI-15 step 4). +4. Hub authorship stays unauthenticated until the Hub changes (owner: state-hub). +5. `actor` values `adm`/`agt`/`atm` predate this standard; mapping `agt` to + IAM `principal_type agent` needs an agreed table with net-kingdom. +6. Scope creep: Glas must not become an identity provider or policy engine; it + carries and records. Authorization stays with flex-auth and the issuer. + +## Recommended order + +1. Contract fields and evidence (b, identity_ref placeholders) and the + boundary declaration with tool-profile echo check (c): no external + dependency, immediately useful. +2. Issuer interface with a test double; fail-closed gateway path. +3. Real KeyCape adapter and delivery once key-cape and sand-boxer agree. +4. Interactive-session contract and a Codex/Grok feasibility note. diff --git a/workplans/GLAS-WP-0018-session-agent-identity-and-tool-boundary.md b/workplans/GLAS-WP-0018-session-agent-identity-and-tool-boundary.md new file mode 100644 index 0000000..029b828 --- /dev/null +++ b/workplans/GLAS-WP-0018-session-agent-identity-and-tool-boundary.md @@ -0,0 +1,101 @@ +--- +id: GLAS-WP-0018 +type: workplan +title: "Session-scoped agent identity, attribution and tool boundary" +domain: infotech +repo: glas-harness +status: proposed +flavor: implementation +owner: claude +topic_slug: session-agent-identity-tool-boundary +created: "2026-10-24" +updated: "2026-10-24" +--- + +# Session-scoped agent identity, attribution and tool boundary + +Request: net-kingdom message 14ea093a (service-identity-privilege_v0.1 draft-3, +SI-14, SI-15; SEC-DSM DSM-AGENT-002, -007, -008). Assessment: +`history/2026-10-24-agent-session-identity-and-tool-boundary-assessment.md`. +Status is `proposed`: needs founder approval and key-cape / sand-boxer replies +before T04. T01 to T03 have no external dependency. No harness behavior has been +changed by drafting this plan. + +## Contract fields and evidence + +```task +id: GLAS-WP-0018-T01 +status: todo +priority: high +``` + +Add optional `identity_ref` (subject, act.sub, jti, issuer, expiry; never the +token), `session_id` and `on_behalf_of` to the request and `ExecutionEvidence`. +Add hashed evidence-receipt location and sha256. Tests; backwards compatible. + +## Boundary declaration and tool-profile echo check + +```task +id: GLAS-WP-0018-T02 +status: todo +priority: high +``` + +Add a profile `boundary` block, record it in evidence, and fail the run when the +rein reports a tool profile different from the requested one. Catalog validation: +profiles with credential routes or an identity requirement must name a +non-default tool profile. Request rein-aharness to export its tool-profile +manifest. + +## Issuer interface and fail-closed path + +```task +id: GLAS-WP-0018-T03 +status: todo +priority: medium +``` + +Define `AgentIdentityIssuer` with a test double. Gateway obtains a per-run token +(ttl = min(profile, remaining timeout, 3600)), fails closed with a new +`identity` failure stage, redacts the token pattern, and discards/revokes at +teardown. Never put the token in argv, task file, evidence or Hub detail. + +## KeyCape adapter and token delivery + +```task +id: GLAS-WP-0018-T04 +status: wait +priority: medium +``` + +Blocked on key-cape (agent-token issuance, `act`, revocation) and the sand-boxer +or credential owner (delivery route). Agree the `actor` (`adm`/`agt`/`atm`) to +IAM principal_type mapping with net-kingdom. Rein presentation of the token is a +rein-aharness task. + +## Per-action attribution and durable evidence + +```task +id: GLAS-WP-0018-T05 +status: todo +priority: medium +``` + +Emit an ActionRecord per observed commit and streamed tool event, with +completeness stated. Require and verify `Assistant`, `Assistant-Session`, +`Assistant-Process` trailers on sandbox commits. Add a durable local outbox for +Hub reports. Receipt stored outside the sandbox; independent verification +step defined with net-kingdom (SI-15 verify). + +## Interactive-session contract and Codex/Grok feasibility + +```task +id: GLAS-WP-0018-T06 +status: todo +priority: low +``` + +Publish a provider-neutral session identity contract for sessions Glas does not +launch. Check what hooks Codex and Grok offer; decide whether a rein for either +is worth building. Record that interactive sessions remain at SI-14 "person's +reach" until then.