fix(release): the blockers and hardening from the 1.8.0 review - #174
Merged
Conversation
…ials
`openai-oauth` (ChatGPT) and `copilot-proxy` (GitHub Copilot) reached a
user's subscription by presenting GitHub's and OpenAI's own OAuth client
IDs (Iv1.b507a08c87ecfe98, app_EMoamEEZ73f0CkXaXp7hrann) and an
`Editor-Version: vscode/1.96.2` User-Agent against endpoints reserved for
first-party clients — api.github.com/copilot_internal and
chatgpt.com/backend-api. That shipped in a signed installer, so the risk
landed on our users' GitHub and OpenAI accounts.
Both vendors expose a sanctioned surface now, so this is a migration, not
an amputation:
- GitHub: the Copilot SDK, where we register our own OAuth App and pass
the user's `gho_` token. Their own client ID does not work against
copilot_internal, which is exactly why every tool on that path
borrows VS Code's.
- OpenAI: `codex app-server` (JSON-RPC over stdio), which inherits the
user's own `codex login` — no client ID ships at all.
Both are agent runtimes rather than /chat/completions, so they land in
their own PR. Removed here: the two registry entries, the four device
flows, the Copilot runtime-token swap, the `chatgpt-account-id` threading
through chat-service/caption-translate/chat-model, the bridge actions,
their contracts, and the device-challenge screen (the provider cards
themselves disappear with the registry entries). Credential blobs written
by an older build still load — getCredential() matches on a usable
`apiKey`, not on `kind`, so no migration is needed.
provider-registry.test.ts is the guard: it fails if a provider comes back
with a non-api-key auth kind or a first-party-only base URL.
…only STT server Four small hardening fixes found while reviewing release/1.8.0. DocumentService serialises saves of a project through a per-INSTANCE queue — its own writeProject comment records that this race destroyed two real project files. handlers.ts built a fresh instance for every runTimelineOperation, so a timeline op and a document.save ran on two queues against one path. temp+rename still kept the file valid JSON, so the symptom was a silently lost save rather than corruption. Hoisted to one instance, alongside LlmConfigStore, whose constructor was doing two sync readFileSync plus a safeStorage decrypt on every chat message. open-external-url passed the renderer's string straight to shell.openExternal, which hands it to the OS handler — `file:`, `ms-msdt:` and UNC paths are launch primitives there. Allowlisted to http/https/mailto. The native bridge marked every INTERNAL_ERROR retryable, including permanent ones, and forwarded error.message verbatim to the renderer, where main-process errors quote absolute paths into UI strings. Now non-retryable by default, path-redacted for the renderer, and logged in full on the main side. whisper-stt-server let OPENSCREEN_WHISPER_HOST override an explicit --host, so an env var could widen a shipped, unauthenticated server's bind address. It is now a fallback only, and refuses anything but loopback. Also gives the save-race test an explicit 30s timeout: 12 rounds of real fsync+rename take ~1.7s idle but exceed vitest's 5s default when the suite runs files in parallel — it failed in the full run and passed alone.
…nto installers Two ways this release could ship broken, and one obligation it was missing. CI never ran on this branch. ci.yml triggered on [main, feat/ai-edition] only, so PRs #167, #168 and #169 — 30k+ lines of deletion and refactor — merged into release/1.8.0 with lint, typecheck, tests, build and the PR-title check all skipped, and CodeRabbit reporting "reviews are disabled for this base branch". Added release/** to both triggers. The installers had no speech-to-text. electron/native/bin/ is gitignored and build-whisper-stt.yml publishes the binaries as artifacts of its own run; nothing carried them into build.yml. The model is downloaded at runtime, the binary is not, so resolveBinaryPath() would find nothing and transcription and captions would fail with a "build it via scripts/build-whisper-stt.sh" message shown to end users. scripts/stage-whisper-stt.sh now fetches them in all four build legs and fails the build if they are missing — a red build beats a silent one. Artifact retention 30 -> 90 days, since a release build now depends on it. Added THIRD-PARTY-NOTICES.md and shipped it (with LICENSE) into resources/. We redistribute FFmpeg's LGPL shared libraries and whisper.cpp; fetch-ffmpeg.mjs went to real lengths to keep the build LGPL rather than GPL, but nothing carried the attribution or the source offer into the installer. Also stops shipping the static ffmpeg.exe on Windows ("!win32-*/ffmpeg.exe"): the compositor addon dlopens the av*.dll set, but no runtime code spawns the exe — it is there for bench-export.mjs. It was adding a large binary and an LGPL obligation to every installer for nothing. Its licence-gate comment also still pointed at electron/media/ffmpegCapabilities.ts, deleted with the web export path. tsconfig.test.json makes the untypechecked half of the repo visible: tsconfig.json includes only src + electron and excludes **/*.test.ts, so no test file has ever been typechecked. It runs as an advisory CI job — 82 pre-existing errors, so gating on it today would just be red.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
continue-on-error left the job reporting "fail" on every PR forever. The run concluded success and merges were never blocked, but a check nobody can fix is a check everyone learns to ignore — which is worse than not having one. It now fails only when the count GROWS past a baseline, so the backlog stays visible in the job summary without crying wolf, and a PR that adds a new fixture-vs-schema drift is caught the day it lands. Baseline 80, measured on this branch; lower it when you fix some, delete the logic at zero.
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.
Findings from the review of
release/1.8.0(main…release = 164 commits, 563 files, +110k/−26k), applied. Three commits, reviewable independently.−1848 / +665. Most of it is deletion.
🚨 The installers had no speech-to-text
electron/native/bin/is gitignored, andbuild-whisper-stt.ymlpublishes the binaries as artifacts of its own workflow run. Nothing carried them intobuild.yml— its onlydownload-artifactsteps collect finished installers in the publish job. There is no runtime download either:modelManager.tsfetches the model,resolveBinaryPath()only probes paths and returnsnull.Result: transcription and captions — headline 1.8.0 features — would fail in every shipped build with
whisper-stt-server binary not found; build it via scripts/build-whisper-stt.sh, a developer message shown to end users.scripts/stage-whisper-stt.shnow stages them in all four build legs and fails the build if they are missing. A red build beats a silent one. Artifact retention 30 → 90 days, since a release build now depends on it.🚨 CI never ran on this branch
ci.ymltriggered on[main, feat/ai-edition]only.gh pr checksconfirms it: PRs #167, #168 and #169 — 30k+ lines of deletion and refactor — merged intorelease/1.8.0with lint, typecheck, tests, build and the PR-title check all skipped, and CodeRabbit reporting "reviews are disabled for this base branch". Addedrelease/**to both triggers.⚖️ Providers shipping borrowed vendor credentials
openai-oauthandcopilot-proxyreached a user's subscription by presenting the vendor's own OAuth client ID (app_EMoamEEZ73f0CkXaXp7hrann,Iv1.b507a08c87ecfe98) andEditor-Version: vscode/1.96.2against endpoints reserved for first-party clients. In a signed installer on the Microsoft Store and winget, so the exposure landed on our users' accounts.Both vendors now offer a sanctioned surface, so this is a migration, not an amputation — tracked in #173. Removed here because the constants had to leave the binary; hiding the UI would not have done it.
The eight API-key providers are untouched.
🐛 Lost saves on the timeline path
DocumentServiceserialises saves of a project through a per-instance queue — its ownwriteProjectcomment records that this race destroyed two real project files.handlers.tsbuilt a fresh instance for everyrunTimelineOperation, so a timeline op and adocument.saveran on two queues against one path. temp+rename still kept the file valid JSON, so the symptom was a silently lost save rather than corruption. Hoisted to one instance, alongsideLlmConfigStore(two syncreadFileSync+ asafeStoragedecrypt, on every chat message).🔒 Smaller hardening
open-external-urlpassed the renderer's string straight toshell.openExternal, which hands it to the OS handler —file:,ms-msdt:, UNC paths are launch primitives there. Allowlisted to http/https/mailto.INTERNAL_ERRORretryable and forwardederror.messageverbatim, so main-process errors quoted absolute paths into UI strings. Now non-retryable by default, path-redacted for the renderer, logged in full on the main side.OPENSCREEN_WHISPER_HOSToverrode an explicit--host, so an env var could widen a shipped unauthenticated server's bind address. Fallback only now, and loopback-only.📄 LGPL notice
fetch-ffmpeg.mjsgoes to real lengths to keep the build LGPL rather than GPL — pinned dated tag, SHA-256 before extract,-L/-buildconf/-encodersall checked. But nothing carried the attribution or the source offer into the installer.THIRD-PARTY-NOTICES.mdadded and shipped intoresources/withLICENSE.Also stops shipping the static
ffmpeg.exeon Windows: the compositor addon dlopens theav*.dllset, but no runtime code spawns the exe (verified —electron/media/ffmpegCapabilities.ts, its old runtime twin, went with the web export path). It was adding a large binary and an LGPL obligation to every installer for a file nothing opens.🧪 Test flake
document-service.test.ts > "leaves valid JSON when a long and a short save race"timed out at vitest's 5s default in the full run and passed alone in 1.7s — 12 rounds of real fsync+rename, sensitive to parallel load. Explicit 30s timeout: the "this actually hung" threshold, not the expected runtime.Verification
tsc --noEmitbiome check .vitest --runBaseline before this branch was 1108 tests with 1 failing.
Two things a reviewer should check
stage-whisper-stt.shpassesbash -n, the YAML parses, anddarwin-${{ matrix.arch }}matches the whisper workflow's tags — butgh run downloadhas not run for real. Worth oneworkflow_dispatchofbuild.ymlbefore cutting the RC, rather than finding out during the release.typecheck-testsis advisory on purpose (continue-on-error: true).tsconfig.jsonincludes onlysrc+electronand excludes**/*.test.ts, so no test file has ever been typechecked and 82 errors have accumulated. The job makes the drift visible and stops it growing; flip the flag off once the count is zero. Fixing all 82 here would have buried everything above.Also noted, not touched:
npm run i18n:checkalready fails onmain(missingcaptions.*keys inar). Unrelated to this branch and not part of CI.