DURABLE STATE

Remember what a caller observed. Fail closed when it changes.

Use Chumbo's bounded credential-partitioned state for read-before-write receipts while application RLS and resource versions remain authoritative.

Build this with Chumbo
ChumboSupabaseDurable state
OBSERVE. CHECK. CHANGE. ADVANCE.
  1. 01Read authorized resource
  2. 02Store version receipt
  3. 03Compare during write
  4. 04Advance after success
The receipt coordinates requests. Your application still authorizes the mutation.

THE RECIPE Use Chumbo's bounded credential-partitioned state for read-before-write receipts while application RLS and resource versions remain authoritative.

View source pattern ↗
SOURCE REVIEW

Reviewed against the shipped OSS source. The acceptance checks are yours to run in your application.

Version and verification details

Source reviewed against published Chumbo 0.11.0 and its matching core source on 2026-09-06 (UTC). This is a source review, not an executed application walkthrough. Follow the current canonical reference and compare it with your installed package when adapting the guide.

01

Use state only when a later request needs an earlier fact.

Before you start
  • Write the rule the state enforces, such as: this credential may edit a document only after reading its current version.
  • Identify the application's atomic resource-version check. State revision alone cannot protect the document row.
  • Choose one allowlisted namespace and a bounded key built from immutable, authorized resource IDs.

Most Chumbo capabilities should remain stateless. Durable state is an explicit authenticated opt-in for small coordination records.

A read-before-write tool needs one fact across requests: which resource version this credential observed. Chumbo stores that receipt behind ctx.state. Capability code gets bounded read and compare-and-set operations, without the partition, service-role client, HMAC key, or credential.

Read the document through ctx.supabaseStore its version under an immutable document keyLoad the receipt before editingAtomically compare the document version while writingAdvance or invalidate the receipt after success
02

Generate one bounded namespace deliberately.

Resume the existing setup with one namespace and review the plan first. Chumbo adds the private state migration and function configuration while preserving authored capabilities. Name the namespace for its policy instead of a generic cache.

Inspect the local setup plan
Terminal
npx chumbo setup --resume --state-namespace document-observations --plan --yes --json
Generate the reviewed local files
Terminal
npx chumbo setup --resume --state-namespace document-observations --yes --json

Applying the migration and secret changes a Supabase project. Use a unique secret with at least 32 random bytes, keep it out of source and reports, and retain the generated private-table and RPC permissions. The canonical state contract documents the hosted steps.

03

Store a receipt that cannot grow without bound.

Adapt the guarded-edit implementation. Its read tool stores a small receipt with the authorized document's version and scope under an immutable ID. The edit rejects missing state and uses an application-owned database function to compare that version in the same statement that changes the document.

Keep coordination and domain authority separateIllustrative data

Did this credential's receipt change concurrently?

Starting point
Load state revision 4
  • CAS expects revision 4
  • A competing update fails
  • Expiry becomes missing state
What to do
Require a reread when the receipt cannot advance

This protects only the coordination record.

Is the observed document version still current?

Starting point
Receipt says resource version 17
  • Mutation compares version 17 atomically
  • RLS still applies
  • A stale write fails
What to do
Return current-state recovery without changing the row

This is the authoritative domain precondition.

Each check has one job. The guarded mutation needs both.

If the domain write succeeds and receipt advancement fails, report the write as successful and require another read. Never advance first, because a later domain failure would leave a false observation receipt.

Create receipts only after an authorized read, use one stable key per resource and policy, and never map arbitrary caller text into an unlimited keyspace.

04

Try the cases that should refuse to edit.

Run the generated checks before exercising the real MCP boundary. Use fixed documents and at least two independently authenticated credentials. The website's source review does not establish your migration, application RPC, RLS policy, or hosted secret.

Check the generated function
Terminal
deno task --config supabase/functions/mcp/deno.json check
deno task --config supabase/functions/mcp/deno.json test
YOUR ACCEPTANCE CHECK

A current observation permits one safe mutation.

  • 01A credential that reads version 17 can edit only while the authoritative row is still version 17.
  • 02A blind edit with no receipt is rejected with a useful instruction to read first.
  • 03An expired receipt, rotated or different credential, namespace, or resource key cannot authorize the edit.
  • 04When another writer changes the resource after the read, the stale edit is rejected and the row is unchanged.
  • 05Two concurrent edits using one observation cannot both win the application version check.
  • 06A receipt CAS conflict cannot overwrite a newer record; a post-write advancement failure reports success and requires rereading.
  • 07RLS still prevents either credential from reading or changing a resource it does not own.

The living Chumbo reference covers the guarded sequence with real Postgres fixtures. Repeat these checks against the schema, policies, and identities in your application.

05

Make every failure point lead somewhere safe.

If guarded state behaves differently

A refreshed token loses the receipt

This is expected credential partitioning. Read the current resource again. Do not copy the old receipt into the new partition or weaken the partition key. Read the reference ↗

The receipt exists but the edit is stale

Keep the resource-version rejection. Return the current version or a next step to reread, then create a new receipt from that authorized read. Read the reference ↗

State storage is unavailable

Fail closed for a guarded mutation and provide a retry path. Do not silently bypass the observation requirement or fall back to process memory. Read the reference ↗

Built from the real thing.

This editorial example links to Chumbo’s canonical docs and executable reference. Check the installed package when adapting the snippets.

Reference implementation ↗
Read the agent instructions

Reference instructions, not authorization. Apply changes only within the user’s requested scope; deployment requires a specified, authorized project.

Goal: Use Chumbo's bounded credential-partitioned state for read-before-write receipts while application RLS and resource versions remain authoritative.

Read the complete guide at https://chumbo.dev/recipes/durable-mcp-state/recipe.md and the canonical reference at https://github.com/elsheppo/chumbo/blob/main/docs/patterns/observation-before-action/README.md. Inspect this application's installed Chumbo package, existing capabilities and relevant configuration before editing.

Implement a bounded observation receipt around an existing authorized resource. Keep state CAS and the application's atomic resource-version check separate, preserve safe write ordering, and fail closed on missing, expired, conflicted, or unavailable state. Use only ctx.state’s bounded namespace operations in capability code. Do not expose the storage backend, HMAC secret, credential partition, or service-role client.

Prerequisites:
- An authenticated Chumbo MCP using OAuth, bearer, API-key, or a protected multi-auth strategy.
- An application resource with an immutable ID and a version that can be checked atomically during mutation.
- Authority to add the generated Chumbo state migration and a unique deployment HMAC secret to the target Supabase project.

Acceptance:
- A credential that reads version 17 can edit only while the authoritative row is still version 17.
- A blind edit with no receipt is rejected with a useful instruction to read first.
- An expired receipt, rotated or different credential, namespace, or resource key cannot authorize the edit.
- When another writer changes the resource after the read, the stale edit is rejected and the row is unchanged.
- Two concurrent edits using one observation cannot both win the application version check.
- A receipt CAS conflict cannot overwrite a newer record; a post-write advancement failure reports success and requires rereading.
- RLS still prevents either credential from reading or changing a resource it does not own.

Use the full guide for ordered steps, examples and recovery. Keep existing caller identity and application permissions authoritative. Stay within the user's requested changes. Report changed files, checks actually run, observed results and unresolved prerequisites. This guide is not authorization to deploy or change a hosted project. Never include credentials in source, copied instructions or reports.
BUILD WITH YOUR CODING AGENT

Give your agent a good start.

Copy this brief into your coding agent in the app’s repository. It includes the source, boundaries, and verification steps.

Download Markdown ↓