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 protocol/api-reference-for-the-cycles-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ Reserve budget before executing work.
| `subject` | Subject | Yes | Budgeting scope |
| `action` | Action | Yes | Action being budgeted |
| `estimate` | Amount | Yes | Estimated cost |
| `ttl_ms` | integer | No | Reservation TTL in ms (default: 60000, range: 1000–86400000) |
| `ttl_ms` | integer | No | Reservation TTL in ms (default: tenant `default_reservation_ttl_ms` or 60000, range: 1000–86400000, capped to tenant `max_reservation_ttl_ms`) |
| `grace_period_ms` | integer | No | Grace period after TTL for late commits (default: 5000, range: 0–60000) |
| `overage_policy` | string | No | `REJECT` (default), `ALLOW_IF_AVAILABLE`, or `ALLOW_WITH_OVERDRAFT` |
| `overage_policy` | string | No | `REJECT`, `ALLOW_IF_AVAILABLE`, or `ALLOW_WITH_OVERDRAFT` (default: tenant `default_commit_overage_policy` or `REJECT`) |
| `dry_run` | boolean | No | If true, evaluate without reserving (default: false) |
| `metadata` | object | No | Arbitrary key-value metadata |

Expand Down Expand Up @@ -391,6 +391,7 @@ curl -X POST http://localhost:7878/v1/reservations/res-abc-123/extend \
| 404 | `NOT_FOUND` | Reservation does not exist |
| 409 | `RESERVATION_FINALIZED` | Already committed or released |
| 409 | `IDEMPOTENCY_MISMATCH` | Same key, different payload |
| 409 | `MAX_EXTENSIONS_EXCEEDED` | Tenant `max_reservation_extensions` limit reached |
| 410 | `RESERVATION_EXPIRED` | Past TTL (no grace period for extend) |

---
Expand Down Expand Up @@ -635,7 +636,7 @@ Record a direct debit event without a prior reservation. Used for post-hoc accou
| `subject` | Subject | Yes | Budgeting scope |
| `action` | Action | Yes | Action being recorded |
| `actual` | Amount | Yes | Actual cost to record |
| `overage_policy` | string | No | `REJECT` (default), `ALLOW_IF_AVAILABLE`, or `ALLOW_WITH_OVERDRAFT` |
| `overage_policy` | string | No | `REJECT`, `ALLOW_IF_AVAILABLE`, or `ALLOW_WITH_OVERDRAFT` (default: tenant `default_commit_overage_policy` or `REJECT`) |
| `metrics` | object | No | Standard metrics |
| `client_time_ms` | integer | No | Client-side timestamp |
| `metadata` | object | No | Arbitrary metadata |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,20 @@ Cycles defines three overage policies, set at reservation time (or on events):

Each policy makes a different tradeoff between ledger accuracy and budget strictness.

### Resolution order

When a reservation or event is created, the server resolves the overage policy in this order:

1. **Request-level** `overage_policy` — if the client specifies one, it is used
2. **Tenant default** `default_commit_overage_policy` — if the tenant has one configured via the Admin API
3. **Hardcoded fallback** — `REJECT`

This means tenant administrators can set an org-wide default (e.g. `ALLOW_IF_AVAILABLE`) and individual requests can still override it.

## REJECT (default)

REJECT is the default overage policy when neither the request nor the tenant configuration specifies one. Tenant administrators can change the default for all reservations and events in their tenant by setting `default_commit_overage_policy` via the Admin API.

REJECT is the simplest and strictest policy.

If `actual > reserved`, the commit is rejected with `409 BUDGET_EXCEEDED`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ Events support the same three overage policies as commits:

If the actual amount exceeds the available budget, the event is rejected with `409 BUDGET_EXCEEDED`.

This is the safest default. It prevents any accounting that would put the scope into negative remaining.
REJECT is the default when neither the request nor the tenant's `default_commit_overage_policy` specifies a policy. It prevents any accounting that would put the scope into negative remaining.

### ALLOW_IF_AVAILABLE

Expand Down
9 changes: 7 additions & 2 deletions protocol/reservation-ttl-grace-period-and-extend-in-cycles.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ When a reservation is created, the server sets an expiration time:
expires_at_ms = created_at_ms + ttl_ms
```

The default TTL is 60 seconds (`ttl_ms: 60000`).
The default TTL is 60 seconds (`ttl_ms: 60000`). Tenant administrators can change this default by setting `default_reservation_ttl_ms` via the Admin API.

The allowed range is 1 second to 24 hours (`1000` to `86400000` milliseconds).
The allowed range is 1 second to 24 hours (`1000` to `86400000` milliseconds). Tenant administrators can further restrict this range by setting `max_reservation_ttl_ms` — any requested TTL exceeding the tenant maximum is capped automatically.

When the clock passes `expires_at_ms`, the reservation enters expiration processing. If it has not been committed or released, the server marks it as `EXPIRED` and returns the reserved budget to the available pool.

Expand Down Expand Up @@ -89,10 +89,15 @@ The reservation is the same reservation. It just lives longer.

- If the reservation is already `COMMITTED` or `RELEASED`: `409 RESERVATION_FINALIZED`
- If the reservation has already expired (past `expires_at_ms`): `410 RESERVATION_EXPIRED`
- If the tenant's `max_reservation_extensions` limit has been reached: `409 MAX_EXTENSIONS_EXCEEDED`
- If the reservation was never created: `404 NOT_FOUND`

Note: extend must happen before TTL expires, not during the grace period. The grace period only covers commit and release.

### Extension limits

Tenant administrators can set `max_reservation_extensions` via the Admin API to limit how many times a single reservation can be extended (default: 10). This prevents infinite zombie reservations from clients that heartbeat indefinitely without committing or releasing.

## The heartbeat pattern

For long-running workflows, the recommended approach is:
Expand Down
Loading