Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions AUDIT.md
Original file line number Diff line number Diff line change
@@ -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<string, string>` 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)

Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, string>` 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.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
23 changes: 23 additions & 0 deletions tests/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, string> 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", () => {
Expand Down