The Dual-Layer Contract

This page documents the contract between the Commit engine (exposed in Python through dsviper) and your application code. Read it before relying on commit behavior to validate your data: the engine produces structurally sound but untrusted output, and your application is what turns it into trusted state.

The Contract

Layer

Guarantees

Commit

Deterministic merge, DAG consistency, immutability

Application

Re-validates engine output before acting on it

When concurrent streams converge, mutations are applied using a best-effort algorithm:

  • Mutations targeting non-existent documents or unresolved paths are silently ignored.

  • Business rule violations are not detected by the engine.

  • LWW arbitration may keep a value that no single submitted intent would have produced.

This is by design. The engine is intentionally agnostic to your domain rules and never refuses a merge — it picks a deterministic outcome and moves on.

Why the Engine’s Output Is Untrusted Data

This is the load-bearing point of the contract.

“Untrusted” usually means data that crossed a boundary you don’t control — network input, a deserialized file, an external API. The natural reflex is to validate at that boundary and then trust the data internally.

Best-effort merge breaks that reflex. The state returned by state(commitId) is itself a boundary, even though the data never left the process:

  • Mutations you submitted may have been silently dropped.

  • Two disjoint updates, each individually consistent, may have produced a combined state that violates a cross-field invariant.

  • LWW may have preserved a value that no submitted commit would have written on its own.

Structurally the data is sound — types check, paths resolve, the DAG is consistent. Semantically, you have no guarantee that the result reflects any single coherent intent. That makes engine output equivalent to untrusted data from the application’s perspective.

Three Error Families

Because of this, validation in a dsviper-based system happens at three distinct places, not one:

Family

Origin

Detected by

Untrusted (external)

I/O, deserialization, type mismatch, malformed path

Engine, fail-fast → dsviper.Error

Untrusted (post-merge)

State returned by the engine after convergence

Application, at read time

Invalid (semantic)

Business-rule violation on otherwise sound data

Application, at read time

The first family is what dsviper.Error covers. The other two are entirely your responsibility — and they share a remediation: re-validate when you read the state, not when you build the mutations.

What Commit Provides

Guarantee

Description

DAG Consistency

Commits form a valid directed acyclic graph

Immutability

Once committed, data cannot be modified

Deterministic Merge

Same inputs always produce the same output

Content-Addressable

CommitId = SHA-1(content), tamper-evident

What Commit Does NOT Provide

Not Provided

Description

Intent Preservation

Deterministic arbitration (LWW), not your intent

Semantic Validation

No business rule checking

Mutation Notification

No alert when mutations are silently ignored

Conflict Detection

No notion of conflict — just deterministic merge

Implications for dsviper Code

The contract shapes how you should write code on top of dsviper.Commit*:

  • Treat the post-merge state as a boundary. It is the symmetric equivalent of deserialized network input: structurally sound, semantically unverified.

  • Do not assume that every operation you build into a CommitMutableState will land. After merging concurrent commits, some operations may have been silently dropped because their targets disappeared.

  • Validate at the application boundary, which means the engine output. If your domain has invariants (uniqueness, referential integrity, cross-field consistency), enforce them when consuming the state.

Summary

“I guarantee structural integrity. I hand you back data that is structurally sound but semantically untrusted. You re-validate it on read. Together, we guarantee data integrity. Separately, neither of us can.”

— The Dual-Layer Contract

See Also

  • Commit — using the commit API from Python

  • Errorsdsviper.Error and exception handling