feat(serve): desktop-app CORS + self-heal beacon re-arm and forcelist reconcile#42
Conversation
… reconcile Widen the loopback serve-surface CORS to desktop-app origins (Tauri built-in + DIG_NODE_CORS_APP_ORIGINS opt-in) and expose the X-Dig-* verification/provenance headers via Access-Control-Expose-Headers, so dig-urn-resolver's browser node-first path can read the Verified-by-Chia attestation instead of failing closed to rpc (#669). Add the always-on self-heal driver (privileged service only): on startup + a 6h tick it re-arms a drifted beacon schedule (dig-updater schedule ensure, opt-out-respecting) and reconciles the ext-forcelist channel-follow state (dig-installer --set-ext-forcelist-channel), resolving sibling CLIs by an absolute path from the admin-only #565 install root and rejecting a user-writable root (#584, #651). Minor bump 0.33.0 -> 0.34.0 (feat, backwards-compatible). Closes #669 #651 Refs #584 Co-Authored-By: Claude <noreply@anthropic.com>
731b4dc to
095f43a
Compare
|
Loop merge-gate: CHANGES-REQUIRED (loop-security HIGH, §565-class LPE) — fix incoming, do not merge. Triple gate: loop-reviewer PASS + adversarial CONFIRMED-SAFE (both flagged the item as non-blocking), but loop-security escalated it to a gate-blocker:
Fix (dispatched): replace the Everything else CLEAR (CORS read-only widening, 10 |
…e powershell spawn
The `windows_owner_is_privileged` LPE gate probed the install-root owner by
spawning `Command::new("powershell")` by BARE NAME. Windows resolves a bare
program name against the application directory (`current_exe()` parent = the
install root) BEFORE System32, so on a USER-WRITABLE root — the exact condition
this gate exists to REFUSE — a low-priv user could plant `<root>\powershell.exe`
and the SYSTEM service would execute it before the owner check returned,
undoing self_heal.rs's own "never a bare name" invariant.
Replace the spawn with a direct Win32 security-API read: `GetNamedSecurityInfoW`
(SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION) -> owner SID -> `ConvertSidToStringSidW`
-> exact SID EQUALITY against the well-known S-1-5-18 (LocalSystem) / S-1-5-32-544
(BUILTIN\Administrators). This launches no process, and the SID-equality match
replaces the old `\administrators` name-suffix (which a domain group literally
named "Administrators" could satisfy). Fails CLOSED on any read error.
Regression test plants a `powershell.exe` in a user-owned root and asserts the
probe classifies it not-privileged and executes nothing (no sentinel written).
Co-Authored-By: Claude <noreply@anthropic.com>
Records the new dig-node-service -> windows-sys dependency edge so the --locked CI clippy/build gates resolve without a lockfile update. Co-Authored-By: Claude <noreply@anthropic.com>
…timeout (#43) * feat(tls): TLS-root owner gate + leaf-rotation hardening + self-heal timeout Batches four #624/#42-arc follow-ups in dig-node-service. - #661: verify the TLS root is SYSTEM/Administrators-owned (Windows) or root-owned + not group/world-writable (unix) before reading the leaf or ca.key; fail CLOSED to plaintext otherwise. Extracts the spawn-free Win32 owner-SID reader from self_heal (#565) into a shared `security` module reused by both the LPE spawn gate and this TLS-root gate (DRY). - #660: set MissedTickBehavior::Delay on the daily leaf-rotation interval so a host sleep/suspend coalesces into one catch-up pass, never a burst. - #659: unit-test the rotation cadence, missed-tick behaviour, and the rotation action (fresh leaf untouched; leaf inside its 30-day window re-issued). - #693: bound each self-heal child spawn to a 120s timeout so a hung dig-updater/dig-installer child cannot stall future 6h passes; document the Tauri app-origin wallet-read CORS exposure in SPEC §4.3 (custody/sign stay token-gated; a route-scoped gate is not currently cheap). SemVer: minor (0.34.0 -> 0.35.0) — the #661 owner gate is a new backwards-compatible capability; the rest are hardening + tests. Closes #661 Closes #660 Closes #659 Closes #693 Co-Authored-By: Claude <noreply@anthropic.com> * fix(self_heal): kill child processes on timeout via kill_on_drop(true) The spawn_process function spawned privileged siblings (dig-updater, dig-installer) without kill_on_drop(true), so on CHILD_TIMEOUT elapse the child process was orphaned instead of killed. The with_child_timeout doc comment and error message claimed the child was "cancelled" but it was actually still running. Added .kill_on_drop(true) to the Command builder so tokio terminates the child when the timeout future is dropped. Updated doc comments and error text to accurately state the child IS killed on timeout. Fixes accuracy (accuracy/LOW per gate agents) and prevents slow orphan accumulation under wedged dependencies. Not a vulnerability (trusted absolute-path siblings, hang not attacker-triggerable), but hardens the implementation. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
Draft — WIP (cap insurance). Single dig-node family lane.
Closes #669 #651
Refs #584
Scope
Status
WIP. Privileged/serve-surface parts go through the dual gate + loop-security before merge. SYSTEM.md CORS/expose-header coherence flagged for the orchestrator.
🤖 Generated with Claude Code