feat: harden model management and release gates - #53
Conversation
- add a managed search-api embedding install and status flow - block unverified GGUF loads by default and harden readiness checks - cover the new backend command and search-api paths with regression tests Tests: pytest, cargo tests
- add separate Settings cards for desktop and search-api semantic models - show model verification state and the advanced unverified-model override - point onboarding to Settings instead of implying setup was already completed Tests: vitest, UI gates
- add a version parity checker and wire it into CI and repo readiness - sync package, Tauri, Cargo, and generated OpenAPI release metadata - run Python dependency auditing through the managed search-api environment Tests: parity, audits, OpenAPI check, perf gates
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request focuses on hardening the model management and release gates within the application. It enhances security by managing the search API embedding model locally and blocking unverified GGUF loads by default. The changes also improve the user experience by clarifying the semantic-search setup and enforcing version parity across different components. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Ignored Files
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces significant hardening for model management and release processes. Key changes include adding a managed local installation flow for the search API's embedding model to prevent runtime downloads, blocking unverified custom GGUF models by default to enhance security, and adding version parity checks to CI. The UI in Settings has also been updated to provide a clearer and safer setup for semantic search. My feedback focuses on improving logging consistency within the search API components for better observability in production environments.
| print(f"Embedding service initialized: {model_name}") | ||
| print(f" Dimension: {self.dimension}") | ||
| print(f" Device: {self.model.device}") | ||
| print(f" Uses prefix: {self.uses_prefix}") | ||
| print(f" Local path: {self.model_path}") |
There was a problem hiding this comment.
For consistency with the rest of the application's logging, these print statements should be converted to logging.info calls. This ensures that initialization messages are properly captured and routed, which is important for monitoring and debugging. You will need to add import logging and logger = logging.getLogger(__name__) at the top of the file.
| print(f"Embedding service initialized: {model_name}") | |
| print(f" Dimension: {self.dimension}") | |
| print(f" Device: {self.model.device}") | |
| print(f" Uses prefix: {self.uses_prefix}") | |
| print(f" Local path: {self.model_path}") | |
| logger.info(f"Embedding service initialized: {model_name}") | |
| logger.info(f" Dimension: {self.dimension}") | |
| logger.info(f" Device: {self.model.device}") | |
| logger.info(f" Uses prefix: {self.uses_prefix}") | |
| logger.info(f" Local path: {self.model_path}") |
| cache_folder=self.model_dir, | ||
| local_files_only=True, | ||
| ) | ||
| print(f"Reranker initialized: {self.model_name}") |
There was a problem hiding this comment.
For consistency with the rest of the application's logging, please use the logging module instead of print() for initialization messages. This ensures that logs are properly captured and routed, which is important for observability.
You'll need to add import logging and logger = logging.getLogger(__name__) at the top of the file.
| print(f"Reranker initialized: {self.model_name}") | |
| logger.info(f"Reranker initialized: {self.model_name}") |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 214d89e16c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let _ = db.save_model_state( | ||
| "llm", | ||
| validated_path.to_string_lossy().as_ref(), | ||
| Some(info.id.as_str()), | ||
| None, |
There was a problem hiding this comment.
Store custom model state in a form startup can reload
Saving custom GGUF loads into model_state with model_id = info.id makes startup auto-load attempt load_model with that ID, but startup only uses llm_model_id and load_model resolves built-in catalog IDs under the managed models directory. That means custom model sessions now record state that cannot be replayed, so restart auto-load silently fails and the previously loaded custom model is never restored.
Useful? React with 👍 / 👎.
| .arg("--app-data-dir") | ||
| .arg(app_data_dir_str) |
There was a problem hiding this comment.
Respect app-data env override when running model manager
Passing --app-data-dir from get_app_data_dir() forces the manager to use the platform default path and bypasses the ASSISTSUPPORT_APP_DATA_DIR override supported by managed_embedding_model.py. In deployments/tests that set this env var to relocate data, Settings install/status writes and reads the wrong directory, while the search API continues checking the overridden directory and reports the model as missing.
Useful? React with 👍 / 👎.
- stub the managed embedding model status in the production smoke harness - override vulnerable transitive audit dependencies and refresh the pnpm lockfile - update the Linux Playwright snapshot to match the new Settings UI Tests: pnpm audit; production smoke
|




What
Why
How
Testing
pnpm run check:version-paritypnpm run ui:gate:staticpnpm testbash scripts/search-api/run-python.sh -m pytest -q tests/test_managed_embedding_model.py tests/test_search_api_endpoints.pycargo test --manifest-path src-tauri/Cargo.toml --test command_contracts --test path_validation --test permission_manifestpnpm run ui:gate:regressionpnpm run perf:bundlepnpm run perf:buildpnpm run perf:assetspnpm run perf:workspacepnpm run perf:memorypnpm run perf:lhci:prodenv -u DATABASE_URL pnpm run perf:dbenv -u DATABASE_URL pnpm run perf:db:enforceenv -u DATABASE_URL BASE_URL=http://localhost:3000 pnpm run perf:apipnpm run perf:summarypnpm run test:security:audit:rustpnpm run test:security:audit:pythonpnpm search-api:openapi:generatepnpm search-api:openapi:checknode scripts/ci/require-tests-and-docs.mjsRisk / Notes
lint-stagedis currently misconfigured for ESLint 9 because the repo does not expose aneslint.config.*file to the hook path; the required project gates above were run successfully before packaging these commitspgvector, so the validated local perf path here is the BM25/hybrid-ready setupPerformance impact
3188 ms, assets about1.13 MB, workspace ready82.7 ms, batch triage865.92 ms, memory delta0.006 MBLockfile rationale
src-tauri/Cargo.lockchanged only to stay aligned with the checked-in Rust/package state and release metadata sync in this hardening passScreenshots