Skip to content

Agents: an external key registers its own agent, naming its owner (0.1.14) - #12

Merged
reoring merged 3 commits into
mainfrom
key-provenance
Nov 12, 2026
Merged

reoring merged 3 commits into
mainfrom
key-provenance

Conversation

@reoring

@reoring reoring commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

Why

An agent could not use its key until a Tracker Admin had registered the same handle by hand (POST /agents). Minting an external-subject key already needs a Project admin, so the second approval added a step and no decision.

What

  • POST /agents/register { name, description?, ownerSub }: an external key whose handle is not registered creates its own agent (201). Already registered and active → 200 with the existing agent, body not applied, so an agent can call it on every start. The handle is the assertion's subject, never a body field.
  • The owner is claimed, not verified. It must be a person with a signed-in write in this workspace (store.KnownName), and the agent records registeredByKey (the Access Key name). The Agents page marks self-registered agents and says the owner is unconfirmed.
  • A disabled agent cannot register again (403 key_subject). The route ignores Idempotency-Key, so a stored 201 is never replayed after a disable.
  • An unregistered external key reaches only this route and GET /agent-guide; every other route still answers 403 key_subject, now naming the route to call.
  • Agents page: "Let an agent register itself" shows the key command and the request with the viewer's own subject as ownerSub.
  • Contract: design/API.md § Self-registration (v0.1.14). Migration 014 adds tracker_agent.registered_key.

Review focus (authorization boundary)

  • route() in cmd/server/internal/api/api.go: the unregistered flag lets exactly two routes proceed when AgentBySubject answers key_subject.
  • RegisterAgent in cmd/server/internal/store/agents.go: CreateAgent keeps its Admin check; self-registration does not go through it.
  • A key names any person who has written here as its owner, without that person's consent. Requests and reviews of that agent default to the owner.

Verification

  • go vet ./cmd/...; go test -count=1 ./cmd/... against a disposable Postgres 17: all packages passed (CI skips the database tests).
  • web: tsc --noEmit, bun test src; bun test hack.
  • Browser, against the mock API: the mark appears only on the self-registered agent; the help renders the viewer's subject, the key command appears for a valid handle and disappears for an invalid one.
  • Not verified: a real external key against a deployed installation.

…1.14)

Registering an agent needed an Admin to type the handle before the key could
be used. Minting an external-subject key already needs a Project admin, so
that is the admission decision: POST /agents/register creates the agent from
the assertion's handle with the owner the agent names. The owner must have a
signed-in write in this workspace; the claim is recorded with the key name
(registeredByKey). Disabled agents cannot register again.
@reoring
reoring merged commit 45ae6d6 into main Nov 12, 2026
3 checks passed
@reoring
reoring deleted the key-provenance branch November 12, 2026 02:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant