docs: document frontend/backend boundary rule and spec workflow
Add the "domain vocabulary lives in Rust" principle, the check:boundary pre-commit gate, and a spec-writing section pointing at the spec template and review checklist.
This commit is contained in:
@@ -39,6 +39,8 @@ only against the mirror if one exists; the canonical remote is
|
|||||||
|
|
||||||
- Frontend: `bun run check` and `bun run test` must pass.
|
- Frontend: `bun run check` and `bun run test` must pass.
|
||||||
- Rust: `cd src-tauri && cargo fmt` then `cargo clippy`, plus `bun run test:rust`.
|
- Rust: `cd src-tauri && cargo fmt` then `cargo clippy`, plus `bun run test:rust`.
|
||||||
|
- **Boundary**: `bun run check:boundary` must pass — no domain taxonomy (Jellyfin
|
||||||
|
item-type category sets) leaked into the frontend. See below.
|
||||||
- **Traceability**: new requirement-implementing code must carry a `// TRACES:`
|
- **Traceability**: new requirement-implementing code must carry a `// TRACES:`
|
||||||
comment (see below).
|
comment (see below).
|
||||||
- **Android source edits**: edit `src-tauri/android/src` (the canonical tree),
|
- **Android source edits**: edit `src-tauri/android/src` (the canonical tree),
|
||||||
@@ -161,6 +163,25 @@ and [docs/build-release.md](docs/build-release.md).
|
|||||||
- **Graceful backend init.** If a native player backend fails to initialize, the
|
- **Graceful backend init.** If a native player backend fails to initialize, the
|
||||||
app falls back to a no-op backend and emits `backend-init-failed` rather than
|
app falls back to a no-op backend and emits `backend-init-failed` rather than
|
||||||
crashing.
|
crashing.
|
||||||
|
- **Domain vocabulary lives in Rust.** The frontend is presentation-only and must
|
||||||
|
not encode Jellyfin's *taxonomy* — e.g. the set of item types that defines a
|
||||||
|
category like "Music". Send an opaque scope/enum across the boundary and let the
|
||||||
|
backend expand it. Single-type presentation (`itemType: "Movie"`, "this page
|
||||||
|
shows albums") is fine; a *category → set of types* mapping in `src/` is a leak.
|
||||||
|
`bun run check:boundary` is the tripwire; the real gate is the spec's layer
|
||||||
|
assignment. See [scoped-search-boundary.md](docs/specs/scoped-search-boundary.md)
|
||||||
|
for the incident this rule came from.
|
||||||
|
|
||||||
|
## Writing specs
|
||||||
|
|
||||||
|
New feature specs go in [docs/specs/](docs/specs/). **Start from
|
||||||
|
[SPEC-TEMPLATE.md](docs/specs/SPEC-TEMPLATE.md)** — its "Layer assignment" section
|
||||||
|
forces each piece of *logic* to be placed in the correct layer (Rust = domain,
|
||||||
|
frontend = presentation) *with a reason*, which is what prevents boundary leaks.
|
||||||
|
Before accepting a spec, run it past
|
||||||
|
[SPEC-REVIEW-CHECKLIST.md](docs/specs/SPEC-REVIEW-CHECKLIST.md). Do **not** frame
|
||||||
|
a spec around "no Rust changes required" — correct layer placement is the goal,
|
||||||
|
not minimal backend churn.
|
||||||
|
|
||||||
## Conventions
|
## Conventions
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user