Save worktree changes

This commit is contained in:
2026-07-25 02:29:19 +01:00
parent 8d3b7d557b
commit db9d718cd8
170 changed files with 11719 additions and 3414 deletions
+187 -3
View File
@@ -4,25 +4,134 @@
Player service base URL: `http://localhost:3001`
This document uses OpenAPI-style sections, but stays in plain markdown.
This document covers the player HTTP surface only. The admin dashboard exposes its own routes for screen commands and onboarding management.
Access note: most player endpoints are unauthenticated because they are meant to run inside a trusted deployment network. Anything that mutates state or writes files should be treated as internal-only unless you add your own auth layer in front of it.
When `PULSE_SIGNAGE_SHARED_SECRET` is set, the player pages sign same-origin API fetches with `x-pulse-page-auth`, and the web app signs server-to-player requests with `x-pulse-request-timestamp` plus `x-pulse-request-signature`. Page tokens auto-renew before expiry while the page stays active, and signed server requests are only accepted when their timestamp is fresh. If the secret is unset, those checks stay disabled for compatibility.
## Endpoints
### `GET /`
Returns a plain-text landing response for the player service.
Returns the player onboarding landing page.
Access: public within the trusted player deployment.
### `GET /onboard`
Returns the onboarding form page.
Access: public within the trusted player deployment.
### `GET /screen/{slug}`
Returns the rendered player page for a screen.
Access: public within the trusted player deployment.
### `GET /api/onboarding/status`
Returns the persisted onboarding status for a device.
Access: public within the trusted player deployment.
Query fields:
- `deviceId` required
### `GET /api/onboarding/screens`
Returns the list of screens available for onboarding.
Access: public within the trusted player deployment.
### `GET /api/onboarding/qr`
Returns an SVG QR code that points to the onboarding form.
Access: public within the trusted player deployment.
Query fields:
- `deviceId` required
### `POST /api/auth/page`
Renews the current page-auth token before it expires.
Access: internal to the player page and onboarding page. The request must include a valid `x-pulse-page-auth` header.
Response fields:
- `token`
- `issuedAt`
- `expiresAt`
### `POST /api/onboarding`
Binds a device to a screen and client name.
Access: internal-only. Protect this endpoint if the player service is reachable outside your trusted network.
Accepted request fields:
- `deviceId` required
- `clientName` required
- `screenSlug` required
Response fields:
- `deviceId`
- `clientName`
- `screenId`
- `screenSlug`
- `screenName`
- `playerUrl`
- `queued`
### `GET /api/media/config`
Returns the upload directory configured for the player service.
Access: internal-only.
### `PUT /api/media/{filename}`
Writes an uploaded file into the player upload directory.
Access: internal-only and write-protected behind your deployment boundary.
### `DELETE /api/media/{filename}`
Deletes a file from the player upload directory.
Access: internal-only and write-protected behind your deployment boundary.
### `GET /api/rtmp/session`
Creates or reuses an RTMP-to-HLS session for a source URL.
Access: internal-only.
Query fields:
- `source` required
- `disableAudio` optional
### `GET /api/rtmp/streams/{key}/index.m3u8`
Returns the RTMP session HLS manifest.
Access: internal-only.
### `GET /api/rtmp/streams/{key}/{fileName}`
Returns an RTMP HLS segment or related stream file.
Access: internal-only.
### `GET /api/screens/{slug}/playlist`
Returns the current playlist payload for a screen.
Access: public within the trusted player deployment.
Response fields:
- `screen`
- `playlist`
- `slides`
- `rssFeeds`
- `apiSources`
- `revision`
### `GET /api/screens/{slug}/connections`
### `GET /api/screens/{slug}/clients`
Returns the live player connection snapshot for a screen.
Access: public within the trusted player deployment, but it exposes live connection state.
Response fields:
- `screen`
- `screenSlug`
- `count`
- `connections`
- `degraded`
### `POST /api/screens/{slug}/commands`
Sends a command to the player connections for a screen.
Access: internal-only. The admin dashboard should remain the protected control surface for commands.
Accepted request fields:
@@ -31,21 +140,87 @@ Accepted request fields:
- `clientId` optional
- `blackout` optional when `command=blackout`
Command-specific fields:
- `url` for `redirect`
- `clientName` for `setclientname`
- `deviceId` for `setclientname`
Supported commands:
- `refresh`
- `reload`
- `redirect`
- `pause`
- `blackout`
- `previous`
- `next`
- `left`
- `right`
- `setclientname`
If `connectionId` or `clientId` is provided, the command targets a single player connection. Otherwise it is broadcast to all connections for that screen.
Response fields:
- `screen`
- `screenSlug`
- `command`
- `connectionId`
- `sent`
- `degraded`
## Response Shapes
### Onboarding Status Response
`GET /api/onboarding/status` returns an object with:
- `deviceId`
- `onboarded`
- `clientName`
- `screenId`
- `screenSlug`
- `screenName`
- `playerUrl`
### Onboarding Screens Response
`GET /api/onboarding/screens` returns an object with:
- `screens`
### QR Response
`GET /api/onboarding/qr` returns SVG markup.
### Upload Config Response
`GET /api/media/config` returns an object with:
- `uploadDir`
### RTMP Session Response
`GET /api/rtmp/session` returns an object with:
- `key`
- `playlistUrl`
- `disableAudio`
- `ready`
### Onboarding Write Response
`POST /api/onboarding` returns an object with:
- `deviceId`
- `clientName`
- `screenId`
- `screenSlug`
- `screenName`
- `playerUrl`
- `queued`
### Playlist Response
`GET /api/screens/{slug}/playlist` returns an object with:
@@ -53,6 +228,9 @@ If `connectionId` or `clientId` is provided, the command targets a single player
- `screen`
- `playlist`
- `slides`
- `rssFeeds`
- `apiSources`
- `revision`
### Connections Response
@@ -62,6 +240,7 @@ If `connectionId` or `clientId` is provided, the command targets a single player
- `screenSlug`
- `count`
- `connections`
- `degraded`
### Command Response
@@ -72,6 +251,7 @@ If `connectionId` or `clientId` is provided, the command targets a single player
- `command`
- `connectionId`
- `sent`
- `degraded`
## Data Models
@@ -113,11 +293,15 @@ If `connectionId` or `clientId` is provided, the command targets a single player
- `id`
- `clientId`
- `clientName`
- `deviceId`
- `label`
- `userAgent`
- `viewport`
- `page`
- `currentSlide`
- `currentSlideId`
- `currentSlideTitle`
- `paused`
- `blackout`
- `clientIp`
@@ -128,4 +312,4 @@ If `connectionId` or `clientId` is provided, the command targets a single player
## Notes
- The player API is the only surface documented here.
- Web UI/admin routes are intentionally omitted.
- Web UI/admin routes are intentionally omitted, except where the player service itself exposes onboarding and upload endpoints.
+27
View File
@@ -6,6 +6,8 @@ Player service websocket base URL: `ws://localhost:3001`
This document uses OpenAPI-style sections, but stays in plain markdown.
The `PULSE_SIGNAGE_SHARED_SECRET` setting does not change the websocket message format here. It is used to sign the player control socket URL and the server-side snapshot subscription; the message payloads themselves remain the same.
## Channels
### `GET /ws/screens/{slug}`
@@ -13,11 +15,15 @@ Player control channel.
This is the bidirectional socket used by the player page. The player sends status messages to the server, and the server sends commands back to the player.
Access: the player page must include a valid `auth` query parameter signed with the shared secret. The browser page refreshes this token automatically while it is active.
### `GET /ws/screens/{slug}/events`
Player snapshot channel.
This is the server-to-dashboard snapshot stream for live player connection state.
Access: internal-only. The web backend subscribes with signed request headers; browsers should not connect directly.
## Player Control Channel
### Messages from player to server
@@ -35,6 +41,8 @@ Example payload:
{
"type": "hello",
"clientId": "client-id",
"clientName": "friendly label",
"deviceId": "device-id",
"userAgent": "browser ua",
"page": "http://.../screen/demo",
"viewport": { "width": 1920, "height": 1080 },
@@ -52,6 +60,8 @@ Example payload:
{
"type": "state",
"clientId": "client-id",
"clientName": "friendly label",
"deviceId": "device-id",
"userAgent": "browser ua",
"page": "http://.../screen/demo",
"viewport": { "width": 1920, "height": 1080 },
@@ -66,6 +76,8 @@ Example payload:
}
```
The server recognizes `clientId`, `clientName`, `deviceId`, `userAgent`, `page`, `viewport`, `paused`, `blackout`, and `currentSlide` from player messages. When `currentSlide` is present, the player includes the active slide id, title, kind, and playlist signature.
### Messages from server to player
The server sends command messages with:
@@ -75,17 +87,21 @@ The server sends command messages with:
- optional `sentAt`
- optional `targetConnectionId`
- optional `blackout` for blackout commands
- optional `url` for redirect commands
- optional `clientName` and `deviceId` for client-name updates
Supported commands:
- `refresh`
- `reload`
- `redirect`
- `pause`
- `blackout`
- `previous`
- `next`
- `left`
- `right`
- `setclientname`
#### `refresh`
Asks the player to refetch the current playlist.
@@ -111,12 +127,19 @@ Example payload:
Use `false` to restore and `true` to blackout.
#### `redirect`
Requests the player page to navigate to a new location. The destination is supplied as `url` by the caller that forwarded the command.
#### `previous` / `left`
Moves to the previous slide.
#### `next` / `right`
Moves to the next slide.
#### `setclientname`
Updates the client name associated with the player session and onboarding record.
The command payload should include `clientName` and may include `deviceId` when the caller is updating a specific onboarding binding.
## Snapshot Channel
### Messages from server to client
@@ -142,11 +165,15 @@ The snapshot channel is server-to-client only.
- `id`
- `clientId`
- `clientName`
- `deviceId`
- `label`
- `userAgent`
- `viewport`
- `page`
- `currentSlide`
- `currentSlideId`
- `currentSlideTitle`
- `paused`
- `blackout`
- `clientIp`