$ sudoscience
~/projects/webpoke

Webpoke

prototype

aka “Restoring Truth and Sanity to Webhooks

# a poke with a hint, then a ranged pull

Webhooks should not deliver truth in flight. A signed, content-free poke plus a cursor-owned ranged pull turns every delivery failure into latency instead of corruption.

The doctrine is named for the 2025 executive order that promised to restore truth and sanity to history; this one settles for event delivery. Truth lives in a pullable ledger; sanity is a cursor you own.

webpoke.sudoscience.devwatch the demo →

problem

Payload-bearing webhooks make delivery the correctness mechanism, which means providers owe signatures, ordering, retry queues, idempotency, dead-letter handling, and replay consoles — then disclaim it all with "don't rely on webhooks," transferring the reconciliation engineering to every consumer independently.

thesis

Move the contract from delivery to cursor. The provider keeps an append-only ledger and sends best-effort pokes; the consumer owns one durable checkpoint and reads ranges from it. Monotone facts can be lost, duplicated, or reordered harmlessly — so the channel gets to be cheap and the data gets to be correct.

reference stack

See poke + pull survive everything you throw at it.

A filmed walkthrough of the standalone reference stack: a vendor appends order events to an S2-shaped ledger and fires a signed, content-free poke; a customer-owned cursor pulls ranged reads, runs one handle(), and commits its checkpoint. Cut the notification channel and nothing breaks — lag climbs, then one heartbeat drains the backlog with events-lost: 0. Abuse the poke; spin up a slow second consumer; rewind re-derives identical state.

Open on YouTube · Filmed against the reference stack in webpoke-demo

the contract

four parts, none clever

signed content-free poke

"Something changed for this stream, frontier ≥ X." Nothing in it is load-bearing; every poke subsumes all earlier ones.

GET /changes?since=<cursor>

Ordered, bounded pages over an append-only ledger, with opaque cursors and a stated replay window.

heartbeat floor

Consumers poll anyway every N minutes. A consumer that missed every poke self-heals; nobody operates a replay console.

consumer-owned checkpoint

One durable row. At-least-once, duplication, reordering, and gap recovery all collapse into "read from my checkpoint."

vendor-shipped consumer

the integration is code the vendor writes

Every provider ships the stateless client — the easy 20% — and abandons consumers at the part that breaks in production. Webpoke inverts it: the vendor ships the stateful half, as deployable infrastructure, and the consumer writes one function.

reference stacks

Terraform / CDK / CloudFormation modules per cloud: poke receiver → cursor row → ranged-pull worker → fan-out → DLQ. ~200 lines of IaC, three flavors (AWS, GCP, plain Postgres-in-a-container).

the handler stub

The consumer's entire obligation is handle(events): everything around it — checkpointing, ordering, retries, fan-out by stream or type — arrives already provisioned and already correct.

day-2 included

Replay is "rewind the cursor." Shadow-running a new consumer version is "same stream, second checkpoint, diff the outputs." These ship as runbook commands, not aspirations.

one design, internal and external

The module the vendor hands partners is the same converger pattern it runs internally. Integration stops being a spec PDF and becomes "deploy this, write your function."

agent-operated onboarding

authorize an integration agent on rails that already exist

The last mile — wiring the vendor's consumer runtime into your stack — is itself delegable. Not by inventing a new trust ceremony, but by granting a vendor integration agent exactly the permissions that existing consent mechanisms already know how to scope, display, and revoke.

one-click provision

An AWS CloudFormation quick-create link (or Marketplace listing, or Terraform Cloud run) stands up the poke receiver, cursor table, and pull worker under a stack-scoped IAM role. The consent screen is the cloud's own — reviewed, logged, revocable.

scoped agent grant

The integration agent assumes only the role the stack created: this queue, this table, this log group. Cloud-side permissioning already solved least-privilege delegation; the agent just rides it.

code integration as a PR

Granted a GitHub App installation with the standard permission prompt, the agent wires the handler stub into your codebase following your conventions and opens a pull request — review remains yours.

verification before cutover

The agent replays a sample range from cursor zero through your handler in shadow mode and attaches the output diff to the PR as evidence. The cursor makes the rehearsal free.

revocation is boring

Delete the stack, uninstall the app, rotate the grant. Because the consumer owns the checkpoint, tearing the agent out never threatens the data.

dividends

offset pull is multi-consumer by construction

permissionless consumers

A new consumer is a reader with credentials and a cursor at zero. Producer cost is O(1) in consumer count — immutable history is the most cacheable workload there is.

consumer isolation

A slow consumer is just behind. No provider retry queues backing up, no "we deregistered your endpoint for failing too often."

history through the same channel

Bootstrap by starting at zero — same channel, same code path, no backfill API, no seam.

replay as an operation

Rewind, re-read, shadow-run, diff. There is no webhook-shaped version of blue-green consumption.

field card: the ledger is already a product

Filed by Rhett's ethos agent (by hand, for now): s2.dev — "the API for unlimited, durable, real-time streams." Durable, ordered, append-only streams readable from any retained point by sequence number or timestamp, with tailing, fencing tokens, and a self-hostable lite build. Relation: credible_actor, implementation_reference; impact: supports — the changes endpoint can be a thin shim over a stream store, and the lab has receipts: desh's stream-in/stream-out POC already replays through S2.

sourcess2.dev

code on demand

ship the filter to the data, not the data to the filter

The cursor pull is the consumer's, but it still pays egress and filters locally. Let it ship a cheap, sandboxed predicate to the query side — pull your slice, not the firehose. The poke stays content-free; only the pull learns a new trick.

push-down at /changes

A small sandboxed WASM filter/map/reduce runs at the changes endpoint before the page is serialized — narrow to one stream, project a few fields, fold a running count. The cursor contract is unchanged; only less crosses the wire.

cheap and safe by construction

WASM instantiates in microseconds and runs resource-capped (fuel, memory, wall-clock; no network, no disk). The provider runs untrusted consumer code the way an edge runtime already runs untrusted handlers.

the provider can bill for it

Pushed-down compute is just another SKU (stock-keeping unit) — count the fuel, estimate the cost, charge it on the same per-request counters CloudCap meters. The consumer pays a little to not move bytes it would have discarded; the provider sells cycles instead of egress.

code-on-demand, finally earning its keep

Fielding's one unused REST constraint. Push-down predicates keep getting reinvented per system (Kafka filters, ClickHouse, ATProto Jetstream wildcards, S2 read-time filters); a WASM filter at the ledger generalizes the move.

sourcesFielding's REST dissertationKafkaClickHouses2.dev

lineage

RSS was right; we're signing it

The pattern is the web's oldest correct answer, read clearly. Greg Young built an event store and served its streams over Atom for exactly these properties — the feed is the log, history is immutable and cacheable, and the consumer owns its checkpoint.

the feed is the log

An Atom or RSS entry is an immutable, addressable fact; the feed is an append-only event stream you fold into state. RFC 5005 makes archived pages infinitely cacheable and the head the only hot page — a CDN accelerates the ledger without ever being trusted to author it.

sourcesRFC 5005

polling is underrated

Conditional GET (ETag / If-Modified-Since → 304) makes re-reading nearly free. The heartbeat floor is not a workaround bolted onto push; it is the web's original liveness mechanism, cached by infrastructure you don't operate.

catch-up subscriptions own their checkpoint

Read from your checkpoint, fold forward to the head, then stay live; resume from it after a crash. Greg Young's catch-up subscription and webpoke's consumer-owned cursor are the same object under two names.

signing is the one addition

RSS trusts the origin to author honestly. A decentralized firehose wants the events themselves signed so untrusted relays can carry them. Sign the events, add a content-free poke to cut poll latency, and webpoke is Atom-over-HTTP, federated.

the general shape

every sync protocol is this invariant, partly admitted

Notifications are hints, signed logs are truth, cursors belong to the consumer. Each protocol rediscovers the split and usually compromises it — which is why decentralized social firehoses keep converging here under load.

decentralized social firehoses

An ATProto repo is a signed, event-sourced commit log; consumers replay subscribeRepos from a seq cursor. The ecosystem's scaling pain is fan-out of full content to every consumer — the half a content-free poke deletes. An untrusted relay should only ever be able to say "go check," never to author.

sourcesATProto

activitypub, the cautionary opposite

Fan-out on write into each inbox, with no log, no cursor, and no replay. An inbox that is down loses the event; a slow inbox backs up the sender. Every failure mode webpoke designs out, push-delivery federation designs in.

sourcesW3C ActivityPub

the rest of the family

Kafka offsets, CDC replication slots, Matrix /sync tokens, Nostr since/until, IMAP IDLE then FETCH, NNTP high-water marks — a log with a per-consumer position, all the way back to newsgroups. The "push" is a long-poll wakeup over a ledger someone is quietly pulling.

the rubric

when the hybrid is wrong

no versioned store to pull from?

Push — durable and acked for imperatives (a lost command is lost intent), fire-and-forget for samples nobody re-reads.

not reducible to a monotone fact?

Then the lattice tricks don't apply; you need delivery semantics and should pay for them knowingly.

floor latency intolerable?

Still build poke + pull — then harden only the poke channel, the half whose failures can't corrupt anything.

ancestors

prior work this absorbed

Named and dated — receipts behind the thesis, not public.

Service Catalog

An Optic-era observation that never shipped: APIs are only a subset of how organizations communicate. One place to document business processes and expose their endpoints and integration points — webhooks included. Webpoke is the integration-point half, finished.

artifacts

status, honestly

doctrinelive

webpoke.sudoscience.dev

reference stack demolive

https://youtu.be/kSyE4aoNthE — filmed walkthrough: poke cut, heartbeat drain, poke abuse, slow-consumer isolation, shadow handler diff

sourcesyoutu.be/kSyE4aoNthE

changes-endpoint RFCsketch

opaque cursors, bounded pages, replay window, signed poke — and an explicit retention floor, so falling behind the window is a declared gap condition, not a surprise

the protocol, model-checkedprototype

a TLA+ model of poke + hint + offset with passing TLC runs: safety invariants, plus the liveness property that is the whole doctrine — consumers reach the head even when every poke is dropped. "Failure is latency, not corruption," checked rather than asserted

vendor scorecard corpussketch

Stripe, GitHub, Shopify, Svix, and Outpost scored against one rubric, each system's pain sorted into essential versus accidental complexity. The headline row: consumer-owned offset checkpoint in the protocol — no, for every vendor. The field still centers on delivery orchestration; that's the column this doctrine deletes

consumer runtime modulesroadmap

AWS, GCP, Postgres reference stacks

integration agentroadmap

one-click provision + PR-based wiring + shadow verification

edges

connected investigations

Distilled from field notes on poke + ranged-pull systems, reactivity models, and the consumer runtime providers never shipped.