Skip to content

Guard the install a user gets, not the tree a contributor has - #257

Open
burakdede wants to merge 2 commits into
mainfrom
fix/256-no-native-published-closure
Open

Guard the install a user gets, not the tree a contributor has#257
burakdede wants to merge 2 commits into
mainfrom
fix/256-no-native-published-closure

Conversation

@burakdede

Copy link
Copy Markdown
Owner

Closes #256. Unblocks #86 and the rest of Phase 6.

The problem

check:no-native scanned the whole node_modules tree. It could not tell a build tool in a contributor's checkout from a native dependency shipped to users, so it refused Miniflare, a dev-only Cloudflare emulator that never reaches a published package, on the strength of a transitive sharp.

Why narrowing is the honest fix

Invariant 7 is "no Python, Docker, compiler toolchain, native add-on, model download, API key or account. Ever." It is a promise about someone installing Lorepack. sharp in a contributor's node_modules breaks none of it.

The check now reads the production closure of the published packages, which is exactly what a user gets. That makes it say something true and checkable instead of something broader and wrong.

I rejected the easier options on #256: an allowlist is a slope, and dropping the emulator would mean testing Worker handlers as plain functions, which cannot prove the Worker starts or the bindings work, and that is most of what #86 is for.

Narrowing a guard is only safe if you prove what survives

tools/arch/test/no-native.test.ts is the mutation, not the happy path. A test that only ran the check and expected zero would pass just as happily against a check that had stopped looking.

  • A published package declaring a native dependency fails it.
  • An install hook in one of our own packages still fails it.
  • The repository as it stands passes.

Both halves are checked, and they catch different things: manifests catch a native dependency the moment it is declared, when a reviewer is looking at the diff; the installed closure catches one that arrives transitively, which no manifest mentions. My first attempt read only the installed tree, and the mutation test caught that a declared-but-uninstalled dependency slipped straight through.

The dependency this admits

wrangler and miniflare, dev-only, recorded in dependencies.md with the reasoning and the checks.

workerd is native and ships a post-install script. It is declined, exactly as esbuild's already is in this repo, because the binary arrives through @cloudflare/workerd-<platform> optional dependencies instead. Verified by starting a Worker with live D1 and R2 bindings with the script refused, so pnpm install --ignore-scripts stays a true statement about this workspace.

What it buys, proven rather than asserted

packages/deploy-cloudflare/test/emulator.test.ts:

  • A Worker with live D1 and R2 bindings round-trips both in one request.
  • Two D1 databases have isolated storage, which is what makes testing a candidate projection meaningful rather than incidental.

Admitting a dependency to buy a capability and then not verifying the capability would be the worst of both, so that file exists.

Verified

pnpm verify green (17 checks), including check:no-native on the narrowed rule and the three guard tests.

`check:no-native` scanned the whole `node_modules` tree, so it could not tell a
build tool in a contributor's checkout from a native dependency shipped to users.
It refused Miniflare, a dev-only Cloudflare emulator that never reaches a
published package, on the strength of a transitive `sharp`.

Invariant 7 is a promise about someone installing Lorepack. The check now reads
the production closure of the published packages, which is what a user gets, so
it says something true and checkable rather than something broader and wrong.

Narrowing a guard is only safe if the part that matters is proven to survive, so
`tools/arch/test/no-native.test.ts` is the mutation rather than the happy path: a
published package declaring a native dependency must fail it. Manifests are read
as well as the installed closure, because the first catches a declaration the
moment it appears in a diff and the second catches one that arrives transitively.

`workerd` ships a post-install script, declined exactly as esbuild's is: the
binary arrives through platform optional dependencies, verified by starting a
Worker with live D1 and R2 bindings with the script refused.

Closes #256
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.

The Cloudflare emulator brings native code into the install tree, and check:no-native is right to refuse it

1 participant