diff --git a/docs/plans/2026-03-22-backend-agent-status-design.md b/docs/plans/2026-03-22-backend-agent-status-design.md new file mode 100644 index 0000000..249a033 --- /dev/null +++ b/docs/plans/2026-03-22-backend-agent-status-design.md @@ -0,0 +1,151 @@ +# Backend-Agent Status Slice Design + +**Goal:** Stabilize the current backend foundation and add the first small, real backend-agent status path without introducing database or MQTT dependencies yet. + +**Architecture:** The backend keeps its existing in-memory/runtime-only character, but gains stronger HTTP test coverage and a minimal player status ingestion endpoint. The agent reuses its internal health snapshot and posts a compact status payload to the backend on a timer, so the first end-to-end data flow is exercised before larger sync and broker work begins. + +**Tech Stack:** Go stdlib HTTP server/client, existing repo docs, existing agent health model. + +--- + +## Decision + +For the next slice, we intentionally do **not** implement full player registration, persistence, authentication, or MQTT. + +Instead we build a narrow vertical slice with these boundaries: + +1. harden existing backend routes and validation coverage +2. add `POST /api/v1/player/status` in the backend with shared error handling +3. add a small agent status reporter that periodically sends the current health snapshot +4. document the temporary v1-dev contract clearly so later persistence and auth can replace it cleanly + +## Why this order + +### Option A - Recommended: backend hardening, then minimal status path + +Pros: + +- least architectural churn for the current repo stage +- gives the project its first real backend-agent integration +- keeps risk low because the payload is small and derived from already tested agent state +- creates a natural foundation for later registration, revisions, and MQTT state + +Cons: + +- still not very visible to end users +- uses temporary in-memory handling on the backend + +### Option B - Agent-first connectivity expansion + +Pros: + +- fast to implement in the agent +- extends the new health model quickly + +Cons: + +- creates local connectivity logic without a meaningful server contract +- duplicates future work once the backend path exists + +### Option C - Bigger vertical slice with registration and status + +Pros: + +- closer to the eventual architecture +- more obviously “real” system behavior + +Cons: + +- too much surface area for the current codebase maturity +- would mix lifecycle hardening, API design, auth placeholders, and agent behavior at once + +## Scope + +### Backend + +- keep `GET /healthz`, `GET /api/v1`, `GET /api/v1/meta`, and the existing `message-wall` route +- add route-level tests for the existing endpoints +- expand `message_wall` validation tests to match the documented rules more closely +- add `POST /api/v1/player/status` +- accept a small JSON payload and respond with a compact acknowledgement +- no database write, no in-memory historical store yet beyond the request/response path unless needed for tests + +### Agent + +- keep the current lifecycle and health snapshot model +- add an HTTP status reporter component that transforms the snapshot into a backend payload +- send periodic status updates on a configurable interval +- keep failures non-fatal and log them as structured events +- no registration, no retries beyond the next normal interval, no MQTT yet + +## Proposed temporary API contract + +### Request + +`POST /api/v1/player/status` + +```json +{ + "screen_id": "info01-dev", + "ts": "2026-03-22T16:00:00Z", + "status": "running", + "server_url": "http://127.0.0.1:8080", + "mqtt_broker": "tcp://127.0.0.1:1883", + "heartbeat_every_seconds": 30, + "started_at": "2026-03-22T15:59:30Z", + "last_heartbeat_at": "2026-03-22T16:00:00Z" +} +``` + +### Response + +```json +{ + "status": "accepted" +} +``` + +### Notes + +- this is a dev-stage HTTP substitute for the richer future status/heartbeat model described in `API-MQTT-VERTRAG.md` +- the payload is deliberately derived from fields the agent already owns today +- later player identity, auth, richer connectivity flags, and persistence can evolve this contract without invalidating the current slice + +## Error handling + +- invalid JSON -> existing shared API error envelope with `400` +- missing `screen_id` or invalid timestamps -> shared API error envelope with `400` +- successful ingest -> `200` with compact acknowledgement +- agent-side send failures -> structured log event, but the agent keeps running + +## Testing strategy + +### Backend tests + +- route tests for `/healthz`, `/api/v1`, `/api/v1/meta` +- route tests for valid and invalid `POST /api/v1/player/status` +- broaden `message_wall` validation tests for version, unit, fit mode, duplicate slots, out-of-bounds slots, empty slots + +### Agent tests + +- reporter payload generation from `HealthSnapshot` +- status send success path using `httptest.Server` +- non-fatal error handling on send failure +- interval-driven reporting using injectable ticker/clock seams where needed + +## Out of scope + +- database persistence of player status +- player registration +- auth tokens +- MQTT broker integration +- screenshots and media sync +- admin UI visualization of the status data + +## Expected result + +After this slice, the repository still remains intentionally simple, but it gains: + +- hardened backend route and validation coverage +- the first real backend-agent HTTP interaction +- a cleaner base for later registration, sync, and MQTT work diff --git a/docs/plans/2026-03-22-backend-agent-status-plan.md b/docs/plans/2026-03-22-backend-agent-status-plan.md new file mode 100644 index 0000000..a169f26 --- /dev/null +++ b/docs/plans/2026-03-22-backend-agent-status-plan.md @@ -0,0 +1,249 @@ +# Backend-Agent Status Slice Implementation Plan + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**Goal:** Harden the backend HTTP foundation and add the first minimal agent-to-backend status reporting path. + +**Architecture:** The backend remains a small in-memory Go service with stronger HTTP and validation tests plus a narrow `POST /api/v1/player/status` contract. The agent reuses its internal health snapshot and periodically posts it over HTTP, logging failures without stopping playback/lifecycle behavior. + +**Tech Stack:** Go stdlib, existing `net/http` router, `httptest`, existing agent health model. + +--- + +### Task 1: Backend route coverage for existing endpoints + +**Files:** +- Modify: `server/backend/internal/httpapi/messagewall_test.go` +- Possibly create: `server/backend/internal/httpapi/router_test.go` + +**Step 1: Write the failing tests** + +Add focused tests for: +- `GET /healthz` returns `200` and `status=ok` +- `GET /api/v1` returns base info and tool list +- `GET /api/v1/meta` returns the documented tool route + +**Step 2: Run test to verify it fails** + +Run: `go test ./internal/httpapi -run 'TestRouter'` +Expected: FAIL because the new route tests do not exist yet or assertions fail. + +**Step 3: Write minimal implementation** + +Only add or adjust router/response code if the tests expose gaps. Do not refactor unrelated HTTP code. + +**Step 4: Run test to verify it passes** + +Run: `go test ./internal/httpapi -run 'TestRouter'` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add server/backend/internal/httpapi/*.go +git commit -m "Ergaenze HTTP-Tests fuer Basisendpunkte" +``` + +### Task 2: Message-wall validation matrix + +**Files:** +- Modify: `server/backend/internal/campaigns/messagewall/resolver_test.go` + +**Step 1: Write the failing tests** + +Add table-driven validation tests for: +- unsupported `version` +- invalid `unit` +- invalid `fit_mode` +- empty slot list +- duplicate `slot_id` +- out-of-bounds slot + +**Step 2: Run test to verify it fails** + +Run: `go test ./internal/campaigns/messagewall -run 'TestValidate'` +Expected: FAIL until the new cases are covered correctly. + +**Step 3: Write minimal implementation** + +Adjust validation only if tests reveal a real mismatch against `docs/LAYOUT-JSON.md`. + +**Step 4: Run test to verify it passes** + +Run: `go test ./internal/campaigns/messagewall -run 'TestValidate'` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add server/backend/internal/campaigns/messagewall/resolver_test.go server/backend/internal/campaigns/messagewall/resolver.go +git commit -m "Pruefe Layout-Validierung systematischer" +``` + +### Task 3: Backend player status endpoint + +**Files:** +- Modify: `server/backend/internal/httpapi/router.go` +- Create: `server/backend/internal/httpapi/playerstatus.go` +- Create: `server/backend/internal/httpapi/playerstatus_test.go` + +**Step 1: Write the failing tests** + +Add tests for: +- valid `POST /api/v1/player/status` returns `200` and `{"status":"accepted"}` +- invalid JSON returns the shared error envelope +- missing `screen_id` returns `400` +- malformed timestamps return `400` + +**Step 2: Run test to verify it fails** + +Run: `go test ./internal/httpapi -run 'TestHandlePlayerStatus'` +Expected: FAIL because handler and route do not exist yet. + +**Step 3: Write minimal implementation** + +Implement a small request struct, parse/validate it, and reuse the existing error/JSON helpers. Keep storage out of scope. + +**Step 4: Run test to verify it passes** + +Run: `go test ./internal/httpapi -run 'TestHandlePlayerStatus'` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add server/backend/internal/httpapi/router.go server/backend/internal/httpapi/playerstatus.go server/backend/internal/httpapi/playerstatus_test.go +git commit -m "Lege ersten Player-Status-Endpunkt an" +``` + +### Task 4: Agent status reporter payload + +**Files:** +- Create: `player/agent/internal/statusreporter/reporter.go` +- Create: `player/agent/internal/statusreporter/reporter_test.go` +- Possibly modify: `player/agent/internal/app/app.go` + +**Step 1: Write the failing tests** + +Add tests for converting `app.HealthSnapshot` into the HTTP payload and for a successful post to an `httptest.Server`. + +**Step 2: Run test to verify it fails** + +Run: `go test ./internal/statusreporter` +Expected: FAIL because package/behavior does not exist yet. + +**Step 3: Write minimal implementation** + +Create a small reporter with injected base URL, `http.Client`, and time source as needed. Keep the API narrow. + +**Step 4: Run test to verify it passes** + +Run: `go test ./internal/statusreporter` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add player/agent/internal/statusreporter/*.go player/agent/internal/app/app.go +git commit -m "Fuehre einfachen Status-Reporter fuer den Agenten ein" +``` + +### Task 5: Agent periodic reporting integration + +**Files:** +- Modify: `player/agent/internal/app/app.go` +- Modify: `player/agent/internal/app/app_test.go` +- Possibly modify: `player/agent/internal/config/config.go` +- Possibly modify: `player/agent/internal/config/config_test.go` + +**Step 1: Write the failing tests** + +Add tests that prove: +- reporting is triggered from the running app +- send failures are logged and do not stop `Run()` +- any new interval config gets sane defaults + +**Step 2: Run test to verify it fails** + +Run: `go test ./internal/app ./internal/config` +Expected: FAIL until integration exists. + +**Step 3: Write minimal implementation** + +Wire the reporter into the app loop with the smallest possible seam. Avoid broad lifecycle refactors. + +**Step 4: Run test to verify it passes** + +Run: `go test ./internal/app ./internal/config` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add player/agent/internal/app/*.go player/agent/internal/config/*.go +git commit -m "Melde Agent-Status periodisch an das Backend" +``` + +### Task 6: Documentation update for the new status path + +**Files:** +- Modify: `API-MQTT-VERTRAG.md` +- Modify: `DEVELOPMENT.md` +- Possibly modify: `README.md` +- Possibly create: `docs/PLAYER-STATUS-HTTP.md` + +**Step 1: Write the failing documentation check** + +Create a short checklist from the implemented contract and verify which docs are stale. + +**Step 2: Run the verification** + +Manual check against the implemented request/response payload and the chosen scope. +Expected: current docs are incomplete for the temporary dev-stage HTTP status path. + +**Step 3: Write minimal documentation updates** + +Document that the current dev slice uses a minimal HTTP status endpoint before the richer long-term API/MQTT model is fully built. + +**Step 4: Run verification** + +Re-read the changed docs and ensure wording matches actual code scope. + +**Step 5: Commit** + +```bash +git add API-MQTT-VERTRAG.md DEVELOPMENT.md README.md docs/*.md +git commit -m "Dokumentiere ersten HTTP-Statuspfad fuer den Agenten" +``` + +### Task 7: Final verification + +**Files:** +- No planned file changes + +**Step 1: Run backend tests** + +Run: `go test ./...` +Workdir: `server/backend` +Expected: PASS. + +**Step 2: Run agent tests** + +Run: `go test ./...` +Workdir: `player/agent` +Expected: PASS. + +**Step 3: Run builds** + +Run: +- `go build ./...` in `server/backend` +- `go build ./...` in `player/agent` +Expected: PASS. + +**Step 4: Run manual integration check** + +Start backend locally, run agent locally with example config, and confirm the backend receives `POST /api/v1/player/status` successfully. + +**Step 5: Commit if needed** + +Only if the verification step itself required code/doc adjustments.