Aenderungen an Codeberg-Issues landeten bisher erst beim naechsten Lauf des
sync-Services auf dem Board (MONITOR_SYNC_INTERVAL, Default 600s). Neu meldet
Codeberg jede Aenderung aktiv per Webhook, der Weg aufs Board dauert damit
wenige Sekunden (Webhook -> Sync -> SSE-Push ans Frontend).
POST /api/v1/webhooks/codeberg wertet den Payload bewusst nicht aus, sondern
fordert nur einen regulaeren Sync an - CodebergSyncService bleibt die einzige
Stelle, die Issues auf Tickets abbildet, und ein verpasster Webhook ist
folgenlos, weil der periodische Lauf denselben Stand ohnehin nachholt.
Der Sync passiert nicht im Request: Forgejo bricht die Zustellung nach wenigen
Sekunden ab (DELIVER_TIMEOUT, Default 5s), ein Sync macht aber mehrere Requests
nach codeberg.org. Der Endpunkt setzt daher nur eine Trigger-Datei im
gemeinsamen ./api-Volume (Sync\SyncTrigger) und antwortet sofort mit 202; der
sync-Service laeuft jetzt im Watch-Modus und greift sie im Sekundentakt auf.
Authentifiziert wird per HMAC-SHA256 ueber den rohen Request-Body
(X-Forgejo-Signature bzw. X-Gitea-Signature) - Codeberg kennt unsere API-Keys
nicht. Ohne gesetztes CODEBERG_WEBHOOK_SECRET weist der Endpunkt grundsaetzlich
mit 401 ab, damit ein vergessenes Secret keinen offenen Sync-Ausloeser im
Internet hinterlaesst. Request traegt dafuer neu den unveraenderten rawBody.
Anders als der sync-Service braucht der api-Service damit eine eingehende
Freigabe in Proxy und Firewall (POST /api/v1/webhooks/codeberg).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Bisher landeten alle offenen Issues unabhaengig von ihren Labels in
Backlog. Jetzt bestimmt das Label die Spalte: wip -> in_arbeit,
testing -> testing, automate -> bereit, sonst backlog. Geschlossene
Issues bleiben in Done. Die "manuell verschoben"-Sperre im
TicketRepository schuetzt jetzt nur noch qa/fertig (zukuenftige
Labels) statt aller Nicht-Backlog/Done-Spalten, damit der Sync
Tickets weiterhin zwischen den automatisierten Spalten verschieben
kann, wenn sich Labels aendern.
Schliesst #14
1. AgentRepository::updateActivity() schrieb current_ticket_id ungeprueft. Eine
unbekannte Ticket-ID lief in die FOREIGN-KEY-Constraint und kam als
ungefangene PDOException samt Stacktrace und Dateipfaden beim Client an.
Jetzt wird die Existenz vorab geprueft (422). Zusaetzlich faengt
Application::handle() unerwartete Throwables ab und antwortet mit einem
generischen 500 - Details gehen nur noch ins Log.
2. Die Normalisierung der Codeberg-Label-Farbe ("#" davor) lag im
CurlCodebergClient statt im CodebergSyncService. Damit haetten andere
Client-Implementierungen unterschiedliche Farbformate ins Ticket geschrieben.
Verschoben in die Domaenenschicht, leere Farben ergeben jetzt null.
3. Config::get() griff selbst auf getenv() zurueck, wodurch ein in der Umgebung
gesetzter CODEBERG_TOKEN in eine explizit gebaute Config durchschlug - im
Testlauf landete der Token im Klartext in der PHPUnit-Ausgabe. Die Umgebung
wird jetzt ausschliesslich in fromEnvironment() eingesammelt.
Regressionstests fuer alle drei Punkte ergaenzt: 104 Tests, 181 Assertions.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>