# Continuity v0.1 — Replayable Path C Fixtures

Replayable SAR-402 Path C / Continuity Evaluation Receipt fixtures for
`ds.continuity_evaluation.v0.1`.

These fixtures let an external implementer recompute the expected `reason_code`,
the signed-core fields, the canonical payload commitment, and the Ed25519
signature verification **without trusting the hosted service response**.

> **SAR** here means **Settlement Attestation Receipt**. These files are
> **Continuity Evaluation Receipt** fixtures, which are a distinct artifact from
> a SAR.

Stable URLs:

- https://defaultverifier.com/spec/continuity-v0.1/fixtures/01-valid-committed-spec-pass.json
- https://defaultverifier.com/spec/continuity-v0.1/fixtures/02-missing-acceptance-spec-indeterminate.json
- https://defaultverifier.com/spec/continuity-v0.1/fixtures/03-malformed-acceptance-spec-indeterminate.json
- https://defaultverifier.com/spec/continuity-v0.1/fixtures/04-caller-submitted-replacement-spec-rejected.json

## 1. What these fixtures prove

A signed Continuity Evaluation Receipt proves **only** that the named evaluator
signed the **pre-execution evaluation state** for the committed `action_ref`
under the stated `policy_ref`. Concretely, the fixtures let you verify offline
that:

- the receipt's signed core canonicalizes (RFC 8785 / JCS) to a specific byte
  string;
- the Ed25519 signature over that byte string verifies against the published
  evaluator public key;
- the `evaluation_state` and `reason_code` follow from the **committed action**
  (the Action Commitment record), not from a hosted-service assertion.

## 2. What these fixtures do NOT prove

A Continuity Evaluation Receipt does **not** prove, and these fixtures must not
be read to claim:

- actual downstream **release** or **access release**;
- **payment finality** or **resource-release finality**;
- **actual execution** of the action;
- **objective correctness** of the evaluated output;
- **legal sufficiency**;
- **official x402 conformance**.

DefaultVerifier does not execute release, control funds, or settle anything.
It signs a pre-execution evaluation state over a committed action.

## 3. The invariant

```text
Transport / invocation errors          -> 4xx, no receipt.
Evaluator conclusions over committed
actions                                -> stored artifact, signable receipt.
```

| Fixture | Class | HTTP | Step 2A record | Step 2B receipt |
| --- | --- | --- | --- | --- |
| 01 valid committed spec, PASS | committed-action evaluator conclusion | 200 | yes | yes (signed) |
| 02 missing acceptance_spec, INDETERMINATE | committed-action evaluator conclusion | 200 | yes | yes (signed) |
| 03 malformed acceptance_spec, INDETERMINATE | committed-action evaluator conclusion | 200 | yes | yes (expected, see §6) |
| 04 caller-submitted replacement spec | invocation rejection | 422 | **no** | **no** |

Fixture 04 is the proof of the first line of the invariant: a transport /
invocation error returns 4xx and produces **no** receipt. Fixtures 01–03 are the
second line: an evaluator conclusion over a committed action is a stored,
signable artifact.

## 4. How to recompute the signed core

For any fixture that carries a `continuity_evaluation_receipt`:

1. Take the `continuity_evaluation_receipt` object.
2. Remove the top-level `signature` object. The remainder is the **signed
   core**.
3. Canonicalize the signed core with **JCS (RFC 8785)**.
4. Verify the base64 Ed25519 signature (from `signature.signature`) over the
   canonical bytes using the evaluator public key (see §5).

Each fixture also embeds `verification.expected_signed_core_canonical_json` so
you can confirm your canonicalization byte-for-byte before verifying the
signature.

The signed core for these fixtures is exactly:

- `action_ref`, `evaluated_at`, `evaluation_state`, `evaluator_id`,
  `policy_ref`, `schema_id`, and `reason_code` when present.

Note that `signature.public_key` is **inside** the `signature` object and is
therefore **not** part of the signed core.

Quick Python check (fixture 01):

```bash
curl -s https://defaultverifier.com/spec/continuity-v0.1/fixtures/01-valid-committed-spec-pass.json -o fx01.json
```

```python
import json, base64, jcs
from cryptography.hazmat.primitives.serialization import load_der_public_key

fx = json.load(open("fx01.json"))
receipt = fx["continuity_evaluation_receipt"]

core = {k: v for k, v in receipt.items() if k != "signature"}
canon = jcs.canonicalize(core)
assert canon.decode() == fx["verification"]["expected_signed_core_canonical_json"]

# Resolve the public key via the Agent Key Binding Assertion (authoritative).
spki_b64 = fx["verification"]["public_key_resolution"]["agent_key_binding_public_key_spki_b64"]
pub = load_der_public_key(base64.b64decode(spki_b64))

sig = base64.b64decode(receipt["signature"]["signature"])
pub.verify(sig, canon)   # raises on failure
print("OK")
```

## 5. How to resolve the evaluator public key

The identity carried on the receipt is `signature.key_id` /
`evaluator_id = agent:defaultverifier:continuity-v1`.

```text
evaluator_id / signature.key_id = agent:defaultverifier:continuity-v1
      |
      v
/.well-known/defaultsettlement-agent-key-bindings.json   (Agent Key Binding Assertion v2)
      -> binding for agent:defaultverifier:continuity-v1
      -> public_key = base64 SPKI DER
      |
      v
/.well-known/sar-keys.json                                (raw key publication)
      -> kid: defaultverifier-evaluator-ed25519-1
      -> public_key_hex = raw 32-byte Ed25519 public key
```

- The **Agent Key Binding Assertion** is the **authoritative** identity
  attestation. Resolve `agent:defaultverifier:continuity-v1` -> public key
  through it. Its `public_key` is base64 SPKI DER (44 bytes decoded).
- `sar-keys.json` is **raw key publication** for byte-for-byte comparison. Under
  kid `defaultverifier-evaluator-ed25519-1` it publishes the same key as a raw
  32-byte Ed25519 value:
  `ad88901c016e2f196ffc6d150227588288f70fe897f54938ef0eeaa567563ee0`. The last
  32 bytes of the SPKI DER from the binding equal this value.
- **Do not** imply `signature.key_id` directly equals
  `defaultverifier-evaluator-ed25519-1`. `key_id` is the evaluator identity;
  `defaultverifier-evaluator-ed25519-1` is the `kid` of the raw key publication.
  They name the same key through two different surfaces.

## 6. Live grounding vs. conformance fixtures

- **Fixture 01** and **Fixture 02** are grounded in **live issued receipts**.
  Their `continuity_evaluation_receipt` and `committed_action_material` were
  captured from `defaultverifier.com` and verify as-is. Both signatures verify
  over the JCS canonical signed core using the published evaluator public key.
- **Fixture 03** and **Fixture 04** are **conformance fixtures** documenting
  expected behavior at the boundary:
  - **03** documents `INVALID_ACCEPTANCE_SPEC` for a committed-but-malformed
    acceptance_spec. It is an evaluator conclusion, so it sits on the
    stored-artifact / signable-receipt side. Its `continuity_evaluation_receipt`
    is `null`; the fixture carries the **expected signed core** to be signed by
    the deployed evaluator or by the local attest-service test harness using
    **fixture/test keys**. No production private key is used to mint it.
  - **04** documents the invocation rejection (caller-submitted acceptance_spec)
    with HTTP 422 and **no receipt**.

## 7. No production secrets

**No production private keys are included in, or required to verify, any of
these fixtures.** Verification uses only the published evaluator **public** key.
Fixture 03, if/when signed, must be minted by the deployed evaluator or by the
local attest-service test harness using fixture/test keys — never with the
production signing key.
