ini file support and cover art
This commit is contained in:
+29
-17
@@ -81,7 +81,9 @@ audio metadata extraction. Its principal domain types are:
|
||||
|
||||
- `music-library`: a stable generated ID, display name, and absolute root path;
|
||||
- `browser-entry`: the name, kind, and root-relative path of a visible item;
|
||||
- `track`: the absolute source file and its display/playback metadata.
|
||||
- `track`: the absolute source file and its display/playback metadata;
|
||||
- `artwork`: MIME type and bytes read on demand from embedded tags or a
|
||||
conventional cover file beside the track.
|
||||
|
||||
Library loading is deliberately lazy:
|
||||
|
||||
@@ -155,7 +157,13 @@ server creates an opaque media token; the agent downloads that track to a
|
||||
temporary file and uses `racket-audio` for local playback. A stable 256-bit
|
||||
application ID and the agent-owned display name are persisted in its local INI
|
||||
file. The server follows the name advertised by the agent and does not own a
|
||||
separate name mapping.
|
||||
separate name mapping. Registration is default-deny: the application ID must
|
||||
be present in the server's `[playback-agents]` INI section. Unknown IDs receive
|
||||
HTTP 403 and cannot register, poll, or download agent media.
|
||||
|
||||
The server sends the next playlist item as a prefetch command. The agent keeps
|
||||
only the current and next downloads and queues the prefetched decoder at EOF,
|
||||
keeping network and polling latency outside the gapless transition.
|
||||
|
||||
### 3.5 Device discovery
|
||||
|
||||
@@ -176,7 +184,7 @@ are recorded in the shared player error field.
|
||||
### 3.6 HTTP and browser layers
|
||||
|
||||
[`private/server.rkt`](private/server.rkt) uses Racket's servlet web server. It
|
||||
serves static assets from [`public/`](public/) and exposes three JSON endpoints:
|
||||
serves static assets from [`public/`](public/) and exposes these API endpoints:
|
||||
|
||||
| Method | Route | Responsibility |
|
||||
| --- | --- | --- |
|
||||
@@ -186,10 +194,12 @@ serves static assets from [`public/`](public/) and exposes three JSON endpoints:
|
||||
| `POST` | `/api/agent/register` | Register or refresh a polling playback agent. |
|
||||
| `POST` | `/api/agent/poll` | Accept agent state and acknowledgements and return its next command. |
|
||||
| `GET` | `/api/agent/media/:app-id/:token` | Download the track currently assigned to an agent. |
|
||||
| `GET` | `/api/artwork/:artwork-id` | Return embedded or adjacent artwork for a playlist track. |
|
||||
|
||||
Responses use `Cache-Control: no-store`. Command failures are returned as HTTP
|
||||
400 JSON responses with an `error` property. Unexpected failures are currently
|
||||
reported through the same client-facing mechanism.
|
||||
JSON responses use `Cache-Control: no-store`; artwork has a private cache
|
||||
header. Command failures are returned as HTTP 400 JSON responses with an
|
||||
`error` property. Unauthorized agents receive HTTP 403 with the stable
|
||||
`agent-not-authorized` error code.
|
||||
|
||||
[`public/app.js`](public/app.js) implements a framework-free client. It:
|
||||
|
||||
@@ -274,7 +284,9 @@ file:
|
||||
- web listen address, defaulting to `127.0.0.1`;
|
||||
- web port, defaulting to `8080`;
|
||||
- DLNA media publication port, defaulting to `8734`;
|
||||
- one or more library root paths.
|
||||
- named library root paths under `[libraries]` (the legacy semicolon-separated
|
||||
setting remains supported);
|
||||
- allowed 256-bit playback-agent IDs under `[playback-agents]`.
|
||||
|
||||
Command-line network settings override INI values. Library paths from both
|
||||
sources are combined and de-duplicated.
|
||||
@@ -285,17 +297,17 @@ state, and all other mutable state.
|
||||
|
||||
## 7. Security and operational boundaries
|
||||
|
||||
The service has no authentication, authorization, TLS termination, CSRF
|
||||
protection, or per-user state. Anyone who can reach the HTTP port can inspect
|
||||
the exposed library names and control the shared player. The default localhost
|
||||
binding is therefore an important security boundary. Binding to a LAN address
|
||||
should be an explicit deployment decision and should use an external trusted
|
||||
network boundary or authenticated reverse proxy when untrusted clients are
|
||||
possible.
|
||||
The browser API has no user authentication, TLS termination, CSRF protection,
|
||||
or per-user state. Anyone who can reach the HTTP port can inspect the exposed
|
||||
library names and control the shared player. The default localhost binding is
|
||||
therefore an important security boundary. Binding to a LAN address should be an
|
||||
explicit deployment decision and should use an external trusted network
|
||||
boundary or authenticated reverse proxy when untrusted clients are possible.
|
||||
|
||||
Playback-agent IDs are random identifiers and media URLs additionally contain
|
||||
an opaque per-track token. They prevent accidental cross-agent media access but
|
||||
must not be treated as authentication when transported over unencrypted HTTP.
|
||||
Playback-agent registration and polling are authorized against a default-deny
|
||||
INI allowlist. Media URLs additionally contain an opaque per-track token. The
|
||||
random application ID therefore acts as a shared bearer credential, but must
|
||||
not be treated as strong authentication when transported over unencrypted HTTP.
|
||||
|
||||
The configured library roots define the intended filesystem boundary. Clients
|
||||
operate on opaque indexes instead of sending paths directly. The DLNA backend
|
||||
|
||||
Reference in New Issue
Block a user