# 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 <api_key>` 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.
