Skip to content

test(no-cloud-guard): budget the whole-tree sweeps instead of timing out - #336

Merged
andrei-hasna merged 1 commit into
mainfrom
fix/no-cloud-guard-timeout
Jul 27, 2026
Merged

test(no-cloud-guard): budget the whole-tree sweeps instead of timing out#336
andrei-hasna merged 1 commit into
mainfrom
fix/no-cloud-guard-timeout

Conversation

@andrei-hasna

@andrei-hasna andrei-hasna commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

The no shipped source file imports the retired package guard has been failing CI intermittently with timed out after 5000ms. The assertion is not flaky — the test is larger than the default budget allows.

The scan is driven off package.json files, so it covers the bundled output in bin/, dist/ and dashboard/dist/ as well as the vendored connectors/ tree: 14,519 files, ~71MB per run. Its duration is governed by how much of that is still in the page cache, which a test cannot control. Warm and idle it is ~250ms; inside a full-suite run on a two-core runner it was observed at 7169ms.

Reproduced with taskset -c 0,1 bun test on the affected branch: 3977 pass, 1 fail, the guard timing out.

Changes

1. An explicit 60s budget on both whole-tree sweeps. This is the fix. A guard over everything the package ships is not a unit test, and on exceeding its budget it reports a timeout rather than the breach it exists to detect — the worst failure mode for a security guard, because to anyone skimming CI it is indistinguishable from a pass.

2. The import scan prefilters on raw bytes before decoding. Every specifier FORBIDDEN_IMPORT can match contains the package name verbatim, so Buffer.includes is an exact prefilter, not an approximation: any file the regex would match must contain those bytes. Halves the sweep warm by not decoding 71MB of mostly generated bundles.

Verification

Measured unpiped (cmd >file 2>&1; echo $?):

check exit
negative control — planted import of the retired package 1 (fails, names the planted path)
same file removed 0 (4 pass / 0 fail)
bun run typecheck 0
full suite, taskset -c 0,1 bun test 0 (3969 pass / 0 fail)
bun run secrets:scan:npmrc 0
bun run check:package-secrets 0

The negative control is the important one: it proves the guard still detects a breach rather than merely running faster. An A/B over the same 14,519 files agreed on the match set across three rounds.

Scope

Test-only; no product code changes. This flake is pre-existing on main and independent of #335 — neither this file nor src/cli/cli.test.ts is touched by that PR.

Known remaining flake, not addressed here

src/cli/cli.test.ts:453 list --json supports --limit and --offset pagination fails rarely with SyntaxError: JSON Parse error: Unterminated string. The payload is 237,506 bytes against a 64KB pipe buffer. I could not reproduce it in ~20 targeted attempts and a rerun of the same commit passed, so I have deliberately not shipped a speculative fix. Recommended follow-up: capture subprocess output via a file descriptor rather than a pipe in the run() helper. Three other test files share that sequential pipe-drain pattern (src/server/server-entry.test.ts, src/mcp/mcp.test.ts, connectors/tiktok-events-api/src/api/events.test.ts).


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

The `no shipped source file imports the retired package` guard failed CI
intermittently with "timed out after 5000ms". It is not a flaky assertion; the
test is simply larger than the default budget allows for. The scan is driven off
`package.json` `files`, which includes the bundled output in `bin/`, `dist/` and
`dashboard/dist/` as well as the vendored `connectors/` tree, so one run covers
14,519 files and ~71MB.

How long that takes is governed by how much of those 71MB is still in the page
cache, which is exactly the thing a test cannot control. Measured warm and idle
it is ~250ms, but inside a full-suite run on a two-core runner it was observed at
7169ms. Reproduced with `taskset -c 0,1 bun test`: 3977 pass, 1 fail, the guard
timing out. A cold cache on CI is the normal case, not the exception.

Two changes, in order of importance:

Both whole-tree sweeps now carry an explicit 60s budget rather than inheriting
the 5s default. This is the fix. A guard over everything the package ships is
not a unit test, and when it exceeds its budget it reports a timeout instead of
the breach it exists to detect — which is the worst possible failure mode for a
security guard, because it is indistinguishable from a pass to anyone skimming.

The import scan also prefilters on the raw bytes before decoding. Every
specifier `FORBIDDEN_IMPORT` can match contains the package name verbatim, so a
`Buffer.includes` test is an exact prefilter and not an approximation: any file
the regex would match must contain those bytes. That halves the sweep warm
(~250ms against ~300-380ms) by not decoding 71MB of mostly generated bundles to
answer a question whose answer is almost always "no match anywhere".

Verified the guard still detects a real breach rather than merely running
faster: planting a file that imports the retired package fails the suite and
names the planted path (exit 1), and removing it returns to 4 pass / 0 fail
(exit 0). An A/B over the same 14,519 files agreed on the match set across three
rounds. Full suite on two cores: 3969 pass, 0 fail. Typecheck clean.
@andrei-hasna
andrei-hasna merged commit a30f90b into main Jul 27, 2026
1 check passed
@andrei-hasna
andrei-hasna deleted the fix/no-cloud-guard-timeout branch July 27, 2026 14:09
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.

1 participant