Files
mad-skills/wiring-diagram/SKILL.md
T
dckc 237b470be8 wiring-diagram: who holds what, drawn like MarkM's ERTP slides
A capability wiring diagram as a self-contained HTML/SVG page plus a
headless-Chromium PNG. Every arrow has to point to something in the
code, and a Mallory holding what's likeliest to leak shows what that
doesn't reach. template.html has the drawing helpers, adapted from
capsite's cookie-rotation-wiring.

README: a TODO to consider adapting agoric-sdk's
sequence-diagram-actor-sim as its companion.

Generated-by: Claude Opus 5.5
2026-10-11 14:22:44 -05:00

5.6 KiB
Raw Blame History

name, description
name description
wiring-diagram Capability wiring diagram, "who holds what" — use when asked for a wiring diagram, a picture of who holds what, a capability diagram, or "a diagram like the cookie-rotation one"; when reviewing a design for POLA and wanting to see the reference graph. MarkM ERTP-slide style: actors are balls, makers pale regions, objects rounded squares, state ledger tables, references dot-to-arrowhead; HTML/SVG plus a headless-Chromium PNG. Not for message order over time: that's a sequence diagram (sequence-diagram-actor-sim in agoric-sdk).

Capability wiring diagram

One picture that answers, for a design: who holds a reference to what, and therefore who can do what. It complements a sequence diagram, which shows when messages flow. This one shows the standing graph of authority that makes those messages possible. For sequences, see ~/projects/ymax-workspace/agoric-sdk/.agents/skills/sequence-diagram-actor-sim/SKILL.md (on agoric-sdk branches connolly/ago-1264-agentic-planning and connolly/ago-1299-agentic-planning-tdd, not yet on master).

Exemplars:

  • ~/oros-bots/capsite-cookie-rotation/docs/cookie-rotation-wiring.html (+ .png): the original.
  • ~/qtrx/packages/umb-download/docs/wiring.html (+ .png): three makers, two outside parties, and an adversary holding a webkey.

Start from template.html, next to this file. It has the drawing helpers and a small example scene to replace.

Read the graph from the code, not the story

Every arrow must correspond to something real: a constructor argument, a stored id, a binding, a held token, or a file someone keeps. Before drawing, list the references as holder → target: where in the code. Read the factories (make…, newX, configure) and anything that stores an id: a DO id held as a string is a reference. If you can't cite where a reference comes from, it doesn't get an arrow.

Watch for references that are dropped on purpose (e.g. a setup route that mints an instance, hands its id to one holder and forgets it). That's often the point of the design. Say so in a caption, or just leave the arrow out.

Vocabulary

element helper means
blue ball actor(cx, cy, label) a person or a program with its own agency
grey ball actor(cx, cy, label, "url(#ext)") outside the system: a browser extension, a third-party service
pale region maker(x, y, w, h, "makeFoo") a maker (factory, DO class) and the instances it made; the stacked inner panes say "there are many"
rounded square obj(x, y, w, h, label, stacked) an object or facet; stacked when one is made per instance
ledger table table(x, y, title, rows, [colW0, colW1]) an object's state; rows are key/value; rowY(i) and colX give arrow anchors
dot → arrowhead ref(x1, y1, x2, y2, bend) holder references target; bend (±0.05–0.3) curves around things
speech bubble the path + code block the one call the picture is about, in E(target).method(args) form
caption cap(x, y, text, attrs) what an actor holds, and what it can't reach

Facets are separate objects (store vs readOnly): drawing them apart is how the picture shows attenuation.

Include an adversary

Add a Mallory who holds whatever is most likely to leak (an instance id, a webkey, a URL), with an arrow to exactly what it reaches. The caption says what she can't reach. Absent arrows are the security argument, and Mallory makes them visible.

Layout

  • Actors in a row along the top (y≈200), makers below (y≈320 onward), captions along the bottom (y≈ height − 14).
  • Put each maker under the actors that mostly use it, so arrows run short and downward.
  • Speech bubble at the top, its tail pointing at the speaker. Move the bubble's path (M x,y) and the tail segment (h… l-38,48 l6,-48) together.
  • Captions: two or three short lines, never on top of an arrow or a ball. Use "text-anchor": "start" to set one beside a ball.
  • Long arrows that cross a maker: increase |bend| until the curve clears tables and objects. The control point is the midpoint offset by bend × (−dy, dx).

Accessibility

Keep <title> short. Write <desc> as prose that names every actor and maker, every reference, the bubble's call, and what the adversary can't reach. Someone who can't see the picture should get the same argument from it.

Render and check

The page is self-contained (no network). Render a PNG with headless Chromium. The viewport comes out shorter than --window-size, so render taller and crop to the SVG size:

chromium --headless=new --disable-gpu --no-sandbox --hide-scrollbars \
  --window-size=W,$((H+100)) --screenshot=full.png "file://$PWD/NAME.html"
python3 -c "from PIL import Image; Image.open('full.png').crop((0,0,W,H)).save('NAME.png')" && rm full.png

Then look at the PNG (Read it) and fix overlaps: captions on arrows, arrows through tables, text clipped at the bottom. Expect two or three rounds. Commit the HTML (source) and the PNG separately, so the source diff stays readable.

Review checklist

  • Does every arrow cite something in the code? Is any real reference missing?
  • Does each actor hold only what its job needs (POLA)? If the picture shows an actor holding more, that's a finding about the design, not a drawing problem.
  • Are facets drawn apart where they differ in authority?
  • Does the adversary's caption match what the arrows show?
  • Does <desc> tell the same story in prose?
  • Is any secret value drawn? Elide values (session=…, {…}): the picture shows that a row exists, not its contents.