# Kraken Player (Raspberry Pi)

Lightweight Raspberry Pi 5 player service for Whitecore.AI.

## Features (current)
- Pairing flow via licensing endpoints
- Device token storage
- Playlist and layout polling
- Media download cache
- Device control command polling + reporting
- Health + heartbeat reporting
- Basic layout HTML renderer (Chromium kiosk)

## Requirements (Pi)
- Raspberry Pi OS (64-bit)
- Chromium installed (`chromium-browser`)
- Optional: `vcgencmd`, `amixer`, `timedatectl` for system commands

## Config
Config file path (default): `/var/lib/kraken-player/config.json`

Example:
```json
{
  "apiBaseUrl": "https://api.dev.whitecore.ai",
  "deviceId": "pi-001",
  "deviceName": "Lobby Screen",
  "platform": "raspberrypi",
  "cacheDir": "/var/lib/kraken-player/cache",
  "renderer": "chromium",
  "chromiumPath": "chromium-browser",
  "heartbeatIntervalSeconds": 30,
  "playlistIntervalSeconds": 20,
  "commandIntervalSeconds": 10,
  "healthIntervalSeconds": 60,
  "allowSystemCommands": false
}
```

If `deviceId` is empty, the player will use `/etc/machine-id` or the hostname.

## Build
```bash
GOOS=linux GOARCH=arm64 go build -o kraken-player ./cmd/kraken-player
```

## Run (manual)
```bash
./kraken-player --config /var/lib/kraken-player/config.json
```

## Install (systemd)
```bash
sudo ./scripts/install.sh
```

### Install with env overrides
```bash
API_BASE_URL="https://api.dev.whitecore.ai" DEVICE_NAME="Lobby Screen" sudo ./scripts/install.sh
```

### Build a packaged release
```bash
./scripts/package.sh staging
./scripts/package.sh prod
```

## Pairing Flow
1. Player calls `/api/pair/request` and prints pairing code.
2. Admin approves in web portal (`/api/pair/confirm`).
3. Player polls `/api/pair/status` and receives device token.

## Auto-update

The player polls `GET /player/update/manifest` every `updateIntervalHours`
(default 6). If a newer build is published for its platform it downloads the
binary, verifies the sha256, swaps itself in place (keeping `<binary>.old`
for rollback), and re-launches. **Opt-in & safe by default:** no published
release for a platform = the manifest always says up-to-date, so the fleet
is untouched until a super-admin deliberately publishes one.

Publishing a release (super-admin):
1. `./scripts/package.sh prod` — note the printed `… binary sha256: …`.
2. Upload the raw binary to Spaces — manually, or via
   `POST /player/releases/<platform>/upload-url {version}` (returns a
   presigned PUT URL + the canonical `spacesKey`).
3. `PUT /player/releases/<platform> { version, sha256 }`. (`spacesKey` is
   always derived server-side from platform+version.)

Platforms: `linux-arm64`, `linux-amd64`, `windows-amd64`. The binary
installs under `/var/lib/kraken-player/bin` (service-user owned) so the
in-place rename works.

Update integrity: sha256 by default. Ed25519 signing is wired end-to-end and
opt-in: build with `KRAKEN_UPDATE_PUBKEY=<pubhex>` (package.sh pins it via
-ldflags) and register each release's `kraken-sign` signature; the player then
refuses any unsigned or mismatched update. Until a key is pinned it stays
sha256-only, so a super-admin who can write a `PlayerRelease` row can still
push code to every device (pin a key to close that). The player doesn't
independently verify CPU arch.

## Notes
- If the device token expires or is revoked, the player clears it and re-enters pairing.
- Set `allowSystemCommands=true` only when running on a real device.
