Files
atomic-design-poc/docs/reference/architecture/dependencies.md
T
ehoandClaude Opus 4.8 7d2a36ff22
CI / frontend (push) Successful in 2m11s
CI / storybook-a11y (push) Successful in 5m46s
CI / backend (push) Successful in 1m29s
CI / e2e (push) Successful in 2m55s
CI / semgrep (push) Successful in 1m1s
CI / api-client-drift (push) Successful in 2m5s
feat(arch): WP-38 — dependency graph + declarative boundaries (dependency-cruiser)
Adopt dependency-cruiser as the single declarative source for bounded-context +
atomic-layer boundaries, replacing the per-context no-restricted-imports blocks that
had to be hand-copied (and had left herregistratie uncovered). `.dependency-cruiser.js`
encodes context direction (everyone→shared, herregistratie→registratie, showcase→*),
domain-purity, contracts-import-nothing, ui↛infrastructure, ApiClient confinement, and
no-circular. `npm run dep:check` enforces (wired into ci-local.sh + the frontend CI job);
`npm run dep:graph` emits a committed mermaid context×layer graph. ESLint slimmed to
no-explicit-any + template a11y. Docs + new-context skill updated to the single source.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 13:51:04 +02:00

2.6 KiB
Raw Blame History

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

npm run dep:graph      # regenerates docs/reference/architecture/dependency-graph.md (mermaid)

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

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.