BurstMedia engineering plan
Status: proposed implementation sequence, 2026-10-29. The public site is an informational surface; media delivery is not implemented. Read with SPEC.md. This plan extends the original STBS-only proposal to free content and shared BurstPay commerce.
Product and ownership
Publish video, music, podcasts, images and downloadable multimedia collections. A release binds immutable resources, accessible descriptions/captions, rights, a license and an access mode. Free public, free signed-in, private, preview and paid are distinct modes; discovery visibility never grants private source access. Anonymous delivery requires explicit publication and a narrowly scoped public policy, without granting an anonymous caller general space access.
| Surface | Responsibility |
|---|---|
| goburst.media | Public discovery, creator information and eventually public release pages/playback |
| goburst.app | Existing OIDC account, creator studio, purchases, private library and operations |
| goburst.dev | API, player integration, deployment and engineering documentation |
| goburst.network | Ecosystem and network architecture |
| Desktop | Shared web UI in a proposed Tauri wrapper; capabilities restricted to required native commands |
Start browser-first. Add installable PWA behavior after playback works. Add signed desktop builds when OS-specific playback, system-browser login, deep links and secure credential storage pass acceptance. Desktop uses a public OIDC client with PKCE or a reviewed one-use account handoff; it must not copy browser cookies or embed client secrets. Keep remote creator content outside privileged desktop IPC. Online authority remains required for protected playback initially; offline licenses are separate future work.
Technology and delivery path
Use the existing Go control host for media metadata, sessions and authorization, with separate bounded processing workers and a streaming delivery gateway. Reuse the current JavaScript/CSS interface and self-hosted fonts. PostgreSQL is the proposed production metadata store, SQLite the local option. Existing authority transactions serialize operations; benchmark that constraint before claiming concurrent production scale. Keep media bytes, transcoding and provider HTTP calls outside long metadata transactions.
Start HLS with fragmented MP4/CMAF, H.264/AAC video, AAC audio and WebVTT captions. Use native HLS when available and hls.js otherwise; detect support and offer an explicit unsupported state. Offer authorized originals and image derivatives separately. Propose 360p/720p/1080p profiles capped at source size and 4-second segments; benchmark before fixing the ladder. Pin FFmpeg builds, record codec/profile versions and run ffprobe/FFmpeg inside the bounded worker. Validate actual output, duration and checksums; reject playlist references or attachments that could cause external fetches. No ambient worker egress.
Flow: encrypted upload → asset validation → durable job → fenced worker → verified encrypted renditions → immutable release → session authorization → bounded gateway streaming → durable usage → BurstPay reconciliation.
The existing object-read implementation is not automatically a seekable streaming store. First prove bounded memory and authenticated chunk/range reads; add an adapter before exposing large media. Keep encrypted replicas/caches distinct from explicitly trusted plaintext-serving gateways. No public plaintext cache for paid objects. Gateway sessions map only to approved rendition resources; rewrite manifest references, including keys and initialization segments, into guarded routes.
Serve paid playback initially on goburst.app with its existing host-only session. goburst.media links there. Later anonymous/public playback can use explicitly public delivery routes; embedded paid playback needs a separate reviewed ticket/origin design. Do not widen cookies across domains. The current static-site CSP intentionally cannot play remote media; update media-src/connect-src only when real delivery is integrated.
Shared commerce contract
BurstMedia owns releases, license acceptance, access eligibility, entitlements and delivery sessions. BurstPay owns offers/quotes, provider attempts, orders, refunds, ledger and payouts. Preserve media-specific quote commitments and STBS escrow semantics through a versioned payment adapter. Do not build a second ledger or let payment override policy.
Current blockers found in code: checkout in burst/internal/control/commerce.go loads a dataset request; stripeWebhook routes all verified payments to datasets.ApplyPayment. burstpay.NewOrder requires a product request but has no typed product binding. Extend these with a validated product kind, release/license/version commitment and product settlement dispatcher. Preserve existing dataset behavior and tests. Payment application, entitlement update and outbox must share one host transaction; delayed/duplicate refunds must never resurrect access.
| Model | Sequence and dependency |
|---|---|
| Free publication and previews | First vertical slice; no wallet or payment configuration |
| One-time purchase/rental and bundles | Shared BurstPay; Stripe test acceptance first, STBS after finality indexer acceptance |
| Subscriptions/memberships | Explicit paid periods, expiry, cancellation and renewal failure policy |
| Tips | Separate receipt; never silently grant a content license |
| Metered consumption | Trusted usage, versioned rates, spending caps and invoice reconciliation |
| Advertising/sponsorship | Later: inventory, consent, fraud controls and independently reconciled impressions |
| Creator revenue splits | Versioned recipient shares, deterministic rounding, refunds and provider-supported payouts |
Operator-owned test sales can use existing Stripe foundations. Third-party creator cash payouts need seller onboarding and Connect (or another explicit payout provider); current gross ledger credits are not withdrawable proceeds. Fiat and STBS remain separate assets and ledgers. No automatic exchange rate or conversion.
Metering that can support money
Separate operational telemetry, estimated audience analytics and billable facts. Client play/pause/heartbeat events help QoE but never independently generate invoices, ad revenue or rewards. Server bytes mean bytes handed to the transport, not proof a human watched them.
| Meter | Trusted boundary | Billing treatment |
|---|---|---|
| Storage byte-hours | Durable object inventory over time | Creator hosting cost; distinguish replicas from logical bytes |
| Processing milliseconds | Worker result with fenced attempt/profile | Count physical retries as operational cost; charge logical successful job once unless terms explicitly differ |
| Egress bytes | Gateway write accounting | Operational cost includes retransmission; viewer charges use the explicit logical-range rule below |
| Unique prepared segment bytes | Durable reservation before response | Conservative quota only; not proof of delivery |
| Playback seconds | Client reports plus server diagnostics | Analytics estimate initially; no watch-time billing |
| Payment and revenue | Verified BurstPay settlement/refund | Per currency, order and immutable fee/split version |
Each usage fact binds tenant, producer, session, release/rendition revision, resource, range, logical operation ID, unit, quantity, occurrence time, price revision and correction reference. Producer identities are authenticated. Never store bearer session secrets in metrics labels. Persist immutable facts and a deduplicated outbox; enforce unique producer/meter/event identities and reject conflicting replays. Keep financial dimensions out of high-cardinality Prometheus labels; use indexed usage tables/rollups.
Reserve bounded byte/spend quota before each response window. Record actual gateway writes afterward; a crash leaves an unresolved reservation, not invented delivered bytes. Reconcile it conservatively for quota and hold disputed usage out of invoices. Stop new billable windows when durable accounting fails or unreported-usage caps are reached. A single whole-file reservation is insufficient for long downloads. Do not write every packet into the control authority transaction.
Proposed viewer-byte billing counts the union of authorized byte intervals per logical playback, resource version and billing period, so overlapping ranges/retries do not double-charge. A new logical playback can be billed separately only under disclosed terms. Gateway-generated attempt IDs record transport attempts; server-issued playback IDs define logical deduplication. Price changes never alter an active price snapshot. Define UTC periods, late-event cutoff, retention covering reconciliation, invoice finalization and append-only corrections before activation. Provider ingestion is asynchronous; reconcile provider totals against internal rollups.
Performance budgets and capacity
These are proposed acceptance targets, not measured results: warm session creation p95 ≤150 ms; warm segment time-to-first-byte p95 ≤100 ms in-region; playback startup p95 ≤2 seconds on a controlled 20 Mbps/50 ms RTT link; rebuffer ratio <1%; active authorization staleness ≤60 seconds. Report cold startup separately. Long downloads need periodic authority checks and cancellation by that deadline. Missing fresh authority denies further protected delivery.
First load gate: 100 concurrent 3 Mbps viewers for 30 minutes, including seeking, slow readers, invalid sessions and revocation. This is 300 Mbps payload and approximately 135 GB/hour decimal egress before overhead. At 1,000 viewers it becomes 3 Gbps and 1.35 TB/hour. Record hardware, rendition mix, cache hit rate, DB wait/lock time, CPU, RSS, queue depth, errors and p50/p95/p99. Memory must scale with configured stream buffers/concurrency rather than object size. Derive cost per watched hour from egress, storage, processing and payment fees before setting prices.
Keep payment providers and Ethereum off the segment request path. Begin with one regional gateway and bounded caches. Scale gateways only after shared quota, revocation and usage consistency pass multi-instance tests. Adopt a broker or analytical store only when measured outbox/rollup load needs it.
Build sequence and acceptance
| Phase | Concrete result | Required evidence |
|---|---|---|
| 0 | Module, scoped records, access modes and shared payment binding | SQLite/PostgreSQL parity, current authority on retries, tenant denial, immutable versions, existing commerce regression |
| 1 | Upload → actual transcode → free authenticated playback/download | Real FFmpeg fixture, hostile/truncated input rejection, sandbox bounds, fenced crash recovery, durable outputs, browser seek/caption playback |
| 2 | Durable meters and quotas | Duplicate/overlapping range tests, abort/crash reconciliation, accounting outage denial, cap concurrency and 100-viewer load report |
| 3 | One-time purchase → entitlement → playback → refund | Product-dispatched Stripe test flow; STBS separately proves indexer finality/reorg/replay/refund; no private source bypass |
| 4 | Creator studio, public releases, library and desktop | Keyboard/mobile/browser matrix, real OIDC, anonymous public boundaries, signed desktop/package/update acceptance |
| 5 | Subscriptions, creator payouts and advanced monetization | Paid-period renewal failure, provider reconciliation, recipient/refund splits, seller onboarding and invoice corrections |
| 6 | Production acceptance | Backup/restore with deletion replay, custody rotation, queue/disk exhaustion, recovery drills and recorded capacity/cost |
Every phase must introduce an executable gate and record actual results before completion. Proposed gate names: scripts/test-media.sh for domain/integration, scripts/test-media-processing.sh for real sandbox work, and scripts/load-media.sh for reproducible capacity. These commands do not exist yet. Existing scripts/test-commerce.sh remains the shared regression gate.
Next implementation: phase 0 plus phase 1 free playback. It exercises the hardest delivery path before charging anyone. Economic activation requires explicit fee/refund/seller configuration; free playback development can proceed independently.