## Canonical JSON & Hashing

`artifacts.jsonHash` (SHA-256 hex) is computed over a canonical JSON form so logically equivalent Memory Units or Receipts hash identically.

### Memory Unit Algorithm

Deterministic steps producing the pre-image for `artifacts.jsonHash`:

1. Deep clone object (lossless copy of JSON data types only).
2. Set `artifacts.jsonHash` to an empty string `""`.
3. Remove `signatures` array entirely if present (and any legacy singular `signature`).
4. Exclude no other fields: every remaining field participates in the hash.
5. Recursively sort all object keys lexicographically (Unicode code point, ascending). Arrays retain their original order; array element objects are independently key-sorted.
6. Serialize with `JSON.stringify` using no whitespace (canonical UTF-8 bytes of the resulting string).
7. Compute SHA-256 over the UTF-8 bytes, output lowercase hex; assign this hex to `artifacts.jsonHash` in the live (non-canonical) object.

**Excluded / Modified Paths** (JSON Pointers):

| Path                  | Action                                         | Rationale                                    |
| --------------------- | ---------------------------------------------- | -------------------------------------------- |
| `/artifacts/jsonHash` | Forced to empty string during canonicalization | Prevent self-reference recursion             |
| `/signatures`         | Removed entirely before hashing                | Allow signatures to attest to stable content |
| (legacy) `/signature` | Removed if still present                       | Backward compatibility cleanup               |

All other paths MUST be preserved exactly; adding fields changes the hash (intended for integrity).

### Receipt Algorithm

1. Build canonical object with `type`, `created_at`, `content` (exclude generated `id`).
2. Sort, stringify, hash as above.

### Signatures (Optional)

If enabled, an ephemeral ECDSA P-256 keypair signs the same canonical string. The `signature` object is excluded from the hash scope to avoid recursion.

```json
"signature": {
  "algorithm": "ecdsa-p256-sha256",
  "publicKey": "-----BEGIN PUBLIC KEY-----…",
  "value": "Base64Signature==",
  "createdAt": "2025-09-12T12:34:56Z"
}
```

### Full Schema Validation

```bash
npm install
npm run validate:schemas
```

This validates all schema examples with AJV.

### Future

- Ed25519 support.
- Multi-signature arrays.
- Canonical CBOR / DAG-JSON.

### Receipt Canonicalization Summary (Quick Reference)

| Step | Action                                                                              |
| ---- | ----------------------------------------------------------------------------------- |
| 1    | Construct object with `type`, `created_at`, `content` only (exclude generated `id`) |
| 2    | Key-sort recursively                                                                |
| 3    | `JSON.stringify` (no spacing)                                                       |
| 4    | SHA-256 lowercase hex -> `hash_hex`                                                 |

### Implementation Notes

- Field ordering must rely solely on sorted keys, not engine insertion order.
- Avoid locale-sensitive comparisons; raw code point compare is required.
- Any introduction of a new excluded path MUST be documented here to avoid verifier divergence.
