docs(#3247): record the capability instruction-surface trust model (#3249)

* docs(#3247): record the capability instruction-surface trust model

ADR-2363 records the trust posture for third-party capability SKILL.md
bodies, which #2322/#2340 made agent-invocable without any content-level
control. The path-level protections that fix shipped are all present; no
content scanner exists, and external-descriptor-trust.cts never had one.
Nothing was bypassed - the control did not exist and the boundary was
never written down.

D1 records the posture: skill bodies are trusted, unscanned agent
instructions. D2 rejects content scanning on Kerckhoffs (a shipped rule
set is readable by the adversary who installs it), on threat-model
non-transfer from ADR-1577 (there, instructions are anomalous inside
data; here they are the payload's legitimate form), and on Goodhart (a
scanned-OK line displaces the judgment the consent prompt exists to
provoke). D3 replaces the executable/non-executable binary with three
classes, adding instruction surface.

D4 keeps instruction surfaces out of the v1 disclosureSignature. The
signature is NOT the activation binding - hasProjectConsent compares
contentHash only, and a global install carries no consent record at all.
What re-encoding would do is perturb the signature of every skill-bearing
capability and fire a spurious re-consent prompt on its next upgrade,
which is what ADR-2782 D4 rule 5 already forbids. If instruction surfaces
ever need to be signature-bound, that lands as a versioned v2 signature
with a migration, never an in-place re-encoding.

Corrects capability-trust-model.md, which claimed skills get lighter
consent because they do not execute code - true, and not the relevant
property, since the agent is the interpreter. Adds the author-side
boundary to develop-a-capability.md and links it from
publish-a-capability.md. Both state that per-skill disclosure at the
consent prompt lands with #3248 and does not happen today.

Docs-only. No behavior change; no consent record perturbed. D5's
mechanism is Phase 1 (#3248), which is why the ADR is Proposed.

Refs #2363

* chore(#3247): backfill changeset pr number to 3249

---------

Co-authored-by: sim <sim@local>
This commit is contained in:
Tom Boucher
2026-08-09 11:47:54 -04:00
committed by GitHub
parent a5b5860b93
commit bc5619dd27
6 changed files with 208 additions and 4 deletions

View File

@@ -209,8 +209,57 @@ signature is a stable, key-order-independent encoding, so any later add or chang
to a surface — including an env or cwd change — deactivates the capability until
the user re-consents, while a harmless key reorder does not.
For non-executable surfaces (skills, agents, workflow files), the disclosure
note explains what they do but consent is lighter — they do not execute code.
For everything else the bundle carries, the disclosure note explains what the
artifact does and consent is lighter. But "everything else" is not one class, and
treating it as one was a mistake this document made until ADR-2363 — see the next
section.
### Instruction surfaces: the agent is the interpreter
A capability's `SKILL.md` bodies are copied verbatim into your runtime skills
directory, where they become agent-invocable instructions. They are **not**
content-scanned — see
[ADR-2363](../adr/2363-capability-instruction-surface-trust.md) for why scanning
them was considered and rejected.
This document used to group skills with inert assets as "non-executable surfaces"
whose consent is lighter *because they do not execute code*. That reasoning was
wrong, and the correction matters more than the wording: a skill body does not
execute code, it **instructs the thing that does**. The consent path was chosen on
a property ("does not execute code") that is true and not the relevant one.
So there are three classes, not two:
| Class | Members | What consent covers |
|---|---|---|
| **Executable surface** | hooks, command modules, MCP servers, reviewer lanes | Code that will run. Disclosed, consent-bound, signature-bound. |
| **Instruction surface** | skills, agents | Instructions that will reach the agent. Reach bounded only by what the agent will do when told. |
| **Inert artifact** | everything else in the bundle | Note only. |
**Not yet itemized at the prompt.** Naming a capability's individual skills in the
pre-install consent summary lands with
[#3248](https://github.com/open-gsd/gsd-core/issues/3248); today a skill-bearing
capability is covered by the bundle's integrity and by your consent to install it,
but its skills are not listed for you one by one. The classification above is
what GSD has decided; the itemized prompt is what it has not yet built.
Installing a capability that ships skills grants it **instruction reach**. That is
a real grant, and it is the same bargain this document already describes for code:
the barrier is consent, integrity and reversibility, not inspection. Naming the
instruction surface tells you a capability ships agent instructions; it tells you
nothing about whether they are benign — exactly as the integrity SHA tells you
nothing about whether the pinned bundle is safe.
Two things worth stating so you do not infer them:
- **First-party skills are equally unscanned.** Their assurance is provenance —
they are the shipped package — not content inspection. There is no content
control on either side.
- **Correcting this document did not disturb any consent you have already
given.** No re-consent prompt follows from it. ADR-2363 D4 keeps instruction
surfaces out of the v1 disclosure signature precisely so that recording the
boundary honestly does not fire a spurious re-consent prompt on every
skill-bearing capability you have installed.
### Integrity pinning
@@ -359,6 +408,13 @@ These three things together mean: you know what you installed, you got what you
were shown, and you can undo it completely. They do not guarantee the content
is safe. The trust model is transparent about this.
The three pillars are stated above in terms of code, because code execution is the
sharpest case. They apply unchanged to **instructions**: you consent to the
instruction surfaces a capability declares, the bundle you consented to is the
bundle whose skill bodies were installed, and removing the capability removes its
instructions from the agent's context. What there is no sandbox for is not only
`require()`'d code — it is also the prose that tells the agent what to do.
---
## Trade-offs: the roads not taken
@@ -417,6 +473,7 @@ the code at all.
## Related documents
- [ADR-1244 D5 — Trust model](../adr/1244-capability-ecosystem.md#d5--trust-model-artifact-parity-is-full-trust-posture-is-tiered)
- [ADR-2363 — Instruction surfaces](../adr/2363-capability-instruction-surface-trust.md) — why skill bodies are trusted and unscanned, and why content scanning was rejected
- [Capability matrix](../reference/capability-matrix.md) — the generated catalogue of all capabilities
- [PRD-1244 §6 — Out of scope](../prd/1244-capability-ecosystem.md#6-scope-160) — why sandboxing is explicitly out of scope
- [ADR-857](../adr/857-capability-system.md) — the 12 loop extension points; D7 and D8 extended by ADR-1244