<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Stephen Sookra </title>
    <description>The latest articles on DEV Community by Stephen Sookra  (@stephensook).</description>
    <link>https://dev.to/stephensook</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3995917%2F9805a979-e04e-45cc-a7e7-f05dccd5f571.jpg</url>
      <title>DEV Community: Stephen Sookra </title>
      <link>https://dev.to/stephensook</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stephensook"/>
    <language>en</language>
    <item>
      <title>How I built Curtail: a governed agent fleet for water curtailment, where the human always signs</title>
      <dc:creator>Stephen Sookra </dc:creator>
      <pubDate>Tue, 18 Aug 2026 03:42:55 +0000</pubDate>
      <link>https://dev.to/stephensook/how-i-built-curtail-a-governed-agent-fleet-for-water-curtailment-where-the-human-always-signs-3861</link>
      <guid>https://dev.to/stephensook/how-i-built-curtail-a-governed-agent-fleet-for-water-curtailment-where-the-human-always-signs-3861</guid>
      <description>&lt;p&gt;In August 2022, a water association serving about 80 ranchers ran its pumps for eight days against a standing drought curtailment order on the Shasta River. The proposed penalty came to $4,000 in total, which is $500 per day. One rancher said, on the record: "We could have kept going for $500 a day."&lt;/p&gt;

&lt;p&gt;The statute has since moved. Water Code 1846(b), as amended effective January 1, 2025, sets the rate at $10,000 per day. But the regulation a person actually reads, 23 CCR 875.9(b), still prints $500. The published rule understates the law by a factor of twenty, and nothing in the state's tooling notices.&lt;/p&gt;

&lt;p&gt;That gap is the product. Curtail is my entry to the Google x Devpost All Things Agentic Hackathon: a governed multi-agent system that watches a river in real time, computes who must stop diverting under California prior-appropriation priority law, and drafts the curtailment order for a named human official to sign. Nothing self-executes. This post is about how it was built, and what building it taught me about putting language models anywhere near legal text.&lt;/p&gt;

&lt;h2&gt;
  
  
  The first decision: what may never be an LLM
&lt;/h2&gt;

&lt;p&gt;The center of the system is not an agent. The Allocation Core, the thing that decides which priority groups a curtailment must reach, is deterministic Python with golden tests and property tests. Priority ordering, decree membership, gage reading against the operative minimum, computed shortfall: these are facts, and facts do not need a temperature parameter.&lt;/p&gt;

&lt;p&gt;Just as deliberately, the Core produces a recommendation, never a determination. The regulation (23 CCR 875(b)) assigns the determination to a human official and expressly preserves their discretion to decline, narrow, or suspend. So the codebase uses the word "recommendation" throughout, and "determination" is reserved for the signature. The signed record shows what the official actually considered, including the judgment inputs the system surfaces but refuses to auto-resolve: weather, fisheries information, voluntary contributions, groundwater evidence.&lt;/p&gt;

&lt;p&gt;Around that core sits a four-node fleet built on Google's Agent Development Kit, running on Cloud Run: a Gage Sentinel that classifies USGS readings against date-period-bounded minimums, an Order Scribe on gemini-3.5-flash via Vertex AI that drafts the legal document, a Herald that models the four legally distinct service methods under Water Code 1121 and never reports a notification as legal service, and a Season Ledger holding the statutory clocks (reconsideration windows, response deadlines) durably in Cloud Firestore. Durability was proven the only way I trust: a second, independently constructed client read the season back after the writer was gone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Guards, because models fabricate exactly where it hurts
&lt;/h2&gt;

&lt;p&gt;Before writing any code I had six external models review the concept. Two of them cited case law that does not exist in any database. Invented authorities, with confident citations, in a legal domain. That settled the security design: a system prompt forbidding invention is not a guardrail.&lt;/p&gt;

&lt;p&gt;So the Scribe's output passes through a deterministic, server-side citation scrubber after the model call. Any authority not present in a verified allowlist is stripped and flagged before the draft can reach the document generator, and the fabricated citations from that review ship in the repository as a CI test fixture, so the guard can never quietly stop guarding. A second layer, ledger validation, rejects any draft that asserts a right, a priority date, or a tier the deterministic Core did not compute, with one retry and then escalation to the human queue marked UNVERIFIED. Model Armor screens untrusted order text on the way in, chunked to fit its documented prompt-injection window, and an unreachable screen reports UNAVAILABLE rather than clean.&lt;/p&gt;

&lt;p&gt;The same discipline applies to my own prose. Every number in the demo video narration, the README, and the Devpost description draws from one generated fact sheet, docs/FACTS.md, computed from the shipped code. CI fails if the file drifts from the code that produces it. A gate reads the narration script and refuses any figure, digits or spelled out, that the fact sheet cannot source. That gate caught real errors before they reached a published, uncorrectable video.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing against the Board's own decisions
&lt;/h2&gt;

&lt;p&gt;The credibility artifact is a backtest. I fetched the State Water Board's published curtailment orders and addenda for the Scott and Shasta rivers, 98 PDFs byte-verified, 95 scorable, and replayed the gage record against them. Curtail reproduces the direction of 6 of 6 scored historical curtailment decisions, with 5 documents excluded before scoring for stated reasons (a bound is not a reading; a named-diverter scope is not a basin threshold decision). The exclusions are reported next to the result, because a denominator you cleaned in private is not a metric.&lt;/p&gt;

&lt;p&gt;The rights tables are the Board's own attachments, not synthetic data. The Scott table carries 384 rights, and here is the finding that justifies the whole architecture: the Board's attachment states each right's curtailment group in its own column, and inferring those groups from the rights' attributes instead agrees with the Board on 8 of 384. Group 1 is curtailed first and group 8 nearly last, so that gap is the difference between a ranch irrigating and a ranch shutting off. Read the record; never re-derive what the agency already stated.&lt;/p&gt;

&lt;p&gt;My favorite fixture is July 2025. Fort Jones read 48.7 cfs on a Sunday night and curtailment was reinstated. Community members disputed the measurement, the watermaster district ran field flows, USGS revised the rating curve, and the same water read 78.4 cfs on Tuesday morning. Curtailment lifted. The river never rose; the measurement moved. An agent system that cannot be corrected by the person responsible for it is not governed, so that sequence, human evidence flowing back into the machine's recommendation, is the demo's centerpiece, and the near-threshold band that flags "field verification recommended" exists because of it.&lt;/p&gt;

&lt;p&gt;There is also a scored axis for restraint: five cases where the right answer is not the obvious action, including a reading inside the near-threshold band and rights the Board published without a priority date. The system refuses or withholds rather than extrapolating. Scoring that axis immediately found a real bug: the Sentinel would classify a negative discharge, which on a sensor fault reads as far below minimum and points at curtailment. That is now unrepresentable at the domain object.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data sovereignty, concretely
&lt;/h2&gt;

&lt;p&gt;One more piece worth naming: document intake runs Gemma (gemma3:4b) locally through Ollama. It reads a published Board order and returns four filing fields, each verified verbatim against the source text before acceptance, and no document leaves the machine. An agency that cannot send landowner records to a third-party inference API can host these weights itself. The model files documents; it is not permitted to read law out of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;Most of my defects were false greens: checks that reported success without checking. A guard scoped to tracked files cannot see the file you are about to commit. A web application firewall serves its block page as HTTP 200, so a corpus fetcher that trusts status codes downloads error pages named as PDFs. A test can assert a figure that no primary document contains, and then defend the error against correction. The pattern underneath all of them: verify the artifact, never the action that claims to have produced it. That principle is also the product thesis, which is the kind of symmetry you only notice after the third incident.&lt;/p&gt;

&lt;p&gt;The demo video's agent section is one continuous, uncut take of the production system, including the full length of the real Gemini call, because a rules requirement ("an unedited, live execution") is also just the honest way to show an agent working.&lt;/p&gt;

&lt;h2&gt;
  
  
  See it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Demo (3:41): &lt;a href="https://youtu.be/Kz5tv6oe070" rel="noopener noreferrer"&gt;https://youtu.be/Kz5tv6oe070&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Live console, no account needed: &lt;a href="https://curtail-console-api-672785135387.us-central1.run.app" rel="noopener noreferrer"&gt;https://curtail-console-api-672785135387.us-central1.run.app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Repository (Apache-2.0): &lt;a href="https://github.com/StephenSook/curtail" rel="noopener noreferrer"&gt;https://github.com/StephenSook/curtail&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I created this piece of content for the purposes of entering the All Things Agentic Hackathon. #AllThingsAgenticHackathon&lt;/p&gt;

</description>
      <category>googlecloud</category>
      <category>ai</category>
      <category>python</category>
      <category>hackathon</category>
    </item>
    <item>
      <title>Building strongly consistent parental consent across regions with Amazon Aurora DSQL</title>
      <dc:creator>Stephen Sookra </dc:creator>
      <pubDate>Mon, 22 Jun 2026 01:56:08 +0000</pubDate>
      <link>https://dev.to/stephensook/building-strongly-consistent-parental-consent-across-regions-with-amazon-aurora-dsql-d8a</link>
      <guid>https://dev.to/stephensook/building-strongly-consistent-parental-consent-across-regions-with-amazon-aurora-dsql-d8a</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclosure:&lt;/strong&gt; I created this article for the purpose of entering the H0 Hackathon, Hack the Zero Stack with Vercel v0 and AWS Databases.&lt;br&gt;
&lt;strong&gt;#H0Hackathon&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🔗 &lt;strong&gt;Live app:&lt;/strong&gt; &lt;a href="https://custody-zeta.vercel.app" rel="noopener noreferrer"&gt;https://custody-zeta.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The gap I wanted to close
&lt;/h2&gt;

&lt;p&gt;When a parent revokes consent or sets a spending cap for a child on a global platform, that decision may not take effect everywhere at once.&lt;/p&gt;

&lt;p&gt;The platform writes the change in one region, replication catches up later, and during that window, the child may still be able to play or spend money somewhere else. There is also rarely verifiable proof of exactly when the parent acted.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;Custody&lt;/strong&gt;, a neutral system of record for parental consent and minor spending controls, to close that gap.&lt;/p&gt;

&lt;p&gt;With Custody, a parent can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Grant or revoke consent&lt;/li&gt;
&lt;li&gt;Set a spending cap&lt;/li&gt;
&lt;li&gt;Apply the decision consistently across regions once it commits&lt;/li&gt;
&lt;li&gt;Verify every decision through a tamper-evident audit trail&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every action becomes a link in a hash chain that can be verified directly in the browser.&lt;/p&gt;

&lt;p&gt;All data in the demonstration is synthetic. It contains no real minors, biometrics, or personal information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I chose Amazon Aurora DSQL
&lt;/h2&gt;

&lt;p&gt;Custody depends on one critical property:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When a write commits, every region must agree on the result.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Amazon Aurora DSQL is an active-active, multi-region database with strong consistency on commit. It provides the property Custody needs without requiring me to build and maintain a distributed consensus layer myself.&lt;/p&gt;

&lt;p&gt;The deployment uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;us-east-1&lt;/code&gt; as one regional endpoint&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;us-east-2&lt;/code&gt; as the second regional endpoint&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;us-west-2&lt;/code&gt; as the quorum witness&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The witness does not expose a database endpoint. Its purpose is to help maintain agreement between the two writable regions.&lt;/p&gt;

&lt;p&gt;One framing rule I followed throughout the project was never calling the process “instant.”&lt;/p&gt;

&lt;p&gt;A commit requires roughly two cross-region network round trips, and an optimistic-concurrency retry may add more time. The accurate claim is that the system is &lt;strong&gt;strongly consistent on commit&lt;/strong&gt;, without a replication-lag window after the commit completes.&lt;/p&gt;

&lt;p&gt;Precision matters more than a superlative.&lt;/p&gt;

&lt;h2&gt;
  
  
  The data model
&lt;/h2&gt;

&lt;p&gt;Custody uses append-only event tables combined with per-entity projection rows.&lt;/p&gt;

&lt;p&gt;Aurora DSQL is PostgreSQL-compatible, but it is not traditional PostgreSQL. The application architecture must respect its specific rules.&lt;/p&gt;

&lt;p&gt;A few important examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Primary keys use random UUIDs instead of &lt;code&gt;SERIAL&lt;/code&gt;, because sequences can create hot keys.&lt;/li&gt;
&lt;li&gt;DSQL does not support foreign keys, triggers, or stored procedures, so referential integrity is handled in the application layer.&lt;/li&gt;
&lt;li&gt;Indexes are created with &lt;code&gt;CREATE INDEX ASYNC&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A unique asynchronous index does not enforce uniqueness until its build job finishes, so migrations wait for completion through &lt;code&gt;sys.jobs&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each consent action and spending action is stored as an append-only event.&lt;/p&gt;

&lt;p&gt;The current consent status and running spending total are stored as projection rows. Each projection is updated in the same transaction as its related event append.&lt;/p&gt;

&lt;p&gt;These projections exist per user or per minor. Custody never relies on a single global counter row because that row would become a hot key and create cascading conflicts under load.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preventing the hash chain from forking
&lt;/h2&gt;

&lt;p&gt;The part of the data model I am most proud of is how it handles concurrent writes.&lt;/p&gt;

&lt;p&gt;Each event table uses a composite primary key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(user_id, seq)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Imagine two requests attempting to append an event for the same user at the same time.&lt;/p&gt;

&lt;p&gt;Both requests:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read the same current chain tip.&lt;/li&gt;
&lt;li&gt;Calculate the same next sequence number.&lt;/li&gt;
&lt;li&gt;Attempt to insert the next event.&lt;/li&gt;
&lt;li&gt;Collide on the composite primary key.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Aurora DSQL then raises a serialization conflict at commit using SQLSTATE &lt;code&gt;40001&lt;/code&gt; with error code &lt;code&gt;OC000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One transaction succeeds. The other retries, reads the new chain tip, and appends after it.&lt;/p&gt;

&lt;p&gt;This prevents the chain from forking.&lt;/p&gt;

&lt;p&gt;I tested this with eight concurrent append requests. The stored events returned with sequence numbers &lt;code&gt;1&lt;/code&gt; through &lt;code&gt;8&lt;/code&gt;, with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No gaps&lt;/li&gt;
&lt;li&gt;No duplicate sequence numbers&lt;/li&gt;
&lt;li&gt;Every &lt;code&gt;prev_hash&lt;/code&gt; matching the previous event’s &lt;code&gt;entry_hash&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The optimistic-concurrency wrapper
&lt;/h2&gt;

&lt;p&gt;Every write passes through the same retry helper.&lt;/p&gt;

&lt;p&gt;The helper:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retries only serialization conflicts using &lt;code&gt;40001&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Uses exponential backoff with full jitter&lt;/li&gt;
&lt;li&gt;Limits the maximum number of attempts&lt;/li&gt;
&lt;li&gt;Retries the entire transaction, never only part of it&lt;/li&gt;
&lt;li&gt;Does not retry normal reads, because DSQL does not conflict-check plain reads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Writes are also idempotent.&lt;/p&gt;

&lt;p&gt;The client provides a request UUID, which is stored under a unique asynchronous index. The application uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;CONFLICT&lt;/span&gt; &lt;span class="k"&gt;DO&lt;/span&gt; &lt;span class="k"&gt;NOTHING&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the same request is replayed, it becomes a no-op rather than creating a duplicate event.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tamper-evident audit trail
&lt;/h2&gt;

&lt;p&gt;Custody’s audit trail is a separate SHA-256 hash chain for each user.&lt;/p&gt;

&lt;p&gt;Each &lt;code&gt;entry_hash&lt;/code&gt; is calculated from:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The canonical JSON representation of the event payload&lt;/li&gt;
&lt;li&gt;The previous event’s hash&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first event uses a genesis previous hash containing 64 zeros.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;entry_hash = SHA256(canonical_payload + previous_hash)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Canonical JSON is important. Custody uses deterministic canonical JSON in the JCS style: object keys are recursively sorted and formatting is stable, so two logically identical payloads always serialize to the same bytes. It is not a full RFC 8785 implementation.&lt;/p&gt;

&lt;p&gt;Without canonicalization, two logically identical JSON objects could produce different hashes because of differences in key ordering or number formatting. That would create false tampering warnings.&lt;/p&gt;

&lt;p&gt;The verification function recalculates every event hash and reports the exact first index where the stored chain no longer matches.&lt;/p&gt;

&lt;p&gt;Verification runs in the browser using the Web Crypto API. A judge can modify an event block in the interface and immediately see the chain turn red starting from the first broken link.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credential-free authentication on Vercel
&lt;/h2&gt;

&lt;p&gt;There is no database password stored anywhere in Custody.&lt;/p&gt;

&lt;p&gt;The frontend uses Next.js 16 and runs on Vercel.&lt;/p&gt;

&lt;p&gt;At runtime:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Vercel issues an OpenID Connect token.&lt;/li&gt;
&lt;li&gt;The application exchanges it through AWS &lt;code&gt;AssumeRoleWithWebIdentity&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;AWS grants access to a restricted IAM role.&lt;/li&gt;
&lt;li&gt;The Aurora DSQL connector creates a short-lived, region-scoped authentication token.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A token created for one region only authenticates against that region’s endpoint. Because of this, the application maintains a separate connection pool for each regional endpoint.&lt;/p&gt;

&lt;p&gt;This architecture removes the need for permanent database credentials in Vercel environment variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demonstrating cross-region consistency with SSE
&lt;/h2&gt;

&lt;p&gt;The cross-region demonstration uses Server-Sent Events.&lt;/p&gt;

&lt;p&gt;Vercel does not host persistent WebSocket servers, so each region has its own SSE route that streams the latest committed state.&lt;/p&gt;

&lt;p&gt;When a parent revokes consent:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A Next.js Server Action submits the transaction.&lt;/li&gt;
&lt;li&gt;The transaction commits to Aurora DSQL.&lt;/li&gt;
&lt;li&gt;Both regional streams read the new committed state.&lt;/li&gt;
&lt;li&gt;Both region panels update.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;code&gt;us-east-2&lt;/code&gt; panel reads from the second Aurora DSQL endpoint. It is not a duplicated client-side animation.&lt;/p&gt;

&lt;p&gt;What appears in the interface reflects the state returned by the two regional database endpoints.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hardening the public demonstration
&lt;/h2&gt;

&lt;p&gt;The deployed application is open for judges and other users to test, so the public database role follows the principle of least privilege.&lt;/p&gt;

&lt;p&gt;It can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SELECT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;INSERT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UPDATE&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It cannot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DELETE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Drop tables&lt;/li&gt;
&lt;li&gt;Run DDL&lt;/li&gt;
&lt;li&gt;Take ownership of tables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aurora DSQL also does not support &lt;code&gt;TRUNCATE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This gives the public application exactly what it needs: read access, append access, and permission to update projection rows. It does not have permission to wipe the database.&lt;/p&gt;

&lt;p&gt;Mutation routes are also rate-limited with Upstash Redis, and the event ledger is append-only by construction.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is wired into the live app
&lt;/h2&gt;

&lt;p&gt;The deployed version includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A multi-region Aurora DSQL ledger&lt;/li&gt;
&lt;li&gt;Strongly consistent cross-region commits&lt;/li&gt;
&lt;li&gt;Optimistic-concurrency retries&lt;/li&gt;
&lt;li&gt;Idempotent writes&lt;/li&gt;
&lt;li&gt;A per-user SHA-256 hash chain&lt;/li&gt;
&lt;li&gt;Client-side tamper verification&lt;/li&gt;
&lt;li&gt;Credential-free Vercel OIDC authentication&lt;/li&gt;
&lt;li&gt;Region-scoped Aurora DSQL tokens&lt;/li&gt;
&lt;li&gt;Live cross-region state streaming with SSE&lt;/li&gt;
&lt;li&gt;SD-JWT age-bracket selective disclosure&lt;/li&gt;
&lt;li&gt;A least-privilege public database role&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The age proof uses selective disclosure under RFC 9901. It is not a complete zero-knowledge proof, and I do not claim that it is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;Custody currently has &lt;strong&gt;88 tests&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;83 unit tests&lt;/li&gt;
&lt;li&gt;5 tests that run against the live Aurora DSQL cluster&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The live-cluster tests include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cross-region read-after-commit verification&lt;/li&gt;
&lt;li&gt;Eight-way concurrent append testing&lt;/li&gt;
&lt;li&gt;Hash-chain integrity checks&lt;/li&gt;
&lt;li&gt;Idempotency verification&lt;/li&gt;
&lt;li&gt;Optimistic-concurrency retry behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Technology stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Database:&lt;/strong&gt; Amazon Aurora DSQL, multi-region and active-active&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend and server:&lt;/strong&gt; Next.js 16 and React 19&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hosting:&lt;/strong&gt; Vercel&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication:&lt;/strong&gt; Vercel OIDC and AWS IAM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate limiting:&lt;/strong&gt; Upstash Redis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit trail:&lt;/strong&gt; SHA-256 hash chains&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Selective disclosure:&lt;/strong&gt; SD-JWT&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live regional updates:&lt;/strong&gt; Server-Sent Events&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try Custody
&lt;/h2&gt;

&lt;p&gt;Custody demonstrates how a globally distributed application can apply parental consent and spending-control decisions consistently across regions while maintaining a verifiable audit trail.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Live app:&lt;/strong&gt; &lt;a href="https://custody-zeta.vercel.app" rel="noopener noreferrer"&gt;https://custody-zeta.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Built with Amazon Aurora DSQL and Vercel for the H0 Hackathon.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#H0Hackathon&lt;/strong&gt; &lt;/p&gt;

</description>
      <category>aws</category>
      <category>database</category>
      <category>distributedsystems</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
