diff --git a/docs/bitvid-bridge-plan.md b/docs/bitvid-bridge-plan.md index 60a58563..9ef0f6d8 100644 --- a/docs/bitvid-bridge-plan.md +++ b/docs/bitvid-bridge-plan.md @@ -148,6 +148,12 @@ BitVid Bridge └── (optional) localhost API → for website control, later DECISION 2 ``` +- **Studio webview sourcing.** The webview loads the **instance's deployed bitvid + web app** (remote URL, cached for offline resilience) rather than a bundled copy. + Benefit: it's always current and **auto-inherits the instance's flags** (so + `FEATURE_LIVE_PUBLISH` off ⇒ no go-live, invariant 6) with no app update needed; + a trimmed bundled fallback covers the offline/first-run case. The instance URL is + configurable (a user may use more than one bitvid instance). - **Media core = a local Media Node.** Same engine as the server-side node (#16c), which is why DECISION 7 (one codebase, two modes) is attractive. - **Stream keys / ingest URLs never leave the device** and never go into Nostr; the @@ -228,6 +234,15 @@ becomes a normal bitvid video automatically. upload-modal-style VOD flow) — minimize net-new signing/auth code. 5. **Optional, not required** — a creator can still stream OBS → public Media Node without the Bridge; the Bridge only *adds* convenience/power. +6. **Respect the connected instance's config.** The embedded Studio webview loads + a specific bitvid instance, so it inherits that instance's flags — if the + instance has `FEATURE_LIVE_PUBLISH` **off**, the Bridge shows go-live as + unavailable for it (nothing to publish to). The Bridge is only useful pointed + at an instance that has publishing enabled; surface that clearly rather than + failing opaquely. +7. **Bind the local ingest to loopback only.** The RTMP/SRT receiver listens on + `127.0.0.1` (not `0.0.0.0`) by default so it isn't exposed to the LAN; + appliance/headless mode (Phase 7) can opt into a wider bind with auth. --- @@ -250,6 +265,13 @@ becomes a normal bitvid video automatically. detect + warn on incompatible input rather than failing silently. - **Scope creep.** This app can sprawl (capture, transcode, appliance). Ship the receiver MVP (Phase 0–1) first; everything else is additive. +- **Instance without publishing enabled.** If a user points the Bridge at an + instance that has `FEATURE_LIVE_PUBLISH` off, go-live must degrade gracefully + (clear "publishing isn't enabled on this instance" state), not error obscurely + (invariant 6). +- **Local ingest exposure.** A misconfigured wide bind would expose an unauth'd + RTMP receiver on the network — default to loopback (invariant 7); require auth + for any non-loopback bind. --- diff --git a/docs/live-publish-plan.md b/docs/live-publish-plan.md index ab717af7..2c2471fb 100644 --- a/docs/live-publish-plan.md +++ b/docs/live-publish-plan.md @@ -129,18 +129,48 @@ BitVid Live over zap.stream/Twitch/YouTube. ## Config flags (off = no trace) -All default `false`, threaded `config/instance-config.js` → `js/config.js` → -`js/constants.js` like `FEATURE_NIP71_INGEST`: +Every "Go Live" surface is instance-config gated and defaults **off**, threaded +`config/instance-config.js` → `js/config.js` → `js/constants.js` like +`FEATURE_NIP71_INGEST`. An operator can ship the code and have publishing be +completely invisible until they opt in. -- `FEATURE_LIVE_INGEST` — watch side (from #16; dependency). -- `FEATURE_LIVE_PUBLISH` — the Studio / Go-Live publishing UI. +- `FEATURE_LIVE_INGEST` — watch side (from #16; a dependency of publish). +- `FEATURE_LIVE_PUBLISH` — the Studio / Go-Live publishing UI (the master + publish switch). - `FEATURE_LIVE_BRIDGE` — Media Node / Bridge session API integration. - `FEATURE_LIVE_RESTREAM` — external restream output management. -When `FEATURE_LIVE_PUBLISH` is off: no Studio, no "Go Live" entry point, no My -Videos → Live sub-tab, no Bridge/session UI, no live-event **builders** wired into -any surface. Bridge/restream UI additionally gated on their own flags. Config -flags are the only footprint. +**Independent of watching.** These are separate from `FEATURE_LIVE_INGEST`, so an +instance can enable *watching* live streams without enabling *broadcasting* (or +vice-versa). `FEATURE_LIVE_PUBLISH` implies ingest is on (you watch your own +stream); it does not force ingest on for everyone if the operator wants +watch-only. + +When `FEATURE_LIVE_PUBLISH` is off, **all** of the following are absent — no tab, +no button, no trace (as if never added): +1. **"Go Live" / Studio entry points** — no Studio launch anywhere (sidebar, + upload modal, profile). +2. **My Videos → Live sub-tab** — not rendered (shorts-plan sub-tab treatment). +3. **Live-event builders** — `buildLiveStreamEvent` / `updateLiveStreamStatusEvent` + are not wired into any UI (the schema definitions can exist dormant; nothing + *invokes* them). +4. **Bridge/session UI** — pairing, ingest settings, health dashboard (also gated + on `FEATURE_LIVE_BRIDGE`). +5. **Restream UI** — output manager (also gated on `FEATURE_LIVE_RESTREAM`). +6. **Archive→VOD "publish recording"** live-origin flow (a normal video upload is + unaffected). +7. **Routes** — any `#view=live-studio` (or equivalent) falls back to default. +8. **Config surface** — the flags are the only footprint. + +Bridge and restream have their own sub-flags so an operator can allow, e.g., +publishing to their own Media Node **without** exposing external restreams. + +**Who may go live (operator control).** Beyond the on/off flags, publishing on an +instance should respect the existing **whitelist/WoT** model — i.e. an operator +can allow only whitelisted creators to broadcast on their instance (reusing +`accessControl`), the same way the feeds are gated. Decide whether go-live is +whitelist-gated by default (recommended: yes on whitelist-mode instances) so a +public instance isn't an open ingest relay. ---