# Agent

Name: Agent 05 - API Keys And Access Control

Stage: API Keys And Access Control

Date: 2026-04-14

## Scope

Implemented the API key lifecycle and access-control stage on top of the existing authenticated admin workspace and the project or tag model from Agent 04.

Completed in this stage:

- added a dedicated `internal/apikeys` service for secure API key generation, SHA-256 hashing, lookup, lifecycle checks, and project scope evaluation;
- implemented full API key repository support for create, update, list, revoke or activate, last-used tracking, project and tag rule storage, and effective access queries;
- added minimal protected admin pages for API key list, creation, detail, update, and revoke or activate actions;
- implemented one-time raw key reveal behavior by showing the generated key only in the immediate creation response while persisting only the short prefix and hash;
- added permission and project-scope middleware helpers for future `/api/v1` client routes using bearer authentication;
- added integration and unit coverage for hashed storage, expired or revoked key rejection, all five scope modes, scope transitions, middleware enforcement, and admin key management flow.

## Files Changed

- `/Users/delete/projects/update_server/internal/app/app.go`
- `/Users/delete/projects/update_server/internal/db/models.go`
- `/Users/delete/projects/update_server/internal/db/apikeys.go`
- `/Users/delete/projects/update_server/internal/apikeys/context.go`
- `/Users/delete/projects/update_server/internal/apikeys/service.go`
- `/Users/delete/projects/update_server/internal/apikeys/service_test.go`
- `/Users/delete/projects/update_server/internal/http/router.go`
- `/Users/delete/projects/update_server/internal/http/handlers.go`
- `/Users/delete/projects/update_server/internal/http/view_data.go`
- `/Users/delete/projects/update_server/internal/http/admin_api_keys.go`
- `/Users/delete/projects/update_server/internal/http/api_key_middleware.go`
- `/Users/delete/projects/update_server/internal/http/api_key_middleware_test.go`
- `/Users/delete/projects/update_server/internal/http/api_keys_integration_test.go`
- `/Users/delete/projects/update_server/internal/http/auth_integration_test.go`
- `/Users/delete/projects/update_server/web/templates/layouts/base.gohtml`
- `/Users/delete/projects/update_server/web/templates/pages/api_keys.gohtml`
- `/Users/delete/projects/update_server/web/templates/pages/api_key_form.gohtml`
- `/Users/delete/projects/update_server/web/static/app.css`
- `/Users/delete/projects/update_server/docs/agents/handoffs/05-api-keys.md`

## Database Changes

- no new migrations were required because the existing `api_keys`, `api_key_project_access`, and `api_key_tag_access` tables already existed from Agent 02 and the scope guard triggers already existed from migration `0003_api_key_scope_guards.sql`;
- the new repository code now actively uses those tables and trigger rules for key lifecycle, project allow or deny lists, and tag allow or deny lists;
- API keys are stored with a short visible `key_prefix` and a hashed `key_hash`; the raw key is never persisted.

## API Or Route Changes

- added protected admin routes:
  - `GET /admin/api-keys`
  - `GET /admin/api-keys/new`
  - `POST /admin/api-keys`
  - `GET /admin/api-keys/{apiKeyID}`
  - `POST /admin/api-keys/{apiKeyID}`
  - `POST /admin/api-keys/{apiKeyID}/activate`
- added reusable middleware helpers for future client API routes:
  - `requireAPIKey`
  - `requireAPIKeyPermission`
  - `requireAPIKeyProjectAccess`
- kept `/api/v1` client endpoints themselves out of scope for this stage so Agent 06 can wire them onto the new middleware and access-resolution layer.

## Commands And Tests Run

- `gofmt -w internal/app/app.go internal/db/models.go internal/db/apikeys.go internal/apikeys/context.go internal/apikeys/service.go internal/http/router.go internal/http/handlers.go internal/http/view_data.go internal/http/admin_api_keys.go internal/http/api_key_middleware.go internal/http/auth_integration_test.go internal/apikeys/service_test.go internal/http/api_key_middleware_test.go internal/http/api_keys_integration_test.go` - passed;
- `GOCACHE=/tmp/go-build-agent05-2 GOMODCACHE=/tmp/go-mod-agent05-2 go test ./...` - passed after downloading dependencies with approval;
- `GOCACHE=/tmp/go-build-agent05-build GOMODCACHE=/tmp/go-mod-agent05-2 go build -o /tmp/update-server-agent05 ./cmd/server` - passed;
- `GOCACHE=/tmp/go-build-agent05-build2 GOMODCACHE=/tmp/go-mod-agent05-2 go build -o /tmp/update-migrate-agent05 ./cmd/migrate` - passed.

## Known Limitations

- CSRF protection is still not implemented for admin forms, including the new API key creation, update, and revoke or activate actions;
- the admin API key UI is intentionally minimal and functional rather than polished;
- the one-time reveal happens on the direct POST response instead of a PRG redirect because the raw key must not be placed into query strings or persistent storage;
- no live client `/api/v1` endpoints use the new middleware yet; the groundwork is ready but the actual project list, latest-release, and download endpoints remain for Agent 06;
- expiration input currently accepts either empty, `YYYY-MM-DD`, or full RFC3339 UTC text rather than a more polished timezone-aware widget.

## Recommended Next Step

Agent 06 should wire the new `requireAPIKey`, `requireAPIKeyPermission`, and `requireAPIKeyProjectAccess` middleware into the client `/api/v1` endpoints for accessible-project listing, latest release lookup, and authenticated artifact download.

## Notes For Validator

- verify that only `key_prefix` and `key_hash` are stored in SQLite and that the raw key appears only in the immediate creation response;
- verify that revoked or expired keys are rejected by `requireAPIKey` with `401` and that missing permissions or blocked project scope return `403`;
- verify effective access resolution across all five scope modes, especially that archived projects do not appear in accessible-project results;
- verify scope transitions clear the incompatible access rows so the existing migration guards continue to succeed;
- verify the admin detail page preview matches the effective active project set for the key.
