Neotoma

Relationships

Relationships are first-class typed edges between entities, not hard-coded foreign keys. They are stored as observations and snapshots, so multiple sources can contribute to the same edge, every edge carries full provenance, and the graph stays open-ontology and queryable.

Sits next to entities. Sources produce relationship observations the same way they produce entity observations; the relationship reducer composes them into a relationship snapshot.

Schema#

Relationship pattern

SQL / TS
Schema or pattern reference for this primitive.
Source → Relationship Observations → Relationship Reducer → Relationship Snapshot // Multiple sources can write the same relationship. // Each write is an immutable observation with its own provenance. // The snapshot merges them with deterministic rules. Source A (Invoice PDF): SETTLES → metadata: { amount: 1500, currency: "USD" } Source B (Bank Record): SETTLES → metadata: { amount: 1500, payment_method: "wire" } Snapshot (merged): metadata: { amount: 1500, currency: "USD", payment_method: "wire" } provenance: { amount: "obs_A", currency: "obs_A", payment_method: "obs_B" }

Core relationship types#

PART_OF (hierarchical containment, e.g. invoice_line_item PART_OF invoice). CORRECTS (corrections supersede originals). REFERS_TO (mentions / references). SETTLES (payment settles invoice). DUPLICATE_OF (entity dedupe). DEPENDS_ON (task ordering). SUPERSEDES (versioning). EMBEDS (container embeds reusable asset, e.g. blog post EMBEDS image).

Open ontology, not hard-coded hierarchies#

Neotoma does not hard-code parent-child columns or a fixed schema of edge types. Hierarchies emerge from edges, which means out-of-order ingestion, multiple parents, overlapping summaries, and corrections all compose without schema changes. New edge types can be introduced without migrating data.

Observation-snapshot pattern#

Each write to a relationship is an immutable observation that carries metadata and provenance. The reducer merges all observations for the same (source_entity, target_entity, type) into a single snapshot. The provenance map records, per metadata field, which observation produced which value, exactly the same shape as entity snapshots.

Queryable in both directions#

Relationships are first-class rows that can be queried by source entity, target entity, type, or metadata. Read paths support traversals (find all PART_OF children of an invoice) and reverse lookups (find every entity that REFERS_TO this contract). Same RLS rules apply, only relationships whose source/target you own are visible.

Invariants#

Every relationship satisfies the following constraints:

MUST

  • Be stored as immutable observations + a deterministically computed snapshot
  • Carry full provenance, every metadata field traces to the observation that set it
  • Be typed (PART_OF / CORRECTS / REFERS_TO / SETTLES / DUPLICATE_OF / DEPENDS_ON / SUPERSEDES / EMBEDS, …)
  • Respect source-ownership RLS on every read path

MUST NOT

  • Be modeled as foreign keys on entity tables
  • Be mutated in place, corrections and supersessions create new observations
  • Be created without explicit source_entity_id, target_entity_id, and type
  • Bypass the relationship reducer for ad-hoc snapshot writes

Where to go next#

  • All primitive record types , index of sources, interpretations, observations, relationships, and timeline events
  • Architecture , how the primitives compose into Neotoma's deterministic state
  • Terminology , canonical glossary of terms used across Neotoma docs