monitor/API.md
fds2610-bot 857fc88834 Phase 1 der Neuausrichtung: REST-API fuer Tickets/Events/Systeme/KPIs/Agenten
Setzt Phase 1 aus Visualization.md um: Vanilla-PHP-REST-API mit SQLite-Persistenz,
statischen API-Keys pro Agent, Codeberg-Sync fuer Backlog/Done, PHPUnit-Tests und
vollstaendiger API.md-Dokumentation - Vorgaben aus Detailantworten.md (F1-F16)
umgesetzt. Entwicklung/Build/Test laufen komplett in Docker-Compose-Containern
(PHP 8.2 + SQLite + Composer + PHPUnit/pcov), analog zum NC-Gantt-Projekt ist auf
dem Host kein PHP/Composer noetig.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-27 19:38:52 +02:00

221 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# monitor REST-API (Phase 1)
Diese API ist die zentrale Schnittstelle, ueber die entfernte Agenten (Menschen oder
automatisierte Systeme) ihre Aktivitaet melden: Tickets anlegen/verschieben, Events melden,
Systemstatus berichten, KPIs eintragen und den eigenen Zustand aktualisieren. Sie ist Teil
von Phase 1 der Neuausrichtung (siehe [Visualization.md](Visualization.md), Abschnitt 9).
Implementierung: Vanilla-PHP (kein Framework), Persistenz in SQLite
(`api/data/monitor.sqlite`). Details zum lokalen Setup: [api/README.md](api/README.md).
## Inhaltsverzeichnis
- [Grundlagen](#grundlagen)
- [Authentifizierung](#authentifizierung)
- [Agenten](#agenten)
- [Tickets](#tickets)
- [Events](#events)
- [Systeme](#systeme)
- [KPIs](#kpis)
- [Codeberg-Sync (Backlog/Done)](#codeberg-sync-backlogdone)
- [Fehlerformat](#fehlerformat)
## Grundlagen
- Basis-Pfad: `/api/v1`
- Request-/Response-Body: `application/json`
- Alle Zeitstempel: ISO-8601 UTC (`YYYY-MM-DDTHH:mm:ssZ`), serverseitig erzeugt via
`Database::now()`, sofern nicht explizit im Request angegeben.
- Lesende Endpunkte (`GET`) sind oeffentlich, da sie das Frontend bedienen.
- Schreibende Endpunkte (`POST`/`PATCH`) erfordern einen Agenten- oder Admin-Key
(siehe [Authentifizierung](#authentifizierung)).
## Authentifizierung
Zwei Schluesseltypen, beide statisch (F14):
| Header | Verwendet fuer | Herkunft |
|---|---|---|
| `X-Admin-Key` | `POST /api/v1/agents` (Registrierung neuer Agenten) | Umgebungsvariable `MONITOR_ADMIN_API_KEY` |
| `X-Api-Key` | Alle anderen schreibenden Endpunkte | Wird bei der Agenten-Registrierung einmalig zurueckgegeben |
Der Klartext-API-Key eines Agenten wird **nur einmal** bei der Registrierung ausgegeben.
Gespeichert wird ausschliesslich ein SHA-256-Hash in SQLite (Tabelle `agents`,
Spalte `api_key_hash`) - der Klartext ist danach nicht mehr rekonstruierbar und muss vom
Agenten sicher verwahrt werden.
Fehlt oder passt ein Key nicht, antwortet die API mit `401 Unauthorized`.
## Agenten
Rollen (F1/F2): `entwickler`, `product_owner`, `qa`, `user`. Ein Agent bekommt bei der
Registrierung fest einen von `MONITOR_DESK_COUNT` (Standard 8) Schreibtischen zugewiesen
(niedrigster freier Index). Die Rolle `user` bekommt nie einen Schreibtisch (kein fester
Sitzplatz). Sind alle Schreibtische belegt, wird trotzdem registriert, aber ohne
Schreibtisch (`desk_index: null`).
### `POST /api/v1/agents` — Agent registrieren
Auth: `X-Admin-Key`.
```json
// Request
{ "display_name": "Alice", "role": "entwickler" }
```
```json
// Response 201
{
"agent": {
"id": 1, "display_name": "Alice", "role": "entwickler",
"desk_index": 0, "state": "idle", "current_ticket_id": null,
"created_at": "2026-07-27T10:00:00Z", "last_seen_at": "2026-07-27T10:00:00Z"
},
"api_key": "‹64 Hex-Zeichen, nur jetzt sichtbar›"
}
```
### `GET /api/v1/agents` — Alle Agenten
Response: `{ "agents": [ ‹Agent-Objekte wie oben, ohne api_key› ] }`
### `POST /api/v1/agents/{id}/activity` — Eigenen Zustand melden
Auth: `X-Api-Key` des betroffenen Agenten (ein Agent darf nur seinen eigenen Zustand
melden, sonst `403`).
```json
// Request
{ "state": "working", "current_ticket": 42 }
```
Response 200: aktualisiertes Agent-Objekt.
## Tickets
Spalten (F3): `backlog`, `bereit`, `in_arbeit`, `qa`, `testing`, `fertig`, `done`.
- `backlog` und `done` werden zusaetzlich regelmaessig aus Codeberg-Issues befuellt
(siehe [Codeberg-Sync](#codeberg-sync-backlogdone)), alle anderen Bewegungen ergeben
sich ausschliesslich aus Agenten-Meldungen (F4).
- Ticket-Typ und Farbe (statt Prioritaet) werden bei Codeberg-Tickets aus dem ersten
Issue-Label uebernommen (F4).
- Stapel-Darstellung ("aelteste 4 + Rest als Stapel", F4) ist reine Frontend-Logik;
die API liefert Tickets dafuer sortiert nach Spalte und Alter.
### `GET /api/v1/tickets` — Board-Zustand
Query-Parameter: `column` (optional, filtert auf eine Spalte).
Response: `{ "tickets": [ { "id", "external_ref", "title", "description", "column_name", "type", "color", "assignee_agent_id", "source", "created_at", "updated_at" }, ... ] }`
### `POST /api/v1/tickets` — Ticket anlegen
Auth: `X-Api-Key`.
```json
// Request (nur "title" ist Pflicht)
{ "title": "Neues Bug-Ticket", "description": "...", "column": "backlog", "type": "bug", "color": "#ff0000" }
```
Response `201` mit dem angelegten Ticket, `422` bei fehlendem `title` oder ungueltiger
`column`.
### `PATCH /api/v1/tickets/{id}` — Ticket verschieben/aendern
Auth: `X-Api-Key`. Erlaubte Felder im Body: `column`, `title`, `description`, `type`,
`color`, `assignee_agent_id` (alle optional, nur uebergebene Felder werden geaendert).
Response `200` mit dem aktualisierten Ticket, `404` falls unbekannt, `422` bei ungueltiger
`column`.
## Events
`severity`: `warning` (gelb) oder `error` (rot). Neuestes Event zuerst (F5).
### `POST /api/v1/events` — Event melden
Auth: `X-Api-Key`.
```json
{ "system_id": "srv1", "name": "Ping", "message": "Host nicht erreichbar", "severity": "error" }
```
Pflichtfelder: `name`, `message`, `severity`. `occurred_at` optional (Default: jetzt).
Response `201` mit dem gespeicherten Event.
### `GET /api/v1/events` — Event-Liste
Query-Parameter: `limit` (Default `5`, entspricht der im Plan festgelegten Zeilenzahl des
Event-Monitors, F5; Maximum intern 200).
Response: `{ "events": [ { "id", "system_id", "name", "message", "severity", "occurred_at", "created_at" }, ... ] }`
## Systeme
Bis zu 9 Kacheln (F6, `SystemRepository::MAX_TILES`), Fehler zuerst sortiert. Aktuell
werden Systeme zusaetzlich aus der bestehenden `status.txt` (geschrieben von
`check_fds.sh`) importiert; per API gemeldete Systeme (`source: "api"`) haben Vorrang und
werden vom Legacy-Import nicht ueberschrieben.
### `POST /api/v1/systems/{id}/status` — Systemstatus melden
Auth: `X-Api-Key`.
```json
{ "status": "ok", "name": "Webserver", "type": "host", "detail": "optional" }
```
`status`: `ok` oder `error`. Response `200` mit dem gespeicherten System, `422` bei
ungueltigem `status`.
### `GET /api/v1/systems` — Systemuebersicht
Response: `{ "systems": [ { "id", "name", "type", "status", "detail", "source", "last_check_at" }, ... ] }`
(maximal 9 Eintraege).
## KPIs
F7: Konkrete Kennzahlen sind noch offen ("kommt spaeter"). Phase 1 stellt nur die
generische Speicher-/Abfragestruktur bereit.
### `POST /api/v1/kpis/{key}` — KPI-Datenpunkt melden
Auth: `X-Api-Key`.
```json
{ "value": 12.5, "label": "Offene Tickets", "unit": "count", "timestamp": "2026-07-27T10:00:00Z" }
```
Pflichtfeld: `value` (numerisch). `label`/`unit`/`timestamp` optional. Response `201` mit
dem KPI inkl. Verlauf.
### `GET /api/v1/kpis` — Alle KPIs
Response: `{ "kpis": [ { "key", "label", "unit", "current_value", "history": [ { "value", "recorded_at" }, ... ] }, ... ] }`
## Codeberg-Sync (Backlog/Done)
`api/bin/sync-codeberg.php` (per Cron oder manuell auszufuehren) liest offene und
geschlossene Issues aus dem konfigurierten Codeberg-Repo (`CODEBERG_OWNER`/`CODEBERG_REPO`)
und gleicht sie ueber `external_ref` (= Issue-Nummer) mit den Tickets ab:
- Offene Issues → Spalte `backlog` (nur falls das Ticket noch in `backlog`/`done` ist -
manuell auf dem Board bewegte Tickets werden nicht zurueckgesetzt).
- Geschlossene Issues → Spalte `done`.
- Ticket-Typ/-Farbe kommen vom ersten Issue-Label (Name/Farbe).
Aufruf via Docker: `docker compose run --rm api php bin/sync-codeberg.php`.
## Fehlerformat
Alle Fehlerantworten haben die Form `{ "error": "‹Meldung›" }` mit passendem HTTP-Status:
| Status | Bedeutung |
|---|---|
| `400` | Ungueltige Anfrage (z. B. unbekannter Endpunkt-Parameter) |
| `401` | Fehlender/ungueltiger `X-Api-Key`/`X-Admin-Key` |
| `403` | Aktion nicht erlaubt (z. B. fremde Agent-Aktivitaet melden) |
| `404` | Ressource nicht gefunden |
| `405` | HTTP-Methode fuer diesen Pfad nicht erlaubt |
| `422` | Validierungsfehler (Pflichtfeld fehlt, ungueltiger Enum-Wert) |