feat(agent-access): add codex OpenClaw ssh-agent TTL wrapper #77
No reviewers
Labels
No labels
W6d-automerge-calibration
agent/claude-code
agent/codex
agent/hermes
agent/iskra
agent/ollama
agent/patchwarden
automerge-candidate
class/security-sensitive
cutover-gate
dependency/blocked
dependency/blocks-others
dependency/cross-repo
dependency/needs-confirmation
domain:agents
domain:ci
domain:docs
domain:forgejo
domain:infra
domain:memory
domain:runtime
domain:signal
domain:ux
flow/architecture
flow/blocked
flow/deployed
flow/done
flow/implementation
flow/intake
flow/maintained
flow/observed
flow/ready
flow/refining
flow/retired
flow/review
iterating
judge/codex-candidate
judge/hermes-candidate
judge/low-confidence
judge/needs-refinement
judge/operator-needed
judge/p0
judge/p1
judge/p2
judge/p3
judge/park
judge/patchwarden-candidate
judge/stale-priority
kind/adr
kind/bug
kind/chore
kind/feature
kind/infra
kind/ops
kind/refactor
kind/research
large-impact
merge/auto
merge/manual
merge/manual-dependency-conflict
merge/manual-failing-tests
merge/manual-merge-conflict
merge/manual-missing-review
merge/manual-operator-preference
merge/manual-red-zone
merge/manual-security-sensitive
merge/manual-unclear-scope
merge/manual-unknown
meta
mode:operator-only
mode:patchwarden-iskra-approved
mode:safe-auto
needs-operator-decision
needs-triage
not-ready
observed/erroring
observed/needs-followup
observed/pending
observed/retire-candidate
observed/unused
observed/used
operator-emotional
owner-attention
phase/02
phase/03
priority:p0
priority:p1
priority:p2
priority:p3
proposed
ready-for-agent
ready-for-operator
recovery
review:claude-reviewed
review:codex-reviewed
review:dziadek-reviewed
review:needs-human
risk/exposure
risk/process
risk/product
risk/runtime
safety:external-write
safety:no-prod-mutation
safety:prod-impact
safety:secret-touch
size/large
size/medium
size/small
size/tiny
size/unknown
source/adr
source/agent-generated
source/manual
source/operator-chat
source/voice-note
status:blocked
status:codex-ready
status:merged:pending-evidence
status:needs-evidence
status:operator-needed
status:parked
tier/full
tier/lite
tier/stacked
tier:0-platform-substrate
tier:1-iskra-value-layer
tier:2-tools-products-modules
type:bug
type:chore
type:docs
type:feat
type:policy
type:research
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
pdurlej/platform!77
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "codex/issues/73-agent-access-ssh-ttl"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Canary status: defer_to_issue — accepted by operator and merged; session lifecycle hardening tracked in #79
Canary Context Pack
Product story
The operator needs to delegate real OpenClaw/VPS1000 checks to Codex without pasting SSH keys into chat or leaving private keys on disk. This is the first narrow child of #76 Agent Access Plane: agents receive a bounded SSH capability, not a standing raw credential.
What changed
scripts/agent-access/codex-openclaw-ssh-agent, a Python wrapper that starts a dedicatedssh-agent, loads an Infisical-injected key viassh-add -t, and writes only non-secret session state under~/.platformctl-runtime/agent-access/sessions/<session-id>/.docs/agent-access/codex-openclaw-ssh.mdwith operator usage, stop conditions, and runtime layout.state/runtime-layout.mdwith the new non-secretagent-access/session directory.--stoprevoke without secret env.ssh_hintnow forcesIdentityAgent="$SSH_AUTH_SOCK",IdentityFile=none, andIdentitiesOnly=no; wrapper printsrevoke_hint;--stop <session-id>kills the session agent and marks metadata; unexpected exceptions now kill started agents; emptyssh-add -loutput becomesAgentAccessError.Why it changed
#73 identified Codex SSH key delivery as the immediate friction point. Oracle review and product framing confirmed the larger direction (#76), but the safe first slice is still one capability:
openclaw.ssh.codex-localvia TTL ssh-agent.Files touched
scripts/agent-access/codex-openclaw-ssh-agentdocs/agent-access/codex-openclaw-ssh.mdcontrol-plane/platformctl/tests/test_agent_access_ssh_agent.pystate/runtime-layout.mdRelevant context
pdurlej/iskra-openclaw#43: broader SecretRef/Agent Vault architecture to migrate/split laterpdurlej/iskra-openclaw#44and PR #45: existing OpenClaw Path A wrapper and public-key sideRuntime evidence
PYTHONPATH=control-plane pytest -q control-plane/platformctl/tests/test_agent_access_ssh_agent.py=> 7 passed.PYTHONPATH=control-plane pytest -q control-plane/platformctl/tests=> 154 passed.git diff --check HEAD~1 HEAD=> pass.--skip infisical --skip review --skip mcp; full doctor still fails on missing local Infisical token-cache, so this PR does not claim full identity-doctor coverage./home-platform/agent_access/ssh/openclaw/codex-localin prod injectsOPENCLAW_SSH_PRIVATE_KEY; wrapper printsPASS capability=openclaw.ssh.codex-localand loads fingerprintSHA256:unGNI4x7pKVTlxP4Cnrs8RhYmlIvRBcGFqo4qByelFAwithttl_seconds=3600.agent.env,ssh-add -l -E sha256lists the same fingerprint;ssh -o BatchMode=yes -o ForwardAgent=no -o IdentityAgent="$SSH_AUTH_SOCK" -o IdentityFile=none -o IdentitiesOnly=no openclaw@vps1000 'ls /home/openclaw/.local/bin/'succeeds via the forced-command wrapper.iskra-canary --json --timeout-seconds 30; it returnsstatus=criticalfrom Iskra runtime health, which is not an SSH/access failure.revoke_hint=scripts/agent-access/codex-openclaw-ssh-agent --stop <session-id>; running it returnsPASS stopped_session=<session-id>and subsequentssh-add -lagainst that socket fails withError connecting to agent: No such file or directory.Known constraints
infisical run. It does not fetch secrets itself and does not print them.ssh-agent/ssh-addprocesses receive a sanitized environment; the private-key env var is popped before child execution.agent.envfile is non-secret but access-bearing while the agent TTL is alive; runtime dir permissions,IdentityFile=none, and TTL bound the exposure.Explicit out-of-scope
infisical run -- bashor arbitrary command execution with secrets$HOME/.ssh,/tmp, dotenv files, repo files, logs, or PR textRequested decision
Approve this first implementation slice for #73 now that Infisical path validation, live forced-command SSH smoke, explicit identity isolation, and revoke smoke pass.
Merge blockers
$HOME/.ssh, or/tmp.ssh-agentorssh-addchild processes.ssh-agentload + forced-command SSH smoke +--stoprevoke.Spec sources read
PLATFORM_CHARTER.md§runtime state and service identities — runtime/secret boundaries.state/runtime-layout.md— canonical machine-local runtime layout.AGENTS.md— identity, canary, and PR body conventions.control-plane/platformctl/identity/codex.py— codex askpass/worktree identity pattern.control-plane/platformctl/tests/test_codex_askpass.py— local pytest style for identity/runtime wrappers.Closes #73
Post-merge note from Codex: operator accepted
defer_to_issueterminal for #77 and merged after live evidence passed.Evidence before merge:
OPENCLAW_SSH_PRIVATE_KEY.ssh-agentloaded fingerprintSHA256:unGNI4x7pKVTlxP4Cnrs8RhYmlIvRBcGFqo4qByelFAwith 1h TTL.openclaw@vps1000succeeded withIdentityAgent="$SSH_AUTH_SOCK"andIdentityFile=none.--stop <session-id>revoke smoke succeeded.