Read first

Start Here

A reference data model for contract, agreement, obligation, supplier, and spend data — designed for SLA-backed document-AI platforms operating at enterprise scale. The principles, the diagram, and how to use the rest of this guide.

Scope

The model covers:

  • Suppliers and supplier hierarchies (parent companies, subsidiaries).
  • Documents (physical files: contracts, amendments, invoices, POs).
  • Agreements (logical contracts — one agreement = many documents).
  • Obligations (extracted commitments per agreement, versioned by extraction).
  • Spend (invoice/PO actuals, linked to agreements where possible).
  • Extraction provenance and quality artifacts.

It does not cover the CLM workflow layer (approval routing, e-signature, drafting). That's a separate product surface; the model here treats the signed document as the input.

Design principles

1. Separate physical from logical

A document is the file; an agreement is the commitment. A signed MSA, two amendments, and three SOWs are four documents and one agreement. Most analytical queries operate on agreements; most debugging operates on documents. The schema must support both natively.

2. Versioned extractions, never overwrite

When a new model version re-extracts a document, the old extraction stays for audit. Extractions are keyed by (document_id, model_version). Marts present the "current" view via a row-effective-from / row-effective-to pattern.

3. Canonicalize, but preserve the raw

Supplier names get resolved to canonical IDs. Raw extracted names are stored alongside, with the resolution method and confidence. If the resolution turns out to be wrong, you can re-resolve without re-extracting.

4. Stable IDs from content

document_id = hash of file contents + customer_id. Deterministic; re-ingest is idempotent. extraction_id = document_id + model_version. agreement_id is platform-assigned (because agreement-document linkage isn't always derivable from content).

5. Provenance on every extracted value

Every extracted field carries the page and bounding box it came from. Auditability and debugging both depend on this. Without it, the platform can't answer "why does the model say the renewal term is 12 months?"

6. Temporal awareness, not temporal everywhere

Agreement status changes over time; supplier hierarchies change; obligation status changes. The model uses SCD-2-style versioning on agreements and obligations, but not on every entity (that would be operational overhead with no analytical payoff).

The model in one diagram

entity-relationship sketch
customers (tenant boundary; all other tables FK to customer_id)
    │
    ├── suppliers ───────┐         supplier_id, canonical_name, parent_supplier_id
    │                    │
    │                    ▼
    ├── agreements ──────┘         agreement_id, supplier_id, parent_agreement_id,
    │       │                      effective_date, current_term_end, status
    │       │
    │       ├── document_agreement_links (M:N)
    │       │
    │       ├── obligations         obligation_id, agreement_id, obligation_type,
    │       │                       value, due_at, status, confidence
    │       │
    │       └── spend ──┐           spend_id, supplier_id, agreement_id (nullable),
    │                   │           amount, currency, accrued_at
    │                   │
    ├── documents       │           document_id, source_uri, file_hash,
    │       │           │           doc_class, ingested_at, page_count
    │       │
    │       └── extractions         extraction_id (=document_id+model_version),
    │                               fields (JSONB), confidence per field,
    │                               provenance per field
    │
    └── supplier_name_resolutions   raw_name, resolved_supplier_id,
                                    resolution_method, confidence

How to use this reference

  • Reading from scratch? 01 → 09 in order. Each chapter builds on the prior. ~2 hours of focused reading.
  • Looking up a query? Jump to 07-sql-pattern-library. The patterns are named ("renewals due in 90 days," "off-contract spend with supplier rollup," etc.) and cross-referenced into the modeling chapters where the underlying decisions are explained.
  • Adapting to your platform's variant? 01 has the rationale per design decision. Most variants substitute one piece (e.g., a different obligation type taxonomy, customer-specific extension tables); the rest of the model stays.
  • Evolving the schema in production? 08-schema-evolution has the backward-compatible migration recipes.
  • Adding dbt tests? 09-quality-tests-dbt.