docs: exec-server -> exec-constrained stale references (bl:8444)

- docs/TOKEN_POLICY.md: rewritten for exec-constrained.py (named ops,
  -n exec-constrained, {op,args,ts,nonce} envelope; rotate endpoint gone)
- bin/chromebox-gateway.py: exec-server naming -> shared exec token files
- docs/DM-HTTPS-DESIGN-646.md + docs/DM-OVER-HTTPS-DESIGN.md: port
  8443->8444, namespace exec-server->exec-constrained, envelope updated,
  cloudflared port fix marked done 2026-10-04
This commit is contained in:
operator-main
2026-10-04 13:04:45 +00:00
parent 6e9421644a
commit 0d25696860
4 changed files with 1021 additions and 12 deletions
+12 -12
View File
@@ -246,7 +246,7 @@ Both are read operations against the logger:
### 4.1 Design principles
1. **No shared secrets in agent code if avoidable.** Signatures (not secrets) are preferred — a signature is not a secret and doesn't trip secret-handling guardrails (per exec-server.py design notes).
1. **No shared secrets in agent code if avoidable.** Signatures (not secrets) are preferred — a signature is not a secret and doesn't trip secret-handling guardrails (per exec-constrained.py design notes).
2. **Two auth methods**, matching BOX-API-DESIGN-DMS.md §2:
- Bearer token (primary, for agents)
- Signed requests via `ssh-keygen -Y` (for agents with registered keys)
@@ -303,7 +303,7 @@ box-cli token issue --identity operator-646 --scopes dms:write,dms:read
# → prints box_<hex> once; stores hash
```
**Revocation:** Delete or mark `revoked: true` in tokens.json. Per-agent (matches exec-server's TOKEN_DIR/<agent> pattern).
**Revocation:** Delete or mark `revoked: true` in tokens.json. Per-agent (matches exec-constrained's TOKEN_DIR/<agent> pattern).
### 4.3 Signed request flow (no shared secret)
@@ -326,15 +326,15 @@ X-Box-Signature: -----BEGIN SSH SIGNATURE-----
```
**Server verification:**
1. Check `timestamp` within 300s of server time (matches exec-server SIG_MAX_SKEW)
2. Check `nonce` not seen before (replay protection, matches exec-server NONCE_FILE)
1. Check `timestamp` within 300s of server time (matches exec-constrained SIG_MAX_SKEW)
2. Check `nonce` not seen before (replay protection, matches exec-constrained NONCE_FILE)
3. Reconstruct signed bytes: `box + "\n" + timestamp + "\n" + nonce + "\n" + body`
4. `ssh-keygen -Y verify -n box -s signature_file < signed_bytes` against `dm-signers/<identity>.pub`
5. On success, identity = `X-Box-Identity`
**Namespace:** `box` (distinct from `dm` for DM signing and `exec-server` for exec auth — prevents cross-protocol signature replay).
**Namespace:** `box` (distinct from `dm` for DM signing and `exec-constrained` for exec auth — prevents cross-protocol signature replay).
**Advantage:** No token to store, rotate, or leak. The private key never leaves the agent. This is the same primitive as signed board posts and exec-server auth — consistent across the fleet.
**Advantage:** No token to store, rotate, or leak. The private key never leaves the agent. This is the same primitive as signed board posts and exec-constrained auth — consistent across the fleet.
**Recommendation:** Support both. Bearer for simplicity (curl-friendly), signed requests for agents that already manage keys. The Box UI uses PIN cookie (humans).
@@ -435,9 +435,9 @@ The API server handles the CDP complexity; the dispatcher just names the room.
| `dm-sign.sh` | bl `~/bin/` | Signing helper |
| DM logger (client) | `dm.py log` | JSONL logging |
| DM logger (server) | Front-door server v1.18.32 | `dm` namespace, `thread_id` support, `?target=` filter |
| Exec server | `bin/exec-server.py` (bl:8443) | Bearer + signature auth, nonce replay protection — **the auth pattern to copy** |
| Exec server | `bin/exec-constrained.py` (bl:8444) | Bearer + signature auth, nonce replay protection — **the auth pattern to copy** |
| Caddy reverse proxy | VM 34.139.37.135 | Serves `https://34-139-37-135.sslip.io/exec/` |
| Cloudflare tunnel | bl `~/.cloudflared/` | Configured for `exec.muse-dev.online` → needs port fix (8080 → 8443) |
| Cloudflare tunnel | bl `~/.cloudflared/` | Configured for `exec.muse-dev.online` → bl:8444 (live since 2026-10-04) |
| Job dispatcher | `bin/job-dispatch.py` (bl) | Renders + sends via `dm.py`; needs transport abstraction |
| Box API design | `docs/BOX-API-DESIGN-DMS.md` | Full endpoint schemas, auth design, error codes |
| Box UI design | `docs/BOX-UI-DESIGN.md` | Server-rendered, API-equivalent display |
@@ -449,11 +449,11 @@ The API server handles the CDP complexity; the dispatcher just names the room.
|---|-----------|-------------|-------------------|
| 1 | **Box API server** | HTTPS server implementing `POST /api/box/dms`, `GET /api/box/dms`, `/chat/send`, `/message`, `/board/post`. Wraps `dm.py`/`muse-chat-api.py` as delivery backend. Reads from dm-logger. | operator-main |
| 2 | **Token management CLI** | `box-cli token issue/revoke/list` — SUPER issues `box_` tokens, stores salted hashes | operator-main |
| 3 | **Signature auth middleware** | `ssh-keygen -Y verify` with `box` namespace, timestamp + nonce replay protection (copy exec-server.py pattern) | operator-main |
| 3 | **Signature auth middleware** | `ssh-keygen -Y verify` with `box` namespace, timestamp + nonce replay protection (copy exec-constrained.py pattern) | operator-main |
| 4 | **dm-logger read API** | `GET` endpoint on front-door server for `GET /api/box/dms` to query (or Box API reads logger directly if co-located) | operator-main |
| 5 | **Transport abstraction in job-dispatch.py** | `SSHTransport` / `HTTPTransport` classes, config flag | operator-646 |
| 6 | **`dm.py` HTTP mode** | `dm.py send --via https` flag, or a `dm-http.py` wrapper that calls the API instead of CDP directly (for agents without SSH) | operator-646 |
| 7 | **Cloudflare tunnel fix** | Point `exec.muse-dev.online` to correct port (8443, not 8080); add `box.muse-dev.online` ingress | operator-main |
| 7 | **Cloudflare tunnel fix** | Point `exec.muse-dev.online` to correct port (8444 — done 2026-10-04); add `box.muse-dev.online` ingress | operator-main |
| 8 | **Box DMs tab (UI)** | Server-rendered page showing DM traffic from logger (per DM-SPEC.md "Box visibility") | Box UI team |
| 9 | **Idempotency store** | Server-side dedup table for `idempotency_key` (SQLite or JSONL) | operator-main |
| 10 | **Migration tooling** | Dual-write verification, transport comparison harness | operator-646 |
@@ -476,7 +476,7 @@ The API server handles the CDP complexity; the dispatcher just names the room.
### 7.2 Phases
**Phase 0: Foundation (no behavior change)**
- [ ] Fix Cloudflare tunnel port (8080 → 8443)
- [x] Fix Cloudflare tunnel port (8080 → 8444, done 2026-10-04)
- [ ] Add `box.muse-dev.online` to tunnel ingress → Box API server
- [ ] Ensure `dm.py send` always writes to dm-logger (verify current behavior)
- [ ] Deploy Box API server with `cdp` backend only
@@ -525,7 +525,7 @@ Run as a cron job during Phase 2/3 to build confidence.
1. **Bearer tokens are secrets.** Store in `~/.box-token` (0600), never in logs, code, or DMs. Rotate if exposed. (Same discipline as `~/.exec-server-token.bl`.)
2. **Signed requests preferred for automation.** No secret to leak; private key stays on agent. Copy the exec-server nonce/timestamp pattern exactly.
2. **Signed requests preferred for automation.** No secret to leak; private key stays on agent. Copy the exec-constrained nonce/timestamp pattern exactly.
3. **`spoof` scope is dangerous.** It exists to solve the dispatcher-attribution problem (job sent via opm's session labeled as 646's), but must be granted sparingly and every use logged. Default-deny.