## Purpose Desktop StudyDeck LAN publish: read-only HTTP catalog and course pack download for iPad. ## Requirements ### Requirement: Publish server lifecycle The desktop StudyDeck application SHALL provide a user-controlled LAN publish mode that starts and stops a read-only HTTP server exposing organized courses for download. The server MUST NOT require authentication. The UI MUST present trusted-LAN-only messaging while the server is running. #### Scenario: Start publish - **WHEN** the parent enables publish/share on desktop StudyDeck - **THEN** the app starts an HTTP listener on a default or fallback port and displays a base URL usable from an iPad on the same LAN #### Scenario: Stop publish - **WHEN** the parent disables publish or the desktop app exits - **THEN** the HTTP server stops accepting requests ### Requirement: Connection affordances While publish is running, the desktop app SHALL show at least the LAN IPv4 address, port, and a QR code encoding the base URL. #### Scenario: QR encodes base URL - **WHEN** publish is running - **THEN** the displayed QR code decodes to the same HTTP base URL shown in the UI ### Requirement: Course catalog API The publish server SHALL expose a JSON catalog of downloadable albums derived from the desktop album store, including both `playlist` and `combo` modes. Each entry MUST include stable `id`, `title`, `mode`, and `updatedAt`. Empty albums MUST NOT appear. Unsaved Explorer drafts MUST NOT appear until they are saved as albums. Orphan combo study sessions MAY be promoted into combo albums so they become listable. #### Scenario: List playlist and combo albums - **WHEN** a client calls `GET /api/courses` while publish is running - **THEN** the response is a JSON array of non-empty playlist and combo albums from the desktop album store, each with its real `mode` #### Scenario: Playlist included in catalog - **WHEN** the desktop store contains a non-empty playlist album - **THEN** that playlist album appears in `GET /api/courses` with `mode` equal to `playlist` #### Scenario: Catalog after saving an album from Explorer - **WHEN** the parent starts or saves a valid playlist or combo album from Explorer so that it is persisted - **THEN** a subsequent `GET /api/courses` includes that album ### Requirement: Course pack download API The publish server SHALL provide `GET /api/courses/:id/pack` that returns a zip archive containing a valid course pack for that album id, or a clear client error if the album is missing or media files are incomplete. Media entries in the zip SHOULD use store (uncompressed) method so large already-compressed media does not rely on client deflate inflate. #### Scenario: Pack succeeds for complete album - **WHEN** a client requests the pack for an existing playlist or combo album whose referenced media files exist on disk - **THEN** the server responds with a zip body and a success status #### Scenario: Pack fails when media missing - **WHEN** a client requests a pack for an album whose referenced media file is missing - **THEN** the server MUST NOT return a success zip and MUST return an error status suitable for client display ### Requirement: Health endpoint The publish server SHALL expose `GET /api/health` that indicates the service is StudyDeck publish and is reachable. #### Scenario: Health ok - **WHEN** a client calls `GET /api/health` while publish is running - **THEN** the response indicates success and identifies the publish service ### Requirement: Browser fallback list The publish server SHALL serve a simple HTML list at `GET /` that links to pack downloads for available playlist and combo albums. #### Scenario: HTML lists albums - **WHEN** a browser opens the publish base URL while albums exist - **THEN** the page lists those albums