1# goq agent guide23goq is a one-host, one-user game-streaming appliance. The public project and4website are **goq.sh**. **Sigil** is the pure Rust Linux host command and5daemon. **Portal** is the installed Tauri client that opens a session to a6Sigil host.78## Product boundary910- Sigil runs on a dedicated, physically headless bare-metal Linux machine.11- Gamescope owns the private Steam/game display; capture must not require an12 interactive desktop or XDG ScreenCast portal.13- The host is a pure Rust daemon. It must never depend on Tauri, WebKit, or a14 host-facing UI.15- Portal is client-only. It must not bundle host capture, encoding, daemon,16 identity, configuration, or Linux input-injection assets.17- Iroh owns native connectivity, endpoint identity, encryption, direct-path18 discovery, and relay fallback.19- Exactly one media session and one matching client are active at a time.20- Controller is the primary interaction model. Keyboard and relative mouse are21 secondary inputs.2223## Current architecture2425- `crates/sigil-protocol` owns bounded, versioned handshakes, capabilities,26 media/audio headers, input messages, protocol limits, and ALPN constants.27- `crates/sigil-host` builds the `sigil` daemon and `sigil-probe` diagnostic.28 - `main.rs` owns the CLI, endpoint/router setup, and capture probes.29 - `server.rs` owns session admission and separate media, input, and audio30 protocols.31 - `source.rs` owns test-pattern and Gamescope PipeWire capture plus AMD GstVA32 H.264 encoding. External `gst-launch` remains the default; an explicitly33 feature-gated in-process backend owns bounded encoder control.34 - `input.rs` owns strict Linux `uinput` pointer, keyboard, and Xbox-style35 virtual gamepad devices.36 - `audio.rs` owns bounded PipeWire/Opus capture.37 - `identity.rs` and `config.rs` own fail-closed persistent host state.38- `src-tauri` is Portal's native boundary.39 - `commands/network.rs` owns Iroh connections, bounded media-object receive,40 binary Tauri channels, input transport, and diagnostics.41 - `commands/auth.rs` owns FIDO2 `hmac-secret` derivation.42 - `commands/state.rs` owns launch options and process-wide bounded state.43- `portal/main.js` and the focused `portal/*.mjs` modules own WebCodecs decode,44 AudioWorklet playback, controller-first navigation, input capture, A/V45 synchronization, window geometry, and client diagnostics.46- `website/` is the static goq.sh site. A merge to `main` publishes it through47 the `goq-sh` Cloudflare Worker after the static-site gate passes.4849## Proven baseline5051- Sigil is independent of Tauri/WebKit and passes the pure-host dependency52 gate.53- Gamescope's exact PipeWire node is resolved from strict configured54 properties. AMD GstVA H.264 sustains the fixed 1280x800/60 first target on55 the GPD Pocket 4 test host with bounded post-encode delivery.56- Existing host configurations default to the proven external `gst-launch`57 backend. `encoder_backend = "in-process-gstreamer"` fails closed unless the58 Linux binary was explicitly built with that feature and its runtime59 GStreamer elements are available. The opt-in backend currently requires CBR;60 CQP remains on the external compatibility backend.61- The preferred media path authenticates and claims the single client over62 `sigil/control/1`, then admits that exact peer to a session-scoped upstream63 `iroh-moq` broadcast and static H.264 track. One configured GOP maps to one64 bounded native MoQ group; a newer independently decodable group cancels its65 predecessor and provides the latest-frame barrier. The custom media v3, v2,66 and v1 protocols remain explicit compatibility fallbacks.67- Portal crosses Rust-to-webview video and audio through bounded binary Tauri68 channels. It reports transport, frontend, decoder, presentation, and audio69 queue/drop timing separately.70- Input uses an Iroh connection independent of media backpressure. The host71 advertises only operational capabilities and neutralizes every held pointer,72 keyboard, and gamepad state when a session ends.73- Relative pointer movement, scroll, keyboard, virtual gamepad reports, Opus74 audio, reconnects, and second-client rejection have focused and loopback75 coverage. Hardware acceptance that remains incomplete is listed below.76- Portal preserves the user's native window geometry across sessions and77 relaunches. The stream surface scales and letterboxes within those bounds so78 larger or differently shaped client windows never stretch the host image.79- Portal's proven relative-pointer capture path is macOS-only. Non-macOS80 builds must mask relative-pointer negotiation unless explicitly built with81 `experimental-non-macos-pointer-capture`; that feature is for platform UAT82 only and must not enter an ordinary or published build.8384## Security boundary8586- Portal's FIDO `hmac-secret` derives its stable Iroh peer identity. Sigil signs87 a short-lived, host-bound invitation for that exact peer and atomically88 persists the enrolled grants before accepting the first media session.89- `--dev-connect` is a test-only routing bypass, never an authorization claim.90 Debug builds and the explicit `demo-direct-node` feature may accept it and91 must display the development warning. Ordinary release builds must reject it.92- Enrollment is one-time; ordinary startup remains **PIN -> tap -> play** and93 reconnects authenticate the enrolled Iroh peer without replaying a ticket.94- View, pointer/keyboard, and gamepad permissions must be independently95 grantable. Replay, expiry, peer mismatch, cross-host use, and capability96 escalation must fail closed.97- The authorization state and replay ledger are security-sensitive host state;98 preserve their owner-only permissions and atomic update rules.99- `docs/compatibility-identifiers.md` freezes Portal's FIDO/Iroh derivation,100 Sigil's local runtime child, and its Linux virtual-input identity tuple.101 Never rename one in place or add a silent alternate acceptance path.102103## Release and installation boundary104105- Sigil is machine setup, not a desktop download. The public bootstrap is106 `curl -fsSL https://goq.sh/install-sigil | bash`.107- `website/install-sigil` intentionally fails closed until a reviewed Minisign108 publisher key and immutable signed release tag are configured.109- Product Sigil packages must come from clean committed source, contain only110 the allowlisted runtime payload, carry complete checksums/provenance, and have111 a detached Minisign signature. Installation must preserve identity and host112 configuration and must not silently start, restart, or enable the service.113- Product Sigil assets use the target-contract suffix114 `linux-glibc2.17-x86_64`, pinned by115 `release/sigil-target-contract.txt`. That name describes the binary ABI, not116 validated host support; the public bootstrap remains Bazzite-only until117 another environment passes its own packaging and hardware gates.118- Portal is a compiled desktop download, never a shell install. The first119 public target is macOS arm64 and requires Developer ID signing, hardened120 runtime, notarization, stapling, and strict Gatekeeper verification. Its121 TeamIdentifier must equal `release/portal-apple-team-id.txt`, and every122 Portal asset must carry protected exact-tag GitHub build provenance. Do not123 advertise an unavailable platform/architecture as a download.124- The Minisign secret, Apple certificate, notarization credentials, host125 identity, and FIDO-derived secrets must never enter the repository, release126 archive, logs, command line, or general website deployment environment.127128## Latency and correctness invariants129130- Bound every capture, encode, media, frontend, decode, audio, and input queue.131- Prefer dropping or cancelling stale video over increasing latency.132- Keep input transport independent from media and audio backpressure.133- Never send uncompressed video through Tauri IPC or Iroh.134- Never reintroduce base64 media events; use binary Tauri channels.135- A discontinuity must resume from a keyframe carrying codec configuration.136- A slow or resetting receiver must not accumulate a playable history.137- Keep H.264 at 1280x800/60 as the known-safe target until adaptive work is138 measured end to end. Do not select codecs by compression ratio alone.139- Preserve native pointer coordinates independently from encoded resolution or140 client window size.141- Map a differently shaped focused Xwayland root through a centered aspect-fit142 region in the native pointer surface; never stretch pointer axes143 independently.144- Session teardown must release all held input transitions and emit a neutral145 gamepad state even after an error or disconnect.146147## Remaining public-alpha gates148149- Issue #3's repository work is implemented: one-time capability enrollment,150 replay protection, grant intersection, and controller-usable Portal import.151 Its exact release candidates still participate in the issue #6 hardware UAT.152- Issue #4: configure the offline Minisign trust root, publish the signed Sigil153 asset set, and prove clean install plus upgrade/rollback from the public154 command.155- Issue #5: configure the committed Apple TeamIdentifier pin, then publish the156 signed/notarized/attested macOS arm64 Portal DMG, digest, and manifest.157- Issue #6: prove physically headless cold boot, physical client controller158 gameplay, mouse buttons consumed by Gamescope/an actual game, sustained A/V159 and resource percentiles without latency growth, difficult-NAT relay160 diagnostics, and reconnect/second-client rejection using the exact release161 candidates.162- Issues #7-#10 are streaming hardening: Iroh/MoQ recovery hardening, adaptive163 bitrate, motion-sensitive resolution, and automatic low-latency codec164 selection. The preferred path now uses pinned upstream `iroh-moq`; the165 external `gst-launch` encoder can still honor a keyframe request only at its166 next natural configured IDR. An opt-in in-process GStreamer control path now167 exists; hardware loss/relay proof remains before claiming issue #7 complete.168 The in-process encoder backend is not part of the product release feature set169 until its native Bazzite and cross-build/package dependency gates pass.170171## Working rules172173- Use Rust edition 2024. Sigil and Portal require Rust 1.91 or newer and the174 repository pins Rust 1.95 in `rust-toolchain.toml`; `sigil-protocol` retains a175 1.85 minimum. Source `~/.cargo/env` before invoking Cargo directly.176- Building Sigil with `in-process-gstreamer` requires the GStreamer core, app,177 and video development packages. Deployment requires their matching runtime178 libraries plus `appsink`, `pipewiresrc`, parser/conversion elements, and the179 selected GstVA encoder plugin; never treat build headers as runtime payload.180- Run `./scripts/verify-demo-build.sh` for the complete repository gate. It181 covers Rust format/tests/clippy, the Linux cross-build when available,182 frontend syntax/tests, ShellCheck, package tests, loopback transport, and183 release-profile containment of `--dev-connect`.184- Run `./scripts/verify-website.sh` for every website or public installer185 change. Exercise interactive website changes in a real browser.186- Treat `docs/fresh-bazzite-host.md`, `docs/public-release-delivery.md`, and187 GitHub issues #3-#10 as the current acceptance sources. Distinguish local188 tests from hardware proof and from still-pending operator acceptance.189- Treat `docs/hardware-uat/MATRIX.md` as the claim contract. Until both190 required rows pass the same exact candidate, name hardware results as191 reference-host evidence; do not use unqualified `hardware-proven` language.192 A development matrix pass is not release-matrix proof.193- Use the strict live capture gate on Bazzite when capture changes:194195 ```bash196 sigil capture probe \197 --source gamescope-pipewire \198 --config ~/.config/sigil-spark/host.toml \199 --frames 300 \200 --expect-size 1280x800 \201 --minimum-fps 55202 ```203204- Any change that can affect Sigil startup, capture, encoding, transport,205 decoding, A/V, input, or session behavior requires a real Portal -> UMPC206 Gamescope connection from the exact candidate commit. A successful config207 check, capture probe, headless probe, or loopback is supporting evidence, not208 a substitute for that end-to-end session. Starting a bypass-enabled daemon209 and observing that it listens is also not an end-to-end test: Portal must210 connect to that exact daemon, the host must admit the session, live media211 diagnostics must advance, and the affected interaction or recovery path must212 be exercised from Portal. Fresh exact-commit builds are not213 expected to be enrolled. This also applies when authentication or identity214 code changed: do not skip the connection because ordinary authentication215 blocks it. For development hardware testing, build Sigil with216 `demo-auth-bypass`, run it with217 `--dev-allow-unauthorized` and a bounded `--max-runtime-seconds`, and connect218 a debug Portal with `--dev-connect`. Verify the affected live diagnostics219 and interaction path, then stop the bypass process, undo temporary Gamescope220 controls, and restore and verify the ordinary authenticated221 `sigil-host.service` before calling the test complete.222- The bypass proves the exact runtime connection, not authorization semantics.223 For authentication, enrollment, identity, grants, invitation, and reconnect224 changes, supplement that session with deterministic FIDO-response tests and225 a persistent software Iroh identity using signed invitations and226 authenticated probes. Cover the relevant grant, replay, expiry, peer/host227 binding, and ticket-free reconnect behavior. A physical security-key PIN or228 tap is not required unless the operator explicitly requests authenticator229 hardware acceptance.230231- On Linux with NVIDIA, set `WEBKIT_DISABLE_DMABUF_RENDERER=1` for Portal.232- Treat `experimental-non-macos-pointer-capture` as an explicit non-release233 build mode. Complete the per-platform checklist in234 `docs/portal-platform-support.md`, including a real Portal -> UMPC session,235 before changing a platform's support status or its default feature policy.236- Preserve the inherited `sigil` checkout that sits beside this repository on237 the development machine untouched; it is not this working repository.238- Preserve unrelated worktree changes. Never sweep generated credentials,239 evidence, local Claude/Codex configuration, `.env` files, or test-host state240 into commits.241- Do not weaken a fail-closed production path to make a development proof pass.242 Keep explicit development flags visibly labeled and build-time contained.