# Dependencies & boundaries How the app's **bounded-context** and **atomic-layer** boundaries are declared, enforced, and visualized (WP-38). One declarative source — `.dependency-cruiser.js` — both **guards** the edges and **draws** the graph, replacing the per-context `no-restricted-imports` blocks that previously had to be hand-copied (and that had left `herregistratie` uncovered). ## The rules (single source: `.dependency-cruiser.js`) **Bounded-context direction** — dependencies point inward; everyone may use `shared`, nothing imports `showcase`: | Context | May import | | ---------------- | ------------------------------------- | | `shared` | (base — no feature context) | | `auth` | `shared` | | `registratie` | `shared` | | `herregistratie` | `registratie`, `shared` | | `brief` | `shared` | | `beheer` | `shared` | | `showcase` | everything (sanctioned teaching page) | **Atomic-layer rules:** `domain/` is framework-free (no Angular); `contracts/` import nothing (pure wire DTOs, ADR-0001); `ui/` + `layout/` never import `infrastructure/` directly (reach data through an application store/command — type-only DTO imports are fine); the generated `ApiClient` is a value only inside `infrastructure/` (+ `shared/upload`). Plus **no circular** dependencies. Sanctioned exceptions: `shared/ui/debug-state` (dev panel) and `showcase`. ## See the graph ```bash npm run dep:graph # regenerates docs/reference/architecture/dependency-graph.md (mermaid) ``` [dependency-graph.md](./dependency-graph.md) is the generated, committed view — contexts × atomic layers, edges are real imports. It renders on the git host; regenerate + commit after a structural change. ## Enforce ```bash npm run dep:check # fails on any forbidden edge; part of `npm run ci` and CI ``` A violation prints the offending `from → to` and the rule name. `dep:check` runs in the local gate (`scripts/ci-local.sh`) and the `frontend` CI job. ## What still lives in ESLint Only the non-dependency rules: `@typescript-eslint/no-explicit-any` and the angular-eslint template accessibility bundle (see `eslint.config.mjs`). Everything about _who may import whom_ is in dependency-cruiser. ## Adding a context Add one `contextRule(...)` entry in `.dependency-cruiser.js` (and the tsconfig path alias + lazy route) — no more hand-copying ESLint blocks. The `new-context` skill covers the full checklist.