Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 38 additions & 33 deletions SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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":["<perk>"]`
to confirm a destructive perk after a push_back; `"traceparent":"<w3c-trace>"`.)*
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":"<w3c-trace>"`.)*

The verdict returns:

Expand All @@ -99,39 +101,41 @@ are just `"1" … "N"` for `N = plan.sequence.length` — **the plan is the only
→ {"type":"hello","run_id":"<run_id>","token":"<session_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":"<st>","plan_sha":"<plan_sha>"}
← {"type":"executed","step":"<st>","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":"<st>","plan_sha":"<plan_sha>"} ← {"type":"grant"} ·or· {"type":"refuse","reason":"…"} → stop
run bash run.sh --step <st> (run.sh = plan.wrapper) with your var VALUES in the ENV
(+ RECORD_STORE=<out dir>, SNIP=<your perks/<perk>/src dir>)
→ {"type":"step_result","step":"<st>","plan_sha":"<plan_sha>","status":"ok"|"error","exit":<code>} ← {"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":"<st>","plan_sha":"<plan_sha>","var_values":{"<KEY>":"<value>", …}}
← {"type":"executed","step":"<st>","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/<run_id>?token=<session_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

Expand All @@ -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/)
Expand Down
6 changes: 6 additions & 0 deletions cyberware_dev/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <file>`) and a one-time possession **proof** (`--proof-key <file>`) that exod
re-checks off-node. When the operator runs exod in **enforce** mode (an ACL-issuer key pinned, `--acl-strict`),
Expand Down
Loading