Auf der Produktionsmaschine traten vereinzelt Timeouts nach codeberg.org auf
("Operation timed out after 15003 milliseconds with 0 bytes received"), waehrend
die Verbindung sonst in ~0,1s antwortet.
Bisher fiel der Dauerlaeufer nach so einem Fehlschlag in den regulaeren Takt
zurueck. Weil SyncTrigger::consume() die Webhook-Anforderung schon vor dem Lauf
quittiert, war eine per Webhook angeforderte Aktualisierung damit verloren und
kam erst bis zu MONITOR_SYNC_INTERVAL Sekunden spaeter - genau die Verzoegerung,
die der Webhook abschaffen sollte.
Neu wird der naechste Versuch nach einem Fehlschlag vorgezogen: 5s, 10s, 20s, …
gedeckelt auf das regulaere Intervall (Sync\SyncSchedule). Ein kurzer Aussetzer
ist damit binnen Sekunden ueberstanden, eine laengere Codeberg-Stoerung laeuft
trotzdem nicht in einen Dauerbeschuss. Nach einem erfolgreichen Lauf gilt sofort
wieder das regulaere Intervall.
Die Wartezeit-Berechnung liegt in einer eigenen Klasse, weil die Schleife in
bin/sync-codeberg.php selbst nicht testbar ist.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>
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>