Solution Architecture Document — Calaite
Project: Calaite (Isobaric Labs) — transcript-driven audio/video editor and publishing platform Author: Jarrod E. Brown Status: Core loop live in production; full productization surface built and exercised in a gated development environment Repository: Private
1. Overview
Calaite is a browser-based, transcript-driven audio and video editor built entirely on Cloudflare's serverless platform. It ingests recorded or live-captured media, transcribes it, presents an editing surface where cutting the transcript cuts the audio, and renders broadcast-quality exports — plus an AI consumer layer (show notes, chapters, titles, highlight clips, audiograms, semantic search), multi-guest remote recording with durable local-first capture, and a commercialization stack (workspaces, usage metering, billing, publishing) that is fully built and dev-exercised behind default-off flags.
There is no origin server, no container fleet to babysit, and no queue broker. The control plane is a single Cloudflare Worker; the editing authority is a Durable Object per project; long-running work is carried by durable Workflows; and heavy media work happens in a CPU container that reads and writes object storage directly. The Worker never touches a media byte.
2. Problem & Context
Producing a weekly two-host podcast exposes the same bottleneck every independent show hits: editing is the constraint. A one-hour conversation takes three to five hours to edit in a waveform editor, and the skill required is not the skill the show is about. Transcript-driven editors solved that ergonomic problem — delete the sentence, delete the audio — and the category leader (Descript) is excellent at it.
Three things kept it from being the answer here. First, cost scales per seat and per transcription hour in a way that does not suit a two-person show with guests who join once. Second, the desktop-plus-cloud hybrid model puts large source files on someone's laptop, which is exactly where a lost take becomes an unrecoverable one. Third, and decisively for an architecture practice: a transcript-driven editor is a genuinely hard distributed-systems problem — a single authoritative document under concurrent edit, long-running media jobs that must survive process death, and a media plane that must never be allowed to flow through a memory-capped edge runtime. It is the kind of problem worth building rather than buying.
What began as tooling for one show is now a product. The editing loop is the commodity; the durable capture path, the flag-gated commercialization surface, and the publish fan-out are what make it a platform rather than a tool.
3. Goals & Requirements
Functional
- Import or record multitrack audio and video; transcribe it; edit it by editing the transcript.
- Preserve non-destructive edits — every cut is an entry in an edit list over immutable source media, reversible at any point.
- Support real-time multi-user editing of a single project with authoritative conflict resolution.
- Record remote guests without accounts, with capture durability that does not depend on the network.
- Render loudness-normalized audio exports and, behind a flag, frame-accurate video exports.
- Generate show notes, chapters, titles, highlight clips, audiograms, and semantic search from the transcript.
- Publish finished assets to podcast hosts and social destinations from inside the product.
- Meter usage, gate workspaces, and bill — as a commercial product, not a personal tool.
Non-functional
- No media byte may transit the control plane. Large media moves only via presigned object-storage URLs.
- Every new capability ships behind a default-off flag such that a deployment with all flags off is byte-identical to the one before it.
- No silent failures. Every failed state transition becomes a visible error record or a non-2xx response.
- Capture durability survives a browser crash, a tab kill, and a network partition.
- Development autonomy must never be able to reach production.
4. Decision Rationale
Why Cloudflare end-to-end rather than a conventional cloud? The workload is three unlike things: a low-latency stateful collaboration surface, a set of long-running media jobs, and a large-object data plane. On a conventional stack that is a websocket tier plus a job queue plus a worker fleet plus object storage plus the egress bill. Cloudflare collapses it: Durable Objects give a single-threaded, addressable authority per project without a coordination service; Workflows give durable, checkpointed orchestration without a broker; Containers give ffmpeg where it is needed; and R2's zero egress fee removes the line item that makes media products expensive. A year of episodes and raw masters costs a couple of dollars a month in storage.
Why a Durable Object as the editing authority instead of a CRDT-first design? Both were designed. The DO won for the primary path because a podcast edit session is small-N and connected — two hosts and occasionally a producer, all online — and a single serialization point gives strictly correct ordering, trivially correct undo/redo, and a place to hold the room roster. Every operation is applied in order, persisted, and broadcast. A CRDT is the right answer for offline-tolerant editing, and the merge design exists for it, but adopting one as the primary model would have bought conflict-free offline editing at the cost of an ordering guarantee the product actually needs today.
Why presigned URLs everywhere instead of streaming through the Worker? The Worker isolate has a 128 MB memory ceiling. A 700 MB 32-bit float WAV is not an edge case for this product; it is a normal take. Rather than fight the ceiling with chunked relays, the architecture declares the Worker a control-plane-only component: the browser uploads directly to object storage, the render container pulls and pushes directly, the ASR provider fetches from a presigned URL, and every publish destination pulls the finished asset from a presigned link. The invariant is now total — after the publisher cleanup described in §11, no code path relays media bytes through the Worker at all, and the data-plane fetch budget that existed to bound such relays has no members left.
Why flag-gated additive delivery? The system is built by an autonomous build loop that ships increments continuously. That is only safe if a deployment cannot change behavior unless someone decides it should. Every capability lands behind a default-off flag; routes for a disabled feature return 404; with the flag set absent, the deployment is byte-identical to the prior one. This is what allows a full commercialization surface — workspaces, metering, billing, publishing, a public API — to be built, exercised, and oracle-pinned in development while production continues to run only the core loop.
Why AssemblyAI as the primary ASR with Whisper as the fallback? Multitrack recording carries speaker identity in the track itself, which means diarization is not needed — and diarization is where hosted ASR quality diverges most. What matters instead is word-level timing accuracy over long files, because the edit list is expressed in word timings. AssemblyAI is submitted a presigned URL per track and returns timings good enough to cut on; Workers AI Whisper stays wired as a fallback so the loop degrades rather than stops when a provider is unavailable or unfunded. A self-hosted WhisperX GPU path was evaluated and held as future state — it wins on cost at volume the product does not yet have.
Why buy publishing rather than build it? All four per-platform social publishers were built, and then deliberately deleted. Each one carried its own OAuth module, its own token store, its own platform verification gauntlet, and its own upload semantics — and two of them were the only remaining code paths that relayed bytes through the Worker. A unified multi-tenant aggregator moves platform verification and end-user token custody off the system entirely, at a per-post price. Podcast hosts, which authenticate with a simple API key and pull from a presigned link, stayed delegated as direct integrations. Deleting working code was the right call: it removed a maintenance surface, an auth surface, and the last two members of the data-plane budget.
5. Architecture Overview
The system is a single Cloudflare Worker acting as control plane, four Durable Object classes holding per-project state, six durable Workflows carrying long-running orchestration, a CPU container running ffmpeg, and a data plane of relational storage, object storage, and a vector index. A React single-page application is served from the same Worker as static assets.
Requests arrive at the Worker, which terminates identity at the edge (Cloudflare Access for members, a Durable-Object-signed token for account-less guests, a service token for automation), mounts roughly forty route modules, and dispatches to the appropriate authority. Interactive edit traffic goes to the project's Durable Object over a hibernatable WebSocket. Long-running work is handed to a Workflow, which checkpoints each step and is independently retryable. Media bytes never enter this path.
6. Components
| # | Component | Type | Responsibility |
|---|---|---|---|
| 1 | Control-plane Worker | Cloudflare Worker (Hono) | Front door. Terminates auth, resolves identity, mounts ~40 API route modules, serves the SPA and the branded standalone surfaces (product landing, login, help, company portal), injects cross-origin isolation headers on the editor document only. Orchestrates but never processes media. |
| 2 | EditDocument | Durable Object (one per project) | The single editing authority. Holds the authoritative word list and non-destructive edit list in memory, persists snapshots and undo/redo history, fans out changes over hibernatable WebSockets. Also the room authority — signs and verifies guest room tokens, relays WebRTC signaling, maintains roster and lock state. |
| 3 | RenderContainer | Durable Object wrapping a Container | The ffmpeg engine, one instance per project, sleeping after five minutes idle. CPU-only, capped instance count. Performs transcode, multitrack mix, the enhancement chain, the single-pass analysis sidecars, passthrough export, and segment-parallel video render — reading and writing object storage directly. |
| 4 | BatchAsrCoordinator | Durable Object | Cross-wave pacing for back-catalog batch transcription, so wave N+1 cannot start before wave N resolves. A single-wave batch is byte-identical to the uncoordinated path. |
| 5 | ScheduledPublishDO | Durable Object (one per project) | Publish-at-time-X coordinator. Holds one pending publish in DO storage and, on its alarm, kicks the same publish Workflow the immediate trigger uses, then clears the pending so a re-armed alarm cannot double-publish. Adds no database table. |
| 6 | Transcribe Workflows | Cloudflare Workflow ×2 | Single-source chunked ASR, and multitrack ASR with a primary provider plus a fallback engine. |
| 7 | Render Workflow | Cloudflare Workflow | Async durable export. Audio always; video behind a flag via a dedicated five-stage state machine (splitting → renderingSegments → stitching → finalizing → done\|failed) persisted on the existing job row. |
| 8 | Pipeline Workflow | Cloudflare Workflow | Post-production fan-out. On a completed transcript, runs the notes / titles / chapters / clips / search consumers concurrently, one checkpointed step and one job row each; a per-consumer failure is caught as an error row so it never fails a sibling. |
| 9 | Publish Workflow | Cloudflare Workflow | Per-destination publish fan-out, dispatched on destination type. Each publisher is a checkpointed step with its own job row. |
| 10 | AI Producer Workflow | Cloudflare Workflow | Durable-run orchestrator for scripted producer plans — fires each live plan step against its mapped internal endpoint and checkpoints the completed step id, so a mid-run failure resumes from the last success. Scaffold; double-gated. |
| 11 | Frontend SPA | React + Vite | Three primary surfaces: project list, editor (multitrack timeline, waveforms, transcript editing, video spine, export and publish panels), and guest join (device pre-flight lobby plus in-room recording with a participant gallery). |
| 12 | RecordingManager | Browser module | Durable local-first capture. Writes every five-second chunk three ways — local disk, object storage, and IndexedDB — with an optional off-main-thread OPFS worker spool. |
| 13 | Tail / alerting service | Second Cloudflare Worker | Bound as a tail consumer of the app Worker. Harvests structured log lines back into observation records, folds them through an alert-rule table in a Durable Object window, and pushes firing rules to a push channel. Development environment only. |
7. Architectural Invariants
Five hard invariants shape every component, and every increment is checked against them.
Development-only autonomy. The build loop deploys only to the development environment on the development branch. It never pushes the release branch and never touches production. Environment isolation is total — separate Worker, separate database, separate bucket, separate domain.
Large media never buffers through the Worker. Every large-object movement is a presigned GET or PUT. The browser uploads directly; the container pulls and pushes directly; the ASR provider fetches directly; every publish destination pulls directly.
Fail loud. State transitions are gated and there are no silent catches. Every failure becomes an
error row or a non-2xx response, and a ten-minute scheduled sweep marks silently-hung jobs as errored
so nothing fails invisibly.
Additive, flag-gated, byte-identical by default. Every new capability lands behind a default-off flag; routes for a disabled feature return 404; with all flags off a deployment is byte-identical to the prior one.
Single editing authority per project. Exactly one Durable Object owns the authoritative transcript and edit document, and every collaborative edit is serialized through it.
8. Edit Model & Collaboration
The transcript is the interface; the edit list is the data. Source media is immutable once uploaded. Every editing action — deleting words, pasting a passage, moving a passage, marking text ignored, renaming a speaker, shaving a pause, applying a filler-word pass, adding a marker, a video scene or caption or overlay operation, undo, redo — is an operation applied against the authoritative document held by the project's Durable Object.
The DO applies operations in arrival order, persists a snapshot plus undo/redo history to both relational storage and DO storage (so state survives hibernation), and broadcasts the result to every connected client. Because the DO is single-threaded and addressable by project id, ordering is a property of the runtime rather than something the application has to reconstruct.
Higher-level editing passes are derived rather than special-cased: speaker-aware cleanup (fillers, correct-all, de-stutter, per-host profiles), speaker-aware pause shaving, and boundary-aware cuts that collapse doubled flanking pauses all reduce to ordinary edit-list operations, which is why they compose with undo and with each other.
9. Media Plane
The media plane is deliberately disjoint from the control plane.
Upload. The browser requests a presigned PUT and uploads directly to object storage; large files use chunked multipart upload, which is what removed the request-size ceiling on full-length takes.
Transcode and analysis. The container downloads sources from object storage over presigned URLs, performs the work, and writes outputs back the same way. Streaming transcode handles large 32-bit float WAVs that would otherwise exhaust the Worker's memory ceiling in a buffered path.
Transcription. The ASR provider is handed a presigned GET per track and fetches the audio itself.
Export and publish. The render container writes the finished asset to object storage; a publish destination is given a presigned GET and pulls it. No relay, in either direction.
The practical consequence is that the Worker's outbound fetch budgets are all control-plane budgets. The separate long-lived data-plane budget that existed for the two publishers that did relay bytes now has zero members, and is retained only as a documented, deliberately-unreferenced constant so that a static gate cannot pass vacuously.
10. Transcription & Voice
Transcription runs in two durable Workflows selected by input type. A single uploaded file is chunked, transcribed by Workers AI Whisper, and stitched — no forced alignment. A multitrack recording, one microphone per speaker, goes through the multitrack Workflow, where AssemblyAI is the primary engine, submitted one presigned track URL at a time, with Workers AI Whisper as the fallback path. Speaker identity is carried by the track, so diarization is deliberately not used, and there is no streaming or real-time speech-to-text.
Voice generation is a separate concern. Overdub — clone a voice, then synthesize a correction in it — is live. The voice engine has since been abstracted behind a provider interface with two adapters and a selector, so the engine is a configuration choice rather than a code path: with the abstraction flag off, the legacy direct calls run unchanged; with it on, the selector-chosen adapter runs, and a request-parity test proves the incumbent adapter is byte-identical to the legacy path. The cutover is reversible by flag flip.
11. Render, Export & Publishing
Audio export is the mature path: enqueue a render, the Workflow drives the container to compose the mix from object storage against the edit list, apply loudness normalization to the selected delivery preset (−16, −14, or −24 LUFS), write the output, and record the export key. The container composes cuts using a concat-demuxer span list rather than a filter-graph split — roughly two orders of magnitude faster on a full-length episode, and the reason async export finishes in the time a producer will actually wait.
Video export is built and dev-exercised behind a flag. When the requested format is MP4 and the flag is on, the render Workflow runs a five-stage state machine: it plans per-source-span video-only encodes with a forced keyframe at each span start, runs them in bounded waves capped at the container instance limit, then stitches with a stream-copy concat — no re-encode — and muxes one continuous audio track separately, because per-segment audio would accumulate encoder priming drift at every seam. Both 1080p and 2160p are supported. The acceptance gate drives the shipped ffmpeg argument vectors through real ffmpeg/ffprobe and asserts frame-count integrity, a keyframe at every boundary, and audio/video sync within 40 ms at both resolutions. With the flag off, MP4 falls through to the unchanged synchronous path.
Publishing is built, dev-exercised, and dormant. A workspace owns pluggable destinations with per-destination presets. A publish request resolves and authorizes the caller's destinations, seeds one job row per target, and kicks the publish Workflow, which fans out concurrently: a no-op export target that simply mints a presigned link, alongside real host publishers that copy from object storage to the host via that link, alongside a webhook announcer that pushes a message carrying a presigned link rather than relaying bytes. Scheduling, history, and per-destination retry are complete.
The direction on publishing changed deliberately. The four per-platform social publishers were built, then demoted to fixtures, then deleted outright — each cleanup increment also removing its OAuth module and its durable status-poll loop, until the Workflow had no poll loop and no sleep step left at all. Three of those platforms are replaced by a unified multi-tenant aggregator, where the aggregator holds end-user tokens and absorbs platform verification; the fourth left with its fixture and has no replacement. The connect URL minting and the account-created webhook for the aggregator path are live; durable persistence of the parsed event is the next increment. Podcast hosts remain direct integrations.
12. Live Capture & Rooms
Remote recording is local-first by construction. During a session each participant's browser captures its own microphone — and, behind a flag, camera — and persists every chunk redundantly to local disk, object storage, and IndexedDB, with an optional off-main-thread spool. Capture durability therefore never depends on the network or on the live call surviving: the acceptance gate for this path kills the tab mid-recording and proves the take is resumed and finalized.
The call itself is separate. A member mints a scoped room token; a guest joins through a device pre-flight lobby with no account. Audio flows over the platform's SFU; the roster and lock authority live in the project's Durable Object, which also relays signaling. Participant video is built behind its own flag with conservative defaults — 640×360 at 24 fps, no simulcast, tiles capped — rendered in a gallery with active-speaker highlighting. Recorded per-participant camera takes attribute to stable slots and assemble into a time-aligned multitrack project, which is a hard gate in the regression set.
13. AI Consumer Layer
From a completed transcript, a set of optional consumers generate show notes, chapters, titles and descriptions, and highlight clips, each routed through a managed AI gateway to a different model vendor under bring-your-own-key — so the Worker holds a gateway token rather than provider credentials. Audiograms are rendered for audio-only episodes, a back catalog can be batch-transcribed, and the transcript is embedded into a vector index for semantic search. Every consumer is grounded on real word timings rather than a reflowed text blob, which is what makes a generated chapter mark land on the right second.
These consumers can run serially on demand, or — behind the fan-out flag — be seeded as one queued job row per consumer and dispatched concurrently by the pipeline Workflow, each reading the same immutable transcript spine rather than each other's output, each reporting into its own job row surfaced as a per-task chip in the UI.
14. Commercialization Surface
The product surface that turns the editor into a business is built, oracle-pinned, and dormant. It runs in the development environment and is absent — therefore off — in production.
Workspaces and identity. A membership model with widen-only admission exists alongside the live authorization gate. Workspaces are real tables and real routes; they currently enforce nothing, because the live gate remains an explicit allow-list.
Usage metering. A completed render contributes processed-media hours to a per-workspace ledger through
an idempotent writer, and a read path reports remaining monthly allowance. A pure evaluator classifies
usage as ok / warn80 / overage / blocked110 against 80 %, 100 % and 110 % thresholds, with a per-tier
overage-accrual function for the 100–110 % band and an admit decision that returns HTTP 402 at the ceiling.
This is not live enforcement. Nothing on the transcribe or render admit path consults the decision function, the usage endpoint returns a neutral zero-state, and the soft-warn seam is neutralized by a hard-coded zero allocation pending a deferred per-workspace attribution decision. No user experiences a 402, a 429, or an overage charge. The graduated model exists as pinned decision functions plus the meter UI — deliberately, so the economics can be reasoned about before they can bite anyone.
Pricing model. Usage-based — meter media hours, enforce usage and concurrency. Tier feature-gating was explicitly abandoned; its flag and predicate remain as obsolete leftovers that gate nothing and are scheduled for removal.
Billing. A payment-provider integration exists as a sandbox scaffold with its own migration and a webhook route that is deliberately exempted from the edge auth gate, in the same way the aggregator webhook is. Entitlement effects are not wired.
Public API. A member-authenticated key-management surface mints prefixed API keys, stored as SHA-256 hashes with only the last four characters retained and the plaintext returned exactly once. A non-interactive bearer guard and a per-tier rate-limit guard are written and pinned but deliberately unmounted, awaiting a dedicated API subdomain. A webhook module provides pure signing shapers — timestamped HMAC signature header, an event allow-list, a retry and backoff schedule — but no delivery call and no delivery table exist yet. This is the most dormant subsystem in the codebase, and it is documented as such rather than presented as a feature.
Lead capture and marketing. The Worker server-renders the product marketing landing, a usage-based pricing section, a login gateway, and a help centre, with a domain-aware default so the company domain serves a portal page and the product domain serves the product landing. The public lead endpoint is mounted ahead of the authenticated chain, validated by a pure normalizer, protected by a managed CAPTCHA that fails open where no secret is configured, and writes to a leads table. The re-skin that was originally flag-gated is now unconditional and is the sole design across marketing, portal, help, and editor; the gating flags were removed once it won.
15. Data Flow
- Ingest. The browser requests a presigned PUT and uploads source media directly to object storage, chunked for large files. A track row is written; no bytes pass through the Worker.
- Transcribe. The appropriate Workflow splits or submits the source, receives word-level timings, writes the word list to relational storage, and pushes it into the project's Durable Object, which broadcasts transcript-ready to every connected client.
- Edit. Members edit over WebSocket. Each operation is applied in order by the DO, persisted to a snapshot plus undo history, and broadcast. Source media is untouched.
- Export. An export request enqueues the render Workflow, which drives the container to compose the final mix or video from object storage against the edit list, normalize loudness to the delivery preset, write the output back to object storage, and record the export key on the job row. The client polls the job.
- Consume. On a completed transcript, the AI consumers generate notes, chapters, titles, clips, and embeddings — serially on demand, or concurrently through the fan-out Workflow.
- Publish. A publish request resolves destinations, seeds one job row per target, and fans out; each destination pulls the finished asset from a presigned link, or is announced with one.
- Share. A read-only public transcript link is minted against a share token, served without the editor's cross-origin isolation headers and without authentication.
16. Data Model
Relational store (Cloudflare D1) — projects, members, words, edit snapshots and versions, jobs, tracks, recordings, markers, share tokens, and per-host profiles form the live core. The productization tables sit alongside them: workspaces and workspace members, the media-usage ledger, subscriptions, publish destinations and publish jobs, API keys, leads, producer runs, and the episode-preset store. Seventeen forward migrations; a schema-contract check runs on every deploy and fails the build if the deployed schema drifts from the checked-in definition.
Object storage (R2) — all media, prefixed per project: source tracks, per-chunk recording segments, analysis sidecars, and finished exports. Immutable sources; outputs written once.
Vector index — transcript embeddings, 768-dimension cosine, one index per environment.
Durable Object storage — edit history for undo/redo, the room signing secret, the room roster, and the single pending scheduled publish. This is the state that must survive hibernation without a round trip to the relational store.
Known debt. The word list lives in the relational store, which is the wrong long-term home for it at back-catalog scale; the first step of the migration is a hot/cold transcript store behind its own flag.
17. External Interfaces
| Interface | Direction | Purpose | Auth |
|---|---|---|---|
| AssemblyAI | Outbound | Primary multitrack transcription; fetches audio from a presigned link | Provider API key (Worker secret) |
| Platform Workers AI | Outbound | Whisper fallback ASR and text embeddings | Platform binding |
| Managed AI gateway | Outbound | Routed access to three LLM vendors for notes, chapters, titles, and clips | Gateway token; provider keys held bring-your-own-key inside the gateway, never in the Worker |
| Voice providers (2 adapters) | Outbound | Voice clone and synthesis for overdub — the incumbent engine plus a lower-cost alternative behind one interface | Provider API key (Worker secret) |
| Realtime SFU + TURN | Bidirectional | Live audio and participant video | Dedicated platform credentials |
| Object storage S3 API | Outbound | Presigning GET/PUT for the media plane | Scoped access key pair (Worker secret) |
| Podcast host APIs (×3) | Outbound | Publish finished episode assets, pulled from a presigned link | Per-destination API key; fail-closed when absent |
| Publish aggregator | Outbound + inbound webhook | Multi-tenant social publishing; connect-URL minting and an account-created webhook | Per-user connect flow; shared-secret webhook verification |
| Payment provider | Inbound webhook | Subscription lifecycle | Signed webhook, exempted from the edge auth gate by design |
| Managed CAPTCHA | Outbound | Lead-form anti-abuse | Site secret; fails open where unset |
| Transactional email | Outbound | Lead notification | Platform binding; no-op until a recipient is configured |
18. Reliability, Observability & Alerting
Durability. Edit state is triple-anchored — in memory, in a relational snapshot, and in Durable Object storage — so it survives hibernation and eviction. Recording is triple-redundant per chunk and resumable after a crash. Workflows are checkpointed and step-retryable, and the video render's stage machine is fail-closed. A scheduled sweep converts silently-stuck jobs into loud error rows every ten minutes.
Cross-origin isolation. COOP and COEP are injected on the editor HTML document only — not on the guest
join path, the API, public share links, or the marketing shells — which scopes SharedArrayBuffer and
crossOriginIsolated to where the editor needs AudioWorklet and WebAssembly without breaking guest capture,
edge auth, or the public surfaces.
Observability. Structured JSON logging throughout, platform observability enabled in both environments, push alerts for build-loop escalations, and a live smoke test on every deploy that asserts the auth redirect for an unauthenticated request, the isolation headers on an authenticated one, and an API round-trip.
Alerting. A second Worker service is bound as a tail consumer of the app Worker — a separate service is required by the platform's tail contract, and it also prevents the log-amplification loop a self-tailing Worker would create. Each traced invocation's structured log lines are harvested back into canonical observation records and folded through a rule table for three conditions: render error rate, Workflow failure burst, and container out-of-memory.
The interesting part is what live measurement changed. Tail batches arrived at size one — one invocation per traced request — so a per-batch in-memory buffer could never accumulate the three failures a burst rule needs. The path was live and correct but useless. Counts therefore moved into a Durable Object owned by the tail service itself, where one named instance serializes the read-modify-write so concurrent batches cannot lose increments the way an eventually-consistent store would. The stored state is counts only — per-rule, one-minute-bucketed pairs, bounded by constants — so no record payload is ever persisted.
Delivery closes the loop: a firing verdict is pushed to the same channel the build loop escalates on. The shaping is a pure leaf that carries the rule id and its counts and nothing else, so a payload cannot leak out of the alert path by construction. De-duplication is what makes it usable — verdicts are folded against a last-notified marker and a rule pushes at most once per thirty minutes, a rule that stops firing drops its marker so a resolved-then-refiring condition pages immediately, and a marker in the future self-heals rather than suppressing forever. Every layer is fail-soft: no topic, no binding, a failed load, a non-2xx push, or a failed save each degrade to the log line, which is emitted unconditionally either way. This whole path exists only in the development environment; production declares no tail consumer.
19. Code-Health Gates
Four engineering sweeps each hardened an entire class of hazard across the source tree and then left behind a self-maintaining tree-wide oracle rather than a fixed allow-list. The shared cadence is: measure the whole tree, pin every member, then invert the census into a rule that a new violation trips without anyone updating a count.
- No bare container dispatch. All 23 container dispatches across 6 files go warm-then-resilient, so a cold-start race can never surface as a user-visible 5xx. The gate asserts that no bare dispatch exists anywhere in the tree, and is guarded against passing vacuously.
- No unbounded external egress. All 20 non-container fetch sites across 11 files are abort-signal bounded on one of four call-path-derived budget tiers. The gate asserts no unbounded external fetch anywhere. It deliberately added no retries — re-firing a paid provider call is a cost and UX decision, not an engineering one.
- No undecided unreferenced symbol. A static census of 1,592 top-level declarations across 166 files partitioned the 57 unreferenced ones by citation polarity and module reachability; ten increments ran the orphan work list to empty. The census now stands as a forward gate that fails the moment a new orphan appears, named by file and symbol.
- No silent catch. A census of the three swallowed-failure shapes pinned the boundary at 24 sites across 13 files; four burn-down tranches made every actionable swallow loud-but-non-fatal via a log breadcrumb, with the happy path byte-identical. The gate is set-valued, so a regression names the offender by file, line, and shape.
These run in the same offline regression set as the feature oracles and are pure static or behavioural checks — they change no route, flag, Durable Object, Workflow, endpoint, table, or integration, so they are production byte-identical by construction.
20. Non-Functional Requirements
| NFR | Target | Basis |
|---|---|---|
| Media through the control plane | Zero bytes | Architectural invariant; enforced by the fetch-budget census, whose data-plane tier now has no members |
| Worker memory headroom | Never approach the 128 MB isolate ceiling | Streaming transcode and presigned transfer; the buffered path that caused isolate OOM on 700 MB float WAVs was removed |
| Export composition | Concat-demuxer span list rather than filter-graph split | ≈100× faster on a full-length episode; the rejected approach was measured, not assumed |
| Video A/V sync | |video − audio| < 40 ms at 1080p and 2160p | Asserted by an end-to-end gate driving the shipped ffmpeg argument vectors through real ffmpeg/ffprobe |
| Video segment integrity | Keyframe at every span boundary; frame-count preserved | Same gate; stream-copy stitch means no re-encode drift |
| Capture durability | A SIGKILL'd take is resumed and finalized | Kill-tab acceptance gate; three redundant chunk sinks |
| Deployment safety | All flags off ⇒ byte-identical deployment | Additive flag discipline; disabled routes 404 |
| Schema integrity | Deployed schema matches the checked-in definition | Schema-contract check gates every deploy |
| Storage cost | Order of a few dollars per month for a year of episodes plus raw masters | Zero egress fees; storage-only pricing |
| Proven end-to-end scale | A 51-minute episode rendered from two ~700 MB 32-bit float source tracks | Reference episode, exercised repeatedly |
21. Tech Stack
| Layer | Technology | Role |
|---|---|---|
| Control plane | Cloudflare Workers (TypeScript, Hono) | API, auth, SPA and marketing shells, orchestration |
| Stateful authority | Durable Objects ×4 | Edit document and rooms, render container, batch pacing, scheduled publish |
| Orchestration | Cloudflare Workflows ×6 | Transcribe, transcribe-tracks, render, pipeline, publish, producer runs |
| Media compute | Cloudflare Containers (CPU) + ffmpeg | Transcode, mix, enhancement chain, analysis sidecars, segment-parallel video render |
| Relational | Cloudflare D1 | Projects, transcripts, edits, jobs, and the productization tables (17 migrations) |
| Object storage | Cloudflare R2 | All media; presigned GET/PUT only |
| Vector | Cloudflare Vectorize | 768-dimension transcript embeddings for semantic search |
| Inference | Workers AI + a managed AI gateway | Whisper ASR and embeddings; routed access to three LLM vendors under BYOK |
| Realtime | Cloudflare Realtime (SFU + TURN) | Live audio and participant video |
| Frontend | React + Vite, served as Worker assets | Project list, editor, guest join |
| Auth | Cloudflare Access + in-Worker membership check | Members, service-token automation; DO-signed tokens for guests |
| Secrets | Worker secrets + a platform secrets store; external vault of record | No provider key in source; LLM keys held inside the gateway |
| CI/CD | GitHub Actions | Typecheck, deploy, schema-contract check, live smoke, advisory security scan |
22. Security & Compliance
Identity and authorization. A managed zero-trust gate sits in front of the API and the editor SPA, presenting a trusted JWT at the edge, backed by an in-Worker membership check. Guests receive a synthetic principal minted from a Durable-Object-signed room token, restricted by allow-list to capture, room-verify, and ICE endpoints and to a capture-capable role. Automation maps to a synthetic smoke identity via a service token. An optional, default-absent internal secret admits a producer self-call as an additional principal through a short-lived HMAC token that resolves to the run's own creator — absent by default, therefore inert, therefore byte-identical.
Deliberate holes, enumerated. The trust boundary has four openings, each intentional and each documented: account-less guest capture, public read-only transcript share links, the payment webhook, and the public lead endpoint. Enumerating them is the point — an undocumented hole is an incident; a documented one is a design.
Credential handling. Provider API keys never live in the Worker for LLM access — the gateway holds them bring-your-own-key and the Worker holds only a gateway token. Object-storage presigning and realtime credentials use dedicated scoped secrets. Publish-host, payment, CAPTCHA, and email secrets are set as Worker secrets or through a platform secrets store and fail closed when absent. The dormant public-API bearer path hashes keys with SHA-256 and never stores plaintext.
Security scanning. An advisory static-analysis, secrets-detection, and dependency-audit track runs locally and in CI on the development branch. It reports but never gates the development deploy, because a blocking scan on an autonomous loop stalls the loop. A genuine live-credential finding escalates to a human rather than being auto-remediated. Blocking scan gates are scheduled to apply from the QA phase of the planned promotion pipeline onward.
Honest limitation. The explicit allow-list is still the sole live authorization gate. Workspaces exist as tables and routes but enforce nothing today. That is stated here rather than implied away.
23. Deployment & Operations
Two fully isolated environments are declared in a single configuration file — separate Worker, database, bucket, vector index, and domain — sharing the same code, the four Durable Object classes, the Workflows, the inference and container bindings, the auth allow-list, and the ten-minute sweep.
| Concern | Production | Development |
|---|---|---|
| Worker | Top-level service | Environment-scoped service |
| Relational / object / vector | Dedicated per environment | Dedicated per environment |
| Feature flags | Core loop, consumers, rooms, passthrough export only | Core loop plus the full productization surface |
| Tail / alerting consumer | None declared — path unreachable | Bound to the alerting service |
| Deploy trigger | Manual dispatch only | Push to the development branch |
The two environments do not carry the same flag set, and that is the operational point rather than an oversight: production cut over to the core loop and has deliberately not been advanced with the later productization sprints.
Deploy pipeline. A push to the development branch runs typecheck, deploys, then runs a schema-contract check that fails the build if the deployed schema has drifted from the checked-in definition — the gate that makes environment drift a hard error rather than a slow mystery — followed by a live smoke test where credentials are present. The build loop verifies its own deploys by calling a version endpoint with a service token.
Planned promotion pipeline. The current model is development-only by invariant. The directed future model is a gated promotion pipeline — development build → QA/UAT with security and functional verification → pre-production regression and green-gate verification → production on a merge to the release branch, with pre-deploy security validation, schema contract, and smoke. It is deliberately not built yet and is human-gated: the loop must not introduce production automation until the development-only invariant is consciously relaxed.
24. Cross-Project Context
The Broken Handle. Calaite exists because The Broken Handle needed it. The podcast is the reference workload — a weekly two-host conversation with remote guests, long-form takes, and a publishing cadence that does not forgive a five-hour edit. The show's own research pipeline and this editor share a platform and a set of design instincts (serverless, cron-driven, zero-egress storage) but no code. Production still runs on the show's domain; the product domain currently serves the development environment and the marketing surface.
Isobaric Labs. The company layer. The Worker is domain-aware: the company domain serves a portal page, the product domain serves the product. That is one deployment, not two sites.
25. Risks, Assumptions & Limitations
- The dormant surface is a liability as well as an asset. Workspaces, metering, billing, publishing, and the public API are built but enforce nothing. Every one of them is code that must keep compiling and keep passing gates while returning nothing to a user. The mitigation is the flag discipline and the gates; the cost is real.
- Usage enforcement is not live. No admit path consults the decision function and the usage endpoint returns a neutral zero-state. Until per-workspace attribution is decided, the graduated model cannot bite — which also means it cannot protect margin.
- Provider dependency on ASR quality and price. Word-level timing accuracy is load-bearing for the edit model. The fallback engine degrades quality rather than stopping the loop, and the self-hosted GPU path is held as future state pending volume.
- Video export needs a production flag flip, not more building. It is dev-exercised and gate-proven; the remaining work is promotion, which the planned pipeline gates.
- CPU-only render. The container is CPU-bound with a capped instance count. Segment-parallel encoding buys throughput, but 4K video render remains the workload most likely to need a larger container class.
- Transcript storage. The word list on the relational store is known debt at back-catalog scale; the hot/cold store is the first step and is not yet the default.
- Documentation and resource-name drift. Cloudflare resource names still carry the pre-rebrand identifiers and are deliberately not renamed — renaming live bindings is a migration, not a rename. The reconciliation is tracked as debt rather than hidden.
- Single-region assumptions. Nothing in the design is region-pinned, but nothing has been exercised under a multi-region access pattern either.
26. Roadmap
Near term — graduate what is already proven. Flip video export to production behind the promotion pipeline; persist the aggregator's account-created events into destinations and finish the connected-accounts surface; wire usage enforcement to a real per-workspace allocation source so metering has an effect.
Next — stand up the promotion pipeline. Development → QA/UAT → pre-production → production, with blocking security and regression gates from QA onward. This is the prerequisite for relaxing the development-only invariant safely, and it is the gate on everything else reaching users.
Then — make the platform layer real. Enforce workspace membership, wire billing entitlement effects, mount the public API's bearer and rate-limit guards on a dedicated subdomain, and implement webhook delivery with a delivery table behind it.
Ongoing — pay down the named debt. Move the word list off the relational store via the hot/cold transcript store, retire the obsolete tier-gating flag, store a real vertical-short render key so social publishing stops falling back to the full export, and reconcile the resource names with the brand.