every.channel
  • Rust 66.7%
  • Python 10.5%
  • Nix 8.1%
  • JavaScript 7.7%
  • Shell 4.5%
  • Other 2.4%
Find a file
Conrad Kramer c763149caa
Some checks failed
ci-gates / checks (push) Failing after 0s
deploy-cloudflare / checks (push) Failing after 0s
deploy-cloudflare / deploy (push) Has been skipped
MoQ E2E working: relay fleet 0.14.3 + three publisher-side fixes
Relay fleet (deploy/fly-relay/, new): moq-relay 0.11.0 -> 0.14.3 on all
four Fly apps, image grafts the crates.io binary onto the digest-pinned
Jul 20 relay-stack base (keeps ec-node/tailscale/entrypoint). Deploy kit
recovered into the repo; scripts/deploy-fly-relay.sh builds once and
rolls the fleet. -a is mandatory: flyctl-repo.sh injects the site app
otherwise (caused a brief site outage, restored from prior release).

Publisher/subscriber fixes, each verified live against the new fleet:
- DNS: prefer IPv4 (Fly UDP anycast is IPv4-only; AAAA-first lookups
  black-holed QUIC connects). Sessions now negotiate moq-lite-05.
- Origin identity: origin::Info::default() is Origin::UNKNOWN (id 0);
  publisher + subscriber sharing it made loop detection drop our own
  announces as reflected. Every session now gets Origin::random().
- fMP4 import: ContainerStream::decode takes incremental bytes in 0.9
  (0.4 consumed from an accumulated buffer); re-feeding the buffer
  duplicated the stream and no media group was ever published. This was
  the root cause of every player stalling after the catalog.

Proven: wt-archive pulls media groups over lite-05; the site's
moq-watch 0.4.1 subscribes 0.m4s and decodes; frames arrive at the
live edge (~166ms cadence). Rendering verified gated only on page
visibility (test pane is a hidden surface; real browsers paint).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 21:42:00 -07:00
.claude Adapt split netboot fetch to systemd stage-1 2026-07-08 20:53:51 -07:00
.forgejo/workflows Allow direct Cloudflare deploy token 2026-06-10 04:10:12 -07:00
apps MoQ 0.9 followups: announce route, catalog keepalive, player 0.4.1 2026-07-26 15:34:31 -07:00
contracts Advance forge rollout, Ethereum rails, and NBC sources 2026-04-01 15:58:49 -07:00
crates MoQ E2E working: relay fleet 0.14.3 + three publisher-side fixes 2026-07-26 21:42:00 -07:00
deploy MoQ E2E working: relay fleet 0.14.3 + three publisher-side fixes 2026-07-26 21:42:00 -07:00
docs Document verified multi-producer channel semantics 2026-07-16 22:16:59 -07:00
evolution/proposals ECP-0041: the Mac app as a first-class peer node 2026-07-19 20:40:33 -07:00
intake Advance forge rollout, Ethereum rails, and NBC sources 2026-04-01 15:58:49 -07:00
nix Auto-update: tauri-plugin-updater end to end (minisign, forge-signed) 2026-07-26 04:37:33 -07:00
patches Developer ID signing via Google Cloud KMS (no key file anywhere) 2026-07-25 20:25:54 -07:00
scripts MoQ E2E working: relay fleet 0.14.3 + three publisher-side fixes 2026-07-26 21:42:00 -07:00
secrets Auto-update: tauri-plugin-updater end to end (minisign, forge-signed) 2026-07-26 04:37:33 -07:00
third_party Advance forge rollout, Ethereum rails, and NBC sources 2026-04-01 15:58:49 -07:00
.dockerignore Recover Fly site deploy into the repo 2026-07-09 16:31:23 -07:00
.envrc ec-node: WebTransport publish + web hang-watch 2026-02-16 12:54:42 -05:00
.gitignore Add repo-scoped Fly CLI auth 2026-07-06 01:36:07 -07:00
AGENTS.md every.channel: sanitized baseline 2026-02-15 16:17:27 -05:00
Cargo.lock MoQ generation upgrade: moq-mux 0.9 + moq-net 0.2 (was 0.4 + moq-lite) 2026-07-26 15:00:34 -07:00
Cargo.toml Add ec-cas: xorb/shard content-addressed archival packing 2026-07-10 02:25:27 -07:00
CONSTITUTION.md every.channel: sanitized baseline 2026-02-15 16:17:27 -05:00
CONTRIBUTORS.md every.channel: sanitized baseline 2026-02-15 16:17:27 -05:00
flake.lock Restore production watch and netboot operations 2026-07-08 00:12:39 -07:00
flake.nix rcodesignPkcs11: wrap with openssl/opensc + pkcs11-provider modules 2026-07-25 20:38:16 -07:00
foundry.toml Advance forge rollout, Ethereum rails, and NBC sources 2026-04-01 15:58:49 -07:00
justfile Advance forge rollout, Ethereum rails, and NBC sources 2026-04-01 15:58:49 -07:00
LICENSE every.channel: sanitized baseline 2026-02-15 16:17:27 -05:00
README.md Speed up station guide startup 2026-06-10 02:34:44 -07:00
secrets.nix Auto-update: tauri-plugin-updater end to end (minisign, forge-signed) 2026-07-26 04:37:33 -07:00

every.channel

A global, disaggregated mesh of relays that turns local ATSC antennas into a coherent, worldwide stream. The stack is Rust-first, MoQ-native, and designed for deterministic chunking so identical broadcasts yield identical data.

Goals

  • Free, global access to broadcast TV through user-run relays.
  • Deterministic encoding and chunking to make availability a coordination problem.
  • Clean layering: capture -> transcode -> MoQ publish -> relay -> client playback.
  • Cross-platform clients: Tauri app, CLI, and a static web UI.

Repository layout

  • crates/ec-core: shared types and determinism profiles.
  • crates/ec-hdhomerun: HDHomeRun discovery and lineup scaffolding.
  • crates/ec-linux-iptv: Linux DVB ingest scaffolding.
  • crates/ec-iroh: iroh transport scaffolding.
  • crates/ec-crypto: stream key derivation helpers.
  • crates/ec-eth: Ethereum-compatible protocol representations and commitments.
  • crates/ec-ts: MPEG-TS timing and table parsing.
  • crates/ec-chopper: deterministic ffmpeg chunking scaffolding.
  • crates/ec-moq: MoQ data model and relay scaffolding.
  • crates/ec-node: node runner (ingest + publish).
  • crates/ec-cli: CLI for discovery and node control.
  • apps/tauri: desktop client shell.
  • apps/tauri/ui: Dioxus web frontend embedded in the Tauri app.
  • docs/USAGE.md: runbook for viewer and ingest pipelines.
  • docs/IROH_EXAMPLES.md: summary of iroh repos/examples used for design.
  • docs/: architecture, roadmap, and MoQ notes.
  • contracts/: Solidity contracts for compact private-chain settlement rails.

Development

Nix:

nix develop

Rust:

cargo build

Runbook:

cat docs/USAGE.md

Git hosting topology:

cat docs/GIT_HOSTING.md

Sovereign forge deploy:

cat docs/DEPLOY_ECP_FORGE.md

OP Stack ecp-forge runbook:

cat docs/OP_STACK_ECP_FORGE.md

NUC PXE rollout (UniFi-only or ProxyDHCP):

cat docs/NUC_UNIFI_NETBOOT.md

WebTransport Watch (MoQ)

Publish (node -> Cloudflare relay):

cargo run -p ec-node -- wt-publish \
  --url https://relay.every.channel/anon \
  --name la-nbc \
  --input http://<hdhr-host>/auto/v4.1 \
  --control-announce \
  --control-endpoint-addr-out /tmp/la-nbc-control-endpoint.json

wt-publish defaults to --passthrough=true so relay and archive retain exact CMAF fragment bytes.

Watch (web):

https://every.channel/watch?url=https%3A%2F%2Frelay.every.channel%2Fanon&name=la-nbc

Archive (relay -> CAS objects + JSONL manifests):

cargo run -p ec-node -- wt-archive \
  --url https://relay.every.channel/anon \
  --name la-nbc \
  --output-dir /tank/every-channel/archive \
  --manifest-dir /var/lib/every-channel/manifests

Replay server (archive -> HLS DVR endpoints):

cargo run -p ec-node -- wt-archive-serve \
  --output-dir /tank/every-channel/archive \
  --manifest-dir /var/lib/every-channel/manifests \
  --listen 0.0.0.0:7788

Control protocol (iroh gossip, relay + direct transport discovery):

# Listener (on node A)
cargo run -p ec-node -- control-listen --gossip-peer <node-b-endpoint-addr-json>

# Announcer (on node B)
cargo run -p ec-node -- control-announce \
  --stream-id la-nbc \
  --relay-url https://relay.every.channel/anon \
  --relay-broadcast la-nbc \
  --gossip-peer <node-a-endpoint-addr-json>

# Resolver (consumer picks best announced path)
cargo run -p ec-node -- control-resolve \
  --stream-id la-nbc \
  --prefer direct-first \
  --gossip-peer <node-a-endpoint-addr-json>

# Bridge iroh control announcements to every.channel public web list
EVERY_CHANNEL_WEB_UPSERT_TOKEN=<token> \
cargo run -p ec-node -- control-bridge-web \
  --directory-url https://every.channel \
  --gossip-peer <node-a-endpoint-addr-json>

wt-publish, control-announce, control-listen, control-resolve, and control-bridge-web print both control endpoint id and control endpoint addr on startup. Use the endpoint addr JSON for --gossip-peer when bootstrapping.

Default discovery identity:

  • If you pass --stream-id, that exact value is announced.
  • If you do not pass --stream-id, ec-node now prefers a broadcast-scoped ID when the selected channel exposes usable broadcast metadata. HDHomeRun sources also probe early TS packets to fill missing tsid / program_number, and raw TS inputs can derive identity directly from PAT data.
  • ATSC PSIP parsing now covers MGT, TVCT/CVCT, STT, RRT, EIT, and ETT. EIT and ETT are accepted on the PIDs advertised by MGT, not only on the base PSIP PID 0x1FFB.
  • Discovery identity currently consumes PAT plus VCT data. RRT, EIT, ETT, and full STT parsing are available for inspection and future policy, but they do not currently change the default dedupe key beyond the existing broadcast identity fields.
  • PAT-derived promotion is intentionally conservative: only single-program streams are promoted. If the probe sees multiple non-zero programs, ec-node does not guess and keeps the stream source-scoped.
  • Sources without usable broadcast metadata still fall back to source-scoped IDs.

Ethereum rails:

  • ec-node keeps BLAKE3 manifest_ids and merkle+blake3 object proofs on the wire, and also emits Ethereum-compatible ABI commitments for settlement.
  • Manifests can now carry both local Ed25519 signatures and optional secp256k1 EIP-712 signatures over ManifestBody. Set EVERY_CHANNEL_MANIFEST_SIGNING_KEY for the local signer and EVERY_CHANNEL_ETH_MANIFEST_SIGNING_KEY for the Ethereum-native signer.
  • Stream descriptors and iroh control announcements now carry Keccak commitments so broadcast identity, discovery, and manifest settlement share one vocabulary.
  • The new contracts/EveryChannelRail.sol contract is intentionally storage-light: it stores only latest commitment pointers, while full manifests and media stay off-chain on iroh/relays/archive.
  • Observation consensus now has dedicated Solidity surfaces: contracts/EveryChannelWitnessRegistry.sol and contracts/EveryChannelObservationLedger.sol.
  • scripts/op-stack/anvil-reality-smoke.sh validates the observation rail against real archive data pulled from ecp-forge, not only synthetic fixtures.
  • nix/modules/ec-op-stack.nix and docs/OP_STACK_ECP_FORGE.md define the repo-owned OP Stack operator path for ecp-forge.
  • The dev shell now includes forge, cast, anvil, and solc, and the repo ships a top-level foundry.toml.

Real-capture PSIP checks:

git clone --depth 1 https://github.com/tsduck/tsduck-test /tmp/tsduck-test
EC_REAL_ATSC_SAMPLE=/tmp/tsduck-test/input/test-040.ts \
  cargo test -p ec-ts real_atsc_sample_matches_known_psip_shape -- --ignored --nocapture
EC_REAL_RRT_SAMPLE=/tmp/tsduck-test/input/test-052.ts \
  cargo test -p ec-ts real_rrt_sample_matches_known_reference -- --ignored --nocapture

Ethereum commitment checks:

cargo test -p ec-eth -p ec-node -- --nocapture
nix develop -c bash -lc 'which forge cast anvil solc && solc --bin contracts/EveryChannelRail.sol >/dev/null'

Observation rail / OP Stack checks:

nix shell .#foundry .#solc -c forge test -vv
nix shell .#foundry .#solc nixpkgs#jq nixpkgs#openssh nixpkgs#curl -c ./scripts/op-stack/anvil-reality-smoke.sh

Coverage:

./scripts/coverage.sh

Build static web:

./scripts/build-web.sh

Deploy to Cloudflare Workers (static site):

./scripts/deploy-workers.sh

Remote website E2E (local publisher -> deployed every.channel web):

./scripts/e2e-remote-website-direct.sh

Remote website E2E (public list/signaling -> website selects stream automatically):

./scripts/e2e-remote-website-directory.sh

Tauri viewer (Dioxus + Trunk):

cd apps/tauri/ui
trunk serve --port 1420 --public-url /
cd ../
cargo run

Status

This repository is intentionally minimal. It captures the initial architecture and scaffold for a MoQ-first network and will expand as proposals are accepted.