# Plan: Add Snacks app to zima-apps ## Context `apps.md` lists "Snacks" (https://github.com/derekshreds/snacks) as a pending app. It is an automated video library encoder with hardware acceleration (NVENC, QSV, VAAPI, AMF). This plan has two parts: 1. Create the Snacks app definition 2. Update `apps.md` with agent instructions for future additions --- ## Part 1: Create `Apps/snacks/` ### Steps 1. **Create `Apps/snacks/` directory** from `_template` 2. **`docker-compose.yaml`** — adapt upstream `deploy-compose.yml`: | Field | Upstream value | ZimaOS target | |---|---|---| | `name` | n/a | `snacks` | | `image` | `derekshreds/snacks-docker:latest` | **Pinned version** — fetch latest release tag from GitHub, verify manifest exists | | `network_mode` | `host` | Keep `host` — required for cluster UDP broadcast discovery | | `privileged` | `true` | Keep `true` — required for `/dev/dri` access on QNAP/ZimaOS | | `devices` | `/dev/dri:/dev/dri` | Keep — VAAPI/QSV hardware acceleration | | `ports` | none (host mode) | Add `6767:6767` for web UI | | `volumes` | QNAP-specific paths | Parameterize as `/DATA/AppData/$AppID/...` | | `environment` | QNAP-specific ffmpeg path | Use default ffmpeg path; make jellyfin-ffmpeg path configurable | Security baseline (MUST): - `security_opt: ["no-new-privileges:true"]` - `cap_drop: ["ALL"]` - `deploy.resources.reservations` set to appropriate value High-risk settings that MUST be documented in README: - `network_mode: host` — required for cluster UDP broadcast - `privileged: true` — required for `/dev/dri` access - Device mount `/dev/dri` — GPU acceleration 3. **`README.md`** — document: - Purpose: automated video library encoder with hardware acceleration - Port: 6767 (web UI) - Volumes: media library, logs, config - High-risk settings with justification, alternatives evaluated, and risks - Hardware acceleration options (VAAPI, QSV, NVENC) - Cluster mode (UDP broadcast requirement) - Health check endpoint 4. **Image pinning**: Before merge, verify the image tag exists in Docker Hub registry (manifest check) 5. **Run validation**: `./scripts/validate-appstore.sh` 6. **Optional**: `HOW_TO_VERIFY.md` with integration test cases ### Risk Assessment - **High risk** due to `network_mode: host`, `privileged: true`, and device mounts - Must document all three in README per AGENTS.md §3 - Image must be pinned — no `:latest` ### Branch name `snacks/initial/add-video-encoder` --- ## Part 2: Update `apps.md` ### Changes Replace current content with a table format that includes: - Done/pending checkbox - App name - Source URL - Brief description - Agent instructions column (how to pick up this item) The file should serve as an agent-facing backlog — clear enough that an agent can read it, understand what is needed, and execute without additional prompting. ### Suggested format ```markdown ## Backlog | # | Done | Name | Source | What | Agent instructions | |---|---|---|---|---|---| | 1 | [ ] | Snacks | https://github.com/derekshreds/snacks | Automated video library encoder | Pick up, follow AGENTS.md §9 workflow, branch `snacks/initial/add-video-encoder` | ## Adding a new app 1. Copy `Apps/_template/` → `Apps//` 2. Set `name` in compose (lowercase + hyphen only) 3. Pin image to explicit version/tag (no `:latest`) 4. Add `x-casaos` metadata 5. Write `README.md` with purpose, ports, volumes, and risk justifications 6. Validate: `./scripts/validate-appstore.sh` 7. Run final validation before release: `./scripts/validate-appstore.sh --enforce-risk-docs` ``` --- ## Verification - `docker-compose -f Apps/snacks/docker-compose.yaml config` passes (no syntax errors) - No `:latest` references - `x-casaos` metadata complete - README documents all high-risk settings with justification - `./scripts/validate-appstore.sh` reports `Validation OK`