diff --git a/AUDIT.md b/AUDIT.md index faeff7a..8ef6ab8 100644 --- a/AUDIT.md +++ b/AUDIT.md @@ -1,7 +1,8 @@ -# Cycles Protocol v0.1.23 — Client (TypeScript) Audit +# Cycles Protocol v0.1.25 — Client (TypeScript) Audit -**Date:** 2026-03-19 (updated), 2026-03-14 (initial) -**Spec:** `cycles-protocol-v0.yaml` (OpenAPI 3.1.0, v0.1.23) +**Date:** 2026-05-21 (v0.3.2 — `from` / `to` ISO-8601 window-filter passthrough on `listReservations` per `cycles-protocol-v0.yaml` revision 2026-05-21; closes the TypeScript-client side of runcycles/cycles-server#159. No code change — `params?: Record` already forwards arbitrary keys; added a regression test that pins the URL-encoded passthrough. 316 tests pass at 98.4% statement / 99.62% line coverage.), +2026-03-19 (updated), 2026-03-14 (initial) +**Spec:** `cycles-protocol-v0.yaml` (OpenAPI 3.1.0, v0.1.25) **Client:** `runcycles` (Node 20+ / native fetch / TypeScript 5) **Server audit:** See `cycles-server/AUDIT.md` (all passing) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a0a730..c617fce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/). +## [0.3.2] - 2026-05-21 + +Wire-passthrough verification for the new `from` / `to` query params on `listReservations`. Implements `cycles-protocol-v0.yaml` revision 2026-05-21 ([runcycles/cycles-protocol#97](https://github.com/runcycles/cycles-protocol/pull/97)) on the client side; runcycles/cycles-server#160 ships the server impl. + +### Added + +- Regression test on `client.listReservations` confirming that `from` / `to` ISO-8601 date-time params are URL-encoded and forwarded to the query string. The client's `params?: Record` signature already accepted these — the test locks the contract so future tightening cannot drop them silently. Both colons are URL-encoded (`from=2026-05-21T00%3A00%3A00Z`). + +### Notes + +- No protocol or wire-format change. Servers older than v0.1.25.20 silently ignore the new params per the additive-parameter guarantee in `cycles-protocol-v0.yaml`. +- 316 tests pass; coverage 98.4% statements / 99.62% lines (gate ≥95% per `CLAUDE.md`). + ## [0.3.1] - 2026-05-07 npm metadata refresh for category-search discovery. **No code changes** — bundle and runtime behavior are identical to 0.3.0. diff --git a/package.json b/package.json index 147c25a..fbd76f3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "runcycles", - "version": "0.3.1", + "version": "0.3.2", "description": "TypeScript AI agent runtime control — enforce LLM cost limits, action permissions, and audit trails for agents before execution.", "license": "Apache-2.0", "author": "runcycles", diff --git a/tests/client.test.ts b/tests/client.test.ts index 07fc8c8..c013971 100644 --- a/tests/client.test.ts +++ b/tests/client.test.ts @@ -123,6 +123,29 @@ describe("CyclesClient", () => { const fetchCall = vi.mocked(fetch).mock.calls[0]; expect(fetchCall[0]).toContain("tenant=acme"); }); + + // cycles-protocol-v0.yaml revision 2026-05-21 — from/to ISO-8601 window + // filter passthrough. The existing Record signature already + // accepts the new params; this test pins the contract so future tightening + // cannot silently drop them. + it("forwards from/to ISO-8601 window params to the URL query string", async () => { + mockFetch(200, { reservations: [] }); + + const client = new CyclesClient(config); + const resp = await client.listReservations({ + tenant: "acme", + from: "2026-05-21T00:00:00Z", + to: "2026-05-22T00:00:00Z", + }); + + expect(resp.isSuccess).toBe(true); + const fetchCall = vi.mocked(fetch).mock.calls[0]; + const url = String(fetchCall[0]); + expect(url).toContain("tenant=acme"); + // URL-encoded form of "2026-05-21T00:00:00Z" — the colons are escaped. + expect(url).toContain("from=2026-05-21T00%3A00%3A00Z"); + expect(url).toContain("to=2026-05-22T00%3A00%3A00Z"); + }); }); describe("getReservation", () => {