{
  "what": "boringtool",
  "workspaces": "every route below but /auth, WS /rpc and /pair is under /w/<workspace>/ — a name like acme, or ~<handle>: a person's Home, made with them the first time they call or sign in, they its member and admin. A workspace answers only who has an active principal there — its members, and the external members of its spaces; where a space is open to every person (person:*), whoever reaches the workspace with no principal there is given one at that first request, as an external member. To anyone else, as for a name the directory does not have, it is the same 404 before the door. Past it, a call is made in the space of what it touches — the thing its input names, the install its ref names, or the space a create names as space_id — and answered only to that space's members; one that touches none is made at the workspace level, for any principal here; a list answers what the caller reaches. workspace.create makes one",
  "routes": {
    "POST /auth/start": "{ email } — a 6-digit sign-in code for that address, mailed, and { ok: true } whatever the address; where handles are taken on trust, { ok: true, code } and no mail, the code null when none is given",
    "POST /auth/verify": "{ email, code, handle? } — the person, and the session cookie, for 30 days; the first time, { handle_needed: true }, until a handle is sent with the code: it names the person and their Home",
    "POST /auth/logout": "{} — this browser's session ended, and its cookie cleared",
    "GET /w/:workspace/tools": "the catalog: builtin and installed, one shape",
    "POST /w/:workspace/rpc": "{ tool, input, secrets?, call_id? } — one tool call, made in that workspace, in the space of what it touches; a body naming a space beside the input is refused. Each `secrets` entry is { name, path }, naming a vault secret of a space you are in and where its {{secret:…}} sits in the input. Answers { stage, output | error, call_id } — or 202 { stage: \"pending\", call_id, waiting } when it has not answered yet: send it again with that call_id to read the answer",
    "WS /rpc": "one connection per caller — ?principal=<handle>, ?token=<token>&workspace=<ws>, bound to that workspace, or the session cookie, for as long as the token or the session stands. { id, workspace, persona?, tool, input, call_id? } — a call made in the workspace the frame names, in the space of what it touches, under a persona of yours there if it names one; progress comes back as { id, ref, emit }, and every answer as { id, stage, status, … }, a call that waits answered later on the same id. { id, workspace, tool, input, follow: true } on a read whose changes can be watched (tool.list marks them followable) answers, then sends { id, changed: true } whenever the answer may have changed — read it again — until { id, stage: \"canceled\", status: 409, error }; { id, unfollow: true } stops one. \"ping\" answers \"pong\"",
    "POST /w/:workspace/codemode": "{ code, call?, uses? } — the same tools, from code; a thin adapter over the `code.run` tool, a workspace-level call: each call its code makes is made in the space of what it touches. ?call_id=<uuid> makes it a put, as call_id does on /rpc",
    "GET /w/:workspace/view/:artifact_id": "the file browser at the pinned version, read through the door as artifact.get — in the artifact's space, to its members; ?version=<n> another version; ?preview=<label> runs a renderer the version's boringtool.json lists",
    "ANY /w/:workspace/app/:namespace/:name/*": "an installed application, the install <namespace>/<name>, answers — as itself, or as whoever is looking when the tool filling iapp.serve runs as its caller",
    "GET|POST /w/:workspace/git/:namespace/:name.git/*": "git's smart HTTP, protocol v0, for the install <namespace>/<name> filling igit — git clone, fetch and push its repository: GET info/refs?service=git-upload-pack | git-receive-pack, POST git-upload-pack, POST git-receive-pack. Each is the install's tool for igit.refs, igit.fetch or igit.push, called through the door as who is calling — a persona's token, as Bearer or as the password of Basic auth; naming nobody is 401 asking for Basic",
    "GET /pair/:socket_id/:token": "a peer dials into a socket it was registered for (websocket) — outside every workspace, as this banner is: a socket's id is global"
  },
  "identity": "Authorization: Bearer <token> — a persona's token, and nothing else with it; on a git route, also Basic with the token as the password. Or x-principal: <handle>, asserted, where handles are taken on trust; or the session cookie /auth/verify sets — either optionally with x-persona: <label | persona_id>. Naming nobody is 401",
  "peer_origin": null,
  "builtin_tools": [
    "tool.list",
    "artifact.local.create",
    "artifact.local.update",
    "artifact.remote.create",
    "artifact.remote.update",
    "artifact.remote.fetch",
    "artifact.pin",
    "artifact.get",
    "artifact.list",
    "artifact.read",
    "artifact.versions",
    "artifact.diff",
    "artifact.withdraw",
    "artifact.run",
    "code.run",
    "interface.create",
    "interface.list",
    "interface.get",
    "integration.install",
    "integration.list",
    "integration.uninstall",
    "integration.config.get",
    "integration.config.put",
    "integration.version.put",
    "activation.put",
    "activation.get",
    "activation.list",
    "activation.delete",
    "bucket.put",
    "bucket.get",
    "bucket.read",
    "bucket.list",
    "bucket.delete",
    "blob.put",
    "blob.read",
    "socket.register",
    "socket.attach",
    "socket.force_attach",
    "socket.pipe",
    "socket.force_pipe",
    "socket.detach",
    "socket.close",
    "socket.status",
    "socket.connected",
    "socket.gone",
    "socket.delivery_failed",
    "socket.list",
    "http.fetch",
    "ai.run",
    "app.serve",
    "app.list",
    "agent.run.turn",
    "agent.run.cancel",
    "agent.run.delete",
    "agent.run.get",
    "agent.run.list",
    "agent.list",
    "workspace.create",
    "workspace.list",
    "workspace.get",
    "workspace.admin.put",
    "workspace.admin.delete",
    "workspace.admin.list",
    "workspace.member.put",
    "workspace.member.delete",
    "workspace.member.list",
    "workspace.reset",
    "space.create",
    "space.get",
    "space.list",
    "space.update",
    "space.member.put",
    "space.member.delete",
    "space.member.list",
    "space.change.list",
    "space.leave",
    "core.reset",
    "conversation.create",
    "conversation.get",
    "conversation.list",
    "message.create",
    "message.get",
    "message.list",
    "link.put",
    "link.delete",
    "link.list",
    "vault.put",
    "vault.get",
    "vault.list",
    "vault.read",
    "vault.delete",
    "vault.spend",
    "event.list",
    "event.get",
    "event.read",
    "trigger.watch.create",
    "trigger.watch.list",
    "trigger.watch.delete",
    "trigger.watch.delivery.put",
    "trigger.watch.delivery.get",
    "trigger.watch.delivery_failed",
    "trigger.schedule.create",
    "trigger.schedule.list",
    "trigger.schedule.get",
    "trigger.schedule.delete",
    "trigger.schedule.pause",
    "trigger.schedule.resume",
    "ask.create",
    "ask.answer",
    "ask.cancel",
    "ask.get",
    "ask.wait",
    "ask.list",
    "review.gate.put",
    "review.gate.list",
    "review.gate.delete",
    "tool.call.get",
    "tool.call.list",
    "tool.call.cancel",
    "persona.create",
    "persona.update",
    "persona.get",
    "persona.list",
    "persona.delete",
    "persona.token.register",
    "persona.token.list",
    "persona.token.revoke",
    "principal.get",
    "principal.list",
    "principal.persona.put",
    "principal.persona.delete",
    "integration.hook.put",
    "integration.hook.delete",
    "integration.hook.list",
    "space.hook.put",
    "space.hook.delete",
    "space.hook.list",
    "space.hook.require.put",
    "space.hook.require.delete",
    "space.hook.require.list",
    "authz.hook.put",
    "authz.hook.delete",
    "authz.hook.list",
    "hook.list"
  ]
}