Skip to content

feat: package and supervise desktop app server - #189

Merged
oratis merged 16 commits into
mainfrom
codex/desktop-sidecar
Aug 2, 2026
Merged

feat: package and supervise desktop app server#189
oratis merged 16 commits into
mainfrom
codex/desktop-sidecar

Conversation

@oratis

@oratis oratis commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Summary

  • bundle the app server as a single Node 22 CommonJS resource and package a target-specific Node runtime as a Tauri sidecar
  • supervise the sidecar in Rust and expose a typed renderer protocol client instead of renderer shell access
  • pin and checksum the release runtime, sign the nested executable before the app, and document measured packaging evidence

Validation

  • pre-commit: format, lint (0 errors; 3 pre-existing warnings), typecheck, 949 TypeScript tests passed / 12 skipped
  • desktop Rust: 33 tests passed
  • frozen lockfile install passed
  • renderer, sidecar, and runtime asset build passed
  • full local Tauri app build passed
  • packaged runtime + app-server initialize handshake passed with an empty PATH
  • nested runtime then app ad-hoc signing passed codesign --verify --deep --strict

Remaining release gates

  • Developer ID signing, notarization, and final DMG validation require release credentials and are not claimed here
  • the existing mac-agent renderer path remains as a compatibility fallback until the next migration PR
  • credential reads are not yet fully centralized behind the app-server boundary

@oratis
oratis changed the base branch from codex/app-server to main August 2, 2026 06:36
@oratis
oratis marked this pull request as ready for review August 2, 2026 06:40
@oratis

oratis commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

Review: approved ✅ — supply chain handled correctly

I looked specifically at the runtime-provenance question, since "bundle a Node binary" is where this kind of change usually goes wrong.

Verified

  • apps/desktop/scripts/prepare-runtime.mjs never downloads anything. It copies from DEEPCODE_NODE_RUNTIME (or process.execPath locally), so there is no build-time network fetch to hijack.
  • if (process.env.CI && !process.env.DEEPCODE_NODE_RUNTIME) throw — CI cannot silently package the runner's ambient Node. That's the guard that makes the pin meaningful rather than advisory.
  • release.yml verifies the downloaded archive with shasum -a 256 --check against a pinned NODE_SIDECAR_SHA256 before it becomes DEEPCODE_NODE_RUNTIME. Pin + checksum + fail-closed CI is the correct three-part answer.
  • Architecture handling is strict, not best-effort: lipo -archs is inspected and a mismatch throws rather than shipping a binary that fails at launch on a user's machine. The universal-target check requiring both slices is the right assertion.
  • Nested executable is signed before the app — required ordering on macOS; getting it backwards produces a bundle that passes local checks and fails notarization.

Operational note: NODE_SIDECAR_VERSION/NODE_SIDECAR_SHA256 are now a manual maintenance item — a Node security release means bumping both together. Worth a note wherever release steps live so the checksum doesn't get bumped without the version (or vice versa) in a hurry.

Renderer moving to a typed protocol client instead of shell access is the security win this enables; #209 tightens the capability set to match.

Validation: CI green (with the desktop bundle-resource stub for Rust checks); full suite green locally at the stack tip.

@oratis
oratis merged commit 6c7651e into main Aug 2, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant