Skip to content

Spec-conformance audit: reserve() panic on additive Decision, retry_after lost on error path #56

Description

@amavashev

Spec-conformance audit (2026-07-04 fleet sweep) against protocol spec v0.1.25.12. Enum tolerance is exemplary (#[serde(other)] Unknown everywhere, no deny_unknown_fields) — findings are mostly error-path ergonomics plus one latent panic.

Bugs / latent breaks

  1. Additive Decision value → panic in reserve() (client.rs:186-189): a non-Deny unknown decision bypasses is_denied() and hits .expect("reservation_id ... must be present when decision is ALLOW"). The #[serde(other)] forward-compat is undercut by control flow — treat non-ALLOW/ALLOW_WITH_CAPS as an error instead of expecting.
  2. retry_after hard-coded None on all error paths (client.rs:436,445): ErrorResponse has no retry_after_ms field and no Retry-After header parse, so Error::is_retryable() (error.rs:71) classifies every BudgetExceeded (and future 429 LIMIT_EXCEEDED) as non-retryable. The 200-body deny path DOES surface retry_after_ms — same server condition, different error richness.
  3. 410 Gone unhandled; 409 IdempotencyMismatch/ReservationFinalized unclassified — all fall to generic Error::Api (client.rs:423-438); 409 path also discards affected_scopes.

Spec-currency gaps

  1. ErrorCode lacks LIMIT_EXCEEDED (spec v0.1.25.12) — tolerated as Unknown today.
  2. Evidence surface (cycles_evidence response fields, GET /v1/evidence/{id}, JWKS) unmodeled; silently dropped. ReservationSummary also lacks committed/metadata/committed_metadata/evidence projections (include=, spec 2026-06-19/22 revisions); ListReservationsParams has the window filters ✓ but no sort_by/sort_dir/include.
  3. validate_extend_by_ms (validation.rs:40) defined but never called on the extend path; retry engine is dead_code ("future release") while guard commit failures propagate directly — either wire or remove.
  4. ListReservationsParams not #[non_exhaustive] (request.rs:142) — every additive param bump is a source-breaking change (already bit v0.2.5/v0.2.6 per CHANGELOG).

Context

Same sweep: spec PRs runcycles/cycles-protocol#120/#121/#122 and fixes across the server fleet. Full inventory details available on request.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions