Skip to content

Data model

Lantern is a thin client over two upstream data models. It does not invent its own — that is by design, so the same artifacts travel from Beacon (producer) through Lantern (reader) without translation losses.

1. Beacon evidence bundle

A bundle is a sequence of receipts in one of three on-disk forms:

Extension Format When to use
.ndjson One JSON object per line The canonical wire form. Append-only friendly.
.jsonl Alias for .ndjson Same shape; tooling parity.
.json A JSON array of receipts Convenient for hand-editing tiny bundles in fixtures.

A receipt is a JSON object that conforms to the upstream OVERT 1.0 receipt schema. See actions.md for the required-field list and the event_type vocabulary.

Lantern's view of a receipt

In Lantern's Python API, a receipt is a Receipt dataclass with one property: raw: dict. Lantern intentionally does not unpack every field into typed attributes — receipts evolve faster than dataclasses, and Lantern's job is to render whatever Beacon emits, not to gatekeep.

Lantern's view of a bundle

from aigovops_lantern.bundle import load

bundle = load("path/to/bundle.ndjson")
len(bundle)                  # receipt count
bundle.event_types           # dict[str, int]
bundle.evidence_type_counts  # dict[str, int]
bundle.signed_count          # int
bundle.id_set                # frozenset[str]

2. Unified Control ID (UCID) registry

A UCID is a stable identifier for a control concept (e.g. dataset-bias examination, human oversight). UCIDs live in umbrella-govops/crosswalks/unified-control-id.yaml.

Schema

ucids:
  - id: UCID-DATA-BIAS-001
    title: Dataset bias examination
    status: provisional       # provisional | stable | deprecated
    implementing_controls:
      - DG-002
    nist_ai_rmf:
      - MEASURE-2.11
      - MAP-2.3
    iso_42001:
      - A.7.4
    eu_ai_act_articles:
      - 10(2)(f)
      - 10(3)
    eu_ai_act_annex_iv:
      - 2(d)
      - 2(g)

Lantern's view

from aigovops_lantern.ucid import load_registry, lookup

registry = load_registry("path/to/unified-control-id.yaml")
u = lookup("UCID-DATA-BIAS-001", registry)
u.id, u.title, u.status, u.nist_ai_rmf

If --registry is omitted, Lantern falls back to an embedded subset (EMBEDDED_FALLBACK) so basic explain queries work offline. Production deployments should always pass the upstream registry path to stay current.

3. Output schemas (the public contract)

Every --format json shape Lantern emits has a published JSON Schema under /schemas:

Command Schema file Top-level shape
lantern read schemas/lantern-read.schema.json {source, receipt_count, receipt_ids, event_types, evidence_types, signed_count}
lantern diff schemas/lantern-diff.schema.json {old, new, added_ids, removed_ids, kept_count, event_deltas}
lantern explain schemas/lantern-explain.schema.json {id, title, status, implementing_controls, nist_ai_rmf, …}

A schema-conformance test (tests/test_schemas.py) runs in CI to keep the schemas honest — if a renderer's output drifts from its schema, CI fails before the change merges.

4. The boundary Lantern enforces

Lantern is a read boundary, not a verify boundary. It will tell you a bundle carries a signature envelope, but it will never tell you the signature is valid. For verified chain-of-custody, run beacon verify first and pass the verified bundle to Lantern.