route tokens
So far every caller authenticated — logged in, minted a sub, passed a grant. But the web surfaces just ahead serve people who never log in: a public chat box on a website, a webhook from GitHub. A route token is the no-login counterpart that lets them in — a 32-byte random string that maps to one JID. POST a body to a URL carrying that token and the body lands as an inbound message at the mapped JID. The JID prefix carries the routing intent — web: for a browser chat, hook: for a webhook from GitHub, Linear, or anything else that can POST JSON. Possession of the URL is the whole credential.
one table, two URLs
All tokens live in the route_tokens table — the raw token is hashed to a lookup key, mapped to a JID, owned by the folder that minted it. Two URLs read that table, one per JID prefix: web: tokens answer at /chat/<token>/, hook: tokens at /hook/<token>. Both serve the same chat widget on GET and append a message on POST, streaming the reply over SSE to browsers and a plain response to everyone else. The binding is enforced at lookup: a hook: token at /chat/… returns 404, and vice-versa, so each surface stays single-purpose. Full column list, payload shapes, and the per-token MCP surface: reference / tokens.
what the JID encodes
web:<folder> means “anonymous visitor chat at this folder.” web:acme is acme's public chat URL. Add a suffix to split one folder across pages: web:acme/support and web:acme/sales are different conversations against the same agent, distinguishable in routing rules.
hook:<folder>/<source> means “webhook from source targeting folder.” hook:acme/eng/github is GitHub events for the acme/eng folder. hook:acme/eng/linear/comments partitions Linear into a comments stream separate from hook:acme/eng/linear/issues. The <source> segment is what the agent sees in the inbound's sender field.
JID prefixes split routing — a hook: message and a web: message can fire different rules even though one table issued both tokens. The URL the request arrived on matches the JID prefix one-to-one.
issuance
Two sources mint tokens, one writer inserts the row.
- An agent over MCP. A turn calls
issue_chat_linkorissue_webhookon its group's MCP socket, gets the URL back once, and hands it to a human to paste. - An operator over REST or CLI.
arizuko token issue(or the OAuth-gated REST route, or a dashd button) mints the same token for a folder. Exact signatures: reference / tokens.
Both paths hit the same insertRouteToken writer — same row shape, same audit trail. The raw token is returned exactly once; only its sha256 is stored, so losing it means reissuing.
Folders do not get a chat token automatically when they are created. A folder gets a token when someone calls issue_chat_link for it. This keeps unused folders from accumulating live URLs.
who can mint for which folder
Resolved by the unified grants tier: lower tier means broader mint reach (tier 0 any folder, tier 1 self and descendants, tier 2 self only, the per-tier table in reference / tokens). Tier 1 at acme can mint hook:acme/eng/github on behalf of the acme/eng child — and the row's owner_folder stays at acme, the issuer, not the JID target. Revocation follows owner_folder, so acme retains control of the tokens it minted.
revocation
One DELETE on the row. The next request to the URL returns 401 immediately — no grace period, no cache to wait out. An agent in folder A cannot delete a token whose owner_folder = B; the ACL gate at revoke_route_token requires admin on owner_folder.
the bearer model
Whoever holds the URL can POST to it. There is no second factor, no signing on the body, no per-caller identity at this surface. webd does not verify X-Hub-Signature or any other upstream HMAC — that belongs to a skill on the agent side, not the platform. Rotation is by reissue: mint a new token, swap the URL at the source, delete the old row.
webd rate-limits per token in memory, the ceiling chosen by JID prefix (web: low for humans, hook: higher for machine bursts), and caps the body at 1 MiB.
go deeper
- how-to: chat link — issue a chat URL, paste it on a site, what the visitor sees.
- how-to: webhooks — wire GitHub, Linear, custom alerts.
- reference: tokens — full HTTP surface, payload shapes, SSE events, MCP tools.
- routing — how
web:<folder>andhook:<folder>/<source>reach an agent. - jid — address shape across every platform.
specs/5/W-webhook-routes.md— the route_tokens spec.