3 Commits

Author SHA1 Message Date
Mert Koseoglu e9a7e69629 fix(assert-bundle): Windows entry-point detection (closes #525 windows ci)
CI run 25655545561 windows-latest failed on
  tests/scripts/assert-bundle.test.ts > exits 0 on a clean fixture bundle
  tests/scripts/assert-bundle.test.ts > exits 1 when given polluted fixture

with "expected '' to match /OK/" and "expected +0 to be 1" — assertions
that only fire if the script produces no output and exits 0 by default.

Root cause: the direct-invocation check at the bottom of the script used
string equality between two values that diverge on Windows:

  import.meta.url            = "file:///C:/path/to/assert-bundle.mjs"
  `file://${process.argv[1]}` = "file://C:\\path\\to\\assert-bundle.mjs"

The first has triple-slash + forward separators (URL form). The second
has double-slash + backslashes (template-literal of the OS path). They
never compare equal on Windows, the fallback `endsWith` likewise never
matches (URL has `/`, argv has `\`), so `isDirectInvocation` was always
false → main() never ran → script exited 0 silently.

The G3 invariant check (`npm run assert-bundle`) was therefore a no-op
on the windows-latest runner — bundles could ship polluted with the
`Dynamic require of` shim and the guardrail wouldn't catch it. This
also explained why the test "current production bundles pass the
assert-bundle clean check" passed-by-accident on Windows: exit 0 from
a silent no-op satisfies `expect(r.status).toBe(0)`.

Fix: use `pathToFileURL(process.argv[1]).href` so the entry-point
comparison is OS-agnostic. Both sides are now normalized to the
canonical `file:///C:/...` form on Windows and `file:///...` on POSIX.

Verified locally on macOS:
  $ npm run bundle && npx vitest run tests/scripts/assert-bundle.test.ts
   Test Files  1 passed (1)
        Tests  4 passed (4)

Bundles are intentionally not rebuilt here — CI step `npm run bundle`
regenerates them from source on every run.
2026-05-11 10:21:57 +03:00
Mert Koseoglu 675e63cc24 chore(ci): assert-bundle catches backtick + whitespace evasions
Review surfaced two evasion gaps in the G3 invariant regex:
1. Template-literal form: require(`node:fs`) slipped through
2. Whitespace expansion: require   (   "node:fs"   ) slipped through

Extend both patterns to allow optional whitespace around require/__require
and the parenthesis, plus accept backtick (`) as a valid quote character.
2026-05-11 10:06:29 +03:00
Mert Koseoglu 61f85398b1 chore(ci): slice 1 — assert-bundle script detects 'Dynamic require of' shim
G3 guardrail (Issue #511 class). Adds scripts/assert-bundle.mjs which
scans bundle files for the esbuild throwing-require shim and exits 1
if any forbidden pattern is matched.

Tracer-bullet RED→GREEN: fixture bundle containing the shim string is
correctly rejected.
2026-05-11 09:36:36 +03:00