Wanted: install it and the two office cameras are already there - but without the release carrying their admin password where anyone with the zip can read it. "Encode it" does not achieve that; anything the installer can decode, anyone holding the installer can decode. pkg/demo seals the camera list with AES-256-GCM under a key that is NOT in the package: a 120-bit unlock code minted when the bundle is sealed, given to whoever runs setup by voice or message, typed once. The code is random, so it is key material directly through SHA-256; a human- chosen passphrase would need a KDF and a dependency, 120 random bits do not. The sealed file contains the format marker and noise. Tested: the password and the host do not appear in it, a wrong code and a flipped byte are both refused as ErrWrongCode, every seal differs. behavision-demo-pack seals; it runs on the build machine and is never shipped. The code is printed once and stored nowhere. behavision-setup, on finding demo-cameras.enc beside the engine source, asks for the code BEFORE the ten-minute download so a mistyped one costs seconds, and adds the cameras at the end - through the running engine's own Add Camera endpoint, not by writing its file. The store's save() is what applies DPAPI to the password on Windows, so this is how the credential ends up encrypted and machine-bound on the demo PC rather than in cameras.json for anyone who can read ProgramData. It then marks the PC standalone, so the app opens on Live instead of asking for an installation code it will never get. Which found the gap that DPAPI only works if pywin32 is importable, and nothing had ever pulled it in - every Windows install to date would have logged the warning and written camera passwords in the clear. Added as a Windows-only dependency. Verified in a clean container: a wrong code refused, the right one unlocks two cameras, every install step passes, both cameras added through the API, standalone set. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KGcjxF1cNLcuwc3DAPcnfj
200 B
200 B