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
1 change: 1 addition & 0 deletions CONFORMANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ A conformant implementation MAY:
- Replace any or all of those reference portions with an alternative provisioning mechanism: OAuth/OIDC for auth, GitOps YAML for policies, internal admin console for tenants, direct DB writes for budget allocation, etc. (The reference portions only — the eight normative cross-plane operations listed under §MUST still apply.)
- Skip `audit_log` entirely. Not required by the protocol.
- Expose additional endpoints beyond those specified, as long as they use a non-`/v1` path prefix or a vendor-namespaced extension path (e.g., `/v1/x-runcycles/...`).
- Emit **CyclesEvidence**: populate the optional `cycles_evidence` ref (`CyclesEvidenceRef`) on decide / reserve / commit / release / error responses and serve `GET /v1/evidence/{id}` (`getEvidence`). Both are additive and optional in `cycles-protocol-v0.yaml`; the signed envelope they reference is specified in the draft companion [`drafts/cycles-evidence-v0.1.yaml`](drafts/cycles-evidence-v0.1.yaml) (see [`drafts/README.md`](drafts/README.md)), which is **not yet part of the conformance target**. A client that ignores `cycles_evidence` is fully conformant.

---

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ See [`CONFORMANCE.md`](CONFORMANCE.md) for the authoritative MUST / SHOULD / MAY
> - **Counter reset** — incident response endpoint for stuck per_run counters
>
> The suite ships as companion specs: [`cycles-protocol-v0.yaml`](cycles-protocol-v0.yaml) (runtime base), [`cycles-protocol-extensions-v0.1.26.yaml`](cycles-protocol-extensions-v0.1.26.yaml) (runtime extension), [`cycles-action-kinds-v0.1.26.yaml`](cycles-action-kinds-v0.1.26.yaml) (registry), [`cycles-governance-admin-v0.1.25.yaml`](cycles-governance-admin-v0.1.25.yaml) (admin base), and [`cycles-governance-extensions-v0.1.26.yaml`](cycles-governance-extensions-v0.1.26.yaml) (admin extension). See [`cycles-spec-index.yaml`](cycles-spec-index.yaml) for the composition manifest and merge recipes.
>
> **CyclesEvidence** (draft): the runtime base also defines an optional `cycles_evidence` reference (`CyclesEvidenceRef`) on the decide / reserve / commit / release / error responses plus `GET /v1/evidence/{id}` (`getEvidence`) — the consumer surface for tamper-evident, content-addressed, Ed25519-signed audit envelopes. The envelope itself is specified in the draft companion [`drafts/cycles-evidence-v0.1.yaml`](drafts/cycles-evidence-v0.1.yaml) (see [`drafts/README.md`](drafts/README.md)). Additive and optional — `0.1.25` clients that ignore it are unaffected.

---

Expand Down
8 changes: 6 additions & 2 deletions changelogs/cycles-protocol-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,12 @@ _(revision 2026-06-13 — surface `cycles_evidence` on the decide response)_
`drafts/cycles-evidence-v0.1.yaml` (`DecidePayload` = `{request, response}`, no
reservation created) with golden fixtures `01-decide-allow` /
`09-decide-risk-points-allow`. Forbidden/validation failures on `/v1/decide`
remain `error`-artifact territory (e.g. fixture `12-decide-live-forbidden`).
Present unless emission is disabled; additive + non-breaking.
are NOT `decide` evidence — they surface as 4xx in the `error`-artifact DOMAIN
(the verifier-domain fixture `12-decide-live-forbidden` illustrates that shape;
the reference server itself omits `cycles_evidence` for such pre-evaluation
auth/validation failures — see the error artifact's domain-vs-emission note in
`drafts/cycles-evidence-v0.1.yaml`). Present unless emission is disabled;
additive + non-breaking.

---

Expand Down
36 changes: 36 additions & 0 deletions cycles-spec-index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,42 @@ documents:
- Platform/operator teams (required for v0.1.26 admin API support)
- Admin tooling authors

- id: evidence_envelope
file: drafts/cycles-evidence-v0.1.yaml
version: "0.1"
role: companion
conformance: reference # non-normative (per the normative|reference vocabulary); see conformance_status
conformance_status: draft
conformance_note: >-
DRAFT — published under drafts/ for review, NOT yet normative. Specifies
the cycles-evidence/v0.1 envelope (JCS-canonicalized, Ed25519-signed,
content-addressed audit artifact) that wraps the bodies the runtime
endpoints return. The runtime base (cycles-protocol-v0.yaml) already ships
the consumer-facing surface — the optional `cycles_evidence` ref on
decide/reserve/commit/release/error responses and the getEvidence endpoint
— as additive/optional (MAY). The envelope shape promotes to a numbered
normative spec once a production implementation ships and a cross-system
consumer (APS) integrates end-to-end. Signer-key authority resolution
(did:cycles / JWKS / rotation) is tracked separately in runcycles/cycles-protocol#103.
title: Cycles Evidence Envelope
plane: cross-system-audit
owns:
- CyclesEvidence envelope (schema_version cycles-evidence/v0.1)
- evidence_id content-hash recipe (RFC 8785 JCS + sha256) and Ed25519 signature derivation
- Per-artifact payloads (DecidePayload / ReservePayload / CommitPayload / ReleasePayload / ErrorPayload)
- Response mirrors (non-attestation note for the transport-only cycles_evidence ref)
integration_points:
- runtime_base: >-
cycles-protocol-v0.yaml carries the wire surface: CyclesEvidenceRef
(cycles_evidence on the five response types) and getEvidence
(GET /v1/evidence/{id}). The envelope draft is what those refs resolve to.
depends_on:
- runtime_base # mirrors its request/response schemas
readers:
- Cross-system audit / receipt consumers (notably APS)
- Compliance + long-horizon archival tooling
- Cycles server + event-tier implementers (producer/signer)

# ---------------------------------------------------------------------------
# MERGE RECIPES
# ---------------------------------------------------------------------------
Expand Down
18 changes: 18 additions & 0 deletions drafts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Cycles Protocol — drafts

Pre-normative specs published here for review. **Drafts are not part of the
conformance target** (see [`../CONFORMANCE.md`](../CONFORMANCE.md)) — they
promote to a numbered spec file at the repo root once a production
implementation ships and a cross-system consumer has integrated against them
end-to-end. They are registered in [`../cycles-spec-index.yaml`](../cycles-spec-index.yaml)
as `conformance: reference` (non-normative) with `conformance_status: draft`.

| Draft | What it is |
|---|---|
| [`cycles-evidence-v0.1.yaml`](cycles-evidence-v0.1.yaml) | **CyclesEvidence envelope** — a JCS-canonicalized (RFC 8785), Ed25519-signed, sha256 content-addressed audit artifact that wraps the request/response of each authorization lifecycle event (`decide` / `reserve` / `commit` / `release` / `error`). It lets a cross-system consumer verify *what Cycles decided* offline, without access to the live ledger. The **consumer surface is already in the runtime base** (`cycles-protocol-v0.yaml`): the optional `cycles_evidence` ref (`CyclesEvidenceRef`) on the five response types, and `GET /v1/evidence/{id}` (`getEvidence`). This draft specifies the envelope those refs resolve to: the hash/signature recipe and the per-artifact payload shapes. Signer-key *authority* resolution (did:cycles / JWKS / rotation) is tracked in [#103](https://github.com/runcycles/cycles-protocol/issues/103). Golden fixtures: [`fixtures/cycles-evidence-v0.1/`](fixtures/cycles-evidence-v0.1/). |
| [`cycles-aps-denial-mapping-v0.1.md`](cycles-aps-denial-mapping-v0.1.md) | Mapping of Cycles denial reason codes to the APS (agent-passport-system) integration vocabulary. |

## Producing & verifying evidence (where the code lives)

- **`cycles-server`** computes the `evidence_id` content hash *synchronously* and returns the `cycles_evidence` ref on the response; it serves stored envelopes at `GET /v1/evidence/{id}`. It holds only the **public** signer identity.
- **`cycles-server-events`** asynchronously builds, **Ed25519-signs** (the private key lives only here), and stores each envelope; it recomputes the id and dead-letters on producer/worker drift. See its [identity enablement runbook](https://github.com/runcycles/cycles-server-events/blob/main/docs/evidence-identity-enablement.md).
11 changes: 11 additions & 0 deletions drafts/cycles-evidence-v0.1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,17 @@ components:
- `release` → POST /v1/reservations/{id}/release (clear without debit; 2xx)
- `error` → 4xx/5xx ErrorResponse from any of the above

DOMAIN vs EMISSION POLICY: the `error` artifact's DOMAIN is any 4xx/5xx
`ErrorResponse` (hence the full `ErrorResponseMirror` ErrorCode enum,
including FORBIDDEN/INVALID_REQUEST) — that is what a verifier must be
able to accept. WHICH of those a given server actually emits an envelope
for is that server's policy, not a requirement of this schema. The
reference Cycles server (`cycles-protocol-v0.yaml`) emits `error`
evidence only for budget/lifecycle DENIALS reached after evaluation
(e.g. 409 `BUDGET_EXCEEDED`, 410 `RESERVATION_EXPIRED`) and deliberately
omits `cycles_evidence` for pre-evaluation failures (validation, auth,
malformed body) — nothing was decided, so there is nothing to attest.

The `error` artifact type is normative for v0.1 because non-dry
reserve denials are the highest-signal evidence APS receipts
carry (per aeoess/agent-passport-system#25) and the canonical
Expand Down
Loading