diff --git a/companion/README.md b/companion/README.md index d0a5e22..6fbc2f5 100644 --- a/companion/README.md +++ b/companion/README.md @@ -4,7 +4,7 @@ This directory is the single Lumi Companion product boundary. The current milest Build prerequisites: the current .NET SDK with the .NET 8 targeting pack on Windows x64. The app targets .NET 8; .NET SDK 10 is recommended for Avalonia 12 source-generator compatibility. The native bridge additionally requires CMake, Visual Studio C++ tools, and the OBS 31+ SDK. -The app accepts a `.lumi-pairing.json` bootstrap package. A paired ZIP downloaded from Lumi contains the per-user Windows setup executable and one bootstrap file. Setup installs Companion under `%LocalAppData%\Programs\Lumi Companion`, imports the adjacent package, and launches the installed app. Companion exchanges the embedded token once, stores the returned device credential with Windows DPAPI, and removes the imported pairing file after success. Do not commit bootstrap packages, credentials, generated installers, build output, or logs. +The app accepts a `.lumi-pairing.json` bootstrap package. A paired ZIP downloaded from Lumi contains the per-user Windows setup executable and one bootstrap file. Setup installs Companion under `%LocalAppData%\Programs\Lumi Companion`, imports the adjacent package when this Windows user is not already paired, and launches the installed app. Existing portable installs retain the same current-user DPAPI credential instead of creating a duplicate device. Companion exchanges a newly imported token once and removes the pairing file after success. Do not commit bootstrap packages, credentials, generated installers, build output, or logs. The companion never performs ASR in this MVP. Audio is normalized to 16 kHz mono signed 16-bit PCM, held in bounded memory, and sent to the paired Lumi host over TLS WebSockets. HTTP/WS works only for a package generated from the exact matching loopback Lumi origin. The OBS bridge talks only to the companion over a same-user named pipe. diff --git a/companion/installer/Lumi.Companion.iss b/companion/installer/Lumi.Companion.iss index fb4483d..461e88f 100644 --- a/companion/installer/Lumi.Companion.iss +++ b/companion/installer/Lumi.Companion.iss @@ -52,6 +52,11 @@ var SourcePath: String; TargetPath: String; begin + { Portable and installed builds share the same DPAPI credential directory. Do + not create another authorized device merely because an existing user moves + the executable into its durable installed location. } + if FileExists(ExpandConstant('{localappdata}\Lumi\Companion\device.credential')) then + Exit; if FindFirst(ExpandConstant('{src}\*.lumi-pairing.json'), FindRec) then begin try diff --git a/companion/src/Lumi.Companion.App/CompanionRuntime.cs b/companion/src/Lumi.Companion.App/CompanionRuntime.cs index 4587a53..fa41459 100644 --- a/companion/src/Lumi.Companion.App/CompanionRuntime.cs +++ b/companion/src/Lumi.Companion.App/CompanionRuntime.cs @@ -104,6 +104,11 @@ public sealed class CompanionRuntime : IAsyncDisposable SetState(WithBridgeState(State with { Detail = "Download a pairing package from Lumi, then open it here." })); return; } + // An installer migration preserves the current-user DPAPI credential. If a + // bootstrap was copied alongside it, it is unnecessary and should not remain + // on disk where a later local reset could accidentally consume it. + var redundantPairing = FindBundledPairingPackage(); + if (redundantPairing is not null) try { File.Delete(redundantPairing); } catch { } SetState(WithBridgeState(State with { Paired = true, DeviceName = Environment.MachineName, Host = credential.Host, Detail = "Connecting securely to Lumi…" })); await ConnectAsync(credential); } diff --git a/plugins/lumi_transcription/companion_manifest.json b/plugins/lumi_transcription/companion_manifest.json index 0570c9c..6495a79 100644 --- a/plugins/lumi_transcription/companion_manifest.json +++ b/plugins/lumi_transcription/companion_manifest.json @@ -10,8 +10,8 @@ "label": "Windows x64 per-user installer", "filename": "Lumi.Companion-Setup.exe", "url": "https://git.rolfsvaag.no/Rolfsvaag_Datateknikk/Lumi/releases/download/companion-v0.1.0-experimental.7/Lumi.Companion-Setup.exe", - "sha256": "df64ef4071edac02a5bce14ab067c68590fcc981922c498cb65bc18749cdd437", - "bytes": 32034028 + "sha256": "a06319ecbda2369e0f756fb4429d95583a58a1c802ae3537cd44faf0032c3ded", + "bytes": 32037289 }, "artifacts": [ { @@ -21,8 +21,8 @@ "label": "Windows x64 self-contained", "filename": "Lumi.Companion-win-x64.zip", "url": "https://git.rolfsvaag.no/Rolfsvaag_Datateknikk/Lumi/releases/download/companion-v0.1.0-experimental.7/Lumi.Companion-win-x64.zip", - "sha256": "f5cbbe7fed80a216b3b8a2832000228c71fb117e757d2b3011eeba66c451403e", - "bytes": 41757364, + "sha256": "5578b61aafbcf40b84cfa846aa31f2e2ff49700f62692e00c8d0587eac0cb414", + "bytes": 41757402, "entrypoint": "Lumi.Companion.App.exe" } ]