# 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: ```sh nix develop ``` Rust: ```sh cargo build ``` Runbook: ```sh cat docs/USAGE.md ``` Git hosting topology: ```sh cat docs/GIT_HOSTING.md ``` Sovereign forge deploy: ```sh cat docs/DEPLOY_ECP_FORGE.md ``` OP Stack `ecp-forge` runbook: ```sh cat docs/OP_STACK_ECP_FORGE.md ``` NUC PXE rollout (UniFi-only or ProxyDHCP): ```sh cat docs/NUC_UNIFI_NETBOOT.md ``` ## WebTransport Watch (MoQ) Publish (node -> Cloudflare relay): ```sh cargo run -p ec-node -- wt-publish \ --url https://cdn.moq.dev/anon \ --name la-nbc \ --input http:///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): ```txt https://every.channel/watch?url=https%3A%2F%2Fcdn.moq.dev%2Fanon&name=la-nbc ``` Archive (relay -> CAS objects + JSONL manifests): ```sh cargo run -p ec-node -- wt-archive \ --url https://cdn.moq.dev/anon \ --name la-nbc \ --output-dir /tank/every-channel/archive \ --manifest-dir /var/lib/every-channel/manifests ``` Replay server (archive -> HLS DVR endpoints): ```sh 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): ```sh # Listener (on node A) cargo run -p ec-node -- control-listen --gossip-peer # Announcer (on node B) cargo run -p ec-node -- control-announce \ --stream-id la-nbc \ --relay-url https://cdn.moq.dev/anon \ --relay-broadcast la-nbc \ --gossip-peer # Resolver (consumer picks best announced path) cargo run -p ec-node -- control-resolve \ --stream-id la-nbc \ --prefer direct-first \ --gossip-peer # Bridge iroh control announcements to every.channel public web list EVERY_CHANNEL_WEB_UPSERT_TOKEN= \ cargo run -p ec-node -- control-bridge-web \ --directory-url https://every.channel \ --gossip-peer ``` `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_id`s 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: ```sh 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: ```sh 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: ```sh 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: ```sh ./scripts/coverage.sh ``` Build static web: ```sh ./scripts/build-web.sh ``` Deploy to Cloudflare Workers (static site): ```sh ./scripts/deploy-workers.sh ``` Remote website E2E (local publisher -> deployed every.channel web): ```sh ./scripts/e2e-remote-website-direct.sh ``` Remote website E2E (public list/signaling -> website selects stream automatically): ```sh ./scripts/e2e-remote-website-directory.sh ``` Tauri viewer (Dioxus + Trunk): ```sh cd apps/tauri/ui trunk serve --port 1420 --public-url / ``` ```sh 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.