Releases: runcycles/cycles-server
Release list
v0.1.25.10 custom Micrometer counters + Redis-disconnect test
What's Changed
- feat(metrics): v0.1.25.10 — custom Micrometer counters + Redis-disconnect test by @amavashev in #97
Adds seven domain-level counters under the cycles_* namespace (reserve, commit, release, extend, expired, events, overdraft.incurred) so operators can answer "how many denials in the last 5 minutes by reason and tenant" without reverse-engineering it from HTTP status codes. New RedisDisconnectResilienceIntegrationTest pauses its Testcontainers Redis mid-request to prove the service fails cleanly and recovers.
Dormant bug fixed: ReservationExpiryService.emitExpiredEvent used the wrong Redis key prefix, silently no-op'ing on every expiry since v0.1.25.3. Surfaced immediately by the new cycles.reservations.expired counter test.
Wire format unchanged vs v0.1.25.9 — no request/response body changes.
Full Changelog: v0.1.25.9...v0.1.25.10
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.
v0.1.25.7 typed Enums.ReasonCode + flaky EventEmitterServiceTest fix
What's Changed
- refactor: type DecisionResponse / ReservationCreateResponse reason_code as Enums.ReasonCode by @amavashev in #83
- test: de-flake EventEmitterServiceTest by replacing Thread.sleep with Mockito timeout/after by @amavashev in #82
Closes #81. Companion spec PR: runcycles/cycles-protocol#26.
Two quality improvements bundled, no wire-format change — JSON output is byte-identical to v0.1.25.6 on every response.
Typed Enums.ReasonCode refactor (#83): DecisionResponse.reasonCode and ReservationCreateResponse.reasonCode retyped from free-form String to a typed enum with 6 values (BUDGET_EXCEEDED, BUDGET_FROZEN, BUDGET_CLOSED, BUDGET_NOT_FOUND, OVERDRAFT_LIMIT_EXCEEDED, DEBT_OUTSTANDING). Mirrors the DecisionReasonCode schema added to cycles-protocol-v0.yaml in runcycles/cycles-protocol#26. Jackson serializes enum to name(), so JSON output is byte-identical to v0.1.25.6. Compile-time safety against drift from the spec enum.
De-flaked EventEmitterServiceTest (#82): 13 Thread.sleep(200) + verify() race-condition patterns replaced with Mockito timeout(5000) / after(200).never() verification modes. Test-only, no runtime impact.
No spec bump required. The companion DecisionReasonCode enum in runcycles/cycles-protocol#26 is forward-compatible regardless of merge order.
Full Changelog: v0.1.25.6...v0.1.25.7
v0.1.25.6 distinguish UNIT_MISMATCH from BUDGET_NOT_FOUND on reserve/event/decide
What's Changed
- fix: distinguish UNIT_MISMATCH from BUDGET_NOT_FOUND on reserve/event/decide by @amavashev in #80
Closes #79. Addresses runcycles/cycles-client-rust#8.
reserve.lua, event.lua, and the Java-side decide / evaluateDryRun paths now probe alternate units when no budget is found at the requested unit. If a budget exists at the scope in a different unit, returns 400 UNIT_MISMATCH with {scope, requested_unit, expected_units} in details so clients can self-correct. 404 BUDGET_NOT_FOUND remains for the truly-missing case.
No hot-path change — the probe fires only on the empty-budgeted-scopes error path. 291 tests / 0 failures / jacoco coverage checks met.
Companion spec update: runcycles/cycles-protocol#25 (broadens normative UNIT_MISMATCH wording, documents 404 on reserve + event endpoints).
Full Changelog: v0.1.25.5...v0.1.25.6
v0.1.25.5 fix duplicate budget events
What's Changed
- fix: transition-based event emission to prevent duplicate budget events (v0.1.25.5) by @amavashev in #78
Full Changelog: v0.1.25.4...v0.1.25.5
v0.1.25.4 - event data payload completeness for spec compliance
What's Changed
- fix: event data payload completeness for spec compliance (v0.1.25.4) by @amavashev in #77
Full Changelog: v0.1.25.3...v0.1.25.4
v0.1.25.3 bugs and stability fixes, emit more events
What's Changed
- fix: case-insensitive scope matching in getBalances/listReservations by @amavashev in #75
- feat: v0.1.25.3 — extended runtime event emission by @amavashev in #76
Full Changelog: v0.1.25.1...v0.1.25.3
v0.1.25.1 initial .25 spec release
What's Changed
- Feature/performance optimizations by @amavashev in #71
- feat: v0.1.25.1 — webhook event emission and runtime optimizations by @amavashev in #72
- Claude/server events implementation u e xga by @amavashev in #73
- docs: update version example in README to 0.1.25.1 by @amavashev in #74
Full Changelog: v0.1.24.3...v0.1.25.1
v0.1.23.3 - peformance optimizations
What's Changed
- Refactor Claude settings and documentation formatting by @amavashev in #62
- Claude/add config files fo5wo by @amavashev in #63
- Refactor test suite: split monolithic tests into focused test classes by @amavashev in #64
- Add coverage badge (95%+ enforced by JaCoCo) by @amavashev in #69
- chore(deps): bump docker/login-action from 3 to 4 by @dependabot[bot] in #65
- chore(deps): bump actions/checkout from 4 to 6 by @dependabot[bot] in #66
- chore(deps): bump docker/build-push-action from 6 to 7 by @dependabot[bot] in #67
- chore(deps): bump docker/setup-buildx-action from 3 to 4 by @dependabot[bot] in #68
- Feature/performance optimizations by @amavashev in #70
New Contributors
- @dependabot[bot] made their first contribution in #65
Full Changelog: v0.1.24.2...v0.1.24.3
v0.1.24.2 bug fixes, debt handling on allow_with_overdraft
What's Changed
- Fix debt handling: allow reservations when debt within overdraft limit by @amavashev in #61
Full Changelog: v0.1.24.1...v0.1.24.2