feat(desktop): backport the baked EXTERNALLY-MANAGED marker to release/0.6.0 - #8857
Conversation
…ort to release/0.6.0) Cherry-pick of a21546a (#8799) onto release/0.6.0 so the 0.6.0 insider line regains edition auto-update: the baked marker is read from app.asar first and trusted as code on every platform, outranking a loose marker; build-desktop.sh step 3b validates and stages it; the managed-command lane pins the Windows shell, sets PYTHONNOUSERSITE=1 and derives KIROCREW_MANAGED_ARGV0; the tool-approval import chain no longer needs the cryptography wheel (lazy imports in wecom/weixin media and secrets/vault, decrypt moved off the event loop). Dropped from the backport: the fix(dashboard) SEL deny-path piece (sel.sel_is_warm() + _audit_denied's warm/cold split, test_api_health.py and test_sel_startup_warm.py). It hardens the direct-enqueue path that #8741 introduced on main; release/0.6.0 does not carry #8741, and its _audit_denied still runs every deny audit through asyncio.to_thread, so there is nothing to fix there. (cherry picked from commit a21546a)
UX Review (Fable 5) — ✅ PASSUX-level review of UX-Verdict: PASS No user-facing surface changes: build-time marker plumbing, electron update internals, and backend lazy imports — the one UX-adjacent effect (About-panel managed updates now working on Windows/user-owned installs) reuses existing, unchanged UI, and the build gate refusing a marker with no [UX-REVIEWED] d4788d0 |
Design Review (Fable 5) — ✅ PASSDesign-level review of Design-Verdict: PASS A sound backport: the baked-marker trust rests on an equal-power argument (rewriting app.asar already means rewriting the reader), the loose-marker provenance gate stays intact, and the build validator's duplicated caps are test-pinned to the reader's constants. [DESIGN-REVIEWED] d4788d0 |
First Principles Review (Fable 5) — ✅ PASSPremise-level review of All claims verified. Writing the review. First-Principles-Verdict: PASS A cherry-pick backport where every piece removes a named, branch-verified harm — including the one deliberately dropped, whose hazard provably doesn't exist here. What this change shipsIntent: let insiders on per-user edition installs (Toolbox, Homebrew,
The fix sits at cause level: #7959's gate structurally refuses every user-owned install, and build-time provenance is the answer to that gate, not a workaround beside it. The riders (items 8–9) shipped in the same merged main commit [FIRST-PRINCIPLES-REVIEWED] d4788d0 |
GPT 5.6 Review — 🔴 changes requested (blocking)GPT 5.6 found at least one blocking issue that must be resolved before merging This comment is updated in place on each push. BLOCKING -- website/electron/auto-update.js:1133 -- The pinned shell trusts a user-writable environment value |
Opus 4.8 Review — ✅ no blocking findingsReviewed Verdict parsed from the review's SHA-scoped output markers for commit False positive or not applicable? A repository writer can comment: |
Problem / Motivation
release/0.6.0(the current insider line,v0.6.0-insider.1) carries #7959's provenance gate on the looseEXTERNALLY-MANAGEDmarker but not #8799, which restores the edition auto-update path that gate closed. On a 0.6.0 insider build every per-user edition install (a Toolbox, Homebrew or~/Applicationstree) reads as bare: the updater is off, the About panel offers no update, the 30 s / 4 h background check never runs, and a remote Linux gateway hides its Toolbox provider.Why it matters
Insiders on an edition build cannot update through their package manager from inside the app until the next release line, and the internal edition's CR that wires its lanes to the baked marker fails closed against a core that does not read one. 0.6.0 is the line those editions ship on.
What changed (motivation → approach → change)
Straight cherry-pick of
a21546ae593bb5c076a0199a130dec346e06a5b9(#8799), same commit, same rationale -- see that PR for the design discussion and the reviewer rounds. In short:website/electron/auto-update.js-- a baked marker (__dirname/EXTERNALLY-MANAGED, insideapp.asar, packaged builds only) is read first and trusted as code on every platform, outranking a loose marker; the loose marker keeps fix(desktop): establish EXTERNALLY-MANAGED marker provenance before shelling it #7959's gate. The managed-command lane pins the Windows shell to%SystemRoot%\System32\cmd.exe(no inheritedCOMSPEC), setsPYTHONNOUSERSITE=1, and derivesKIROCREW_MANAGED_ARGV0 = process.execPathfor edition wrappers.packaging/build-desktop.shstep 3b --KIROCREW_MANAGED_INSTALL_MARKER=<json>is validated (string fields, reader caps,updateCommandrequired) and staged for the build only (EXIT trap armed before the copy; stale-marker cleanup ahead of theSKIP_ELECTRONexit).fix(hooks)--cryptographyimported lazily inwecom/media.py,weixin/media.py,secrets/vault.py, so the tool-approval import chain no longer needs the wheel; WeCom/Weixin decrypt runs throughasyncio.to_thread.package.jsonbuild.files,.gitignore, and the sharedtest/build-time-inputs.js.Dropped from the backport: the
fix(dashboard)SEL deny-path piece (sel.sel_is_warm(),_audit_denied's warm/cold split,test_api_health.pychanges,test_sel_startup_warm.py). It hardens the direct-enqueue path that #8741 introduced onmain;release/0.6.0does not carry #8741 and its_audit_deniedstill runs every deny audit throughasyncio.to_thread, so the hazard does not exist on this branch. Those four files stay at the branch's own versions (that was the only cherry-pick conflict).Tests
website/electron:node --testonauto-update.test.js/packaging.test.js/shell-contract.test.js-- 199 pass, 0 fail (baked-marker precedence and trust, unpackaged-build gate, constructed-env assertions incl. the pinned shell andKIROCREW_MANAGED_ARGV0,build.filesstaleness with the shared build-time-inputs set).test/test_build_desktop_managed_marker.py(18) -- step 3b accept / reject branches, trap-before-copy and cleanup-before-SKIP_ELECTRONordering, caps parity with the reader's constants.test/test_approval_chain_no_cryptography.py(3) -- the approval chain imports withcryptographyblocked; the decrypt helpers still raiseImportErroron use.test_wecom_media.py,test_weixin_media.py,test_api_health.py-- 144 Python tests pass together on this branch; flake8 and eslint clean.Manual verification
N/A beyond #8799's -- the diff is byte-identical to the merged commit minus the dropped SEL files; the edition-side lanes exercise it end to end once this is on an insider build.
Related Issues
no linked issue: backport of #8799 to the 0.6.0 insider line.
Pattern harvest
Not generalizable: a release-line backport of an already-reviewed change; the harvest lives on #8799.
Checklist
feat|fix|docs|refactor|perf|test|chore|ci|build|revert: ...)