Principles
Principle
Cross-source conform
Silver tables clean within a lane. Enterprise conformity is the full journey: many native shapes conform to one locked canonical model, share one governed vocabulary via SPEC, then Identity decides sameness, Span projects the intersection, and Publish names one consumer result still composed of its Conform sources. CRISP keeps those jobs separate on purpose — this page walks them in order.
1 · Canon shape — per lane, no merge yet
Adaptors map each landed source onto the same typed columns. Teaching example: name is filled now; party_kind exists on the contract but stays unset until Rules. Native kind literals (CORP / COMPANY), ids, and lane-only fields ride in extensions.
Per lane · source → Conform (shape only)
Same canon shape, separate Conform assertions. Native kind tokens ride in extensions for the next pass — A does not absorb B here.
System A
AccountHolder
holder_id
AH-77421
name
NORTHBRIDGE MARINE LTD
holder_type
CORP
sic_code: 65120
Conform · PARTY
System A assertion
name
NORTHBRIDGE MARINE LTD
party_kind
unset
extensions:sys_a
source_id: AH-77421
holder_type: CORP
sic_code: 65120
variance · not typed canon
System B
BillParty
bill_party_id
BP-99102
customer
Northbridge Marine Limited
party_form
COMPANY
lei: 5493001KJT…
Conform · PARTY
System B assertion
name
Northbridge Marine Limited
party_kind
unset
extensions:sys_b
source_id: BP-99102
party_form: COMPANY
lei: 5493001KJT…
variance · not typed canon
A → shape — name → name; holder_id → extensions.source_id; CORP held for Rules
B → shape — customer → name; bill_party_id → extensions.source_id; COMPANY held for Rules
2 · SPEC — variable catalogue across sources
Shape alone is not enough: enums still disagree. Catalogue holds approved core_code values; Map sends each source’s literal into that set.
Cross-source · SPEC map → catalogue
Each lane keeps its own native spelling. A Map scoped by source_system sends that literal into the shared Catalogue. Here both maps produce party_kind = ORGANISATION — one approved programme code, not two competing enums.
A Map — CORP
Catalogue ∩ — ORGANISATION
B Map — COMPANY
Apply that Map and the Conform rows from step 1 now carry the shared programme code:
Per lane · Rules apply SPEC
Re-read the same Conform rows after Map: CORP and COMPANY both stamp party_kind = ORGANISATION.
System A
AccountHolder
holder_id
AH-77421
name
NORTHBRIDGE MARINE LTD
holder_type
CORP
sic_code: 65120
Conform · PARTY
System A assertion
name
NORTHBRIDGE MARINE LTD
party_kind
ORGANISATION
extensions:sys_a
source_id: AH-77421
sic_code: 65120
variance · not typed canon
System B
BillParty
bill_party_id
BP-99102
customer
Northbridge Marine Limited
party_form
COMPANY
lei: 5493001KJT…
Conform · PARTY
System B assertion
name
Northbridge Marine Limited
party_kind
ORGANISATION
extensions:sys_b
source_id: BP-99102
lei: 5493001KJT…
variance · not typed canon
A Map — CORP → ORGANISATION
B Map — COMPANY → ORGANISATION
Two layers of conformity
Cross-source work is not one blob. Shape and codes are both programme meaning — but they are authored and applied differently.
- Canon shape — which entities and typed columns exist (e.g.
PARTY.name,party_kind). A:name → name,holder_id → extensions.source_id. B:customer → name,bill_party_id → extensions.source_id. See Conform and ER modelling. - Variable catalogue (SPEC) — which programme codes are approved, and how each source’s native literals map into them (
CORPandCOMPANY→ORGANISATION). Rules stamps those values onto Conform rows after the write. See Rules.
Spec surfaces in more depth
Spec is how variable meaning becomes shareable across sources without rewriting adaptors for every spelling. Two SPEC row kinds share one vocabulary table:
| SPEC surface | Question | Cross-source role |
|---|---|---|
| Catalogue | Which programme codes are approved? | One closed set of core_code values for a scope (e.g. party kind, country, transaction kind) — not each system’s native spelling. |
| Map | Which catalogue entry does this native literal belong to? | Per-source crosswalk (usually scoped by canonical source_system, optional release): System A’s token and System B’s token → the same core_code. |
Together with canon shape: adaptors put evidence on the right columns; SPEC puts the right codes in those columns. Neither step clusters subjects — that remains Identity. Specialised rule families (sign, lifecycle, eligibility) leave the vocabulary table when the outcome is not a simple core_code.
Scopes can be cross-entity (spec_type — e.g. country) or entity-bound (spec_entity — e.g. PARTY_ROLE_TYPE). Both are rows in the shared map — not one physical SPEC table per domain.
3 · Identity + Span — where A and B intersect
Up to here, A and B are parallel Conform rows on one shape. Identity decides they are the same subject; Span projects one consume facade with a winner and participants — the intersecting picture. Variance (A’s sic_code, B’s lei) stays reachable without joining raw feeds.
For this teaching pair, a single IDENTITY_RULE_CLUSTER row folds legal-form suffixes in the match key (Conform display names stay native) and requires the same party_kind:
# IDENTITY_RULE_CLUSTER · party · name_match_within_kind
rule_id: PARTY_NAME_KIND_V1
subject: party
match_expression: # build key from Conform name
upper(name)
.replace("LIMITED", "LTD")
.replace(/[^A-Z0-9]/g, "")
guard_expression: party_kind = 'ORGANISATION' # same subtype only
min_cluster_size: 2
winner_rank: valid_from ASC # then steward exceptions
# Applied to our Conform rows:
# A name = NORTHBRIDGE MARINE LTD → key NORTHBRIDGEMARINELTD
# B name = Northbridge Marine Limited → key NORTHBRIDGEMARINELTD
# → one hub, two members; A wins on earliest valid_fromThat is one rule type. Identity also uses exception surfaces (equivalence, force-discrete, steward cluster-link) and optional hints — different jobs, fixed rebuild order. More detail: rules, exceptions, and hints · four-step rebuild · Span.
Identity → Span · A ∩ B
Conform kept A and B as separate rows on the same shape. Identity decides they are one party; Span is where the journey shows as an intersection — shared canon in the middle, lane variance still on the lobes via participants / extensions.
Left lobe — A participant
Centre ∩ — Span winner / canon
Right lobe — B participant
4 · Publish — one consumer result, two Conform sources
Publish is what consumers bind to: one consume_party_key and the winner facade (Northbridge Marine Ltd). That single result is still comprised of both Conform assertions — A as WINNER, B as MEMBER — so lineage and lane-only fields remain reachable without joining raw System A / B feeds. Tableau, Power BI, REST APIs, and SQL all hit the same contract — typically via the short synonym SP_CORE.PARTY for SP_CORE_PUBLISH.PARTY as-is. See Publish.
Publish · one result · two Conform sources
Tableau, Power BI, REST, and SQL all read SP_CORE.PARTY — a synonym for SP_CORE_PUBLISH.PARTY as-is. One named subject; under the facade, both lanes remain addressable.
Publish · PARTY
consume_party_key
CPT-NORTHBRIDGE-01
Northbridge Marine Ltd
party_kind = ORGANISATION
Winner facade · what consumers bind to by default
Conform · System A
participant · WINNER
source_id: AH-77421
NORTHBRIDGE MARINE LTD
party_kind: ORGANISATION
sic_code: 65120
extensions:sys_a
Conform · System B
participant · MEMBER
source_id: BP-99102
Northbridge Marine Limited
party_kind: ORGANISATION
lei: 5493001KJT…
extensions:sys_b
One Publish name · two Conform assertions · no raw-lane join for “the customer”
-- Tableau / Power BI / REST bind to the same grain as SQL
-- SP_CORE.PARTY is a synonym for SP_CORE_PUBLISH.PARTY AS_IS
SELECT
consume_party_key,
name,
party_kind
FROM SP_CORE.PARTY
WHERE name = 'Northbridge Marine Ltd';
-- → one row (the winner facade), not two Conform natives
-- Under the facade (lineage / rare lookup — still Publish/Span, not raw A/B):
-- participants include SYS_A (WINNER, AH-77421) and SYS_B (MEMBER, BP-99102)Pipeline overview
Many lanes · one contract
Identity
Cross-source matches
Publish
consume_* keys
Adaptors keep native keys · Identity does not invent cluster ids at load
The split
- Per-lane adaptors map native fields into locked canon columns (
name,party_kind, …) and park native ids / variance underextensions— without forcing premature cluster keys. - Rules / SPEC normalise tokens to programme catalogue codes, scoped by source system — so
CORPandCOMPANYbecomeORGANISATION. - Identity clusters only identity subjects; Span projects the ∩; roles, links, and money stay at Conform relationship / fact grain.
- Publish names one consumer row (winner facade) that remains composed of its Conform participants — never a wipe of the other lane.
lanes = [SYS_A, SYS_B, SYS_C, …]
# 1–2 Canon shape + SPEC (still separate assertions)
for lane in lanes:
conform_load(lane) # C — name/customer → name
# holder_id/bill_party_id → extensions.source_id
# variance → extensions; CORP/COMPANY via Rules
rules_apply(lane_batch) # R — CORP/COMPANY → ORGANISATION (+ families)
# 3 Cross-source sameness + consume projection
rebuild_identity("party") # I — sparse clusters (A ∩ B decided here)
project_span("party") # S — winner facade + participants[]
# 4 Consumer contract — one row, still two Conform sources
read SP_CORE.PARTY # P — synonym for SP_CORE_PUBLISH.PARTY AS_IS
# consume_party_key = winner
# participants[] = {A WINNER, B MEMBER}