Back to demos

Ledger — a governed write path for Salesforce

SalesforceHubSpotSnowflakeClaudeData Governance

Four systems want to write to the same CRM record. Instead of letting them, every source submits a proposal and a gateway decides: identity resolution with Claude breaking ties, a per-field authority matrix with freshness decay, echo suppression for sync loops, and an append-only audit ledger. Watch a captured run of the real system, then break the rules yourself in the playground.

The walkthrough is a captured run of the real system— a live Salesforce org, live Snowflake, a live Claude call — replayed here, not re-run, because the gateway writes to a real CRM. The rationale you'll see in beat 2 was written by Claude during that run. The playground, though, runs entirely in your browser: same decision engine, ported line for line.

The write path

Nothing writes to Salesforce directly. Every system submits a ProposedChange — a request, never an instruction — and the gateway runs it through five stages in a fixed order. The write lands as an upsert on a unique, case-insensitive external ID, so a duplicate account isn't policed after the fact; it's impossible.

[hubspot]form fills, lists[product]Snowflake usage[clay]enrichment, no key[human]a person typingProposedChangea request, never an instructionTHE GATEWAY1resolve identitydeterministic → fuzzy → Claude2suppress echoesour own write, bouncing back3authority matrixper field: allowed · fresh · ranked4one governed writeupsert on the unique external ID5append to the ledgerrulings, refusals, receiptsONE AccountCanonical_Domain__cunique · case-insensitiveduplicates impossibleaudit ledgerappend-only · no UPDATErefusals recorded too

Identity — which company is this even about?

Three tiers, each weaker and louder than the last. The interesting one is the narrow band in the middle: when name similarity is genuinely ambiguous, Claude referees — it can only choose from candidates the resolver found, its rationale is written into the audit trail, and any failure means "no match," because a missed match is a duplicate a human merges in ten seconds while a wrong merge fuses two customers' histories.

entity hints — domain · website · email · company name · (sometimes nothing at all)TIER 1 · DETERMINISTICcanonicalized domain hits an existing recordURLs, emails, www., ports, unicode → one registrable domain · public webmail refusedconfidence 1.0TIER 2 · FUZZYno domain — probe plausible domains built from the name, verify every hit by name similarity“Acme Robotics Automation” probes acme-robotics.io — a wrong guess cannot silently bind two companies≥ 0.90 · capped 0.95TIER 3 · ADJUDICATEDsimilarity lands in the ambiguous band — Claude breaks the tie, as a refereecan only choose from found candidates · rationale written into the ledger · fails closedband 0.60 – 0.90NEWnothing matched — create the accountkeyless proposals park on <slug>.unresolved.invalid — deterministic, obviously flaggedcreates it

One authority ruling, end to end

This is the exact ruling from beat 3 of the walkthrough. Four claims arrive for one field; the allow-list strikes product before it can compete, freshness decay and the confidence floor discount the old, authority rank decides among survivors, and the incumbent competes like everyone else — with exact ties going to it. Try bending this policy yourself in the Playground.

NumberOfEmployeesauthority: clay > hubspot > human · never: product · half-life 21d · floor 0.35clay · 180conf 0.92 · 2d oldhubspot · 40conf 0.70 · freshproduct · 4seats, not peoplehuman · 40the incumbent, via Provenance__callow-listnever · absentfreshnessconf × 0.5^(age/t½)rankrank 0 beats rank 1product may never write NumberOfEmployeesthe incumbent competes as a claim — no veto, no automatic overwrite; exact ties go to itWRITE · 180[clay] eff 0.86 · rank 0“clay wins at rank 0, confidence0.92 decayed to 0.86 over 2d…”every ruling ships its sentencelosers are recordedoutranked · barred · decayed —each with the reason it lost,permanently in the ledger

Echo — breaking the sync loop

The gateway's own write syncs out and comes straight back as the freshest "observation" in the system — the write that starts an infinite loop. Three checks catch it, and the third is the one an idempotency guard can't do: values that came back reformatted still normalize to the claim we ourselves wrote seconds ago. In production traffic this fired unprompted, catching HubSpot's duplicate event for a single form submission.

gatewaystamps Ledger_Write_Id__cgoverned writeSalesforcethe record everyone syncsnative syncHubSpotrecords a “change”webhook: our own data, back as a “new” observation — the freshest claim in the systemTHREE CHECKS, STRONGEST FIRST1 · stamp — it carries an id only we mint, even nested or re-cased2 · value — same account, 15-min window, every field matches (87 ≈ “87”)3 · round-trip — values came back reformatted, so exact matching fails —but they’re the fields we sourced from that system seconds ago: the same claimA genuinely changed value is a genuine observation and is written. A proposal from a human is never suppressed, under any check.