diff --git a/CONFORMANCE.md b/CONFORMANCE.md index 1f14fb3..24ad123 100644 --- a/CONFORMANCE.md +++ b/CONFORMANCE.md @@ -96,7 +96,7 @@ A conformant implementation SHOULD: - Emit events for budget-state changes (reservation.*, budget.*, quota.*) matching the `EventType` enum. Implementations MAY sample or filter which events they emit, but emitted events MUST follow the schema. - Propagate `X-Cycles-Trace-Id` and W3C `traceparent` headers per `cycles-protocol-v0.yaml` §CORRELATION AND TRACING. Trace correlation is central to multi-service debugging. - Implement `POST /v1/decide` — marked OPTIONAL in the v0 spec, but agent frameworks need soft-landing signals for graceful degradation. -- Implement `GET /v1/reservations` (**listReservations**) — marked OPTIONAL in v0; useful for reservation recovery (re-discover a lost `reservation_id` via `idempotency_key`) and for identifying stuck `ACTIVE` reservations. +- Implement `GET /v1/reservations` (**listReservations**) — marked OPTIONAL in v0; useful for reservation recovery (re-discover a lost `reservation_id` via `idempotency_key`), for identifying stuck `ACTIVE` reservations, and for time-window queries via the additive `from`/`to` parameters (v0.1.25, revision 2026-05-21). - Implement `GET /v1/reservations/{reservation_id}` (**getReservation**) — marked "optional, for debugging" in v0; valuable for support / monitoring of long-running reservations. - Implement `POST /v1/events` (**createEvent**) — marked OPTIONAL in v0; the post-only accounting path for cases where pre-estimation is unavailable (bills-later providers, receipt ingestion). diff --git a/changelogs/cycles-protocol-v0.md b/changelogs/cycles-protocol-v0.md index cc4c5df..8f5304b 100644 --- a/changelogs/cycles-protocol-v0.md +++ b/changelogs/cycles-protocol-v0.md @@ -6,6 +6,58 @@ New entries are added directly to this file. See `scripts/validate_changelogs.py --- +## v0.1.25 — 2026-05-21 + +_(revision 2026-05-21 — `from`/`to` created-time range filters on listReservations)_ + +- Adds two optional query parameters to `listReservations` + (`GET /v1/reservations`): + * `from`: ISO 8601 date-time. Inclusive lower bound on + reservation `created_at_ms`. May be supplied alone (no + upper bound) or paired with `to`. + * `to`: ISO 8601 date-time. Inclusive upper bound on + reservation `created_at_ms`. May be supplied alone (no + lower bound) or paired with `from`. +- Closes a real client-side cost: today, fetching "last 24h + of reservations" requires sort-by-`created_at_ms` + a + page-size escalation loop until the oldest item falls + outside the window. For high-volume agent clusters this + scans far more rows than the caller actually needs. With + `from`/`to`, the server boundaries the scan to the + requested window and pagination over that window remains + cursor-stable. +- Both parameters bind to `created_at_ms` regardless of + `sort_by`. A client sorting by `expires_at_ms` while + filtering by `from`/`to` gets the expected behavior: + results in the requested window, ordered by expiry. This + keeps the contract predictable across sort keys (no + per-key filter semantics to memorize). +- Validation: + * Servers MUST reject `from > to` with HTTP 400 + INVALID_REQUEST. + * Either parameter alone is valid; absent parameter + means "no bound on that side." + * Malformed date-time values MUST be rejected with HTTP + 400 INVALID_REQUEST (consistent with other ISO 8601 + query parameters in the spec family). +- Additive-parameter guarantee: servers that don't recognize + `from`/`to` MUST ignore without error and return the + unfiltered set. Older clients that never send them get the + pre-revision wire behavior byte-for-byte. +- Naming and wire-type rationale: matches the family-wide + `from`/`to` + `format: date-time` convention already in + use on `listAuditLogs`, `listEvents`, + `listWebhookDeliveries`, `listTenantEvents`, and + `listTenantWebhookDeliveries` in the governance-admin + spec. Bespoke `created_after`/`created_before` names or + Unix-epoch wire types would split the convention for + clients and codegen. +- Backward compatible: purely additive. No request or + response schema changes. Both ApiKeyAuth and AdminKeyAuth + callers see the new parameters. + +--- + ## v0.1.25 — 2026-04-18 _(revision 2026-04-18 — trace_id cross-surface correlation, W3C Trace Context-compatible)_ diff --git a/cycles-protocol-v0.yaml b/cycles-protocol-v0.yaml index 34b1409..d8cbea7 100644 --- a/cycles-protocol-v0.yaml +++ b/cycles-protocol-v0.yaml @@ -1470,6 +1470,20 @@ paths: - Query parameters tenant/workspace/app/workflow/agent/toolset filter on the canonical Subject fields. - Filtering on Subject.dimensions is out of scope for v0 unless explicitly implemented by the server. + TIME-RANGE FILTERS (NORMATIVE, ADDITIVE): + - Query parameters `from` and `to` (ISO 8601 date-time strings) + bound the `created_at_ms` of returned reservations, inclusive + on both ends. + - The filter is fixed to `created_at_ms` regardless of `sort_by`; + sorting by `expires_at_ms` while filtering by `from`/`to` is + valid and well-defined. + - Either may be supplied alone (open interval) or together + (closed window). `from > to` MUST return 400 INVALID_REQUEST. + - Both are additive parameters: servers that don't recognize + them MUST ignore without error and return the unfiltered set. + This matches the family-wide `from`/`to` convention on + `listAuditLogs`, `listEvents`, and `listWebhookDeliveries`. + TENANCY (NORMATIVE): - Under ApiKeyAuth: the server MUST scope results to the effective tenant derived from auth. If the tenant query parameter is @@ -1524,6 +1538,43 @@ paths: in: query required: false schema: {type: string} + - name: from + in: query + required: false + description: >- + Inclusive lower bound on reservation creation time. ISO 8601 + date-time. When set, the server MUST return only reservations + whose `created_at_ms` is greater than or equal to this + timestamp. The filter ALWAYS binds to `created_at_ms`, + independent of `sort_by`. May be supplied alone (no upper + bound) or paired with `to`. Servers MUST reject `from > to` + with HTTP 400 INVALID_REQUEST. + + Additive parameter — servers that don't recognize it MUST + ignore without error (additive-parameter guarantee). Matches + the `from` / `to` convention on `listAuditLogs`, + `listEvents`, and `listWebhookDeliveries` in the governance + spec family. + schema: + type: string + format: date-time + - name: to + in: query + required: false + description: >- + Inclusive upper bound on reservation creation time. ISO 8601 + date-time. When set, the server MUST return only reservations + whose `created_at_ms` is less than or equal to this + timestamp. The filter ALWAYS binds to `created_at_ms`, + independent of `sort_by`. May be supplied alone (no lower + bound) or paired with `from`. Servers MUST reject `from > to` + with HTTP 400 INVALID_REQUEST. + + Additive parameter — servers that don't recognize it MUST + ignore without error. + schema: + type: string + format: date-time - name: sort_by in: query required: false diff --git a/merged/cycles-openapi-protocol-merged.yaml b/merged/cycles-openapi-protocol-merged.yaml index 8f97f90..0f2101c 100644 --- a/merged/cycles-openapi-protocol-merged.yaml +++ b/merged/cycles-openapi-protocol-merged.yaml @@ -2186,6 +2186,20 @@ paths: - Query parameters tenant/workspace/app/workflow/agent/toolset filter on the canonical Subject fields. - Filtering on Subject.dimensions is out of scope for v0 unless explicitly implemented by the server. + TIME-RANGE FILTERS (NORMATIVE, ADDITIVE): + - Query parameters `from` and `to` (ISO 8601 date-time strings) + bound the `created_at_ms` of returned reservations, inclusive + on both ends. + - The filter is fixed to `created_at_ms` regardless of `sort_by`; + sorting by `expires_at_ms` while filtering by `from`/`to` is + valid and well-defined. + - Either may be supplied alone (open interval) or together + (closed window). `from > to` MUST return 400 INVALID_REQUEST. + - Both are additive parameters: servers that don't recognize + them MUST ignore without error and return the unfiltered set. + This matches the family-wide `from`/`to` convention on + `listAuditLogs`, `listEvents`, and `listWebhookDeliveries`. + TENANCY (NORMATIVE): - Under ApiKeyAuth: the server MUST scope results to the effective tenant derived from auth. If the tenant query parameter is @@ -2246,6 +2260,24 @@ paths: required: false schema: type: string + - name: from + in: query + required: false + description: |- + Inclusive lower bound on reservation creation time. ISO 8601 date-time. When set, the server MUST return only reservations whose `created_at_ms` is greater than or equal to this timestamp. The filter ALWAYS binds to `created_at_ms`, independent of `sort_by`. May be supplied alone (no upper bound) or paired with `to`. Servers MUST reject `from > to` with HTTP 400 INVALID_REQUEST. + Additive parameter — servers that don't recognize it MUST ignore without error (additive-parameter guarantee). Matches the `from` / `to` convention on `listAuditLogs`, `listEvents`, and `listWebhookDeliveries` in the governance spec family. + schema: + type: string + format: date-time + - name: to + in: query + required: false + description: |- + Inclusive upper bound on reservation creation time. ISO 8601 date-time. When set, the server MUST return only reservations whose `created_at_ms` is less than or equal to this timestamp. The filter ALWAYS binds to `created_at_ms`, independent of `sort_by`. May be supplied alone (no lower bound) or paired with `from`. Servers MUST reject `from > to` with HTTP 400 INVALID_REQUEST. + Additive parameter — servers that don't recognize it MUST ignore without error. + schema: + type: string + format: date-time - name: sort_by in: query required: false