Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Compiled framework profiles

RiffDB does not implement an external framework’s generic CRUD store or transaction callback. An integration repository resolves the framework’s configured models and plugins at generation time, emits an ordinary RiffDB contract with named commands and queries, and dispatches only to that compiled surface. Unknown models, hooks, plugins, and transaction shapes fail during generation instead of degrading into sequential writes at runtime.

The adapter remains application code. No framework dependency, identity protocol, session logic, or privileged storage path enters RiffDB. A framework “transaction” is supported only when one generated command describes its complete atomic graph. Bounded collection commands cover finite repeated graphs; workflow commands cover revision-checked session transitions. An adapter must never run several commands and report that they were one atomic transaction.

The framework-agnostic acceptance contract at fixtures/adapters/framework-profile/riffdb/contract.riff demonstrates the generic capabilities:

  • transactional unique identities and provider/account links;
  • one bounded atomic user/account/session create graph;
  • compiler-owned session initialization plus exact-revision refresh/revoke;
  • secret-classified session and verification-token digests;
  • consume-once verification with transaction-time expiry refusal; and
  • server-observed transaction time and UUID values.

It is a workload shape, not a bundled framework adapter.

Repository ownership boundary

Framework-specific contracts, profiles, generated SDKs, route hosts, and route- level compatibility tests belong to the integration repository that owns the adapter. That repository pins an immutable RiffDB release and records its framework version, enabled plugin/model surface, generated identities, and acceptance observations. RiffDB does not copy those artifacts into its own source tree.

The RiffDB repository retains framework-neutral fixtures for the compiler, providers, authorization, generated transports, and cross-language semantics. For exact result sets, the generic Document corpus proves contains, starts- with, ends-with, typed optional filtering, deterministic orders, bounded direct offset, and complete exact total. An adapter can depend on that public capability, but neither its route vocabulary nor its userland policy becomes a RiffDB feature.

External adapters can pin fixtures/riffql/operational-query-capability-v5.json. V5 preserves the immutable V1 through V4 receipts and extends the neutral operational-access corpus with binary UTF-8 interval/complement alongside shared equality, membership, prefix, canonical range/complement, nullable, cursor, policy, and dependent-key shapes. It binds the exact application lock and generated Rust, Go, TypeScript, Python, and MCP artifacts.

V5 also binds one value-free external tuple-changelog receipt demonstrating that one bytewise text-key index can supply strict lower/upper selection and order, and that its exact package may declare only a generated Go surface. That receipt contains hashes and typed verification classes only; it contains no external schema, route, adapter, generated profile, or stored value. It explicitly does not claim external runtime, full external application, or framework conformance.

The distinct terminal fixtures/riffql/wp775-external-binary-text-interval-execution-v1.json receipt now proves one narrow owning-repository runtime case: two invocations of the same generated strict-lower/strict-upper query returned original logical strings in bytewise ascending order, and the consumer reused a returned string as its own next lower token. The run used one existing index, one partition, two bounded result pages, and no client filter, sort, page walk, duplicate index, or token conversion. This is not evidence that a framework route, the complete adapter surface, or a full external application conforms; those wider claims still require their own owning-repository acceptance.

Better Auth support boundary

The Better Auth integration supports only the exact materialized profile its owning repository generates, configures, and tests. The framework’s generic facade is a profile-bound dispatcher to exact generated commands and named queries; it is not generic RiffDB CRUD or a public transaction surface. The profile fixes its models, fields, plugins, schemas, atomic command shapes, queries, roles, and generated identities before deployment.

Additional fields or plugins require generation and review of a new materialized profile, followed by its generated operations, installation review, and conformance evidence. Unsupported configuration fails while the profile is generated or configured. Unknown runtime calls refuse instead of synthesizing an operation, omitting a field, falling back to a generic store, or splitting one framework transaction across several RiffDB commands. The RiffDB-owned neutral fixture proves underlying symbolic capabilities but does not widen the supported external profile or establish a complete Better Auth upstream-suite claim.

The complete ten-record classification and the separately scoped Better Auth admin and lifecycle evidence are listed in Adapter evidence classes.

Keyless upstream retries

When an upstream framework supplies no idempotency key, the adapter owns the logical request identity:

  1. Mint one bounded RiffDB command idempotency value before the first dispatch.
  2. Freeze the complete generated command input containing that value.
  3. Reuse that exact input for every transport retry and uncertainty-resolution attempt until a terminal declared outcome is known.
  4. Allow the driver to mint a fresh transport request ID for each attempt; the transport ID is not the command’s idempotency identity.

If retry must survive adapter process loss, retain the mapping from a stable upstream operation identity to the minted command identity before dispatch. If the framework provides no stable operation identity and the adapter did not retain one, it cannot honestly claim process-loss idempotency and must surface that limitation. Never mint a new key after an uncertain result, and never derive the key from a plaintext token or other secret.

The Rust driver test adapter_minted_idempotency_survives_driver_retries_with_fresh_transport_ids proves that bounded retries preserve the byte-identical command input while using fresh transport request IDs. On the admission side, equal_key_commands_commit_once_and_replay_exactly proves the property the minted identity rides: equal-identity submissions commit exactly once, the replay returns the byte-equal stored outcome under one commit sequence and one provenance record, and different input under the same identity is refused as an input mismatch.

Acceptance evidence

Run the focused profile gate:

./scripts/adapter-framework-profile-acceptance

It compiles and round-trips the profile, exercises the atomic graph and token/ workflow refusal paths, runs the real-redb concurrent uniqueness schedule, and checks retry identity preservation. The full deployable-alpha gate invokes the same focused phase.