Reference
Arch rules
The boundary policy enforced on the product codebase.
The product repo's architecture rules are not conventions — they're enforced
by tools/arch-policy.mjs, the single source for oxlint overrides and
ktb-arch/* rules.
The boundary
| Layer | May import | May NOT |
|---|---|---|
| Ports / plugins / domain packages | each other, effect, shared kernel | adapters, apps/, node:*/bun:*/deno:*/cloudflare:*/workerd:*, process/Bun/Deno, provider literals (@cf/*, endpoints) |
Adapters, apps/*, infra/*, @ktb/app-host | anything (the exempt edge) | — |
| Tests | domain code | adapter imports still banned; platform/provider rules exempt |
Consequences
- Plugins never import from
apps/— inject dependencies via route composition (apiobjects inapps/web/src/routes/). - Provider literals live only in adapters —
@cf/model ids, vendor endpoints,wrangler-isms. - Composition is explicit — plugin discovery is by convention
(
import.meta.globinpackages/app-host), wiring is in the app host.
Generated files
Never hand-edit: Paraglide output (src/paraglide/), routeTree.gen.ts,
drizzle migrations. They're regenerated by vp build/check and
db:generate.
If lint fails
The error names the rule (ktb-arch/*). The fix is almost always: move the
import behind a port, or move the file to the edge layer that owns it.