-- Give a session a SCOPE, so a credential can be handed to something that is -- not a person. -- -- `AuthService::authenticate` returns a full `AuthedUser` carrying the user's -- role. There is no narrower credential in the system, so any component that -- needs to call the ClawMates API must be given one that can do everything the -- user can. -- -- That is the blocker on deploying the MCP door to mission agents -- (`docs/TOOL-CALL-ARCHITECTURE.md` §3, which calls it "config, not code"). -- Reaching `/mcp/skills` from a mission container means putting a bearer token -- in a file inside that container — and mission agents run arbitrary `Bash` -- with egress and no read gate, which is the platform's own documented -- security posture. An owner-scoped token there turns "the agent runs commands -- in a sandbox" into "the agent drives the whole API as the owner". -- -- Verified before building this: no such credential is in a mission container -- today. The runtime's config.toml has no `[mcp.servers]` block and no bearer, -- so this would be a NEW exposure rather than an existing one. -- -- FAIL CLOSED. The default is 'full', so every existing row and every existing -- caller behaves exactly as before; `authenticate` REJECTS anything else, and a -- route must opt in by asking for the scope it accepts. A scope added later and -- wired nowhere therefore grants nothing, which is the safe direction for the -- mistake most likely to be made here. ALTER TABLE auth_sessions ADD COLUMN IF NOT EXISTS scope TEXT NOT NULL DEFAULT 'full'; COMMENT ON COLUMN auth_sessions.scope IS 'full = a person''s session, accepted everywhere. Anything else is a narrow credential accepted only by routes that name that scope (see AuthService::authenticate_scoped). Never widen a token in place; mint a new one.'; -- The lookup is by token_hash and already indexed; this supports auditing and -- revoking a whole class of narrow credential at once (e.g. every skills token -- for a workspace after a leak). CREATE INDEX IF NOT EXISTS auth_sessions_scope_idx ON auth_sessions (scope) WHERE scope <> 'full';