fix(plugin-dev): resolve @objectstack/plugin-security from source in tests, shrink the alias registry - #10415
Merged
Conversation
… the alias registry
`dev-plugin.ts` boots the real SecurityPlugin through a dynamic
`await import('@objectstack/plugin-security')`, and the enforcement-warning test
deliberately leaves that chain unmocked. Without a source alias that import
resolved through `exports` to `dist/`, so the file's verdict was a function of
build state: on an unbuilt closure the whole file died at collection
(`Test Files 1 failed` / `Tests no tests`), and on a built-but-stale closure it
would have passed against the old artifact silently -- the quiet failure
`check:test-source-alias` exists to make impossible.
The alias goes in `vitest.config.ts`, not on the test's import specifier: a
config alias covers the production dynamic import too, because Vite resolves the
whole module graph through it. Aliasing the specifier instead was measured to
leave the two divergent and re-arm the clocked-window cost #10115 removed.
Aliasing a dep to source imports its entire surface into this package's
resolution domain, so plugin-security's own `formula` / `metadata-core` /
`platform-objects` imports are aliased with it. `platform-objects` publishes a
FILE-shaped `./plugin` subpath alongside directory-shaped ones, so that rule is
listed separately ahead of the enumerated group.
With the import off `dist/`, `@objectstack/plugin-security` comes off
`@objectstack/plugin-dev`'s entry in the shrink-only
`KNOWN_UNALIASED_TEST_IMPORTS` registry (10 -> 9), which the gate's
set-equality audit then requires.
Fixes #10112
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019bmVFqoQPq63zhKrxdYG1r
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 3 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #10112
packages/plugins/plugin-dev/src/dev-plugin.tsboots the realSecurityPluginthrough a dynamicawait import('@objectstack/plugin-security'), anddev-plugin-security-enforcement-warning.test.tsdeliberately leaves that chain unmocked — the real plugin'sinit()/start()phase split is the subject under test. With no source alias, that import resolved throughexportstodist/, so the file's verdict was a function of build state.Both directions of that were live:
Test Files 1 failed (1)/Tests no tests,Failed to resolve entry for package "@objectstack/plugin-security".check:test-source-aliasexists to make impossible, and this file is exactly its shape.What changed
Six alias entries in
packages/plugins/plugin-dev/vitest.config.ts, and one member off the shrink-only registry inscripts/check-test-source-alias.mjs('@objectstack/plugin-dev': 10 entries to 9).The alias goes in the config, not on the test's import specifier. A config alias covers the production dynamic import too, because Vite resolves the whole module graph through it — one entry beats an edit at either import site. Rewriting the test's line-51 specifier instead was measured and rejected: it leaves
dev-plugin.ts's dynamic import still pointing atdist/, so the two diverge, line 51 pre-warms a copy nothing uses, and the cold transform lands back inside a clocked test body. That line is untouched by this PR.Aliasing a dep to source imports its entire surface into this package's resolution domain (the gate's own "Where the walk goes" note), so plugin-security's
formula/metadata-core/platform-objectsimports are aliased with it — without them the resolution failure merely moves outward one package at a time.platform-objectspublishes a FILE-shaped./pluginsubpath alongside directory-shaped ones, so that rule is listed separately, ahead of the enumerated group.Measured
All readings through
scripts/pm/os-verify-lock.sh, exit codes captured before any pipe, at102b1c71c.Unbuilt closure (
pnpm installonly,packages/plugins/plugin-security/distabsent):Test Files 1 failed (1)·Tests no testsTest Files 1 passed (1)·Tests 4 passed (4)Test Files 1 failed | 5 passed (6)·Tests 54 passed (54)Test Files 6 passed (6)·Tests 58 passed (58)Built closure — the clocked-window cost that PR #10120 moved out of a timed body must not come back. Paired control, same built
dist, same box:testsphaseNo regression. For contrast, the rejected line-51 variant measured 476ms on bail #1 against the same artifact — a 17x regression, which is why it is not what landed.
Reverse verification — the green above is not vacuous. Collapsing the
./pluginrule into a prefix-matching bare entry (the exact trap rule 5 exists to catch) turnscheck:test-source-aliasred, on this diff, with the ENOTDIR signature:Restored and re-confirmed green afterwards.
Gates
Re-derived from the real diff rather than recalled —
node scripts/pm/dispatch-gates.mjswith no path arguments (2 path(s) vs merge base 900e48935), then every family it named, pluspnpm lint:check:test-source-aliascheck-test-source-alias OK — 72 packages with tests scanned; 61 registered as still resolving a workspace dep through dist/; 44 published subpath(s) resolved through every alias table.check:cross-package-test-inputsOK: 12 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob.check:slot-lookupslot-lookup ratchet holds: 107 unswept site(s) in 25 file(s), none newcheck:type-source-resolutioncheck-type-source-resolution OK — 76 packages with a tsconfig.json scanned; 51 registered...scripts/check-cross-package-test-inputs.mjsscripts/docs-audit/check-affected-docs.mjspnpm linteslint . --no-inline-config); both changed files confirmed in eslint's configured population via--format json(2 files linted, 0 errors, 0 warnings) rather than inferred from a bare exit 0Scope
No gate was weakened: no ceiling raised, no registry entry added or widened, nothing skipped, quarantined or retry-wrapped. The registry moves in the shrink direction only, which is the direction it documents as sanctioned. The test's assertions are byte-identical and its line-51 import is untouched in both specifier and position.
dev-plugin.tsis not modified.This PR carries
skip-changeset: it changes one package's vitest configuration (not published —plugin-dev'sfilesisdist/README/CHANGELOG) and one CI-internal script, so it releases nothing.check:type-source-resolutiontracks a separate tsconfig-level ledger that this change does not touch and does not claim to move.Generated by Claude Code