Files
czcdr 8e2acfdffc fix: close the 18-item audit and adapt to DSH 0.2.2-rc.1 (2.0.14)
An external audit of 2.0.13 found that install state could lie: a partially
failed install was recorded as a success, a broken recorded path was vouched for
by a different working copy, and an expired lock was deleted out from under a
live process. Every finding shares one shape — the thing verified was not the
thing being delivered — so the fix in each case is to make the probe look at the
artefact that will actually be used, and to keep "cannot prove" distinct from
"proved false". All 18 items are addressed. No upstream component moved: REA
6.8.0 / Ghidra 12.1.4 / JDK 21 / apktool 3.0.3 / jadx 0.7.1 / Node 24.22.1.

Provisioning (scripts/setup.mjs)
- multi-file components are all-or-nothing: every entry must arrive, files are
  staged in <target>.staging and swapped in atomically only when complete, the
  previous directory is kept as .backup and restored if the swap or the probe
  fails, and the record carries one {id,version,sha256} per entry with the
  primary chosen by kind instead of by manifest order
- a recorded component is probed AT its recorded path (independent resolve
  context) and its version is checked against the manifest pin; JDK matches by
  major floor; an enabled Ghidra gate override is honoured so a plain setup can
  no longer silently re-pin over one
- JSON state files are written through writeJsonAtomic(); an unparseable
  setup.lock is replaced instead of throwing; --dry-run writes nothing at all
- Frida's native binding is repaired by naming the one package whose install
  script is load-bearing (npm rebuild frida) and then proved with
  import('frida') + enumerateDevices(); checked in main, so existing bundles
  (i.e. every upgrade) get fixed too, and reported as skip rather than failing
- the tar fallback passes filter='data' to Python's extractall

Runtime (bin/rea-shim.mjs)
- one definition of bundleUsable = loaded.ok && resolveRea(...).ok drives the
  launch decision, the --shim-status exit code and the repair path; an unusable
  bundle no longer wins against a working system REA, and status returns 78
- liveness outranks age for a running lock: a live pid is never deleted, an
  expired one is reported as in-flight-stale; locks with no pid keep the old
  time-based rule; setup heartbeats `at` from log(); shim->setup handoff uses a
  token (REA_BUNDLE_LOCK_TOKEN) instead of a pid

Dependencies (scripts/vendor-lock/, scripts/check-dependency-advisories.mjs)
- REA pins zod exactly at 4.4.3, which sits inside GHSA-mrhx-c7xc-m3w5; the
  closure is now replayed from an audited lock with npm ci and overrides to zod
  4.6.7 / minimatch 11.0.5 / glob 14.0.4, verified afterwards against 4.6.6
- an offline gate fails the build if the lock drifts back, and CI runs it

Host adaptation (scripts/host-compat.mjs)
- HOST_RELEASES 10 -> 16: 0.2.2-rc.1, 0.2.2-alpha.3, 0.2.1-rc.5, 0.2.2-alpha.2,
  0.2.1-rc.4, 0.2.1-rc.3, all three-source verified and in release-date order;
  engines.dsh and OUTSIDE_HOSTS unchanged

Also fixed while verifying (not in the audit)
- a bare-major pin ("21") was treated as a family prefix, so 25.0.5 counted as
  drift while setup counted it as satisfied; it is a floor, in all three files
- check-updates.ps1 no longer reports a false red: `rea doctor` exits non-zero
  for any unconfigured optional capability, so that exit code is now [upstream]
  and the parsed provider checks decide
- two new JSON reads went around the BOM-tolerant reader; routed through
  readJsonSafe

Tests: 154 (151 pass / 0 fail / 3 skipped), audit 24/24 hash-pinned clean,
dependency gate clean, host-compat 16 covered, verify-branch ALL CHECKS PASSED.
2026-11-06 23:08:33 +08:00
..