From a612b9a3499627511619d0bd028862912d895e99 Mon Sep 17 00:00:00 2001 From: Rui He Date: Wed, 15 Jul 2026 01:43:57 -0400 Subject: [PATCH] docs(SKILL): govd/exod usage is HTTP-only; local client + cooperative move to cyberware_dev; document the cargo data channel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ouroboros pass on the agent-facing contract. The root SKILL.md now describes ONE method — the pure wire protocol: GET /catalog -> POST /govern -> per-run WebSocket, with exod running each step confined server-side (intent in, status out; you run nothing). Two gaps that caused real confusion are now documented: - var_values: a delegated run's VALUES ride the per-run WS step_request (the claim plane stays KEYS-only), re-gated on the actor's params ACL axis; secrets stay *_FILE. - the cargo data channel: the wire is status-only, so a step that returns DATA writes it under the /cyberware_cargo bind (claim carries cargo:ro|rw) and the caller reads the artifact off the shared mount. Verified end-to-end (delegated fleetbook/retrieve OUT). The cooperative grant/step_result run-from-your-own-registry method + the ./govd-client CLI live entirely in cyberware_dev/SKILL.md — the local-dev path an external agent never needs. Co-Authored-By: Claude Opus 4.8 --- SKILL.md | 71 ++++++++++++++++++++++-------------------- cyberware_dev/SKILL.md | 6 ++++ 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/SKILL.md b/SKILL.md index 5b5894f..2d5159e 100644 --- a/SKILL.md +++ b/SKILL.md @@ -5,9 +5,10 @@ description: >- and more — through cyberware's GOVERNED channel instead of ad-hoc shell. You emit only a CLAIM (a skill, a perk, and your var KEYS) over three calls to the node — GET /catalog, POST /govern, then a per-run WebSocket — and the governance server blesses a value-free plan; you never write, paste, or improvise the - commands. Two run modes: delegated (the node's exod runs each step confined and signs it — you run nothing; - the default for any agent) and cooperative (you run the blessed plan from your own on-disk registry). Reach - for this whenever a task maps to a governed skill. + commands. The node's exod runs each step confined and signs it — you run nothing but the HTTP + WebSocket + calls, and only KEYS + status ever cross the wire (a step's DATA comes back through the cargo mount). A + local-dev cooperative mode that runs the plan from an on-disk registry lives in cyberware_dev. Reach for + this whenever a task maps to a governed skill. --- # cyberware — the governed channel for an agent @@ -72,7 +73,8 @@ issuance**). Send **names + KEYS only — never the values:** **Secrets are never a value, and never a plain key:** a secret-ish key (`PGPASSWORD`, anything `*_TOKEN`, …) is **refused** (`plaintext_secret_key`). Pass it as a **`*_FILE` pointer** instead — a key ending `_FILE` whose value is a path to a `chmod 600` file the snippet `cat`s at runtime. *(Optional body fields: `"approve":[""]` -to confirm a destructive perk after a push_back; `"traceparent":""`.)* +to confirm a destructive perk after a push_back; `"cargo":"ro"|"rw"` to bind the node's `/cyberware_cargo` into +the confined step — the data channel, see step 3; `"traceparent":""`.)* The verdict returns: @@ -99,39 +101,41 @@ are just `"1" … "N"` for `N = plan.sequence.length` — **the plan is the only → {"type":"hello","run_id":"","token":""} ← {"type":"hello_ack","authorized":true} ``` -Then drive the steps — **the exchange differs by execution mode:** - -- **Delegated — *intent in, status out* (the default for any agent that doesn't carry the skill code):** the - node runs each step; `step_request` is answered **directly** with the signed result — there is **no `grant` - frame**: - ``` - for st = 1 … N: - → {"type":"step_request","step":"","plan_sha":""} - ← {"type":"executed","step":"","status":"ok","exit":0,"authority":"exod"} ·or· {"type":"refuse","reason":"…"} → stop - ``` - **exod** ran the step **confined** and Ed25519-signed the status; **you run nothing and send no `step_result`.** - (Requires the node in delegated `exec_mode` with exod attached, else every step is `refuse`d — fail-closed.) -- **Cooperative — you run it from your OWN registry** (you have the skillChip on disk; this is the `./govd-client` - path): `step_request` is answered with `grant`; you run the blessed step locally, then report **status only**: - ``` - for st = 1 … N: - → {"type":"step_request","step":"","plan_sha":""} ← {"type":"grant"} ·or· {"type":"refuse","reason":"…"} → stop - run bash run.sh --step (run.sh = plan.wrapper) with your var VALUES in the ENV - (+ RECORD_STORE=, SNIP=/src dir>) - → {"type":"step_result","step":"","plan_sha":"","status":"ok"|"error","exit":} ← {"type":"recorded"} - stop on the first non-ok step - ``` - First verify your perk's src files match `plan.snippet_shas` (sha256) — file bodies never cross the wire; you - prove authenticity locally. [`cyberware_dev/SKILL.md`](cyberware_dev/SKILL.md) automates all of this. +Then drive the steps — **intent in, status out.** The node's **exod** runs each step **confined** and +Ed25519-signs the status; there is **no `grant` frame**, and **you run nothing** and send no `step_result`: + +``` +for st = 1 … N: +→ {"type":"step_request","step":"","plan_sha":"","var_values":{"":"", …}} +← {"type":"executed","step":"","status":"ok","exit":0,"authority":"exod"} ·or· {"type":"refuse","reason":"…"} → stop +``` + +- **`var_values`** is how a delegated run passes VALUES: the `/govern` claim is **KEYS-only**, so the non-secret + values ride the per-run WS **here** (never the claim plane). The node forwards ONLY plan-declared, non-secret + keys and re-gates them on your **`params`** ACL axis; secrets never cross — keep them `*_FILE` pointers that + exod's vault resolves server-side. +- Requires the node in delegated `exec_mode` with **exod attached**, else every step is `refuse`d (fail-closed). Send a WebSocket **close** frame when the steps finish (or after the first non-ok step). +*(Cooperative mode — running the blessed plan from your OWN on-disk registry, with `grant` / `step_result` +frames instead of `executed` — is the local-dev path in [`cyberware_dev/SKILL.md`](cyberware_dev/SKILL.md). An +external agent never needs it.)* + +**Getting DATA back — the cargo channel.** The wire is **status-only**: `:5773` returns exit codes + signed +provenance, never a perk's output, and a confined step's `RECORD_STORE` is a **server-side** workspace you +cannot read. So a step that must return DATA writes it to the **cargo** bind: add **`"cargo":"ro"|"rw"`** to the +`/govern` claim (binds the node's `/cyberware_cargo` into the confined step), set the perk's output var (e.g. +`OUT`) to a path under `/cyberware_cargo/…`, and read the artifact off that shared mount after the run. The +cargo mount is the **only** data channel out of the confined box — the wire itself stays value-free end to end. + **4 · Read the verdict.** The full signed provenance is `GET BASE/ledger/?token=` (the run token, **not** the Bearer). Confirm each step ran `ok`, note the `plan_sha`, continue. Done. -**Nothing but KEYS in and status out crosses `:5773`** — no var values, no secrets, no command output, and no -agent-authored code. You never edit the blessed plan: a tamper snapshot refuses on drift, and the WS gate -refuses any step whose `plan_sha` or upstream order doesn't match the pinned plan. +**Nothing but KEYS in and status out crosses `:5773`** — no var values on the claim plane, no secrets, no command +output, and no agent-authored code (delegated var VALUES ride the per-run WS; a perk's DATA rides the cargo +mount). You never edit the blessed plan: a tamper snapshot refuses on drift, and the WS gate refuses any step +whose `plan_sha` or upstream order doesn't match the pinned plan. ## Never @@ -149,8 +153,9 @@ review. Once merged and govd's image is rebuilt (the build re-checks every index ## More -The **local-dev `./govd-client` wrapper** (the `task-ledger.json` form, cooperative-from-registry, the -in-container exec, the ACL attestation/proof flags) is in [`cyberware_dev/SKILL.md`](cyberware_dev/SKILL.md). +The **local-dev `./govd-client` wrapper** (the `task-ledger.json` form, the cooperative `grant`/`step_result` +run from an on-disk registry, the in-container exec, the ACL attestation/proof flags) is in +[`cyberware_dev/SKILL.md`](cyberware_dev/SKILL.md) — the local method an external agent never needs. The govd-less local pipeline (validator → composer → compiler → oversight → executor) is in [`cyberware.md`](cyberware.md); the service internals (HTTP, WebSocket, authenticity, dashboard) are in [`docs/governance-service.md`](docs/governance-service.md); the live [dashboard](https://cyberware.systems/) diff --git a/cyberware_dev/SKILL.md b/cyberware_dev/SKILL.md index 763e4d8..7f7d6a4 100644 --- a/cyberware_dev/SKILL.md +++ b/cyberware_dev/SKILL.md @@ -75,6 +75,12 @@ exod is the authority. You run **nothing** and hold no porter. Requires the node exod attached, else each step is refused (fail-closed). This is the same wire any external agent uses by default — see [`SKILL.md`](../SKILL.md). +Two things a delegated run needs that a cooperative one doesn't: (1) **values** ride the WS, not the claim — +`--ledger`'s `vars` are forwarded as `var_values` on each `step_request` (non-secret, plan-declared keys only; +re-gated on the actor's `params` ACL axis). (2) a perk's **output** lands in a server-side workspace you cannot +read, so to get DATA back add `"cargo":"ro"|"rw"` to the ledger and set the perk's output var (e.g. `OUT`) under +`/cyberware_cargo/…`; read the artifact off that shared mount. The wire stays status-only. + If your principal carries a **per-actor ACL**, a scoped claim on a body also rides an operator-signed **attestation** (`--attestation `) and a one-time possession **proof** (`--proof-key `) that exod re-checks off-node. When the operator runs exod in **enforce** mode (an ACL-issuer key pinned, `--acl-strict`),