v0.1.25.8 — admin-on-behalf-of dual-auth on reservations
Stage 2 of the dashboard ops gap rollout. Admin operators can now read and force-release reservations via the existing endpoints without a tenant API key — closes the runtime-plane side of the gap.
Spec alignment
Implements cycles-protocol revision 2026-04-13 + audit-discoverability clarification. All NORMATIVE requirements verified by contract tests against `cycles-protocol@main`.
Endpoints with new dual-auth
- `GET /v1/reservations` (listReservations) — admin: `tenant` query param REQUIRED as filter; 400 if missing
- `GET /v1/reservations/{id}` (getReservation) — admin bypasses tenant ownership; reservation_id pins the owner
- `POST /v1/reservations/{id}/release` (releaseReservation) — admin force-release + audit-log write
`create` / `commit` / `extend` remain ApiKeyAuth-only by design.
Admin audit-log writing
On admin-driven release, the server writes an audit-log entry with `metadata.actor_type=admin_on_behalf_of` to the store that the governance plane's `GET /v1/admin/audit/logs` reads from — so admin-driven releases surface in the dashboard's existing Audit view without any cross-service plumbing. User-controlled `reason` field is CR/LF-sanitized before recording to prevent log-line forgery.
Tenant-self-service releases do NOT write audit entries (audit remains admin-action-focused, matching the governance plane's existing pattern).
New env var
`ADMIN_API_KEY=` — same value cycles-server-admin uses. Unset → X-Admin-API-Key on allowlisted paths returns 500 with a clear "server misconfiguration" message.
Tests
125/125 pass (was 105; +20 net) — filter admit/reject coverage, controller branching, audit entry verification, CR/LF sanitization regression, fall-through for non-allowlisted admin paths. Contract validation passes against post-merge spec. JaCoCo coverage check passes.
Image
`ghcr.io/runcycles/cycles-server:0.1.25.8` (also `:latest`).
Downstream
Stage 2.3: dashboard PR adding a ReservationsView that surfaces these endpoints. Depends on this image being published.