# SyncVision WebRTC Build Runbook

SyncVision keeps the default Windows build free of third-party runtime dependencies. The WebRTC path is an explicit opt-in build that uses libdatachannel v0.24.5 from commit `188ec93f6a0b01c2032ddb4c8c013118f7f30232`.

## Default Build

```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\build.ps1 -Configuration Release
```

This builds the legacy relay path. `stream_backend=auto` resolves to TCP relay without loading or requiring WebRTC files. An explicit `--stream-backend webrtc` returns a clear "not compiled" error in this build.

## WebRTC Build

Prepare libdatachannel for x64 Windows with media and SRTP enabled. The build must use `NO_MEDIA=OFF`; SRTP is required. The default durable prepared roots are configuration-specific and protected from lower-privilege mutation:

```powershell
C:\ProgramData\SyncVisionDependencyPreparation\prepared\release
C:\ProgramData\SyncVisionDependencyPreparation\prepared\debug
```

Prepare each configuration from the reviewed source and vcpkg inputs:

```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\prepare-webrtc-dependency.ps1 -Configuration Release
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\prepare-webrtc-dependency.ps1 -Configuration Debug
```

Preparation parses the canonical repository lock before running any external build input. Its canonical tree digest records every directory as `D|relative` and every file as `F|relative|sha256`, sorts records ordinally, and therefore detects unmanaged empty directories as well as changed files. It hashes the complete libdatachannel worktree excluding only `.git`, hashes the immutable vcpkg/toolchain tree and the complete installed dependency tree, and rejects every reparse point it traverses. It does not run Git, a PATH-resolved CMake, `CMAKE_COMMAND`, or a generated target from an existing cache.

`vswhere.exe` is resolved from the fixed Visual Studio Installer location and authenticated before execution. The schema-v4 lock pins the SHA-256, location-independent four-part `file_version_raw`, Microsoft Authenticode signer subject, and signer thumbprint for `vswhere.exe`, Visual Studio CMake, MSBuild, `cl.exe`, `link.exe`, `cmd.exe`, and Windows PowerShell. Localized `FileVersion` text remains metadata for diagnostics only: Windows can return different display strings for the same signed bytes under another UI language or after copying a system executable into a frozen snapshot. The lock additionally pins the complete CMake installation tree containing `bin`, sibling DLLs, and `share\cmake-*` modules, plus the complete permitted MSBuild, VC, and Windows SDK import/tool roots and the framework XAML target. Trusted path checks reject reparse points, untrusted owners, and lower-privilege mutation rights through each parent boundary. Any Visual Studio, CMake, VC tools, or Windows SDK update that changes these identities requires explicit lock review.

Every run creates a unique protected workspace under `C:\ProgramData\SyncVisionDependencyPreparation`. The already authenticated source, vcpkg toolchain, installed inputs, and complete CMake runtime/module tree are copied into that workspace, rehashed, ACL-sealed against lower-privilege writes, and used exclusively for configure and build. Configuration executes only the CMake executable inside that sealed tree, eliminating a validation/use swap against the installed Visual Studio tree. CMake receives only sealed source/build/vcpkg paths, the authenticated generator instance, x64/v143 toolset, reviewed media/SRTP/shared options, and deterministic path/link settings. MSBuild runs with ambient `Directory.Build.props`/`Directory.Build.targets` and user extensions disabled, isolated user/extension roots, pinned import properties, and a cleared allowlisted process environment. Source, vcpkg, CMake, import roots, executable identities, sealed-tree hashes, and the fresh cache are revalidated after the build. Only then are the three reviewed vcpkg runtime DLLs copied into fresh staging.

The generated schema-v4 manifest is an integrity snapshot, not a trust root. The reviewed trust root is `msbuild\SyncVisionWebRtcDependency.lock.json`, which pins complete input identities, the CMake runtime tree, and the complete prepared output tree in addition to the header tree, import library, and four runtime DLL hashes. Publication uses ACL-protected global locks plus a validated sibling candidate and backup; final validation is part of the transaction, and an incomplete rollback preserves the previous validated backup for recovery. A schema-v3 predecessor may be recognized only as the rollback source during the schema-v4 cache migration, and only when its exact manifest and output tree match the schema-v4 lock's rollback identities. It is never accepted as a new candidate or build input. `build.ps1` and packaging require schema-v4 inputs and recompute the same canonical directory-plus-file digests.

Then build with the explicit switch:

```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\build.ps1 -Configuration Release -EnableWebRtc
```

The switch passes `/p:SyncVisionEnableWebRtc=true` and one `/p:SyncVisionWebRtcPreparedRoot=...` property inside the sealed product workspace. Release selects the protected `prepared\release` root; Debug selects `prepared\debug` so Debug never links the Release ABI. Paths containing spaces are supported. To consume another already prepared root, pass `-WebRtcPreparedRoot C:\path\to\prepared-root`; the build copies it into the protected workspace before validation and use, and the copy must match the repository lock exactly.

Each prepared root is self-contained. `include`, `lib`, and `bin` are always derived from the same root, and the build rejects any changed, missing, extra, or reparse-point output before using the selected configuration. It copies only the four lock-approved DLLs. Debug builds also require the installed Visual Studio Debug CRT.

`SyncVisionBuildFlavor.json` records both the prepared-manifest hash and the repository lock path/hash. Packaging validates both again, including with `-SkipBuild`, so an existing binary set cannot be paired with different lock bytes or a locally re-minted dependency snapshot.

## Lock Update Boundary

Do not regenerate `msbuild\SyncVisionWebRtcDependency.lock.json` blindly from one local output. When a legitimate dependency or tool update changes a hash, preparation prints a candidate component snapshot and fails. Review the source tree, vcpkg commit/toolchain/installed trees, each Microsoft tool signature and binary identity, repeated fresh-build reproducibility, and every changed output hash independently. Update the lock only as a deliberate reviewed change, then rerun preparation for Debug and Release, both WebRTC builds, loopback tests, and packaging validation.

Do not use a direct ambient MSBuild invocation for a trusted product build. `build.ps1` authenticates the locked Visual Studio, compiler, linker, SDK, and import roots; copies repository and WebRTC inputs into a random protected workspace; clears import-affecting environment variables; disables `Directory.Build.*` and user extensions; and invokes MSBuild with `/m:1 /nodeReuse:false`. A direct `MSBuild.exe SyncVision.sln` command is outside that trust boundary. Use:

```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\build.ps1 -Configuration Release -EnableWebRtc
```

Use `scripts\build.ps1` for release artifacts because it validates the dependency snapshot and repository lock, copies the approved runtime DLLs, and writes `SyncVisionBuildFlavor.json` provenance.

## Smoke Test

```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\run-webrtc-build-smoke.ps1 -Configuration Debug
```

This script builds with WebRTC enabled, verifies the lock-approved runtime sidecars by SHA-256, runs the complete test binary, and explicitly runs `--webrtc-loopback-only`. It accepts the same single `WebRtcPreparedRoot` override as `build.ps1`.

Run the real local Host/Viewer transport smoke with:

```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\run-local-control-share-webrtc-smoke.ps1 -Configuration Release
```

The smoke starts an isolated relay, one Host, a primary Viewer, and a late-joining Viewer. Both Viewers must decode H.264 over WebRTC. After cutover, relay video counters must remain stable across the static refresh interval. A temporary raw Viewer then sends the normal `video_policy` control message with JPEG, which makes the Host fall back all active PeerConnections. The temporary Viewer disconnects; relay video counters must increase for the two original Viewers. A second policy change restores H.264, both original Viewer processes must decode fresh H.264 frames over TCP relay, and neither Viewer PID may change.

## Packaging Boundary

Dynamic libdatachannel builds require `datachannel.dll` and its transitive DLL sidecars next to the SyncVision executables. Create a WebRTC-enabled package explicitly:

```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\package-release.ps1 -Version 0.1.0 -EnableWebRtc
```

`-EnableWebRtc` builds the WebRTC Release binaries and packages exactly the runtime DLL names and hashes approved by the repository lock and recorded in build provenance. Production packaging consumes only the canonical protected trusted-build cache under `C:\ProgramData\SyncVisionTrustedBuild`; alternate cache roots are reserved for explicit test fixtures. The complete package tree, checksum manifest, digest sidecar, and ZIP are constructed and hashed in protected ProgramData staging, copied to validated caller-visible candidates, and published transactionally with exact post-copy identity checks. Any extra DLL in the output directory is excluded. Without that switch, no WebRTC runtime DLL is packaged, preserving the dependency-free default package.
