Reference

Contract Scenarios

The contract scenarios are TableTheory’s executable specification. Each scenario is authored language-neutrally and run against the runtimes that declare support for that capability using shared DynamoDB Local infrastructure. A scenario that passes in one supported runtime and fails in another is a parity regression — never a “runtime-specific quirk.”

Scenarios live in contract-tests/scenarios/p0/ with runners under contract-tests/runners/ and shared infrastructure in contract-tests/docker-compose.yml.

The P0 scenarios

The current P0 directory contains these scenarios:

File Behavior pinned
01-crud-basic.yml Create / read / update / delete against a single-table model with composite keys.
02-omitempty.yml How zero values are handled when omitempty is present vs absent.
03-lifecycle-created-updated.yml Persisted createdAt / updatedAt shape and update ordering in the contract fixture.
04-version-optimistic-lock.yml Versioned update succeeds once, then stale-version update fails with a typed condition error.
05-ttl-epoch-seconds.yml TTL role persists a numeric epoch-seconds attribute and reads it back unchanged.
06-release-state-write-policy.yml Release-state write-policy enforcement.
07-release-state-protected-fields.yml Release-state protected-field enforcement.
08-release-state-transactional-transition.yml Release-state transition append performed transactionally.
09-release-state-provenance-confidence.yml Release-state deploy-authority provenance and confidence validation.

CRUD

The bedrock. Create / read / update / delete against a single-table model with composite keys. Verifies that supported runtimes produce compatible DynamoDB items for identical inputs and read them back identically.

See: Features · CRUD & Marshaling

Omit-empty

How zero values ("", 0, False, empty collections) are handled when theorydb:"omitempty" is present vs absent. Every type variant in the matrix is exercised across supported runtimes.

Lifecycle timestamps

The lifecycle fixture pins the persisted createdAt / updatedAt fields and the ordering expectation after an update. Go, TypeScript, and Python all execute this shared P0 fixture and generate lifecycle values on the high-level write paths used by the scenario.

See: Features · Lifecycle Timestamps

Optimistic locking

The version field is populated on read, incremented on versioned write, and conditional-expression-guarded against concurrent writers, with consistent typed error behavior when a version mismatch occurs.

See: Features · Optimistic Locking

TTL

The TTL fixture pins the ttl role as a numeric epoch-seconds attribute. It does not assert read-time masking of still-present expired items. DynamoDB TTL deletion is eventual, and current read paths return any item DynamoDB physically returns.

See: Features · TTL

How P0 grows

P0 scenarios grow only through deliberate extend-contract-scenarios work that runs the supported runtimes against the new scenario before adding it to the P0 set. New shapes incubate in P1/P2 status — important but not yet frozen — until they pass cross-runtime in three consecutive releases.

How a scenario is run

# Bring DynamoDB Local up
cd contract-tests
docker compose up -d

# Run scenarios across all supported runners
make contract-tests          # or: bash contract-tests/run-all.sh

Locally and in CI, the runners share the same DynamoDB Local instance, ensuring that “the Go runtime wrote it” and “another runtime read it” are exercised against literally the same persisted items when the scenario requires that shape.

Why this is the arbiter

When runtimes disagree for a supported scenario, the contract scenario is the deciding evidence. There is no Go reference runtime; there is no TypeScript reference runtime. There is the scenario, and there are peers that pass it (or one of them is broken).

A change that makes one runtime convenient at the cost of breaking a scenario in another runtime is a refusal by default — the scenarios are the load-bearing surface of the framework.