Merged
Size
L
Change Breakdown
Bug Fix60%
Security25%
Maintenance15%
#63311fix(plugins): keep test helpers out of contract barrels

Test helpers removed from production contract barrels

Production contract barrels no longer export test-only helpers that were pulling vitest into the Slack plugin build, causing runtime crashes when the plugin loaded.

When the Slack plugin loaded at runtime, it threw a cryptic TypeError: Cannot read properties of undefined (reading 't') during configuration. The root cause: a test harness function was exported through the production barrel, and the bundler followed the import chain to pull vitest and testing utilities into the production dist.

Functions like createSlackOutboundPayloadHarness and createIMessageTestPlugin were sitting in production-facing export surfaces alongside genuine runtime code. The bundler had no reason to exclude them—they were exported, so they were bundled.

This fix moves test-only exports off the production contract barrels and onto separate surfaces. Shared test helpers that need these functions now load them through the bundled plugin test surface loader rather than repo-relative imports. The path normalization logic was hardened to reject empty, absolute, or traversing artifact paths.

Guardrails were added to catch this leak shape going forward. Test-only implementation files were renamed to *.test-harness.ts and *.test-plugin.ts to make their purpose unmistakable.

View Original GitHub Description

Summary

  • keep bundled plugin contract barrels runtime-only so test helpers do not leak into production surfaces
  • move Slack and iMessage test-only helpers onto test-api and route shared channel helpers through bundled plugin public/test surface loaders
  • keep the plugin guardrail lightweight while still covering Slack-style harness leaks, make the test-only filenames more explicit, and validate bundled artifact paths stay plugin-local

Changes

  • remove test-helper exports from extensions/slack/contract-api.ts and extensions/imessage/contract-api.ts
  • add/keep test-only exports on extensions/slack/test-api.ts and extensions/imessage/test-api.ts
  • add plugin-level contract barrel guardrails in src/plugins/contracts/plugin-entry-guardrails.test.ts
  • simplify the contract-barrel source scan to TypeScript source extensions actually used by bundled plugin contract barrels
  • remove the redundant Slack-specific channel guard now that the plugin-level guard covers that leak shape
  • update shared channel helpers to use loadBundledPluginTestApiSync(...) / loadBundledPluginPublicSurfaceSync(...) instead of repo-relative extensions/** imports
  • reject bundled plugin artifact paths that are empty, absolute, or traverse outside the plugin root while still allowing valid nested plugin-local paths like src/...
  • rename obvious test-only implementation files to clearer names like outbound-payload.test-harness.ts and imessage.test-plugin.ts

Validation

  • node scripts/run-vitest.mjs run src/plugins/public-surface-runtime.test.ts src/plugins/contracts/plugin-entry-guardrails.test.ts src/channels/plugins/contracts/channel-import-guardrails.test.ts extensions/slack/src/outbound-payload.test.ts extensions/imessage/src/test-plugin.test.ts src/plugin-sdk/facade-loader.test.ts src/plugin-sdk/facade-runtime.test.ts
  • pnpm build:strict-smoke
  • independent verify passes over general, tests, and silent-failure lanes during iteration

Linked Issues

  • Refs #62949
  • Refs #63239
© 2026 · via Gitpulse