Skip to documentation

Lineage

Data lineage

Lineage is the module slice that answers one question about any document, completely and in a single read: where did this come from, what knowledge did it produce, and what breaks if it changes? The other slices leave a trail — Intake records provenance, Atlas records which concepts a document mentions, Warrant records verification, Lens records which answers cited it — and Lineage stitches that scattered evidence into one DocumentLineage object. No LLM, pure SQL aggregates, deterministic ordering, every read tenant-scoped under row-level security.

Two directions from one document

Lineage reads both ways from a document at once. Upstream: the source it was ingested from and the governance stamped on it. Downstream: the concepts, relations, answers, and cache entries that now depend on it. That second direction is the impact analysis — the blast radius if the document were edited, deprecated, or deleted.

The trail

Read left to right: upstream provenance and governance flow into the document; the document produces derived knowledge; that knowledge — plus the document itself — is what downstream consumers depend on.

Document lineage trail

Origin and Governance are upstream; revision and audit summaries explain how the document changed; chunks, concepts, and relations are derived knowledge; answers, cache entries, and grounded entities are the downstream blast radius.

Rendering diagram

Downloads

Concepts

  • Data lineage
  • Upstream — where it came from
  • Derived — knowledge it produced
  • Downstream — impact if it changes
  • History — how it changed
  • Trail

Keywords

  • concepts via mentions
  • authority · lifecycle
  • relations via evidence
  • answers that cited it
  • dependent cache entries
  • revision summaries
  • total + newest 50
  • document audit events
  • newest 50
  • connector · vault · upload
  • external id · source version · last sync
  • verification tier · review-due
  • path · version · contentHash
  • N live entities grounded on it
  • Origin
  • Governance
  • Document
  • chunks
Source and generation provenance

Status: current

Generated at: 2026-08-12T23:38:03.023Z

Source hash: e8959b4591296a17051669e229bac822dbb6a4ccc59e24067ef937bc53ea6d1f

Metadata payload hash: ccd415e7700d5a1d5d4a9041ee7a683d38ebb86ea86faaeb2dfcc3dba784955a

Canonical appearance

src/app/(docs)/docs/concepts/data-lineage/page.tsx:32 route /docs/concepts/data-lineage

All appearances

  • canonicalsrc/app/(docs)/docs/concepts/data-lineage/page.tsx:32 route /docs/concepts/data-lineage

No mirrored appearances.

Generation versions

App: eli-ai 0.1.0

Mermaid: 11.16.0 · Mermaid CLI: 11.16.0

Node: v26.3.1 · Yarn: 4.17.1

Renderer config hash: 68c10966fe84406ee626034d58bfabd555df9f65f691204b7c46db24038da101

Renderer theme hash: c80287a78d80ad63d27bd5ca348b2ef9a7e2f44da289e436be6484ea28a1b033

Adapter versions: diagramGenerator=2, drawioFlowchart=1, drawioGantt=1, drawioSequence=1, drawioState=1

Full sidecar JSON: document-lineage-trail-e8959b45.json

The seven sections

A DocumentLineagehas seven parts, each sourced from a different slice's append-only record:

  • document — identity and content fingerprint: path, version (bumped on every save), contentHash, and the created/updated actors.
  • governance Warrant's document verification tier (unverified · verified · certified · deprecated), who verified it and when, the next re-verify date, and reviewOverdue — true when a verified doc is past its SLA.
  • origin Intake provenance. kind is connector, vault, or upload; connector docs carry the source type (confluence · sharepoint · slack), external id, source version, last sync time, and up to ten recent sync runs.
  • revisionstotal plus up to 50 immutable summaries newest first. Each item carries version/change kind, sorted changed-field names, whether a recoverable content snapshot exists, activity, actor, note, and timestamp. Large content blobs never enter the lineage payload.
  • audit — the append-only document.* event trail targeting this doc, newest first, capped at 50: create, update, verify, delete — with actor, timestamp, and meta.
  • derived Atlas knowledge the document produced: chunk count, the canonical concepts it contributed mentions to (top by mention count, capped at 50, each with authority and lifecycle), and the count of live relations whose evidence cites it.
  • downstream — impact. Lens answers that cited it (citedByAnswers), the semantic-cache entries that depend on it, and impactedEntities — the live concepts grounded on it that a deprecation would touch.

The DocumentLineage shape

The full response type. Timestamps are ISO-8601 strings; nullable fields are explicitly | null. Arrays are deterministically ordered and capped so the payload is bounded.

DocumentLineagetypescript
type DocumentLineage = {
  document: {
    id: string; path: string; title: string; version: number;
    contentHash: string; createdAt: string; updatedAt: string;
    createdBy: string | null; updatedBy: string | null;
  };
  governance: {
    verification: "unverified" | "verified" | "certified" | "deprecated";
    verifiedBy: string | null; verifiedAt: string | null;
    nextVerifyAt: string | null;
    reviewOverdue: boolean;                       // verified/certified & past due
  };
  origin: {
    kind: "connector" | "vault" | "upload";
    sourceId: string | null;                      // connector_sources row (null = vault)
    sourceType: string | null;                    // confluence | sharepoint | slack | markdown_upload
    externalId: string | null;
    sourceVersion: string | null;
    lastSyncedAt: string | null;
    recentSyncRuns: {                             // up to 10, newest first
      id: string; kind: string;
      startedAt: string; finishedAt: string | null; error: string | null;
    }[];
  };
  revisions: {
    total: number;
    items: {                                      // newest first, cap 50; no content blobs
      id: string; version: number; changeKind: string;
      changedFields: string[]; hasContent: boolean;
      activity: string | null; changedBy: string | null;
      note: string | null; createdAt: string;
    }[];
  };
  audit: {                                        // document.* events, newest first, cap 50
    event: string; actor: string | null; at: string; meta: Record<string, unknown>;
  }[];
  derived: {
    chunkCount: number;
    entities: {                                   // top by mentionCount, cap 50
      id: string; name: string; type: string;
      authority: "machine_extracted" | "asserted" | "curated" | "certified";
      lifecycleStatus: "draft" | "pending_review" | "published" | "deprecated" | "superseded";
      mentionCount: number;
    }[];
    relationCount: number;                        // live relations whose evidence cites this doc
  };
  downstream: {
    citedByAnswers: number;                       // persisted answers whose [Sn] sources include this doc
    cachedAnswers: {                              // dependent cache entries, cap 50
      entryId: string; question: string; invalidated: boolean;
    }[];
    impactedEntities: number;                     // live entities grounded on it — the blast radius
  };
};

Read it over the API

One GET, scoped to the key's workspace. Accepts kb:read (preferred) or the legacy runs:read grant — the same read scopes as the manifest. The document ACL is checked before lineage is assembled, so an inaccessible restricted id is the same 404 as an unknown, cross-tenant, or soft-deleted id.

GET/api/v1/documents/{id}/lineageBearer · kb:read or runs:read

The unified per-document lineage trail: origin provenance, governance, the document audit trail, derived knowledge, and downstream impact. 404 on an unknown or deleted id.

Example requestbash
curl -s https://eli.ai/api/v1/documents/01KY10AAAAAAAAAAAAAAAAAAAA/lineage \
  -H "Authorization: Bearer $ELI_KEY" | jq '{origin: .origin.kind, concepts: (.derived.entities | length), citedBy: .downstream.citedByAnswers}'
Responsejson
{
  "document": {
    "id": "01KY10AAAAAAAAAAAAAAAAAAAA",
    "path": "ops/order-platform-runbook.md",
    "title": "Order Platform incident runbook",
    "version": 4,
    "contentHash": "9f2b1c…",
    "createdAt": "2026-06-02T14:20:00.000Z",
    "updatedAt": "2026-07-18T09:05:00.000Z",
    "createdBy": "usr_01KY0Z9M2E5Q4RS8T0V1WX2Y3Z",
    "updatedBy": "usr_01KY0Z9M2E5Q4RS8T0V1WX2Y3Z"
  },
  "governance": {
    "verification": "certified",
    "verifiedBy": "usr_01KY0Z9M2E5Q4RS8T0V1WX2Y3Z",
    "verifiedAt": "2026-07-01T00:00:00.000Z",
    "nextVerifyAt": "2026-12-28T00:00:00.000Z",
    "reviewOverdue": false
  },
  "origin": {
    "kind": "connector",
    "sourceId": "01KY0V000CONNECTOR00000001",
    "sourceType": "confluence",
    "externalId": "CONF-88213",
    "sourceVersion": "17",
    "lastSyncedAt": "2026-07-18T09:00:00.000Z",
    "recentSyncRuns": [
      { "id": "01KY18…", "kind": "incremental", "startedAt": "2026-07-18T09:00:00.000Z", "finishedAt": "2026-07-18T09:00:12.000Z", "error": null }
    ]
  },
  "revisions": {
    "total": 4,
    "items": [
      {
        "id": "01KY17…", "version": 4, "changeKind": "update",
        "changedFields": ["contentHash", "sourceVersion", "title"],
        "hasContent": true, "activity": "connector",
        "changedBy": null, "note": null,
        "createdAt": "2026-07-18T09:05:00.000Z"
      }
    ]
  },
  "audit": [
    { "event": "document.verify", "actor": "usr_01KY0Z9M…", "at": "2026-07-01T00:00:00.000Z", "meta": { "verification": "certified" } },
    { "event": "document.update", "actor": "usr_01KY0Z9M…", "at": "2026-07-18T09:05:00.000Z", "meta": { "version": 4 } }
  ],
  "derived": {
    "chunkCount": 12,
    "entities": [
      { "id": "01KY0ZW3…", "name": "Order Platform", "type": "system", "authority": "certified", "lifecycleStatus": "published", "mentionCount": 9 },
      { "id": "01KY0ZX8…", "name": "Fulfillment Console", "type": "system", "authority": "curated", "lifecycleStatus": "published", "mentionCount": 3 }
    ],
    "relationCount": 5
  },
  "downstream": {
    "citedByAnswers": 14,
    "cachedAnswers": [
      { "entryId": "01KY19…", "question": "how do we handle stuck orders?", "invalidated": false }
    ],
    "impactedEntities": 7
  }
}

Also over MCP and the BFF

The same trail is an MCP tool — kb_document_lineage { docId } (scope kb:read or runs:read) — so an agent can trace provenance mid-run. The workspace UI reads it from the BFF at GET /api/w/{workspaceId}/documents/{docId}/lineage and renders the trail on the document page. All three surfaces return the identical DocumentLineage.

Why it is trustworthy

  • Tenant isolation is total. Every query runs under FORCE row-level security and also filters workspace_idexplicitly — workspace B can never read workspace A's lineage.
  • It reads the append-only record. The audit trail and entity revisions are never mutated in place. The response exposes a bounded document-revision summary with the uncapped total, so clients can see both recent change shape and whether older history exists without transferring content snapshots.
  • It is deterministic. No model call, stable ordering, bounded caps — the same document yields the same lineage every time, which is what makes it citable in a report or an audit.
  • Downstream is live. citedByAnswers matches persisted answers whose [Sn] sources include this document via a jsonb containment query, and cachedAnswers reflects current cache dependencies — so impact is measured against what is actually deployed, not a snapshot.

Put it to work

Walk lineage inside a real workflow in Sales enablement, end to end — where step four traces a grounded answer back to the exact certified documents behind it. For the whole platform in one view, see the Capability map.