cat / goq
clone

turns a linux box into a private steam streaming appliance: plug in, tap your key, play from another computer

Merge pull request #126 from FelineStateMachine/docs/readme-and-repo-hygiene

FelineStateMachine committed 0bd0cd9
Rewrite README as a public project description; scrub personal paths
commit
0bd0cd95c807400b7de34a2110bda529a238ef57
parent
cbae9bbc741a13e5ebb0807987d2996d70bf32f2
parent
83a3d0ad58ca2cb5158d2157508f20046c6895ed
author
FelineStateMachine <dami.etoile@gmail.com>
4 files changed, +162 -316
M.gitignore3+
MAGENTS.md4+-
MREADME.md463++++++++++--------------------
Mdocs/fresh-bazzite-host.md8+-
M .gitignore +3 -0
M AGENTS.md +2 -2
M README.md +153 -310
@@ -1,344 +1,187 @@
11 # goq.sh22 3-goq.sh is one-to-one, low-latency Steam streaming over iroh: Portal is the4-installed Tauri client, and Sigil is the pure Rust bare-metal Linux host.5-6-The project starts from an inherited working remote-desktop implementation. Native7-iroh connectivity, hardware video encoding, WebCodecs decoding, FIDO-derived8-identity, and remote input are already present. The next phase replaces the9-desktop-oriented hot path with a headless Gamescope pipeline.10-11-## Target architecture3+**Your key is the address. Plug in, tap, play.**4+5+goq turns one Linux machine into a personal Steam streaming appliance. You6+dedicate that machine to your games, plug in nothing but power and network,7+and play from another computer with a controller. The goal is the latency of8+sitting at the machine, not the latency of a screen-sharing tool.9+10+goq is not a multi-tenant streaming service and not a desktop-sharing tool.11+It streams a private [Gamescope](https://github.com/ValveSoftware/gamescope)12+session that exists only for your games: the host needs no monitor, no13+desktop environment, and no interactive login. Exactly one client is admitted14+to exactly one session at a time, authenticated by a hardware security key.15+16+## The two programs17+18+- **Sigil** is the host: a pure Rust daemon for a bare-metal, physically19+ headless Linux machine. Gamescope owns the private game display, PipeWire20+ provides capture, and hardware H.264 plus Opus leave the machine over21+ [iroh](https://github.com/n0-computer/iroh), so the client reaches the host22+ by its cryptographic identity rather than an IP address.23+- **Portal** is the client: an installed Tauri desktop application with a24+ native iroh endpoint, WebCodecs video decode, AudioWorklet playback, and25+ controller-first navigation.1226 1327 ```text14-Sigil · bare-metal Linux host15- Gamescope headless16- -> PipeWire video/audio17- -> hardware H.264 + Opus18- -> iroh/MoQ19-20-Portal · Tauri client21- native iroh endpoint22- -> binary Tauri channel23- -> WebCodecs video24- -> audio output25- controller/keyboard/mouse26- -> iroh input protocol27- -> host uinput devices28+Sigil · bare-metal Linux host Portal · installed desktop client29+ Gamescope headless session native iroh endpoint30+ -> PipeWire video/audio -> binary Tauri channels31+ -> hardware H.264 + Opus -> WebCodecs video + audio out32+ -> iroh / MoQ media objects controller, keyboard, mouse33+ uinput virtual devices <---- -> iroh input protocol2834 ```2935 30-The host is intended to run without a physical display or desktop environment.31-Gamescope supplies the private graphical session and virtual display seen by32-Steam and games.33-34-## Current migration status35-36-- A shared, bounded and versioned protocol crate owns handshakes, H.264 media,37- input messages, limits, and ALPNs.38-- The Linux host is the pure Rust `sigil` binary with no Tauri or webview39- dependency.40-- The core host captures the standard upstream Gamescope PipeWire video source,41- derives the encoded size from its bounded native caps by default, and uses42- AMD GstVA H.264. An explicit width/height pair remains available for43- downscale proofs; 1280×800/60 is the first measured target, not a product44- constraint. Bazzite remains the only packaged appliance, and the GPD Pocket45- 4 run is reference-host evidence rather than a completed hardware matrix.46- SteamOS packaging, cold boot, encoder availability, and cross-host hardware47- UAT remain unproven.48-- Gamescope video keeps the proven external `gst-launch` pipeline as its49- configuration default. Linux builds made explicitly with50- `in-process-gstreamer` can opt into an in-process pipeline for bounded51- bitrate, force-keyframe, and two-tier resolution control. Published Sigil52- packages include that backend while keeping the external pipeline as the53- runtime default.54-- Portal reports bounded receiver queue, drop, latency, and recovery telemetry55- over a session-authenticated feedback stream. The host combines it with56- trusted path and scheduler pressure, applies hysteresis, and commits an57- in-process CBR bitrate decision only after exact encoder readback. External58- encoder sessions remain explicitly advisory-only.59-- On the opt-in in-process backend, fresh damage-driven frame progress and60- authenticated receiver pressure select either the resolved native mode or61- an exact same-aspect three-quarter motion tier when one exists. A switch62- commits only when GStreamer emits a target-size IDR with SPS/PPS; Portal then63- starts a new decoder epoch while pointer mapping remains tied independently64- to the native Gamescope surface. Modes without an exact even reduced tier65- continue at native resolution instead of rejecting the stream.66-- Portal delivers encoded frames to WebCodecs through a raw Tauri binary67- channel. The handoff is capped at four frames, the decode queue and68- presentation queue at two, and a bounded watchdog recovers a suspended69- webview animation-frame callback without presenting a frame twice. Its70- transport/frontend/decoder drop counters are reported separately.71-- Media and input use separate Iroh connections; one active client is enforced.72-- Linux `uinput` supports bounded relative-mouse and keyboard injection plus a73- separate Xbox-style virtual gamepad, with strict device74- ownership/mode/ACL preflight and neutralization when a session ends.75-- The installed Portal application is client-only: it contains no host daemon,76- host registration, capture, encoder, or desktop input-injection path.77-- FIDO2 `hmac-secret` derives Portal's stable Iroh peer identity. A signed,78- short-lived Sigil invitation enrolls that peer once with exact view,79- pointer/keyboard, and gamepad grants; ordinary reconnects remain80- **PIN -> tap -> play**. Debug builds retain a visibly labeled routing bypass,81- while release builds reject it. The82- [identity and appliance compatibility identifiers](docs/compatibility-identifiers.md)83- are frozen independently from display branding.84-- Controller-first client navigation includes a D-pad PIN pad, negotiated85- latest-state gamepad routing, and a one-second Back+Start escape chord.86-- Portal's proven relative-pointer capture is macOS-only. Default non-macOS87- builds negotiate absolute pointer, keyboard/text, and gamepad without88- advertising relative capture; the Tao + browser Pointer Lock path requires89- the explicitly experimental `experimental-non-macos-pointer-capture` build90- feature and the platform UAT in91- [`docs/portal-platform-support.md`](docs/portal-platform-support.md).92-- The Bazzite host has an allowlisted deterministic runtime package with93- checksum-bound release IDs, serialized install/upgrade, tamper-checked94- rollback, and package-owned user assets that follow the active release.95-- Sigil exposes a versioned, redacted local appliance-status document and96- daemon-lifetime lock as the foundation for a controller-first Decky Loader97- management plugin. The plugin remains a UI over the user service, not a98- second streaming host.99-100-The software JPEG client decode fallback and legacy wire compatibility remain.101-The preferred video path authenticates the client over a dedicated control102-connection, then admits that exact peer to a session-scoped upstream103-`iroh-moq` broadcast. Sigil publishes an immutable `catalog.json` snapshot;104-Portal discovers and strictly validates the versioned Goq extension before it105-subscribes to the H.264 track. The extension identifies Goq's `SGV1` media106-envelope and GOP layout, so it does not falsely advertise the track as a107-standard Hang rendition. Older hosts without a catalog retain an explicit108-static-track compatibility path. Configured GOPs become bounded native MoQ109-groups, and a new independently decodable group cancels the stale predecessor.110-The custom media v3, v2, and v1 transports remain explicit compatibility modes.111-A dedicated persistent PipeWire sink, bounded Opus datagrams, WebCodecs decode,112-and AudioWorklet playback are implemented; longer-run audio/video113-synchronization measurement remains. The debug direct-node bypass is routing,114-not authentication.115-116-## Immediate milestones117-118-1. **Done:** split Sigil into a pure Rust host binary; keep Portal client-only.119-2. **GPD Pocket 4/Bazzite reference-host evidence:** capture the exact Gamescope120- PipeWire node without an XDG portal. Physically headless cold boot and121- service startup remain public-alpha acceptance gates.122-3. **GPD Pocket 4/Bazzite reference-host evidence:** encode H.264 at123- 1280x800/60 with bounded buffers and no B-frames.124-4. **Done:** replace base64 WebCodecs delivery with a bounded binary Tauri channel.125-5. **Upstream Iroh/MoQ transport implemented; hardware proof pending:** an126- authenticated control lease gates a session-scoped upstream MoQ broadcast;127- bounded native groups cancel stale GOPs and recover through explicit128- keyframe requests. The opt-in in-process encoder turns recovery requests129- into coalesced forced IDRs without blocking media publication; the external130- encoder responds at its next natural configured IDR. Bazzite/package131- acceptance and induced-loss relay proof remain in issue #7.132-6. **GPD Pocket 4/Bazzite reference-host evidence; physical client controller133- pending:** the virtual Xbox-style controller negotiated over Iroh and134- produced the expected button, stick, trigger, D-pad, and neutral-release135- events on that host. Client controller navigation and mapping are covered136- by focused tests; the remaining integration gate is forwarding a physical137- controller attached to the client. Keyboard injection was exercised on the138- same reference host, and the conventional relative mouse replaces139- Gamescope-incompatible absolute motion.140-7. **GPD Pocket 4/Bazzite reference-host evidence:** bounded PipeWire audio141- capture, a persistent headless sink, Opus delivery, and client playback.142- Quantify longer-run A/V synchronization.143-8. **Done:** add signed, peer-bound, one-time capability enrollment with144- durable replay protection and controller-usable Portal onboarding.145-9. **Adaptive control implemented; hardware proof pending:** feedback remains146- constant-size and generation-scoped, coalescing retains cumulative pressure,147- and `applied=true` requires exact in-process encoder readback. Native Ubuntu148- x264 control is CI-proven; Bazzite GstVA loss/relay acceptance and product149- packaging remain in issue #8.150-10. **Motion-sensitive resolution implemented; hardware proof pending:** the151- in-process backend lowers resolution during sustained damage-driven motion152- or receiver pressure and restores native detail only after stillness,153- clean feedback, and cooldown. Every transition is an exact configured-IDR154- discontinuity with truthful per-frame dimensions. Portal reconfigures155- WebCodecs atomically and preserves native pointer mapping. Ubuntu x264 CI156- covers downscale and restore; repeated GstVA/Portal acceptance on Bazzite157- remains in issue #9.158-159-## Development160-161-Requirements:36+## Design principles37+38+- **Latency over history.** Every capture, encode, transport, decode, and39+ input queue is bounded. Stale video is dropped or cancelled rather than40+ buffered, so a slow receiver never accumulates a playable backlog. Media41+ travels as bounded MoQ groups: one GOP is one group, and a newer42+ independently decodable group cancels its predecessor.43+- **Input is independent.** Controller, keyboard, and relative mouse travel44+ on their own iroh connection, unaffected by media backpressure. Session45+ teardown always releases held keys and emits a neutral gamepad state, even46+ after an error or disconnect.47+- **Fail closed.** Portal derives its stable iroh identity from a FIDO2 key48+ with `hmac-secret`. A signed, short-lived, peer-bound invitation from Sigil49+ enrolls that one client once, with independently granted view,50+ pointer/keyboard, and gamepad permissions and durable replay protection.51+ Every ordinary launch after that is **PIN -> tap -> play**.52+- **Strict product boundary.** Sigil never depends on Tauri or a webview.53+ Portal never bundles capture, encoding, a daemon, or host input injection.54+55+## Status56+57+goq is pre-release. The reference host is an AMD machine running58+[Bazzite](https://bazzite.gg); H.264 at 1280x800/60 is the known-safe59+measured benchmark, while production capture accepts any even native mode60+within the protocol's bounded pixel limits.61+62+Working today:63+64+- The pure Rust Sigil daemon: Gamescope PipeWire capture at the display's65+ native mode, AMD GstVA H.264 encoding, and bounded PipeWire/Opus audio.66+- Authenticated session admission over a control connection, then a67+ session-scoped upstream `iroh-moq` broadcast with a strictly validated68+ catalog, with earlier custom media protocols kept as explicit compatibility69+ fallbacks.70+- Adaptive bitrate and motion-sensitive resolution on the opt-in in-process71+ encoder backend: session-authenticated receiver feedback, hysteresis, and72+ changes that commit only on exact encoder readback or a target-size IDR.73+- Portal playback through bounded binary Tauri channels into WebCodecs and an74+ AudioWorklet, with per-stage queue, drop, and latency diagnostics.75+- Linux `uinput` keyboard, relative mouse, and an Xbox-style virtual gamepad,76+ with strict device preflight and end-of-session neutralization.77+- One-time FIDO-bound enrollment, replay protection, and controller-usable78+ onboarding in Portal.79+- A deterministic, checksum-bound Bazzite runtime package with serialized80+ install/upgrade and tamper-checked rollback, plus the foundation of a81+ controller-first Decky Loader management plugin over a redacted local82+ appliance-status contract.83+84+The streaming-hardening roadmap, where the remaining work is hardware85+acceptance on the reference host, is tracked as86+[MoQ recovery hardening](https://github.com/FelineStateMachine/goq/issues/7),87+[adaptive bitrate](https://github.com/FelineStateMachine/goq/issues/8),88+[motion-sensitive resolution](https://github.com/FelineStateMachine/goq/issues/9),89+and [automatic codec selection](https://github.com/FelineStateMachine/goq/issues/10).90+The remaining public-alpha acceptance gates (headless cold boot, physical91+controller gameplay, sustained A/V measurement, and the signed public release92+path) are tracked in issues93+[#4](https://github.com/FelineStateMachine/goq/issues/4) to94+[#6](https://github.com/FelineStateMachine/goq/issues/6).95+96+## Repository layout97+98+| Path | Contents |99+| --- | --- |100+| `crates/sigil-protocol` | Bounded, versioned handshakes, media/audio headers, input messages, limits, ALPNs |101+| `crates/sigil-host` | The `sigil` daemon and the `sigil-probe` diagnostic |102+| `src-tauri/` | Portal's native side: iroh transport, FIDO2 identity, binary channels |103+| `portal/` | Portal frontend: WebCodecs decode, audio playback, controller navigation |104+| `decky/` | Decky Loader management plugin for the Sigil appliance |105+| `website/` | The static goq.sh site, published via a Cloudflare Worker |106+| `scripts/` | Build, packaging, verification, and host provisioning tooling |107+| `docs/` | Runbooks and contracts for provisioning, releases, and hardware acceptance |108+109+## Getting started110+111+You need:162112 163113 - Rust 1.91 or newer (the repository pins Rust 1.95)164114 - Tauri v2 system dependencies165-- A FIDO2 key with `hmac-secret` support for the normal identity flow166-167-The Linux `in-process-gstreamer` host feature additionally needs the GStreamer168-core, app, and video development libraries at build time. Its matching runtime169-libraries and plugins, including `appsink`, must be installed on the host.170-Published Sigil packages include this feature while retaining the external171-pipeline as the runtime default until a host opts into the in-process backend.172-173-### Enroll one Portal174-175-On first launch, enter the security-key PIN and choose **show portal id**. On176-the Sigil host, create an invitation for that exact peer:177-178-```bash179-sigil invitation create \180- --config ~/.config/sigil-spark/host.toml \181- --peer PORTAL_PEER_ID \182- --pointer-keyboard \183- --gamepad \184- --output ~/portal.goq-invite185-```186-187-Move the owner-only invitation file to the client, open it with Portal, and188-confirm the displayed host, peer, expiry, and grants. Sigil consumes it once;189-future launches are simply **PIN -> tap -> play**. `--print-deep-link` is190-available for an explicit `goq://invite/...` handoff, but prints the short-lived191-credential to the terminal and should not be used in recorded shells.192-193-To move Portal to another Sigil, revoke the host enrollment first, disconnect194-Portal, then use **client -> reset enrollment** and confirm the displayed host.195-The reset is intentionally explicit and controller reachable; importing a new196-invitation never silently replaces a working enrollment.197-198-Activate an installed dedicated AMD host with the portable, package-owned199-[Sigil host activation guide](docs/sigil-host-activation.md). It uses the200-current gaming user, dynamically discovered hardware, and installed package201-assets without assuming a maintainer hostname or checkout path. The202-[fresh Bazzite host runbook](docs/fresh-bazzite-host.md) remains the engineering203-and hardware-acceptance log, including the temporary `slate` stand-in.204-The backward-compatible [appliance status v1 contract](docs/sigil-appliance-status-v1.md)205-and explicit [v2 contract](docs/sigil-appliance-status-v2.md) define the local,206-redacted interface intended for the Decky management surface.207-The [transactional configuration v1 contract](docs/sigil-appliance-config-v1.md)208-defines its bounded, crash-recoverable settings workflow.209-The [enrollment reset v1 contract](docs/sigil-appliance-enrollment-reset-v1.md)210-defines the offline, identity-preserving reset used by that surface.211-Run `scripts/bazzite-inventory.sh` on a candidate host for a read-only report;212-add `--smoke` to exercise a bounded 1280×800/60 VA-API encode. On the first SSH213-login after a physically headless cold boot, use `--cold-boot` for a strict,214-read-only connector, session, service, PipeWire, and boot-order gate.215-216-Run the complete local demo gate before transferring a snapshot:115+- A FIDO2 security key with `hmac-secret` support116+- For a host: a dedicated AMD Linux machine (Bazzite is the packaged target)217117 218-```bash219-./scripts/verify-demo-build.sh220-```118+Building Sigil with the optional Linux `in-process-gstreamer` feature119+additionally needs the GStreamer core, app, and video development libraries;120+the matching runtime libraries and plugins must be installed on the host.221121 222-After transferring the two prebuilt Linux binaries to a Bazzite host, stage an223-exact hash-pinned release without starting it:122+Run Portal against a Sigil host during development:224123 225124 ```bash226-scripts/stage-bazzite-release.sh \227- --release-id <commit-or-source-snapshot-sha256> \228- --host-binary <absolute-path> --host-sha256 <sha256> \229- --probe-binary <absolute-path> --probe-sha256 <sha256>125+source ~/.cargo/env126+cargo tauri dev230127 ```231128 232-The stager atomically updates the user-owned `current` symlink only after both233-binaries, their dynamic libraries, and bounded startup commands validate. Host234-identity, hardware-specific configuration, and service activation remain235-separate gates in the package-owned activation guide.129+On Linux with NVIDIA, prefix with `WEBKIT_DISABLE_DMABUF_RENDERER=1`.236130 237-The thin binary stager is only for unmanaged development layouts. It refuses238-activation when package-managed service, audio, rollback, or udev links follow239-`current`; use the complete runtime package installer for those hosts so the240-active release always includes matching assets and rollback metadata.131+### Provision a host241132 242-Create the Bazzite runtime package from a committed source revision. Product243-mode exports clean tagged `HEAD` and builds the host and probe itself with244-locked `cargo-zigbuild` in an isolated target directory; it never accepts245-externally supplied binaries. The builder emits an unsigned candidate for the246-separate offline signing ceremony; the explicit development flags are only for247-temporary testing:133+Activate an installed dedicated AMD host with the portable134+[Sigil host activation guide](docs/sigil-host-activation.md). To evaluate a135+candidate machine first, run `scripts/bazzite-inventory.sh` for a read-only136+hardware report; add `--smoke` to exercise a bounded 1280x800/60 VA-API137+encode, or `--cold-boot` on the first login after a physically headless boot138+for a strict readiness gate.248139 249-```bash250-scripts/package-bazzite-release.sh \251- --release-tag v0.1.0 \252- --output /tmp/sigil-v0.1.0-linux-glibc2.17-x86_64.tar.gz253-254-# Temporary development package only:255-scripts/package-bazzite-release.sh \256- --output /tmp/sigil-spark-host-dev.tar.gz \257- --allow-dirty --allow-unsigned258-259-# Temporary externally built binaries require both development flags:260-scripts/package-bazzite-release.sh \261- --output /tmp/sigil-spark-host-prebuilt-dev.tar.gz \262- --allow-dirty --allow-unsigned \263- --host-binary /absolute/path/to/sigil \264- --probe-binary /absolute/path/to/sigil-probe265-```140+### Enroll one Portal266141 267-Verify the unsigned candidate, then follow the offline signing and protected268-draft-promotion ceremony in [public release delivery](docs/public-release-delivery.md).269-The GitHub workflow and package builder never receive the Minisign secret.270-271-The package contains the primary `sigil` host executable, its byte-identical272-`sigil-host` compatibility copy, the `sigil-probe` diagnostic, installer and273-rollback tools, service/audio/udev assets, the portable activation guide,274-license, checksums, and build provenance. It cannot contain the source tree,275-`.env` files, identities, host configuration, or test evidence. Its release ID276-is the SHA-256 of the complete installed-file checksum manifest. Identical277-inputs produce a byte-identical archive. The manifest marks product binaries278-as built from clean `HEAD`; caller-supplied development binaries are explicitly279-marked as having unverified provenance.280-281-During the legacy rollback window, `sigil-host.service` deliberately starts282-the byte-identical `sigil-host` compatibility filename. Interactive and283-documented host commands use `sigil`; retaining the service filename allows an284-older installed rollback helper to validate and reactivate a newer release.285-286-Verify the detached signature against the separately trusted public key before287-extracting, then run `payload/stage-this-release.sh` as the gaming user. Install288-and upgrade never restart PipeWire or start/enable the service. Roll back an289-installed upgrade with `sigil-spark-host-rollback`; add `--restart` only when a290-service interruption is intended.291-292-The macOS Portal build currently produces an arm64 DMG for development. A public293-Portal release additionally requires Developer ID signing with hardened294-runtime, notarization, stapling, and strict Gatekeeper verification; ad-hoc295-development signatures are not a distributable package. Before tagging, the296-public TeamIdentifier in `release/portal-apple-team-id.txt` must match the297-protected certificate, and the tag-ref workflow attests every published Portal298-asset. With Apple credentials configured as described by the official299-[Tauri macOS signing guide](https://v2.tauri.app/distribute/sign/macos/), run:142+On Portal's first launch, enter the security-key PIN and choose **show portal143+id**. On the Sigil host, create an invitation for that exact peer:300144 301145 ```bash302-scripts/package-macos-client.sh \303- --release-tag v0.1.0 \304- --output-dir /absolute/release/directory146+sigil invitation create \147+ --config ~/.config/sigil-spark/host.toml \148+ --peer PORTAL_PEER_ID \149+ --pointer-keyboard \150+ --gamepad \151+ --output ~/portal.goq-invite305152 ```306153 307-The repository publication and website-manifest procedure is documented in the308-[Portal release runbook](docs/portal-release.md).309-310-Run Portal against Sigil during development:154+Move the owner-only invitation file to the client and open it with Portal.155+Sigil consumes it once; every later launch is **PIN -> tap -> play**. To move156+Portal to a different Sigil host, revoke the enrollment on the old host and157+use **client -> reset enrollment**. A new invitation never silently replaces158+a working enrollment.311159 312-```bash313-source ~/.cargo/env314-cargo tauri dev315-```160+## Verification316161 317-On Linux with NVIDIA:162+Run the complete repository gate before sharing work:318163 319164 ```bash320-WEBKIT_DISABLE_DMABUF_RENDERER=1 cargo tauri dev165+./scripts/verify-demo-build.sh321166 ```322167 323-The static `website/` directory is published as Cloudflare Worker static assets324-after a merge to `main`. See the [Cloudflare Worker release setup](docs/cloudflare-worker.md)325-for the one-time service and GitHub environment configuration.168+It covers Rust format, tests, and clippy, the Linux cross-build when169+available, frontend syntax and tests, ShellCheck, package tests, and loopback170+transport proof. Website and installer changes go through171+`./scripts/verify-website.sh`. Hardware acceptance evidence lives under172+[`docs/hardware-uat/`](docs/hardware-uat/README.md), separate from local173+tests.326174 327-Portal is distributed as a compiled, signed desktop application; it is never328-installed through a shell pipe. Sigil uses a separate Bazzite machine bootstrap329-at `https://goq.sh/install-sigil`. That bootstrap intentionally fails closed330-until the Minisign publisher trust root and first signed release exist. The331-[public release delivery contract](docs/public-release-delivery.md) defines the332-remaining signing and asset gates.175+## Releases333176 334-The promoted streaming-hardening roadmap is tracked as bounded335-[Iroh/MoQ media objects](https://github.com/FelineStateMachine/goq/issues/7),336-[adaptive bitrate](https://github.com/FelineStateMachine/goq/issues/8),337-[motion-sensitive resolution](https://github.com/FelineStateMachine/goq/issues/9),338-and [Auto Codec](https://github.com/FelineStateMachine/goq/issues/10). H.264 at339-1280×800/60 remains a known-safe benchmark while production capture accepts340-any even native mode within the protocol's bounded pixel limits.177+Sigil is machine setup, not a desktop download: the public bootstrap is178+`https://goq.sh/install-sigil`, and it intentionally fails closed until the179+Minisign publisher trust root and the first signed release exist. Portal is a180+compiled, signed desktop application, never a shell install; the first public181+target is macOS arm64. The packaging, signing, and publication ceremonies are182+documented in [public release delivery](docs/public-release-delivery.md) and183+the [Portal release runbook](docs/portal-release.md).341184 342185 ## License343186 344-MIT187+[MIT](LICENSE)
M docs/fresh-bazzite-host.md +4 -4