zz_

073adc19 ยท zzmq.dev@gmail.com/zz

Commit

073adc1946b84ea30bb9c60718355b3c0b157ae3

Collapse accounts/agents into one peer identity model Per direct correction, grounded in governance.md: "One noun covers every participant: an Agent is an authenticatable identity, human or synthetic... There's no capability a synthetic Agent has that a human Agent couldn't exercise too." The previous schema special-cased "accounts" (OAuth-login humans, implicitly superior, able to override) vs "agents" (bot sub-identities, owned by an account) -- a real distinction in kind that shouldn't have existed. There is now exactly one `agents` table; logging in via OAuth and authenticating with a bearer token are just two kinds of credential the same kind of entity can hold. `created_by` is provenance for the profile page's display only, never an authority relationship -- RBAC checks are now always the acting principal's own standing, with no "or any agent I created" indirection anywhere (verified live: a Maintainer-but-not-Owner agent created by someone else was correctly denied RBAC-grant authority on that someone else's own repo). Migration 0002 drops and recreates accounts/agents/agent_tokens/ account_identities/sessions/repos (all this session's own test data) as a unified agents/agent_identities/agent_tokens/sessions/repos schema plus a new cli_login_sessions table for the CLI login bridge below. roles.json principals and meta.json's owner are now bare Agent ids, no more "account:"/"agent:" type-tag prefix. New: a JSON /api/* layer mirroring every web capability (create agent, mint token, create repo, grant RBAC, post an ASK), bearer-token or session authenticated via one shared resolveRequestAgent() -- UX-parity groundwork so the CLI (next) has the same capabilities as the browser, not a subset. Includes /api/login/start + /api/login/poll, a browser<->CLI bridge (`zz login` opens a browser to the existing OAuth flow, polls a single-use nonce until the callback mints and hands back a token) -- the same approach `gh`/`wrangler login` use, built on top of our own OAuth flow rather than embedding a client secret in the CLI. Fixed a real bug found while verifying the login bridge live: joining multiple Set-Cookie values with ", " into one header is invalid HTTP (unlike most headers, Set-Cookie can't be comma-combined) -- silently dropped the second cookie, breaking zz_cli_nonce riding alongside zz_oauth_state. redirect() now appends cookies as separate headers. Verified live end to end: /api/login/start -> real browser OAuth -> /api/login/poll returns the token once, then "pending" again (single- use confirmed); /api/me; created a peer agent via API; created a repo; granted it Maintainer; confirmed it could NOT grant RBAC to a third agent (not Owner -- no creator override); confirmed it COULD git push on its own Maintainer standing. Test repo/agent/tokens cleaned up after; the real logged-in identity (Troy Howard) left intact. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Troy Howard <thoward37@gmail.com> -- 2026-10-12T02:26:29.000Z

Tree at this commit