Files
DeepSeek-Reasonix/internal/desktopinstance
SivanCola 9f286c6ee6 Fix Windows junction path identity and upgrade recovery / 修复 Windows Junction 路径身份与升级恢复 (#10656)
* fix: resolve Windows junction identities without breaking upgrade locks

Problem: Windows users whose existing data directory is a junction cannot
start sessions after configuration locks begin requiring physical identity.
Recovery also labels runtime-start failures as failed draft saves.

Root cause: EvalSymlinks can leave a junction leaf unchanged and reject its
children, splitting aliases or failing before the OS lock is acquired.

Fix: resolve existing Windows paths through native metadata handles, retain
legacy workspace lock spellings, isolate/rebuild derived catalog identities,
and separate historical draft submission errors from persistence errors.
Add a read-only probe and native regressions to the Windows PR selectors.
Preserve current eager session creation and authoritative user data formats.

Verification: owning Go suites, host/Windows golangci-lint, repolint, frontend
production/test typechecks, draft ownership and recovery regressions, real
Chromium recovery interactions, and Windows selector coverage passed.
Native Windows execution and complete upgrade qualification remain CI/manual
gates; cross-compilation does not establish those results.

* fix: preserve native Windows error kinds and verify historical lock spelling

Problem: native Windows CI rejected dangling-link and loop error kinds, and
the legacy-lock fixture expected the unexpanded runner temporary path.
The recovery UI also exceeded an almost exact startup-byte budget.

Root cause: os.IsNotExist does not traverse arbitrary wrapping, native
reparse exhaustion uses ERROR_CANT_RESOLVE_FILENAME, and EvalSymlinks expands
8.3 ancestors even when it preserves a junction leaf.

Fix: use wrapped-error matching and the native reparse-loop code; derive the
fixture's legacy key with the historical filesystem algorithm. Keep all
rejection and lock assertions. Remove a duplicated browser invocation.
Adjust only the raw startup ceiling to the measured producer size: same
source/dependencies/commit stamping adds 506 B raw (0.024%) and 120 B gzip;
Linux Electron measures 2103802 B, rounded to 2054.5 KiB.

Verification: pathidentity, workspacelease and probe tests; host/Windows
lint; repolint; bundle budget; same-toolchain base/candidate production builds.
All compressed, chunk, CSS, locale and residency budgets remain unchanged.

* test: exercise native junction identity across Windows volumes

Problem: the reported regression crosses system and data volumes, while the
initial regression fixtures only created same-volume junctions.

Root cause: filesystem alias tests did not exercise drive-prefix changes.

Fix: create a temporary junction from the system temp drive to RUNNER_TEMP
and compare entry and missing-tail identities with the physical target.
Require the two-volume fixture on GitHub Windows runners. Single-volume
local machines still run the unconditional same-volume regression suite.

Verification: Windows-target lint and cross-compilation; the native Windows
PR lane is required to execute the cross-volume fixture.

* Preserve credential ACL recovery and bind artifact consumers to producer Node

Problem: native identity resolution blocked credential ACL repair before edit locking, and prepared frontend consumers selected different Node patch versions.

Root cause: FILE_READ_ATTRIBUTES requires permissions that legacy read-deny ACLs remove; floating Node majors resolve independently on hosted runners.

Fix: use zero-access metadata handles, keep read denials intact until credential recovery, cover linked and unrecorded ACL cases, and propagate the producer Node version to every artifact consumer without weakening verification.

Verification: pathidentity/config tests, Windows cross-compilation and golangci-lint, 40 workflow/artifact/selector tests, repolint and diff checks passed. Native Windows execution remains a CI gate.

* Bind memory screening consumers to their build Node version

Problem: a memory shard rejected the prepared build before running because its floating Node major selected a different patch version.

Root cause: the independent app-memory workflow owns a second producer-consumer identity contract.

Fix: propagate its producer runtime to shards and aggregation, preserving exact identity validation. Add a workflow regression for both consumers.

Verification: 51 workflow and memory protocol tests, repolint, and diff checks passed.

* Open Windows identity handles with exact native access rights

Problem: CreateFile with zero desired access still fails against legacy credential DENY RX ACLs.

Root cause: Win32 adds SYNCHRONIZE and FILE_READ_ATTRIBUTES, as already documented by the credential ACL recovery owner.

Fix: open a zero-access NtCreateFile handle that follows reparse points, use the native namespace for long/UNC paths, and translate NTSTATUS failures back to Win32 codes for existing error classification.

Verification: Windows compilation and golangci-lint, repolint, and diff checks passed. Existing save/load/revision tests require identity to resolve while content reads remain denied; native CI verifies this contract.

* Request valid metadata access for native Windows identity queries

Problem: NtCreateFile rejects a zero access mask, breaking ordinary Windows identity queries.

Fix: request FILE_READ_ATTRIBUTES without implicit synchronization; when an ACL denies that right, try READ_CONTROL, which file owners retain for security metadata. Neither handle grants content access or mutates the ACL. Preserve NTSTATUS classification and all denial assertions.

Verification: Windows compilation and golangci-lint, repolint and diff checks passed; Windows execution is required before qualification.
2026-09-22 19:29:56 +08:00
..