# Agent Name: Agent 06 - Client API And Admin UI Stage: Client API And Admin UI Date: 2026-04-15 ## Scope Implemented the usable end-to-end product flow for admins and client applications on top of the existing project, release, and API key work from Agents 04 and 05. Completed in this stage: - added bearer-authenticated client endpoints under `/api/v1` for: - listing accessible active projects; - looking up the latest active release for an accessible project; - fetching release metadata by release ID for an accessible project; - downloading private release artifacts by release ID after auth, permission, and scope checks; - reused the existing API key middleware and scope-evaluation service so disabled or expired keys return `401`, missing download permission returns `403`, and inaccessible projects or releases return `404` to avoid leaking unauthorized resources; - added project slug lookup and latest-active-release repository queries so client handlers can resolve project-scoped metadata cleanly from persisted release rows; - added a safe artifact-open path on top of the existing private local storage so downloads stream from the artifact root instead of exposing raw filesystem paths or static URLs; - updated the API index and the home or dashboard copy so the live client API is discoverable instead of still looking like a placeholder; - added small admin UI improvements on project detail and API key detail pages that show the client API paths and a bearer-auth quick-start example after an admin uploads a release or creates a key; - added integration coverage for the client flow, including auth failures, scope enforcement, latest-release selection, release metadata lookup, and authorized or unauthorized download behavior. ## Files Changed - `/Users/delete/projects/update_server/internal/db/projects.go` - `/Users/delete/projects/update_server/internal/db/releases.go` - `/Users/delete/projects/update_server/internal/storage/local.go` - `/Users/delete/projects/update_server/internal/releases/service.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/admin_common.go` - `/Users/delete/projects/update_server/internal/http/admin_projects.go` - `/Users/delete/projects/update_server/internal/http/view_data.go` - `/Users/delete/projects/update_server/internal/http/client_api.go` - `/Users/delete/projects/update_server/internal/http/client_api_integration_test.go` - `/Users/delete/projects/update_server/internal/http/api_keys_integration_test.go` - `/Users/delete/projects/update_server/internal/http/projects_integration_test.go` - `/Users/delete/projects/update_server/web/templates/pages/project_detail.gohtml` - `/Users/delete/projects/update_server/web/templates/pages/api_key_form.gohtml` - `/Users/delete/projects/update_server/web/templates/pages/api_keys.gohtml` - `/Users/delete/projects/update_server/web/static/app.css` - `/Users/delete/projects/update_server/docs/agents/handoffs/06-client-api-ui.md` ## Database Changes - no new migrations or schema changes were required; - added repository queries against the existing `projects` and `releases` tables: - project lookup by slug; - latest active release lookup ordered by persisted `created_at DESC, id DESC`; - continued using the existing API key scope tables and scope modes without redesign. ## API Or Route Changes - kept `GET /api/v1` public and upgraded it from a placeholder to a real client API index; - added protected client routes behind bearer API key auth plus `can_download` permission: - `GET /api/v1/projects` - `GET /api/v1/projects/{projectSlug}/releases/latest` - `GET /api/v1/releases/{releaseID}` - `GET /api/v1/releases/{releaseID}/download` - resource access behavior for client routes: - missing, invalid, disabled, or expired API key -> `401` - authenticated key without download permission -> `403` - inaccessible or archived project or release -> `404` - admin UI additions: - project detail page now shows the relevant client API paths for that project and latest release; - API key detail page now shows a bearer-auth quick-start example plus the accessible project metadata paths. ## Commands And Tests Run - `gofmt -w internal/db/projects.go internal/db/releases.go internal/storage/local.go internal/http/view_data.go internal/http/admin_common.go internal/http/admin_projects.go internal/http/router.go internal/http/handlers.go internal/http/client_api.go internal/releases/service.go internal/http/api_keys_integration_test.go internal/http/projects_integration_test.go internal/http/client_api_integration_test.go` - passed - `GOCACHE=/tmp/go-build-agent06-http GOMODCACHE=/tmp/go-mod-agent06-http go test ./internal/http ./internal/releases ./internal/db ./internal/apikeys` - initially failed in sandbox because module downloads could not resolve DNS, then passed after rerunning with approval - `GOCACHE=/tmp/go-build-agent06-all GOMODCACHE=/tmp/go-mod-agent06-http go test ./...` - passed - `GOCACHE=/tmp/go-build-agent06-build GOMODCACHE=/tmp/go-mod-agent06-http go build -o /tmp/update-server-agent06 ./cmd/server` - passed - `GOCACHE=/tmp/go-build-agent06-migrate GOMODCACHE=/tmp/go-mod-agent06-http go build -o /tmp/update-migrate-agent06 ./cmd/migrate` - passed ## Known Limitations - “Latest” currently means the newest active persisted release by `created_at` and `id`, not semantic-version comparison; - the optional client query parameters mentioned in the product spec (`current_version`, `channel`, `platform`, `arch`) are still not implemented; - the client API does not yet expose full per-project release listing; this stage focused on the required list, latest-metadata, metadata-by-ID, and download flow; - the admin quick-start example can show the real raw key only on the one-time create response; later detail views intentionally fall back to a placeholder token; - broader hardening work such as CSRF completion, rate limiting, security headers, audit logging polish, and deployment proxy setup remains out of scope for this stage. ## Recommended Next Step Run the validation pass for Agent 06, then move to Agent 07 to implement the planned hardening and deployment-focused follow-up: CSRF, security headers, rate limiting, audit/logging polish, and deployment readiness around the now-working end-to-end product flow. ## Notes For Validator - verify that client routes require `Authorization: Bearer ` and that disabled or expired keys are rejected with `401`; - verify that client routes require `can_download` and return `403` when the key authenticates but lacks download permission; - verify that unauthorized, archived, or out-of-scope projects and releases return `404` from metadata and download paths rather than leaking through a `403`; - verify that `GET /api/v1/projects` returns only active projects allowed by the key’s scope evaluation; - verify that the latest-release endpoint selects the newest active persisted release row for the project; - verify that the download endpoint streams bytes from private artifact storage and does not expose static URLs or raw filesystem paths; - verify that the project detail and API key detail admin pages visibly expose the new client API quick-start information.