fix(exec): ship the SDK with the CLI instead of fetching it at run time - #601
fix(exec): ship the SDK with the CLI instead of fetching it at run time#601davidsu wants to merge 2 commits into
Conversation
The exec wrapper imported npm:@base44/sdk, so every `base44 exec` needed a live registry fetch from Deno. Wherever the npm registry is proxied behind a TLS-intercepting gateway that serves a CA certificate as its server certificate, Deno rejects the connection outright (CaUsedAsEndEntity) and exec fails — as do all 17 exec tests. Bundle the SDK into the runtime assets at build time and redirect the specifier there via the import map the runtimes already ship, the same way the functions runtime resolves base44:runtime. Import map entries resolve relative to the map, so this holds even though the wrapper runs from a temp directory. Verified with a cold Deno cache and no .npmrc — the failing form: the wrapper runs and the SDK loads with no network access, while the same invocation without the import map still fails at the registry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🚀 Package Preview Available!Install this PR's preview build with npm: npm i @base44-preview/cli@0.1.9-pr.601.c76ac1fPrefer not to change any import paths? Install using npm alias so your code still imports npm i "base44@npm:@base44-preview/cli@0.1.9-pr.601.c76ac1f"Or add it to your {
"dependencies": {
"base44": "npm:@base44-preview/cli@0.1.9-pr.601.c76ac1f"
}
}
Preview published to npm registry — try new features instantly! |
|
CI status: all functional checks green — Test on all four matrix legs (ubuntu/windows × npm/binary), Lint, Typecheck, Knip, Build, Package Preview Publish, Wix Gateway Proxy. The two red checks ( i.e. the package version is younger than the 14-day minimum-release-age the gateway enforces, so the Claude action can't install itself. That needs a pinned older Notably, the exec suite passing in this CI run is itself the proof of the fix: the wix-gateway-proxy step is active in these jobs, so |
The runtime import map points at the bundle, so a binary built from a partial dist would ship an exec that only fails once a user runs it. The assets archive already picks the file up; this just fails the build early when it is missing, like the other required assets. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Final CI state: every functional check green, all four test legs included (ubuntu/windows × npm/binary). The Remaining red: |
The bug
base44 execspawns a Deno wrapper whose first job isimport { createClient } from "npm:@base44/sdk"— a live registry fetch on every invocation. That breaks wherever the npm registry is proxied behind a TLS-intercepting gateway (the wix-embargo setup): the gateway serves its CA certificate as the server certificate, and Deno's TLS stack rejects a CA cert used as a server identity before consulting any trust store:No client-side configuration can fix that —
DENO_CERT,DENO_TLS_CA_STORE,NODE_EXTRA_CA_CERTS, keychain trust and--certwere all verified failing, because the rejection is about the certificate's role, not its trust. npm tolerates the same certificate, which is why only Deno breaks.Impact today: 14 of 17
exec.spec.tstests red on any branch on an embargo machine, and the same in CI — see main's run 31506489004 (104×CaUsedAsEndEntityacross all four matrix legs).The fix
Stop fetching at run time. The SDK is bundled into the runtime assets at build time, and the specifier is redirected there through the import map the Deno runtimes already ship — the same mechanism
function-manager.tsuses forbase44:runtime.infra/vendor/base44-sdk.tsexport * from "@base44/sdk")infra/build.tsdist/assets/backend-runtime/vendor/base44-sdk.jsbackend-runtime/import-map.jsonnpm:@base44/sdk→./vendor/base44-sdk.jssrc/core/exec/run-script.ts--import-mapto the Deno spawn (it passed none)src/core/assets.tsgetImportMapPath()No new dependencies:
@base44/sdkwas already adevDependency(^0.8.23), and the bundle is produced by the existing Bun build. Import map entries resolve relative to the map, which is what makes this correct even thoughrun-script.tscopies the wrapper to a temp file before running it.Verification
The interesting failure mode only appears with a cold Deno cache and no
.npmrc— a warm cache or a dev machine's~/.npmrc(which points Deno at an internal mirror) hides it, which is exactly why this looked CI-only. So the mechanism was proved directly, replaying the CLI's own Deno invocation with the shipped artifacts:base44global is live, zero network access--import-map→ still fails withCaUsedAsEndEntity(control, so the test can fail)Suite results on an embargo machine:
exec.spec.ts17/17 (was 3/17), full suite 732/732, typecheck / lint / knip clean.Decisions & trade-offs recorded
exec. Registry latest is 0.8.41 — bumping is a separate, deliberate call, not folded in here.npm:@base44/sdkget the vendored copy too. Deliberate: same benefit, one artifact.base44 execstill needs a working registry path — the general fix remains gateway-side (serve aCA:FALSEleaf signed by the existing embargo CA), which is being pursued separately with the platform team.--unsafely-ignore-certificate-errorswas rejected as a shipped default: it works and would also rescue user scripts, but it disables TLS verification for a host on every user's machine. If ever wanted, it should be an explicit opt-in env var.ensureNpmAssetsguard left alone. I first extended it to require the newvendor/dir and a test correctly caught that this breaks its one-time-bootstrap contract (local edits must survive). A published version always ships identical assets, so a same-version dir can never legitimately lack the bundle — the guard would have been ghost code. Dev machines usingbun linkstill needrm -rf ~/.base44/assets/<version>after changing assets, which is pre-existing and documented.Background and full evidence:
suss-tasks/exec_tests_broken_by_wix_embargo.md.🤖 Generated with Claude Code