90 lines
6.1 KiB
Markdown
90 lines
6.1 KiB
Markdown
# 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.
|