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.

What did you build?

A governed write path for Salesforce. Marketing automation, product telemetry, an enrichment vendor, and humans all want to create and update the same Account — so none of them get to. Each submits a proposal; a gateway resolves which company the proposal is even about, decides per field who is allowed to win, suppresses its own writes bouncing back through sync loops, writes once with field-level provenance, and appends every ruling — including the refusals — to an audit ledger that cannot be rewritten.

It is a working system, not a mock: it queries live Snowflake, PATCHes a live Salesforce org, calls Claude to break identity ties, and a real HubSpot webhook has been proven end to end — form submit, signature verified, record hydrated, identity resolved, Account created.

What problem does it solve?

Every GTM stack has this disease. HubSpot, Salesforce, the warehouse, and an enrichment tool each believe they know the truth about a company, and each writes it directly. The result is three “Acme Robotics” records, a headcount that flips between 40 and 180 depending on who ran last, a lead score squatting in the field meant for a product-qualification score, and a sync loop rewriting the same row every four minutes forever.

None of that is a data-quality problem to be cleaned up afterward. It is a write-path problem: there is no single place where “who is allowed to say what about this account” is decided. Ledger is that place.

What's the value?

Reps trust the record because every field says who set it, when, and at what confidence — and “why does this field say that?” has an answer months later, under pressure. RevOps owns the policy as one page of YAML, not code spread across four integrations. Duplicates stop being a cleanup queue because the identity key is a unique, case-insensitive external ID — Salesforce itself makes the second record impossible, not unlikely. And automation becomes safe to scale: an agent that proposes instead of writes can be wrong without being destructive.

Who is it for?

The revenue-operations and data teams of any product-led company whose self-serve motion generates thousands of low-touch signups while sales works six-figure contracts — two motions, one CRM, and half a dozen systems that can each mint “a company.” The demo is fictional; the recon that shaped it was not: the target company's own site runs a marketing stack where at least six systems can independently create or mutate account records.

How was it built?

Python: FastAPI at the door, Pydantic v2 contracts with extra="forbid" everywhere, SQLite in WAL mode with no UPDATE and no DELETE as the ledger, the sf CLI as the Salesforce transport, key-pair auth into Snowflake, and Claude — with structured output, so the adjudicator can only choose from candidates the resolver actually found. Policy lives in authority.yaml: thirteen governed fields, each with an ordered authority list, a hard exclusion list, a freshness half-life, and a confidence floor.

The build itself was multi-agent: eleven agents built modules against a shared contract in parallel, then seven more attacked the result adversarially and fixed what they found — about eighteen reproduced defects, every one now a regression test.

AI literacy — where does the model belong?

The LLM is used exactly once in the write path, as a referee with three properties: it can only choose (a verdict naming a domain outside the candidate set is discarded), it must show its work (every verdict carries a one-sentence rationale that lands in the ledger, in language a human can dispute), and it fails closed (a timeout or a malformed reply means “no match” — a missed match is a duplicate a human merges in ten seconds, a wrong merge fuses two customers' histories). Record contents are rendered as data inside delimiters, never as instructions; a per-process budget caps spend before the request is made.

Just as deliberately: everything else is not a model. Authority is a sorted list, decay is arithmetic, echo detection is value matching. Where a rule can decide, a rule decides — the model gets the narrow band in the middle where rules run out.

Path to production

The honest gaps are known and written down. The per-entity lock is in-process — two gateway workers need a shared lock or an Apex compare-and-set. The public-suffix list is hand-rolled and should be the real PSL. A field where every claim is refused leaves no ledger row, and deserves a REFUSAL event kind that doesn't need a winner. Beyond those: a steward approval loop in Slack for low-confidence merges, bidirectional governance (the HubSpot write-back, making echo suppression a genuine two-system loop), and the same proposal contract offered to every agent that wants to touch the CRM.

The defect story — a governed system that lied in its audit trail

The adversarial review round is more convincing than a clean build, so it gets told rather than hidden. Among the eighteen: two concurrent proposals could bypass the authority matrix entirely — each read an empty record, each decided against no incumbent, and the ledger showed two uncontested wins with last-writer-wins underneath, the exact behaviour the system exists to make impossible. The audit trail printed WROTE for values Salesforce had rejected — a governance system asserting writes its target refused. Two unrelated companies silently merged under myshopify.com, because tenant platforms make “same domain” a lie. An unauthenticated endpoint let any caller elect itself the highest-ranked source — reproduced live by writing “PWNED” into the org through the front door.

And the worst one for a demo: the on-screen “live Claude call” was a cache read. The adjudicator memoizes verdicts, the reset step wiped Salesforce and the ledger but not the cache, so a rehearsed demo was filming a JSON file while saying the words “one Claude call.” The fix is why beat 0 of the walkthrough deletes the verdict cache on camera — every run pays for its answer, and the rationale is worded differently every take. That variance is the receipt. A rehearsed demo prints the same words twice.

One thing was never scripted at all: when the real HubSpot form was submitted, HubSpot fired two webhooks for the one submission — contact.creation and company.creation. The gateway wrote the first and suppressed the second as an echo of its own write, one second later, on traffic nobody designed. The mechanism a reviewer had called the most staged-looking beat caught a real duplicate the platform itself generated.

The captured run on the Walkthrough tab is this system doing all of the above against live services. The Playground is its decision engine, ported to TypeScript, verified against the Python engine's own fixtures — in your browser.