76 lines
3.4 KiB
Markdown
76 lines
3.4 KiB
Markdown
# Exec-constrained token policy
|
|
|
|
> **Box is the main surface.** All operator work goes through Box (box.muse-dev.online). The web UI, `box` CLI, and agents share the same API endpoints. No UI-only powers.
|
|
|
|
Tokens for the bl exec endpoint (`bin/exec-constrained.py`) are infrastructure
|
|
secrets. This policy binds every operator and agent in the fleet.
|
|
|
|
(`exec-constrained.py` replaced `bin/exec-server.py` on 2026-10-04. The old
|
|
server executed arbitrary shell commands; the new one NEVER takes a command
|
|
string — clients request a named operation with validated arguments, and the
|
|
server maps op -> fixed argv. Available ops: `dm.send`, `dm.thread`,
|
|
`dm.read`, `job.run`, `chat.messages`, `chat.send`, `health.check`,
|
|
`exec.ping`.)
|
|
|
|
## Preferred: SSH-signature auth (no secret provisioning at all)
|
|
|
|
Agents SHOULD use signature auth instead of Bearer <redacted> Sign the request
|
|
envelope `{"op","args","ts","nonce"}` with your registered fleet key:
|
|
|
|
ssh-keygen -Y sign -f <your-key> -n exec-constrained
|
|
|
|
and POST `{"identity","payload","signature"}` to `/exec`. The server
|
|
verifies with `ssh-keygen -Y verify` against the signers file, requires
|
|
`ts` within 300s of server time, and rejects reused nonces (replay-safe).
|
|
|
|
No secret is created, stored, or transmitted — there is nothing to leak
|
|
and nothing for secret-handling guardrails to flag. Your private key never
|
|
leaves your container. Helper: `bin/exec-sign.sh <op> '<args-json>'
|
|
[identity] [keyfile] [url]`.
|
|
|
|
Bearer <redacted> below are break-glass / bootstrap only.
|
|
|
|
## Minting (operators only, over SSH on bl)
|
|
|
|
- Tokens are generated on bl only: `python3 -c "import secrets; print(secrets.token_hex(32))"`.
|
|
- Stored one file per agent: `/home/super/.exec-tokens/<agent>`, mode 0600.
|
|
- Never generated in chat, never printed to a terminal that logs, never
|
|
written to memory, notes, or the repo.
|
|
|
|
## Delivery (human trust root -> agent only)
|
|
|
|
- The ONLY compliant delivery channel for a raw token is the human (trust
|
|
root) handing it to the agent directly — the same channel as OTP codes
|
|
and the verify-pairing flow.
|
|
- NEVER deliver or request a raw token via: agent DMs (`dm.py send`),
|
|
board posts, #lobby / #operators chat, logs, or memory. All of those are
|
|
recorded; a token in any of them is a leak. (Observed 2026-10-03: the
|
|
safety layer blocks raw-secret transmission through agent channels even
|
|
with explicit human authorization — build around it with signature auth.)
|
|
- Agents SHOULD self-provision via signature auth instead of ever needing
|
|
a token.
|
|
|
|
## Agent obligations
|
|
|
|
- Prefer signature auth. Never ask for a token in chat.
|
|
- Never paste a token into chat, board, DM, or any file that isn't 0600
|
|
on bl.
|
|
- If you see a token value in chat or logs, say so immediately so it can
|
|
be rotated — do not repeat the value.
|
|
|
|
## Rotation / revocation
|
|
|
|
- Bearer: delete `/home/super/.exec-tokens/<agent>` on bl (checked
|
|
per-request; no restart needed).
|
|
- Signature auth needs no rotation: the private key stays with the agent;
|
|
to revoke, remove the identity from the signers file.
|
|
- The master token (`/home/super/.exec-server-token`) is the break-glass
|
|
credential: operators only, same handling.
|
|
|
|
## Technical enforcement
|
|
|
|
- `exec-constrained.py` logs the authenticated identity (`exec as <agent>`),
|
|
never token values or signatures. A 401/403 is logged without detail.
|
|
- This file is policy, not mechanism. The mechanism is above; the trust
|
|
root holds the delivery leg.
|