feat(policy): Enforce org-required local model downloads - #1836
Merged
Conversation
Managed users whose org requires local models (requiredLocalModels) now hit a blocking onboarding step right after sign-in: required whisper/parakeet models download sequentially with per-row progress and retry, Back/Skip are suppressed, and Continue is gated on disk truth. The step is latched into the session so a mid-download policy refresh cannot rebuild the route under the user, and a capture effect pulls a just-signed-in session back from the permissions step once the policy and disk checks settle. Already-onboarded users get a non-dismissable ControlPanel banner with an inline download action instead of a hard block. Disk truth drives both surfaces via useRequiredLocalModels; a new openwhispr-local-models-changed event re-checks after downloads and deletions anywhere in the window. Policy validation stays shape-only so future server-side model ids cannot invalidate the managed policy — unknown ids are filtered at enforcement time, with minAppVersion as the backstop.
The background download tray subscribes to all model download progress events, so it duplicated the required-models step's own progress pill and offered a cancel that cannot stick — the step auto-restarts org-mandated downloads, making the cancel silently ineffective. Drop row-creating events while the persisted onboarding session sits on the required-models step. Completions still pass so a pre-existing row from a resumed local-setup download can clear and activate normally.
policyRules is imported by SyncService, whose node-run tests stub a partial window. Importing ModelRegistry pulled in the settings and enterprise-identity stores, whose module scope calls window.setInterval when any window exists — crashing all 11 syncServiceFolders tests in CI at load time (they skip locally on the DB-binding ABI, which is why the local run stayed green). requiredLocalModelIds only needs the registry's model ids, so read modelRegistryData.json directly, the same pattern policyValidation.js already uses. This restores the lean module graph policyRules had before the requiredLocalModels feature.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Desktop half of enterprise-enforced model downloads (
requiredLocalModels):Onboarding gate — managed users with required models missing on disk hit a blocking
required-modelsstep right after sign-in: sequential auto-started downloads with per-row progress and retry, a dead-end alert card for repeated failures, Back/Skip suppressed, Continue gated on disk truth. The step is latched into the session (survives relaunch mid-download), and a capture effect pulls a just-signed-in session back frompermissionsonce the policy and disk checks settle. Guest path untouched.Fleet gate — already-onboarded managed users get a non-dismissable amber ControlPanel banner (mirrors the update-required banner) with an inline download action; it reappears if a required model is deleted later. Nag surface, not a hard block.
Plumbing — shape-only validation (
policyValidation.js) so future server-side ids can't invalidate the whole managed policy;requiredLocalModelIdsfilters to registry-known ids with a warning; shareduseRequiredLocalModelshook joins policy with disk truth; newopenwhispr-local-models-changedevent re-checks after downloads/deletions anywhere in the window. i18n keys in all 10 locales.Deploy order
Ships last: API → console → desktop release. Admins should then set Minimum app version ≥ this release.
Testing
npm test: 2812 pass, 0 fail (10 new: route insertion/ordering/clamping/progress, validator shape cases, selector filtering/set-difference)npm run typecheck,npm run lint,npm run format:check,npm run i18n:checkall clean