feat(web,service): the owner mints and revokes agent tokens in a browser Issuing a credential required SSH to the host, which made the remote agent write plane unusable from anywhere else: to hand an agent a token the owner had to be at the machine. /tokens is that page — list, mint, revoke — behind the same owner-only gate and same-origin guard as approve/reject. The mint is owner-only, and that rule is what revocation depends on: an agent allowed to mint would survive having its own credential revoked by issuing itself another, and "revoke the token" is the entire incident response this design has. An agent asking for the page gets 403 rather than the read plane's login redirect — it is authenticated already, so bouncing it to meta would answer a question it did not ask. The plaintext is rendered in the response to the POST rather than after a redirect. A redirect would either drop the secret or carry it in a URL, where it lands in history and in every proxy log on the way; the cost is that a reload re-submits and mints a second token, which is one click to revoke on that same page, whereas a lost token is not recoverable. service.IssueAgentToken/ListAgentTokens/RevokeAgentToken hold the ACL and the mint, and `specsrht token` now goes through them too, so the CLI and the page cannot drift into two ideas of what issuing a token is. spec-ejq.3
feat(cmd): agent tokens and host-side proposals get admin commands Two entry points were missing, and both left a deployment unable to do the thing it exists for. `token create|list|revoke` — db/ has had the whole agent-token lifecycle since Phase 1, but nothing called it: no CLI, no page. A fresh instance therefore had no credential for the agent write plane, which refuses an anonymous caller by design, and the only way to mint one was an operator hand-writing an INSERT with a sha256 hash. The plaintext is printed once and never logged; only its hash is stored, and the listing deliberately omits the hash so nobody mistakes it for the credential. `doc propose ~owner/space <file>...` — the two agent write surfaces are remote and so need a bearer token. When the operator and the documents are already on the host, that token is ceremony: the process can open Postgres and the bare repositories directly, so it constructs the agent principal itself rather than resolving one from an agent_token row. Provenance is not waived — --agent and --session are recorded exactly as a remote agent's are, so `git log` cannot tell the two apart, and neither can a reviewer. It calls service.Propose, so If-Match, the branch cut, the trailers and the auto-merge gate stay spelled once. Flags parse before, after and between the positionals: Go's flag package stops at the first non-flag, which would make `doc propose ~bigbes/rfcs spec.md --title x` drop --title and fail one layer down complaining about a missing title rather than the flag it ignored. spec-rsb, spec-ovo