postUnpack did not run in the npmDeps fixed-output derivation, so prefetch-npm-deps couldn't find package-lock.json. preBuild runs in both the fetcher and main build, ensuring consistent CWD for the lock file lookup. Backend patch moved to prePatch/postPatch so it only applies in the main build. npmDepsHash values remain placeholders (lib.fakeHash).