chore(lint): enforce web ↔ server import boundary (ban-web-server-imports)#4469
Merged
Conversation
The frontend (apps/mesh/src/web) ships as a separate bundle and talks to the
API over HTTP via @decocms/mesh-sdk. It may import backend *types* (erased at
build) but must not make *value* imports from server-only trees — those risk
pulling server runtime/secrets into the browser bundle and couple the UI to the
server's internal layout.
New oxlint plugin flags value imports (and re-exports / dynamic imports) from
apps/mesh/src/web into @/{storage,core,api,tools,auth,ai-providers,...}; allows
`import type` and frontend-safe trees (@/mcp-apps, @/web, @/lib, @/shared) and
workspace packages. Landed as "warn": 21 pre-existing violations across 20 files
to clean up incrementally (mostly tools/*/schema, ai-providers data, core
constants that belong in a shared contract surface). 9 unit tests.
Companion to ban-cross-tree-imports.js and ban-e2e-app-imports.js.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
pedrofrxncx
approved these changes
Jul 11, 2026
… cli gaps The blocklist was fail-open: a new server tree leaked into the browser bundle until someone remembered to add it, and it already missed `@/cli`. Flip to an allowlist of frontend-safe trees (web, mcp-apps, lib, shared) so new server dirs are guarded by default. Also resolve `../` relative climbs (not just `@/` alias imports) and skip web test files (never bundled). Same 21 pre-existing violations across 20 files — no new noise. 12 tests.
pedrofrxncx
enabled auto-merge (squash)
July 11, 2026 20:00
tlgimenes
pushed a commit
that referenced
this pull request
Jul 16, 2026
…TS.md (#4475) Mined ~300 merged PRs for the delta between the first PR proposal and the work added before merge. The dominant shape: a first draft ships the happy path, then a hardening pass (often a different engineer who takes over the branch and merges — the vibecoder→engineer handoff) adds the same categories every time. Encoded those 9 categories as an actionable first-pass checklist, each citing a real PR (#4008, #4230, #4365, #4409, #4426, #4445, #4357, #4355, #4449, #4350, #4373, #4416, #4446, #4461, #4134, #4469). Covers: variant/edge-case handling, tenant/permission scoping, concurrency & silent-data-loss, test-per-fix + invert-bug-tests + real-PG, dead-code/knip, lifecycle symmetry + state reset, kill-switch/GC/git-exclude for risky infra, input validation vs over-engineering, compile-time type-safety. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Summary
Adds an oxlint plugin,
ban-web-server-imports, that enforces the web ↔ server boundary insideapps/mesh— the cheap, enforceable version of "separate the frontend and API" (see the analysis in #4468, WI-12).Why not a full package split? The frontend and API are already separate at build (
build:client→dist/clientvsbuild:server), image (nginx-webcontainer vs Bun-apicontainer, independent tags —deploy/helm/studio/templates/deployment.yaml), and runtime (SPA calling the API over HTTP via@decocms/mesh-sdk, 207 files). The only shared thing is the source tree, and the coupling there is almost entirelyimport type(erased at build — end-to-end type safety is a feature we want to keep). A fullapps/websplit would break ~240 type imports for little runtime gain. The real risk is the handful of value imports that reach into server-only trees.What the rule does. Files under
apps/mesh/src/web/may not make a value import (or re-export, or dynamic import) from a@/<server-tree>/…specifier (storage,core,api,tools,auth,ai-providers,services,mcp-clients,event-bus,harnesses,sandbox, …). It allows:import type/import { type X }(erased), frontend-safe trees (@/mcp-apps,@/web,@/lib,@/shared), and workspace packages (@decocms/mesh-sdk). This makes the bundle/secret boundary real and gives frontend-vibecoding agents a hard fence.Landed as
warn(noterror) because there are 21 pre-existing violations across 20 files — all genuine leaks where a Zod schema / constant / pure helper lives on the server side and gets value-imported by the UI:@/tools/*/schema,registry/shared,registry-metadataconnection-sidebar.tsx→@/tools/connection/schema@/ai-providers(model lists, tiers)agent-models.tsx→CLAUDE_CODE_MODELS@/core(constants,org-archived)utils/constants.ts→@/core/constants@/api/routes/decopilot/mesh-storage-uriparseMeshStorageKey@/file-storage,@/commerce-discoveryThe fix for each is to move the shared value into
@/web/@/lib/@/shared/@decocms/mesh-sdk, or import it type-only. Once the list is drained, flip the rule toerror. (Confirmed the rule correctly ignores the 18 legit@/mcp-appsvalue imports — that tree is frontend code.)Testing
bun test plugins/ban-web-server-imports.test.ts→ 9 pass (bans value import / tools-schema / dynamic import / value re-export; allowsimport type, inlinetypespecifiers, frontend-safe trees, relative + workspace imports, non-web files).bun run fmtclean.Companion
Sibling to
plugins/ban-cross-tree-imports.js(packages ↛ apps/mesh) andplugins/ban-e2e-app-imports.js(e2e black-box wall). Part of the audit in #4468.🤖 Generated with Claude Code
Summary by cubic
Adds an oxlint plugin
ban-web-server-importsto enforce the web ↔ server import boundary inapps/mesh, blocking value imports from server-only trees into the web bundle. Lands aswarnto surface 21 violations while we move shared values; supports WI-12.New Features
@/web,@/mcp-apps,@/lib,@/shared); bans value imports, re-exports, and dynamic imports from otherapps/mesh/src/<tree>paths.@/and relative../climbs; skips web test files; allowsimport typeand workspace packages like@decocms/mesh-sdk..oxlintrc.json; adds 12 tests.Migration
@/web,@/lib,@/shared, or@decocms/mesh-sdk, or switch toimport type.errorafter cleanup.Written for commit 2096040. Summary will update on new commits.