id: credentials
title: A session gets a credential without a wrapper process
status: open
crates: [didbot-attest]
dependsOn: [oauth, attestation]
exitCriterion: >
An ordinary session, configured only through settings.json, receives a
credential scoped to its own agent account and writes with it. #
The system installs as configuration the harness already reads, and may not
require a wrapper. That costs the kernel-level session marker a wrapper
would give, and moves the anchor up to the node.
The shape mirrors SPIFFE: a node attests once, a local component issues
credentials, and the workload talks to the server itself. Nothing brokers a
write, and nothing assumes co-location.
The daemon presents each context's agent token on the four sign-in decision
routes, and didbot-oauth direct mode spends one from the environment.
auth-types names that token as the one to retire. This
section decides what replaces it before any of it is built.
Until then the daemon keeps the agent token, and no call changes which
credential it presents.
Adjacent, and worth knowing about here: a harness client
carries a write credential (didbot_pds::credential, minted at
provisioning) by stamping it onto the tool call, not through
CLAUDE_ENV_FILE. That solves plan/auth-types.md's narrower problem — a
credential has to exist and reach the write path at all, for the repo write
surface to require one without breaking every write this deployment already
makes — without solving this epic's actual shape: a credential a hook stamps
into one tool call is bound to that call, not delivered to the session for
every later tool execution the way this epic's CLAUDE_ENV_FILE item asks
for. It also does not touch node identity, the trusted-set question, or
either of the per-agent boundary items below. Whether the stamped credential
is the same thing this epic should end up issuing, or a stopgap this epic's
delivery mechanism eventually replaces, is not decided here.