overengineeringstudio / overengineeringstudio/effect-utils
Add export runtime-safety checks for package entrypoints
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 82
- Forks
- 2
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 121
Description
Parent context: #698 and #719
Problem
This repo now has package entrypoints that must be import-safe for different runtimes. For example, @overeng/notion-datasource-sync/cli/effect-command must remain safe for the Bun-compiled root notion CLI, while store/replica/runtime entrypoints may reach Node 24 node:sqlite. We need a principled gate so future exports cannot accidentally reach a forbidden runtime dependency transitively.
Direction
Prefer an Oxc/Oxlint-aligned implementation over dependency-cruiser. We already use Oxlint/Oxfmt, and the long-term check should stay close to that toolchain instead of adding an older standalone dependency graph stack.
Use two layers:
- Direct import guard in Oxlint now. Add
no-restricted-importsor a small local Oxlint JS plugin rule to ban directnode:sqliteimports outside explicitly owned datasource-sync runtime files. This gives fast editor/CI feedback for the simplest class of mistakes. - Oxc-powered export graph checker for transitive safety. Build a small repo-local checker that uses Oxc tooling to parse and resolve the module graph from package export entrypoints, then validates reachability against explicit runtime policy.
Do not rely on plain no-restricted-imports for the core invariant. Oxlint’s built-in rule is per-file/static-import oriented; the invariant we need is export-entrypoint reachability.
Proposed Implementation
Use the Oxc ecosystem as the graph substrate:
oxc-parser: parse TS/TSX quickly and collect ESM import/export metadata.oxc-resolver: resolve relative imports, package subpaths, TS paths, and packageexportswith Node-compatible semantics.- A repo-local policy file mapping package export subpaths to runtime classes.
Initial runtime classes:
type ExportRuntime = 'browser' | 'bun' | 'node' | 'node24-sqlite'
Initial policy sketch:
browser: no reachablenode:*, nobun:*, no Node-only workspace exports.bun: allow only a reviewed Bun-compatible builtin allowlist; explicitly denynode:sqlite.node: allow Node builtins exceptnode:sqlite.node24-sqlite: allownode:sqliteand requireengines.node >=24.
Concrete first classifications:
@overeng/notion-datasource-sync ./cli/effect-command:bun@overeng/notion-datasource-sync ./cli:node24-sqlite@overeng/notion-datasource-sync ./store:node24-sqlite@overeng/notion-datasource-sync ./replica:node24-sqlite
Algorithm:
- Read workspace package
exportsandpublishConfig.exports. - Assert source and publish export keys match.
- Resolve each export target, including conditional exports where relevant.
- Require every export to be classified in the explicit policy map. New exports fail until classified.
- Parse source files with
oxc-parserand collect static imports/re-exports plus any dynamic import forms we decide to support/fail on. - Resolve import specifiers with
oxc-resolverusing repo tsconfig/package export semantics. - Build a transitive closure per export entrypoint.
- Fail when a reachable builtin/package/export violates the declared runtime class.
- Print a readable path trace, for example:
@overeng/notion-datasource-sync ./cli/effect-command is declared bun-safe but reaches node:sqlite:
src/cli/effect-command.ts -> src/cli/main.ts -> node:sqlite
Oxlint Integration Shape
Start with a standalone devenv task because it naturally needs a whole-repo graph:
tasks."package:check:exports" = {
after = [ "pnpm:install" ];
exec = "bun run scripts/check-export-safety.ts";
description = "Check package export runtime/import safety";
};
Then decide whether to expose the same logic as an Oxlint JS plugin rule. Use an Oxlint plugin only if the plugin API can handle project-wide cached graph state cleanly without turning a per-file lint rule into a hidden global analysis pass.
Secondary Gates
Keep these separate from runtime-taint enforcement:
publint: package metadata, invalid exports, missing files, and package compatibility checks.@arethetypeswrong/cli: type resolution and ESM/CJS declaration compatibility.- Oxlint direct import rules: fast local guardrails for direct forbidden imports.
Acceptance Criteria
- New package exports fail until classified by runtime policy.
@overeng/notion-datasource-sync ./cli/effect-commandis enforced as Bun/root-CLI safe.node:sqlitereachability is allowed only from explicitly classified Node 24 SQLite exports.- Failures include a readable path trace such as
export -> file -> node:sqlite. - Direct Oxlint restrictions catch simple forbidden imports early.
- The transitive export-safety check runs as a devenv task and is included in the quick semantic gate once stable.
- The implementation uses Oxc/Oxlint-aligned tooling rather than dependency-cruiser unless Oxc resolver/parser blockers make that impractical.
Research Notes
- Oxlint
no-restricted-importsis useful for direct static imports but is not sufficient for transitive export reachability. - Oxlint supports JavaScript plugins, so a local rule is possible for direct or narrowly scoped checks.
oxc-parserexposes fast TS/JS parsing and module metadata.oxc-resolverprovides Node-compatible resolution including package subpath/export behavior.publintand ATTW remain valuable for package shape/type quality but do not enforce runtime/environment taint.
Posted on behalf of @schickling
| field | value |
|---|---|
agent_name |
🪩 co3-playa |
agent_session_id |
4a8a20a2-8712-4752-87fc-db098c203de6 |
agent_tool |
Codex CLI |
agent_tool_version |
0.131.0 |
agent_runtime |
Codex CLI 0.131.0 |
agent_model |
unknown |
worktree |
effect-utils/schickling/2026-05-25-notion-md-db |
machine |
dev3 |
tooling_profile |
dotfiles@4db6783 |
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the workspace package exports and existing devenv tasks, then review the proposed scripts/check-export-safety.ts entry point and the Oxlint/Oxc research notes. Trace the listed @overeng/notion-datasource-sync exports and their runtime classifications. Done means unclassified exports and forbidden transitive dependencies fail with readable path traces, with the check running as the package:check:exports task.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- build-system, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100