# Spec: <feature name>

<!--
  Copy this file to docs/specs/<kebab-name>.md and fill it in. Delete the HTML
  comments as you go. The section that matters most for this project is
  "Layer assignment" — read its comment before writing it.

  Before merging a spec, run it past docs/specs/SPEC-REVIEW-CHECKLIST.md.
-->

**Status:** Proposed <!-- Proposed | Accepted | Implemented | Superseded -->
**Requirements:** <!-- UR-xxx → DR-yyy; allocate new DRs in requirements.md. -->
**UX spec:** <!-- link to the relevant ux-flows.md section, or "n/a". -->
**Supersedes / revises:** <!-- link any spec this changes, or delete this line. -->

## Summary

<!-- 2–4 sentences. What changes for the user, in plain terms. -->

## Motivation

<!-- Why now. The problem being solved. -->

## Layer assignment

<!--
  🔴 THIS IS THE SECTION THAT KEEPS THE ARCHITECTURE HONEST. Do not skip it, and
  do NOT reframe it as "how little backend work can we get away with."

  The project rule (CLAUDE.md, architecture/02-svelte-frontend.md): the Rust
  backend owns ALL business logic — auth, catalog, sessions, downloads, offline,
  playback, AND domain vocabulary (e.g. what Jellyfin item types the category
  "Music" means). The Svelte frontend is PRESENTATION ONLY: rendering, layout,
  navigation, view/order preferences, input handling.

  For each distinct piece of *logic* this feature introduces, put it in the table
  and name the layer it belongs to and WHY. "It's less work in the frontend" and
  "the backend already accepts this parameter" are NOT reasons to place logic in
  the frontend — the backend accepting a parameter does not make deciding that
  parameter's value a presentation concern.

  Litmus test for "does this belong in Rust?": Would this logic have to change if
  Jellyfin changed its API, added an item type, or altered a business rule? If
  yes, it is domain logic → Rust. Would it change if we redesigned the UI? If
  yes (and only yes), it is presentation → frontend.

  A past incident: scoped-search.md placed the item-type taxonomy (what "Music"
  means as a set of Jellyfin types) in the frontend because the backend already
  accepted an includeItemTypes filter. That was a boundary leak; see
  scoped-search-boundary.md. This section exists to catch that class of mistake
  at spec time, not in review three features later.
-->

| Logic / responsibility | Layer | Why it belongs there |
|------------------------|-------|----------------------|
| <!-- e.g. scope → item-types --> | Rust | <!-- domain vocabulary; changes with Jellyfin's API --> |
| <!-- e.g. group display order --> | Frontend | <!-- pure presentation; changes only if UI is redesigned --> |

<!--
  If a row is genuinely borderline, say so and give the tie-breaker you used.
  Borderline defaults to Rust for anything touching domain data or vocabulary.
-->

## Design

<!--
  How it works. Wire shapes for anything crossing the IPC boundary. Remember:
  - Command NAME must match the Rust fn name exactly.
  - Top-level params auto-convert snake_case → camelCase (Tauri v2).
  - Nested struct fields need #[serde(rename_all = "camelCase")].
  - Events are kebab-case.
  (See CLAUDE.md §IPC and architecture/04-type-sync-and-threading.md.)

  Regenerate bindings.ts from Rust types; never hand-edit it.
-->

## Out of scope

<!-- What this spec deliberately does NOT do. -->

## Acceptance criteria

<!-- Checkable statements. Include the standard gates: -->

- [ ] `bun run check` and `bun run test` pass.
- [ ] `cargo fmt` clean, `cargo clippy` clean, `bun run test:rust` passes (if Rust changed).
- [ ] `bun run check:boundary` passes (no taxonomy leak into the frontend).
- [ ] New requirement-implementing code carries `// TRACES:` comments.
- [ ] `bindings.ts` regenerated if Rust types changed.

## Testing

<!-- Rust: cargo test. Frontend: vitest, src/lib/**/*.test.ts. What to cover. -->

## TRACES

<!-- Suggested tags per new/changed piece: UR-xxx | DR-yyy | tests. -->

## Notes for the implementer

<!--
  - A parallel Claude session may be active in this repo — `git diff` before
    "repairing" unexpected changes (see project memory / CLAUDE.md gotchas).
  - Anything else non-obvious.
-->
