Commit graph

123 commits

Author SHA1 Message Date
fds2610
75fa035712 Merge pull request 'Event-Monitor: Zeilen passen in den Monitor, Volltext im Tooltip' (#47) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/47
2026-08-07 18:36:41 +02:00
fds2610-bot
e51b373f07 Event-Monitor: Zeilen passen in den Monitor, Volltext im Tooltip
Lange Meldungen liefen ueber den Monitorrahmen hinaus in die Szene. Jedes
Event belegt jetzt zwei Zeilen (Zeit + System, darunter eingerueckt die
Meldung), beide auf die Innenbreite gekuerzt. Die vollstaendige Meldung
zeigt ein <title>-Tooltip beim Hover ueber das Event.

Die Kuerzung selbst sitzt als truncateToWidth() in office-scene.js und ist
damit ohne DOM testbar; die Zeichenbreite ist an der breitesten der in
Frage kommenden Monospace-Schriften ausgerichtet, damit auf keinem System
etwas ueberlaeuft.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 17:49:09 +02:00
fds2610
890f901400 Merge pull request 'Frontend-Tests wieder lauffaehig: Node 24 im Test-Container' (#46) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/46
2026-08-07 10:52:39 +02:00
fds2610-bot
eb48e34bfd Frontend-Tests wieder lauffaehig: Node 24 im Test-Container
Der letzte Commit stellte das Test-Skript in package.json auf ein Glob-Muster um,
weil "node --test tests/frontend" seit Node 24 das Verzeichnis nicht mehr als
Testverzeichnis aufloest. Der Test-Container lief aber weiter auf node:20-alpine,
und Node 20 kennt Globs in "node --test" noch nicht - es sucht woertlich nach einer
Datei mit Sternchen im Namen und bricht ab:

  Could not find '/app/tests/frontend/**/*.test.js'

Auf dem Entwicklungsrechner (Node 24 auf dem Host) fiel das nicht auf, auf dem
Produktionsserver liefen die Frontend-Tests dadurch gar nicht mehr. Da update.sh
mit "set -e" laeuft, brach es an dieser Stelle ab, noch bevor es die Abschlusszeile
ausgeben konnte - das Update selbst war zu dem Zeitpunkt aber schon vollstaendig
eingespielt, die Tests laufen erst nach dem Neustart der Dienste.

Statt das Glob zurueckzubauen das Image angehoben: node:20 ist seit April 2026
ohnehin ohne Support. Unter node:24-alpine laufen die 76 Frontend-Tests durch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 10:51:18 +02:00
fds2610
a745af5d88 Merge pull request 'PHPUnit-Ergebnis-Cache nicht mehr versionieren' (#45) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/45
2026-08-07 10:43:16 +02:00
fds2610-bot
63ee4744e5 PHPUnit-Ergebnis-Cache nicht mehr versionieren
api/.phpunit.result.cache ist ein reines Laufzeit-Artefakt von PHPUnit
(zuletzt fehlgeschlagene Tests + Laufzeiten fuer die Testreihenfolge). Da
update.sh am Ende die Testsuiten ausfuehrt, schreibt PHPUnit die Datei bei
jedem Update neu - das Arbeitsverzeichnis war danach dirty und der naechste
Lauf von update.sh brach mit "Lokale Aenderungen vorhanden" ab.

Datei aus dem Index entfernt und in .gitignore aufgenommen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 10:40:50 +02:00
fds2610
baf9c8682d Merge pull request 'Abgelaufene Claude-Anmeldung eines Agenten sichtbar machen' (#44) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/44
2026-08-07 10:36:25 +02:00
fds2610-bot
62e5cb0751 Abgelaufene Claude-Anmeldung eines Agenten sichtbar machen
Laeuft einem Agenten die Claude-Anmeldung aus, laeuft das Cron-Skript um ihn
herum unbeeindruckt weiter: es meldet "working", ruft claude auf, bekommt nichts
Brauchbares zurueck und meldet am Ende "idle". last_seen_at ist frisch, der
Agent sieht beschaeftigt aus - waehrend Lauf fuer Lauf nichts entsteht. Der
Ausfall fiel bisher erst auf, wenn jemand merkte, dass keine PRs mehr kommen.

Agenten melden den Fall jetzt ueber zwei neue state-Werte (auth_expiring,
auth_expired) am bestehenden Activity-Endpunkt. state ist serverseitig nicht
eingeschraenkt, daher ohne Migration und ohne Aenderung an der API.

Dargestellt in drei Stufen der Aufmerksamkeit:
- Schloss ueber dem Avatar (bei auth_expired pulsierend), entsaettigter Koerper,
  eingefaerbter Bildschirm und Namensschild am Platz
- Header-Banner mit den betroffenen Agenten, gelb bei Vorwarnung, rot bei
  Ausfall - auch aus einigen Metern Entfernung noch lesbar
- KPI-Kachel "Problem: n", die sich nur einfaerbt, wenn n > 0

Kern ist isAgentVisible(), bewusst getrennt von isAgentPresent(): ein
blockierter Agent bleibt sichtbar, obwohl er sich nicht mehr meldet, zaehlt aber
nicht als "Online" mit. Ohne das verschwaende er nach dem Praesenz-Timeout genau
dann vom Schreibtisch, wenn seine Warnung dort stehen soll.

MAX_KPI_TILES von 4 auf 5, sonst verdraengen Agenten/Online/Problem/Hooks die
gemeldeten KPIs (F7) vollstaendig.

Nebenbei: "npm test" lief seit Node 24 nicht mehr (das Verzeichnis-Argument wird
nicht mehr als Testverzeichnis aufgeloest), jetzt per Glob.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 09:52:08 +02:00
fds2610
3767c8dc13 Merge pull request 'KPI-Kacheln direkt untereinander statt ueber die Monitorhoehe verteilt' (#42) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/42
2026-08-05 18:31:18 +02:00
fds2610-bot
1aec163edc KPI-Kacheln direkt untereinander statt ueber die Monitorhoehe verteilt
renderKpiMonitor() hat die Hoehe des KPI-Monitors gleichmaessig unter den Kacheln
aufgeteilt (rowH = (frame.h - 30) / tiles.length, rund 78px pro Zeile bei vier
Kacheln). Der Platz ging dabei in die Sparkline-Kaesten - und genau die
Zaehler-Kacheln "Agenten"/"Online" (Issue #39) und "Hooks" (Issue #38) haben
history: [] und damit gar keine Linie. Zwischen den Werten standen deshalb grosse
leere Kaesten.

Die Zeilen stapeln sich jetzt mit fester Hoehe von oben, und einen Sparkline-Kasten
bekommt nur noch, wer wirklich einen Verlauf hat: eine Zaehler-Kachel braucht damit
24 statt 77,5 Pixel, vier davon zusammen 96 statt 310. Der Kasten ist ausserdem 32px
hoch - die Hoehe, fuer die buildKpiSparklinePoints() die Punkte berechnet; vorher war
er rund 51px hoch und die Linie fuellte ihn nie aus.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 18:30:21 +02:00
fds2610
6ff5c16197 Merge pull request 'Hooks-KPI im KPI-Monitor ergaenzen' (#41) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/41
2026-08-04 13:52:43 +02:00
fds2610-bot
79ccef099d Hooks-KPI im KPI-Monitor ergaenzen (Issue #38)
Die im Issue beschriebene Event-Anzeige (neuestes Event oben, aeltere
schieben nach, Ueberschuss wird abgeschnitten) ist bereits seit Phase 4
umgesetzt (buildEventLines()/MAX_EVENT_LINES, F5) und braucht keine
Aenderung.

Neu ist die vierte, immer sichtbare KPI-Kachel ganz rechts im
KPI-Monitor: "Hooks: n" zaehlt die seit dem letzten Start des
api-Containers empfangenen Webhooks. Der Zaehler ist dateibasiert
(Metrics\HookCounter), weil der eingebaute PHP-Server jede Anfrage als
eigene Skriptausfuehrung behandelt; docker/entrypoint.sh setzt die Datei
beim Start des api-Containers (nicht des sync-Containers) zurueck. Neuer
oeffentlicher Endpunkt GET /api/v1/webhooks/stats liefert den Stand,
das Frontend haengt ihn als eigene Kachel an (buildHooksKpi()) und
reserviert ihr dafuer eine feste Kachel statt sie der MAX_KPI_TILES-
Kappung der uebrigen KPIs zu unterwerfen. Der Wert fliesst zusaetzlich
in den SSE-Fingerabdruck (ChangeFeed) ein.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 13:18:05 +02:00
fds2610
5dcf080b27 Merge pull request 'KPI-Monitor zeigt Agenten/Online-Kacheln wieder an' (#40) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/40
2026-08-04 13:02:34 +02:00
fds2610-bot
042a535c78 KPI-Monitor zeigt Agenten/Online-Kacheln wieder an
Die KPI-Kacheln "Agenten" (registrierte Agenten) und "Online" (davon
in den letzten 10 Minuten aktiv, siehe AgentRepository::isPresent())
wurden auf der Monitor-Wand nie angezeigt. Statt eine eigene
Meldepflicht dafuer einzufuehren, leitet buildAgentCountKpis() beide
Werte direkt aus der ohnehin geladenen Agentenliste ab und stellt sie
den ueber /api/v1/kpis gemeldeten Kennzahlen voran.

Schliesst #39
2026-08-04 12:51:32 +02:00
fds2610
5471940389 Merge pull request 'Auto-Update per Push-Webhook fuer Produktionsserver einrichten' (#37) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/37
2026-08-04 12:34:47 +02:00
fds2610-bot
6bad9b470c Auto-Update per Push-Webhook fuer Produktionsserver einrichten
deploy-webhook.py laeuft auf dem Host, prueft eingehende Codeberg-Webhooks per
HMAC-Signatur (analog zu POST /api/v1/webhooks/codeberg) und stoesst bei einem
Push auf main - also nach jedem manuell gemergten PR - das bereits vorhandene
update.sh an. README_UPDATE.md dokumentiert die dafuer noetigen manuellen
Vorarbeiten auf dem Server (Checkout, Docker, systemd-Unit, Webhook-Einrichtung).

Schliesst #36
2026-08-04 12:20:41 +02:00
fds2610
58eb022113 Merge pull request 'Kanban-Farbe verwaister Tickets nach Projekt-Entfernung zuruecksetzen' (#35) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/35
2026-08-04 12:07:43 +02:00
fds2610-bot
ce8862014f Farbe verwaister Tickets zuruecksetzen statt Projektfarbe zu behalten
Wenn ein Projekt im Projekte-Modal entfernt oder umbenannt wurde, hat
CodebergSyncService dessen Tickets nicht mehr angefasst - sie blieben
also dauerhaft in der alten Projektfarbe eingefaerbt, obwohl es dafuer
gar kein Projekt mehr gab (Issue #34). sync() setzt die Farbe solcher
Tickets nun nach jedem Lauf auf NULL zurueck, wodurch das Kanban die
Standardfarbe statt der veralteten Projektfarbe zeigt.

Schließt #34
2026-08-04 11:07:56 +02:00
fds2610
edf71d1892 Merge pull request 'PO bewegt sich nicht mehr faelschlich fuer Agenten-eigene wip-Wechsel' (#33) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/33
2026-08-03 19:35:37 +02:00
fds2610-bot
fe95035a0a PO bewegt sich nicht mehr faelschlich fuer Agenten-eigene wip-Wechsel
Statuswechsel von/zu "in_arbeit" (Label "wip") loest ein Agent selbst aus,
wenn er ein Ticket nimmt bzw. abgibt, und meldet die Bewegung ueber seinen
eigenen state. detectUnassignedTicketChanges() zaehlte diese Wechsel
bislang trotzdem als "niemandem zugeordnet" und liess zusaetzlich den PO
dafuer zum Board laufen.

Schliesst #32
2026-08-03 19:23:09 +02:00
fds2610
40c48ed46a Merge pull request 'CORS-Preflight beantworten, damit das Projekte-Modal speichern kann' (#31) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/31
2026-08-03 18:57:50 +02:00
fds2610-bot
a3d39f7f9a Merge branch 'main' of https://codeberg.org/fds2610/monitor 2026-08-03 18:57:02 +02:00
fds2610-bot
2f5321ac8e CORS-Preflight beantworten, damit das Projekte-Modal speichern kann
Schreibende Aufrufe aus dem Frontend (POST/PATCH/DELETE auf /repo-configs und
/agents) schicken X-Admin-Key und Content-Type: application/json. Beides macht
aus dem fetch() einen preflighted request: Der Browser fragt zuerst per OPTIONS
nach. Fuer OPTIONS war aber keine Route registriert, der Router warf daher
MethodNotAllowedException (405), und ausserdem fehlte
Access-Control-Allow-Headers fuer den X-Admin-Key. Der Browser sendete den
eigentlichen POST damit nie und das Modal meldete nur "Netzwerkfehler beim
Abrufen der Ressource" - Lesen funktionierte, weil GET ohne Custom-Header ein
simple request ohne Preflight ist.

Application::handle() beantwortet OPTIONS jetzt vor dem Routing mit 204, und
Response::send() liefert Allow-Methods, Allow-Headers und Max-Age mit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 18:56:57 +02:00
fds2610
80d121f703 Merge pull request 'Tickets auf dem Board in der Farbe ihres Projekts zeichnen' (#30) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/30
2026-08-02 22:40:44 +02:00
fds2610-bot
ebf7dba537 Tickets auf dem Board in der Farbe ihres Projekts zeichnen
Das Projekte-Modal am PO laesst seit #27 je Projekt eine Farbe pflegen, und
GET /api/v1/tickets liefert sie pro Ticket mit (ticket.color) - auf dem Board
kam sie aber nie an: renderBoard() bekam nur Zaehler je Spalte, jeder Zettel
war derselbe gelbe Standardzettel.

buildBoardColumnLayout() bekommt deshalb zusaetzlich die gruppierten Tickets
und liefert die Farbe je Zettel mit. Ohne Ticketliste (Demo-Modus, der nur
Zaehler kennt) bleibt alles wie bisher.

Ein Stapel steht fuer mehr Tickets als er Zettel hat und zeigt die ersten
verschiedenen Farben darin - so ist auch an "Done" (immer ein Stapel) zu
sehen, aus welchen Projekten die Tickets stammen. Reichen die Farben nicht
fuer alle drei Zettel, werden sie zyklisch wiederholt: ein ungefaerbter
Rest-Zettel saehe sonst wie ein weiteres Projekt aus, denn --color-note ist
von einem gelben Projekt kaum zu unterscheiden.

Gefaerbte Zettel bekommen ausserdem eine neutrale statt der gelben Kontur.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 22:32:34 +02:00
fds2610
d525e51815 Merge pull request 'Klick auf den PO oeffnet den Projekte-Dialog zuverlaessig (#27)' (#29) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/29
2026-08-02 22:15:57 +02:00
fds2610-bot
d5f7ac9f92 Klick auf den PO oeffnet den Projekte-Dialog zuverlaessig
Der Konfig-Dialog liess sich in der Praxis kaum oeffnen (Fehlerbericht in
Issue #27). Drei Ursachen, alle reproduziert:

- Ein Klick auf den PO selbst tat gar nichts: der Klick-Handler hing nur am
  Schreibtisch, die Figur liegt aber in der Avatar-Schicht darueber. Genau sie
  meint das Ticket ("bei Klick auf den PO"). Der Avatar ist jetzt klickbar,
  auch waehrend er am Board steht.
- Klicks auf den Platz trafen nur, wenn sie zufaellig auf einem gefuellten
  Moebelstueck landeten - eine <g> faengt in ihren Luecken keine Klicks. Der
  Platz hat jetzt eine eigene Trefferflaeche, wie die Board-Spalten.
- Dass hinter dem PO ueberhaupt etwas steckt, war nicht zu sehen. Ein kleines
  Zahnrad auf seinem Tisch (mit Tooltip) zeigt es an.

Ausserdem oeffnet der Dialog jetzt auch bei nicht erreichbarer API - er meldet
dann selbst, dass er die Projekte nicht laden konnte, statt tot zu wirken.

Und genau dieser Fall trat leicht ein: der eingebaute PHP-Server beantwortet
Anfragen nacheinander, eine offene SSE-Verbindung blockiert damit alles andere
(gemessen 16s fuer ein GET /api/v1/tickets, ab dem zweiten offenen Monitor
dauerhaft). Das Frontend faellt dann auf Demo-Daten zurueck. Mit
PHP_CLI_SERVER_WORKERS=4 sind es 0,006s; PRAGMA busy_timeout deckt die
Schreibzugriffe ab, die sich jetzt begegnen koennen.

ApplicationTest::testFullFlowCreateUpdateAndDeleteRepoConfigWithAdminKey war
seit dem Seed in 003_repo_configs.sql rot (legte fds2610/monitor ein zweites
Mal an) - der Test nutzt jetzt ein nicht geseedetes Repo.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 22:09:31 +02:00
fds2610
1ad4f25777 Merge pull request 'Codeberg-Projekte anzeigen und per Modal konfigurierbar machen (#26, #27)' (#28) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/28
2026-08-02 20:50:53 +02:00
fds2610-bot
d72c945a61 Codeberg-Projekte des Sync ueber ein Modal am PO konfigurierbar machen
Klick auf den PO oeffnet ein Modal, in dem sich die Projekte (Owner/Repo +
Farbe), aus denen der Codeberg-Sync liest, hinzufuegen, bearbeiten und
loeschen lassen - Icon-Schaltflaechen mit Tooltip statt Textbuttons. Die
Projektliste war bisher eine Umgebungsvariable (CODEBERG_REPOS, Issue #26)
und wandert dafuer in eine neue Tabelle repo_configs (Migration
003_repo_configs.sql, geseedet mit den bisherigen drei Default-Projekten);
CodebergSyncService liest sie ueber RepoConfigRepository bei jedem Lauf
frisch ein, damit eine Aenderung im laufenden --watch-Prozess ohne Neustart
wirkt. Neue Endpunkte GET/POST/PATCH/DELETE /api/v1/repo-configs, Schreiben
hinter X-Admin-Key wie die Agenten-Registrierung; das Frontend fragt den Key
bei der ersten Aenderung per Prompt ab und merkt ihn sich im lokalen
Speicher. office-modal.js bekommt dafuer einen Oeffnen-Token
(isCurrentModal()), damit ein verspaetet aufloesender Request nach dem
Oeffnen eines anderen Modals nicht dessen Inhalt ueberschreibt.

Schliesst #27
2026-07-30 17:53:39 +02:00
fds2610-bot
3aaf6aea54 Tickets aus mehreren Codeberg-Projekten anzeigen (monitor/Steuerkram/nc-gantt)
Der Codeberg-Sync liest nun Issues aus mehreren konfigurierbaren Projekten
(Config::codebergRepos(), Default: fds2610/monitor gelb, fds2610/Steuerkram
gruen, fds2610/nc-gantt blau) statt nur aus einem einzigen Repo. Damit
external_ref (Issue-Nummer) projektuebergreifend nicht kollidiert, ist es
jetzt zusammen mit dem neuen Ticket-Feld "repo" eindeutig; Migration
002_multi_repo_tickets.sql ergaenzt die Spalte und den Index. Da Migrationen
dadurch nicht mehr rein additiv sind, trackt Database::migrate() jetzt
angewandte Dateien in schema_migrations, damit ALTER TABLE nicht bei jedem
Prozessstart erneut laeuft. Das Frontend baut Codeberg-Links jetzt aus dem
repo-Feld jedes Tickets statt aus einer global fixen owner/repo-Angabe.

Schliesst #26
2026-07-30 17:34:49 +02:00
fds2610
523e8a4dcf Merge pull request 'Fehlgeschlagenen Codeberg-Sync zeitnah wiederholen statt bis zum naechsten Intervall zu warten' (#25) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/25
2026-07-29 21:31:53 +02:00
fds2610-bot
ad14447092 Fehlgeschlagenen Codeberg-Sync zeitnah wiederholen statt bis zum naechsten Intervall zu warten
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>
2026-07-29 21:29:20 +02:00
fds2610
cddba1ee8f Merge pull request 'Codeberg-Webhook fuer Sofort-Sync statt Warten auf den Polling-Lauf' (#23) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/23
2026-07-29 21:08:29 +02:00
fds2610-bot
3efa0ee423 Codeberg-Webhook fuer Sofort-Sync statt Warten auf den Polling-Lauf
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>
2026-07-29 21:04:06 +02:00
fds2610
f0018976bf Merge pull request 'Agent-Praesenz serverseitig berechnen (is_present-Feld)' (#22) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/22
2026-07-29 18:26:44 +02:00
fds2610-bot
49ff9dd8e4 Agent-Praesenz serverseitig berechnen (is_present-Feld statt Client-Zeitarithmetik)
Der Client verglich last_seen_at bislang selbst gegen Date.now() - je nach
Client-Zeitzone/-Uhr konnte das falsche Ergebnisse liefern und liess Agenten
faelschlich als abwesend erscheinen (Issue #20, Folge von #17). Die API
liefert die Anwesenheit jetzt direkt als is_present-Feld mit, berechnet
serverseitig via gmdate()/time() (AgentRepository::isPresent()). Das Frontend
liest das Feld nur noch aus, ohne eigene Zeit-Arithmetik.
2026-07-29 18:25:01 +02:00
fds2610
1879aa7057 Merge pull request 'API.md: Diagnose-Hinweis für last_seen_at auf der Produktionsmaschine' (#21) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/21
2026-07-29 17:38:06 +02:00
fds2610-bot
c6f9f6d89f API.md: Diagnose-Hinweis fuer last_seen_at auf der Produktionsmaschine ergaenzen
Seit dem Praesenz-Timeout aus Ticket #17 verschwindet ein Agent aus der
Buero-Visualisierung, sobald last_seen_at aelter als zehn Minuten ist. Damit sich das auf
der Produktionsmaschine nachvollziehen laesst, dokumentiert GET /api/v1/agents jetzt, dass
der Endpunkt unauthentifiziert ist (last_seen_at also per curl abrufbar ist) und wie sich
derselbe Wert notfalls direkt aus der SQLite-Datei auslesen laesst.

Schliesst #20
2026-07-29 17:32:16 +02:00
fds2610
5a645e1d12 Merge pull request 'Agent-Praesenz mit Zehn-Minuten-Timeout versehen' (#18) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/18
2026-07-29 17:16:52 +02:00
fds2610-bot
811a7d9f69 PO bekommt festen Platz + laeuft bei niemandem zugeordneten Ticketwechseln zum Board
Der Product Owner ("PO") ist keine ueber die API registrierte Rolle, sondern
repraesentiert die Produktverantwortung des Systems selbst: eigener, fester
Platz ausserhalb des dynamischen 8er-Schreibtisch-Rasters, anwesend genau
dann, wenn die API erreichbar ist (statt ueber last_seen_at). Ausserdem laeuft
er zum Board, sobald sich dort ein Ticket-Status aendert, der noch keiner
anderen Rolle zugeordnet ist (z.B. Wechsel nach "bereit" durchs Label
"automate", wie es diesem Issue selbst passiert ist) - Wechsel nach
fertig/done bleiben weiterhin Sache der Rolle "user" (Tuerbesuche).

Schliesst #19
2026-07-29 17:13:59 +02:00
fds2610-bot
e96b2e1843 Agent-Praesenz mit Zehn-Minuten-Timeout versehen
Ein registrierter Agent gilt im Bueromonitor nur noch als anwesend,
solange last_seen_at hoechstens zehn Minuten zurueckliegt (isAgentPresent,
office-scene.js). Meldet er sich laenger nicht, bleibt sein Schreibtisch
frei und er erscheint auch nicht mehr im Ueberlauf-Ruheplatz vor der Tuer,
statt weiterhin faelschlich als anwesend dargestellt zu werden.

Schliesst #17
2026-07-29 17:02:49 +02:00
fds2610
db92f5126e Merge pull request 'Codeberg-Sync: offene Issues per Label der richtigen Board-Spalte zuordnen' (#16) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/16
2026-07-29 16:49:50 +02:00
fds2610-bot
29a13e89eb Codeberg-Sync ordnet offene Issues per Label der richtigen Spalte zu
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
2026-07-29 16:48:23 +02:00
fds2610
b135d112fd Merge pull request 'Buero-Headline durch Agent-Status ersetzen + kosmetischer Reload-Countdown' (#13) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/13
2026-07-29 00:05:34 +02:00
fds2610-bot
ec380d2ff8 Buero-Ueberschrift durch Agent-Status ersetzen, Erklaertext durch Reload-Countdown ersetzt
Der fett gedruckte Titel "Buero" ueber der Visualisierung heisst jetzt
"Agent-Status", der laengere erklaerende Fliesstext darunter entfaellt.
Stattdessen zeigt der Header rechtsbuendig einen rein kosmetischen
Sekunden-Countdown, der von MONITOR_SYNC_INTERVAL herunterzaehlt und nach
Erreichen von 0 wieder von vorn beginnt (Issue #12). Der Wert wird dazu wie
MONITOR_API_BASE per config.js/envsubst ans Frontend durchgereicht.
2026-07-29 00:03:26 +02:00
fds2610
f785440872 Merge pull request 'Codeberg-Sync als Dauerlaeufer (Compose-Service) - leeres Board auf Produktion' (#11) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/11
2026-07-28 23:47:04 +02:00
fds2610-bot
6d199f8530 Codeberg-Sync als Dauerlaeufer statt manuellem Aufruf
Auf der Produktion blieb das Kanban-Board leer, obwohl die API lief und der
registrierte Agent angezeigt wurde: Tickets entstehen nur aus Agenten-Meldungen
oder aus bin/sync-codeberg.php, und das Skript war zwar als "per Cron oder
manuell" dokumentiert, wurde aber nirgends automatisch ausgefuehrt.

Neuer Compose-Service "sync": nutzt Image, Volume und SQLite-Datei des
api-Service, macht sofort beim Start einen Lauf und wiederholt ihn alle
MONITOR_SYNC_INTERVAL Sekunden (Default 600). Ein fehlgeschlagener Lauf bricht
die Schleife nicht ab, damit ein Codeberg-Ausfall keinen Restart-Loop ausloest.
Der Service verbindet sich ausschliesslich ausgehend nach codeberg.org und
braucht daher kein Port-Mapping - in Produktion sind weder Proxy- noch
Firewall-Freigaben noetig.

update.sh startet den Dienst mit, die Doku beschreibt den Service statt des
Cron-Hinweises; der manuelle Aufruf bleibt als Debug-Weg dokumentiert, weil dort
die Klartext-Fehler des Codeberg-Clients sichtbar werden.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 23:29:40 +02:00
fds2610
96ccaae674 Merge pull request 'Frontend-API-URL ueber MONITOR_API_BASE konfigurierbar + Banner bei nicht erreichbarer API' (#10) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/10
2026-07-28 23:03:32 +02:00
fds2610-bot
ba52522415 Frontend-API-URL ueber MONITOR_API_BASE konfigurieren statt aus dem Port raten
Die Basis-URL der API wurde bisher aus dem Port der Seite abgeleitet
(office.html: `if (location.port === "8090")`). Laeuft das Frontend hinter
anderen Ports - in Produktion 4443 (web) / 4444 (api) - griff die Bedingung
nicht, der relative Default /api/v1 lief gegen den Webserver ins Leere, und
die Szene fiel still auf Demo-Daten zurueck: fremde Agenten-Namen und
erfundene Ticketzahlen bei gleichzeitig leeren Detail-Modals.

Die URL kommt jetzt aus MONITOR_API_BASE (.env, Default passend zum
Port-Mapping in docker-compose.yml). Der Webserver liefert den Wert zur
Laufzeit als /config.js aus; das nginx-Image setzt ihn beim Start per
envsubst in die Config ein (default.conf -> default.conf.template). Damit
bleibt html/ ein rein statisches, read-only gemountetes Verzeichnis - kein
Build-Schritt, kein eigenes Entrypoint-Skript. Ein leerer Wert bedeutet
"gleicher Origin" und faellt auf /api/v1 zurueck.

Zusaetzlich macht ein roter Banner "API nicht erreichbar!" den Demo-Fallback
sichtbar, statt ihn wie bisher stillschweigend als echte Daten auszugeben.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 22:54:36 +02:00
fds2610
9f1fa520d7 Merge pull request 'Phase 6+7 der Neuausrichtung: Tuer-Besuche + alte Tabellenansicht entfernt' (#9) from fds2610-bot/monitor:main into main
Reviewed-on: https://codeberg.org/fds2610/monitor/pulls/9
2026-07-28 22:08:20 +02:00