docs: add boundary violation fixture and document rule in COLLABORATING.md

Adds src/lib/tag/__fixtures__/cross-domain.fixture.ts — a permanent fixture
that demonstrates the boundaries rule firing on a tag → person import. The
fixture is excluded from npm run lint via --ignore-pattern; run
npm run lint:boundary-demo to see it produce an error (exit 1).

Documents the full allow-list, the escape hatches ($lib/shared/ move, explicit
rule entry, eslint-disable-next-line), and the verify command in COLLABORATING.md.

Refs #410
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-05-05 17:39:13 +02:00
committed by marcel
parent 4966855c24
commit 9cb44fc70c
2 changed files with 44 additions and 0 deletions

View File

@@ -185,3 +185,40 @@ Quick reminders:
- No premature abstractions — KISS beats DRY
- No backwards-compatibility shims for code that has no callers
- Validate at system boundaries only (user input, external APIs)
## Frontend Domain Boundaries
The frontend mirrors the backend's package-by-domain structure. Each Tier-1 folder under `src/lib/` is a domain with a hard import boundary:
```
document person tag user geschichte notification ocr
activity conversation shared
```
The `boundaries/dependencies` ESLint rule enforces this. The full allow-list lives in `frontend/eslint.config.js`. The rule fires at error severity and blocks `npm run lint`.
### Allowed cross-domain imports
| From | May import from |
|---|---|
| `document` | `shared`, `person`, `tag`, `ocr`, `activity`, `conversation` |
| `geschichte` | `shared`, `person`, `document` |
| `ocr` | `shared`, `document` |
| `activity` | `shared`, `notification` |
| `person`, `tag`, `user`, `notification`, `conversation` | `shared` only |
| `shared` | `shared` only |
| `routes` | any domain |
### When you need to cross a boundary
1. **Move the code to `$lib/shared/`** — the correct fix when the code is truly generic (a UI primitive, a pure utility, a formatting helper).
2. **Add an explicit rule** — if a cross-domain dependency is architecturally justified (e.g., `document` importing `PersonTypeahead`), add the allow entry to `eslint.config.js` with a comment explaining the reason.
3. **Use `// eslint-disable-next-line boundaries/dependencies`** — last resort, only for cases where neither option is practical. Leave a comment explaining why.
### Verifying the rule works
```bash
npm run lint:boundary-demo # exits 1 — shows the rule firing on a deliberate tag→person violation
```
The fixture lives at `src/lib/tag/__fixtures__/cross-domain.fixture.ts` and is excluded from `npm run lint` via `--ignore-pattern`.