---
title: "Ledger Record Format"
description: "Fields, identifiers, seals, and validation rules for ledger format version 0."
canonical: https://y2.dev/docs/ontology/reference/ledger-format/
---

Ontology & Fusion

# Ledger Record Format

Fields, identifiers, seals, and validation rules for ledger format version 0.

A ledger contains one canonical JSON record per line. Keys are sorted by UTF-16 code unit. Numbers are integers, and insignificant whitespace is omitted. Every field is present. Unknown times and numbers use `null`. Empty string fields use `""`. The portable implementation is `@y2/ontology`.

## Common fields

| Field         | Type                                                | Meaning                                         |
| ------------- | --------------------------------------------------- | ----------------------------------------------- |
| `v`           | `0`                                                 | Format version                                  |
| `seq`         | integer                                             | Position in the log, starting at 1, contiguous  |
| `id`          | string                                              | Record ID, with a prefix for its kind           |
| `kind`        | `subject`, `designator`, `observation`, `assertion` | Record kind                                     |
| `recorded_at` | time                                                | Record time, strictly increasing along the log  |
| `prev`        | hex or `null`                                       | Previous line hash, or `null` on the first line |
| `hash`        | hex                                                 | SHA-256 of the canonical line without `hash`    |

Times are ISO 8601 in UTC with milliseconds, exactly as `Date.prototype.toISOString` prints them.

## Records

### Subject

| Field   | Meaning                                                               |
| ------- | --------------------------------------------------------------------- |
| `class` | `person`, `organization`, or `system`. A subject never changes class. |

A subject has no name. Names and identifiers arrive as designators and claims.

### Designator

| Field             | Meaning                                                                              |
| ----------------- | ------------------------------------------------------------------------------------ |
| `designator_kind` | See [Vocabulary](https://y2.dev/docs/ontology/reference/vocabulary#designator-kinds) |
| `value`           | The canonical string                                                                 |
| `namespace`       | Platform, algorithm, registry, or exchange MIC. Empty for kinds without one.         |
| `normalized`      | Case-folded for names and handles. Otherwise equal to `value`.                       |

A ledger permits one designator per `(kind, namespace, normalized)`. A second record with that key is rejected. The existing ID must be reused.

### Observation

| Field          | Meaning                                                                  |
| -------------- | ------------------------------------------------------------------------ |
| `method`       | One passive method, or `analyst-note`                                    |
| `source_grade` | `primary`, `secondary`, or `analytic` (only for a note)                  |
| `source_url`   | Page URL. Required for a retrieval, optional for a note.                 |
| `archive_url`  | A preserved copy, or `null`                                              |
| `retrieved_at` | Retrieval time, or `null` on a note                                      |
| `content_hash` | SHA-256 of `excerpt`, or of an archived blob when `archive_url` is set   |
| `excerpt`      | A quote of 1–500 characters, or `null` when an archive holds the content |
| `collector`    | Recording label, 1–80 characters                                         |
| `cites`        | Observations cited by a note. Empty on a retrieval.                      |

### Assertion

| Field                     | Meaning                                                                                                                  |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `op`                      | `assert` or `retract`                                                                                                    |
| `predicate`, `from`, `to` | The claim. See [predicates](https://y2.dev/docs/ontology/reference/vocabulary#predicates)                                |
| `qualifier`               | Public role on `member-of`. Otherwise `""`.                                                                              |
| `supersedes`              | The current head of the claim key, or `null` on the key's first line                                                     |
| `confidence`              | Integer 0–100, or `null` on a retraction                                                                                 |
| `verification`            | A [verification state](https://y2.dev/docs/ontology/reference/vocabulary#verification-ladder), or `null` on a retraction |
| `valid_from`, `valid_to`  | Valid-time interval with an exclusive end. `null` means unknown.                                                         |
| `evidence_refs`           | 1–20 earlier observations                                                                                                |
| `note`                    | Up to 1,000 characters of caveat                                                                                         |

The claim key is `predicate|from|to|qualifier`. Each key has exactly one chain of lines.

## Identifiers

Record IDs contain a kind prefix and 24 hexadecimal digest characters. The SHA-256 input combines the record type and workspace ledger position.

| Kind        | Prefix | Example                        |
| ----------- | ------ | ------------------------------ |
| Subject     | `sbj_` | `sbj_0123456789abcdef01234567` |
| Designator  | `dsg_` | `dsg_0123456789abcdef01234567` |
| Observation | `obv_` | `obv_0123456789abcdef01234567` |
| Assertion   | `clm_` | `clm_0123456789abcdef01234567` |

The offline format accepts any lowercase ID with the right prefix, such as `sbj_ada` in the fictional fixtures.

## Rules

Each rule has a code. The API returns codes in `detail`. The offline checker prints them per line.

| Code                                                                  | Rule                                                                                                   |
| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `shape.*`                                                             | Exact field set and field types for the kind                                                           |
| `format.json`, `format.canonical`                                     | The line is JSON in canonical form                                                                     |
| `chain.seq`, `chain.prev`, `chain.hash`                               | Contiguous `seq`, `prev` links the previous hash, `hash` matches                                       |
| `chain.time`, `time.format`                                           | Record time strictly increases. Times use the required format.                                         |
| `id.format`, `id.duplicate`                                           | Prefix matches the kind. IDs are unique.                                                               |
| `designator.*`                                                        | Canonical value, correct normalization, and one record per designator key                              |
| `observation.method`, `observation.grade`                             | Supported passive method. Only a note is `analytic`.                                                   |
| `observation.url`, `observation.time`                                 | HTTP(S) URL without userinfo. Retrieval time must not exceed record time.                              |
| `observation.note`, `observation.cites`                               | Notes cite earlier observations and have no retrieval time. Retrievals cite nothing.                   |
| `observation.excerpt`, `observation.hash`, `observation.preservation` | Excerpt of 1–500 characters or an archive. The hash matches the excerpt unless archived.               |
| `assertion.endpoint`                                                  | Distinct endpoints of permitted kinds. `same-as` and `distinct-from` require matching subject classes. |
| `assertion.qualifier`                                                 | Only `member-of` carries a lowercase role                                                              |
| `assertion.chain`                                                     | First claim supersedes nothing. Later claims supersede the head. Consecutive retractions are rejected. |
| `assertion.evidence`                                                  | 1–20 distinct earlier observations                                                                     |
| `assertion.confidence`, `assertion.interval`                          | Integer confidence of 0–100. `valid_from` precedes `valid_to`.                                         |
| `assertion.verification`                                              | The state is one the evidence supports (see the ladder)                                                |
| `assertion.retract`                                                   | A retraction clears confidence, verification, and the interval                                         |
| `assertion.label`                                                     | `preferred-label` needs a live `designated-by` for the same pair                                       |

## Examples

The repository supplies two valid fixtures in `packages/ontology/v0/examples`:

- `fictional.ndjson` demonstrates corrections, retractions, and disputed identity.
- `fictional-cyber-market.ndjson` demonstrates company identifiers and supplier relationships.

The [local tutorial](https://y2.dev/docs/ontology/tutorial) checks the company fixture and shows its expected output.
