Skip to content

fix(desktop): keep node:crypto out of the renderer's protocol barrel import graph - #4720

Closed
bytelazy wants to merge 1 commit into
apache:mainfrom
bytelazy:fix/renderer-node-crypto-protocol-barrel
Closed

fix(desktop): keep node:crypto out of the renderer's protocol barrel import graph#4720
bytelazy wants to merge 1 commit into
apache:mainfrom
bytelazy:fix/renderer-node-crypto-protocol-barrel

Conversation

@bytelazy

@bytelazy bytelazy commented Sep 4, 2026

Copy link
Copy Markdown

Summary

The Desktop renderer stays on the index.html preload skeleton forever when launched with vite dev. The renderer startup graph imports a value (MESSAGE_QUEUE_MAX_ENTRIES) from @maka/runtime-host/protocol, whose barrel export * re-exports client-capability.js. That module imported node:crypto for clientCapabilityEntityId. Vite dev does no tree-shaking, so evaluating the barrel evaluates client-capability.js in the browser, where the top-level node:crypto destructure throws and kills the renderer import graph before React mounts — with no terminal error.

The fix moves clientCapabilityEntityId (and its node:crypto import) out of protocol/client-capability.ts into a Node-only module packages/runtime-host/src/capability-entity-id.ts, re-exported as @maka/runtime-host/capability-entity-id (the same standalone-subpath shape as profile-kind). The three call sites (two Desktop main-process, one CLI) import it from there. The protocol barrel and every module it re-exports are now free of node: builtins, so the renderer can keep importing browser-safe values without evaluating node:crypto.

clientCapabilityEntityId had no unit test before; one is added so the moved behavior is pinned.

Verification of the root cause against the current tree:

  • packages/runtime-host/src/protocol/client-capability.ts:20 imported node:crypto, the only Node builtin in the barrel's export * closure.
  • A grep of every export * from './*.js' target in packages/runtime-host/src/protocol/index.ts confirms no other node: builtin remains.
  • The renderer imports MESSAGE_QUEUE_MAX_ENTRIES (value) from the barrel in session-workspace-actions.ts:38, which is what triggers module evaluation.

Fixes #4706

Verification

  • New unit test for clientCapabilityEntityId (5 cases): wire-safe passthrough, space/punctuation normalization, over-length truncation, digest distinction, explicit max length — all pass with node --test --experimental-strip-types (Node v24.20.0).
  • clientCapabilityEntityId references now point only at the new module and the three call sites; no call site still imports it from @maka/runtime-host/protocol.
  • client-capability.ts has no remaining node:crypto / createHash reference.
  • tsconfig.json (include: ['src'], rootDir: src, outDir: dist) compiles src/capability-entity-id.ts to dist/capability-entity-id.js, matching the added exports["./capability-entity-id"] — same pattern as the existing profile-kind subpath.

Not run: the full Desktop dev launch (npm run dev) and the runtime-host test:dist/typecheck, because a full workspace npm ci does not complete from this network. The change is a pure relocation with no logic change and a pinned unit test; a maintainer with the workspace installed can confirm npm run dev renders past the skeleton, and npm --workspace @maka/runtime-host run typecheck.

AI use

  • Generative tooling made a substantive contribution

Tool(s) and scope: Claude Code — traced the import chain to the node:crypto source, relocated clientCapabilityEntityId, updated the call sites and exports, and wrote the unit test. The commit carries a Generated-by: Claude (Claude Code) trailer.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

(The runtime-host typecheck/test suites are not runnable from this environment as noted under Verification; the new unit test passes locally via type-stripping.)

Does this PR entail a change in behavior?

  • Yes — the renderer can once again mount under vite dev, which it could not before.

…import graph

The renderer startup graph pulls a value import from @maka/runtime-host/protocol
(MESSAGE_QUEUE_MAX_ENTRIES in session-workspace-actions.ts). The barrel
re-exports client-capability.js, which imported node:crypto for
clientCapabilityEntityId. Vite dev does no tree-shaking, so evaluating the
barrel evaluates client-capability.js in the browser, and the top-level
node:crypto destructure throws — the renderer stays on the preload skeleton
forever with no terminal error.

Move clientCapabilityEntityId into its own Node-only module
(packages/runtime-host/src/capability-entity-id.ts) with the node:crypto
import, and re-export it as @maka/runtime-host/capability-entity-id (the same
shape as profile-kind). Point the three call sites (two desktop main, one cli)
at it. The protocol barrel and every module it export-* now has no node:
builtin, so the renderer can import browser-safe values from it without
evaluating node:crypto.

Add a unit test for clientCapabilityEntityId, which had none before, so the
moved behavior is pinned.

Fixes apache#4706

Generated-by: Claude (Claude Code)
@github-actions github-actions Bot added the effort/M Under 500 readable lines label Sep 4, 2026
@bytelazy

bytelazy commented Sep 4, 2026

Copy link
Copy Markdown
Author

Closing — #4705 landed the same fix (merged 2026-09-04 02:38 UTC) while this PR was still in the review queue. Same root cause, same approach (move clientCapabilityEntityId into a Node-only Runtime Host export), and #4705 is more complete: it also adds a protocol-compatible-changes entry and a vite-workspace-packages regression test that mine lacks. No reason to keep this open. Sorry for the duplicate — I should have checked recently-merged PRs, not just open ones, before opening this.

@bytelazy bytelazy closed this Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/M Under 500 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(desktop): npm run dev stuck on preload skeleton — protocol barrel pulls node:crypto into the renderer

1 participant