Skip to content

fix: spec compliance for reservation 410 and event charged field#60

Merged
amavashev merged 9 commits intomainfrom
claude/audit-spec-compliance-Nc9Hh
Mar 24, 2026
Merged

fix: spec compliance for reservation 410 and event charged field#60
amavashev merged 9 commits intomainfrom
claude/audit-spec-compliance-Nc9Hh

Conversation

@amavashev
Copy link
Collaborator

@amavashev amavashev commented Mar 24, 2026

Summary

Fixes two spec compliance gaps found during YAML spec audit:

  • m3: GET /v1/reservations/{id} now returns HTTP 410 with RESERVATION_EXPIRED when the reservation status is EXPIRED. Spec normative: "Expired reservations MUST return HTTP 410 with error=RESERVATION_EXPIRED."
  • m7: Event charged field is now only included in the response when overage_policy=ALLOW_IF_AVAILABLE and capping actually occurred (charged < requested). Previously always returned.

Test plan

  • Existing unit tests pass (verified: 93 tests, 0 failures in non-integration modules)
  • Integration tests with Redis verify 410 response for expired reservations
  • Integration tests verify event response omits charged when no capping occurs
  • Integration tests verify event response includes charged when ALLOW_IF_AVAILABLE caps the amount

https://claude.ai/code/session_018QQFJnBJBjvMU24LCNMjvT

claude added 9 commits March 24, 2026 19:51
- Return HTTP 410 RESERVATION_EXPIRED when GET /v1/reservations/{id}
  fetches an expired reservation (spec normative requirement)
- Only include `charged` in event response when overage_policy is
  ALLOW_IF_AVAILABLE and capping actually occurred (per spec description)

https://claude.ai/code/session_018QQFJnBJBjvMU24LCNMjvT
- GET /v1/reservations/{id}: also check expires_at_ms against server
  time for ACTIVE reservations (background expiry service may lag)
- Add test: shouldReturn410ForExpiredReservation
- Add tests: shouldIncludeChargedWhenCapped, shouldOmitChargedWhenNotCapped

https://claude.ai/code/session_018QQFJnBJBjvMU24LCNMjvT
Replace System.currentTimeMillis() with jedis.time() in
getReservationById() to match Lua scripts and avoid inconsistent
expiry decisions from JVM-Redis clock drift.

https://claude.ai/code/session_018QQFJnBJBjvMU24LCNMjvT
The real-time expiry check in getReservationById() now calls
jedis.time(), but existing tests used past-dated expires_at values
without mocking jedis.time(). Add default mock returning a time
before test reservation expiry so ACTIVE reservations don't
false-trigger the 410 path.

https://claude.ai/code/session_018QQFJnBJBjvMU24LCNMjvT
Remove the 410 RESERVATION_EXPIRED check from getReservationById().
GET is read-only and always returns 200 with the reservation detail
including the status field (ACTIVE, COMMITTED, RELEASED, or EXPIRED).

The 410 response applies to mutating operations (commit/release/extend)
which enforce expiry in their Lua scripts. GET is for debugging and
must show the current state regardless of lifecycle stage.

https://claude.ai/code/session_018QQFJnBJBjvMU24LCNMjvT
Add Issue 9 (event.lua charged field fix) and document confirmed
non-issues validated against the YAML spec (ErrorResponse.details,
Balance optional fields, CommitResponse.released, GET reservation 200).

https://claude.ai/code/session_018QQFJnBJBjvMU24LCNMjvT
Spec line 52: "Expired reservations MUST return HTTP 410 with
error=RESERVATION_EXPIRED." GET endpoint explicitly lists 410 (line
1212). Implementation was returning 200 — now returns 410.

- Add EXPIRED status check in getReservationById()
- Update integration tests to assert 410 RESERVATION_EXPIRED
- Update unit test to assert 410
- Update AUDIT.md with Issue 10

https://claude.ai/code/session_018QQFJnBJBjvMU24LCNMjvT
Spec NORMATIVE: "On replay with the same idempotency_key, the server
MUST return the original successful response payload."

- event.lua: replay now reconstructs charged (when capping occurred)
  and balances from stored event hash + current budget state
- commit.lua: replay now includes balances and affected_scopes_json
  by reading affected_scopes from reservation hash
- release.lua: replay now includes balances by reading affected_scopes
  from reservation hash

https://claude.ai/code/session_018QQFJnBJBjvMU24LCNMjvT
Spec compliance audit fixes: idempotency replay, event charged field,
GET reservation 410.

https://claude.ai/code/session_018QQFJnBJBjvMU24LCNMjvT
@amavashev amavashev merged commit fde0342 into main Mar 24, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants