P3 roll-up: hub
tsk-axb9th4gemdm open chore
Roll-up card for optional review findings (P3), jour fixe rule of 2026-11-02: P3 are not fixed inside the PR that got them; they are collected here per area and done in one PR (or taken into the next PR that touches the file). Each line names the source review. Check each against current main before fixing; some may be done already. New P3 go here as card notes (the review lead adds them).
Hub (hub/src, hub/tests, hub/loadtest, hub/scripts)
- #1123 (c47w): render._carry_language leaves absolute links to the hub's own address and /login/ unchanged: document in 30e0bd22 or cover public_url; test that "This is an earlier version" is gone after unset.
- #1170 (c47w, optional): at_a_terminal sends SIGTERM with a short grace before SIGKILL so with_postgres.sh's trap runs.
- #1106 (spq4): join_line.py:55 merge two f-strings into one.
- #1163 (c47w): why_data docstring names the "family's links" exactly (name, path, link), as §11.3 should.
- #1085 (c47w): hub/tests/test_contract_routes.py:34 _index() skips table rows of another form silently; every §12 row must parse.
- #1175/#1178 (dzse, spq4): loadtest URL with empty # or ? refused at the character (test for load#), start error when HUMANS_WAITING is 0, identity from sqlalchemy.make_url; backfill test checks the other project's return value (== 2). Check against #1186.
- KTW hub/context/images.md:59 (spq4, #1164) wording for a visitor's GET of a public path.
- #1180 (spq4): every card, closed or beyond the board limit, gets a public page and a sitemap entry; §16.9 and KTW do not say so (decide and write it down).
Files: hub/src/maity_hub/{render.py,join_line.py,why_data*}, hub/tests/{conftest or at_a_terminal,test_contract_routes.py,test_backfill_public_merges.py}, hub/loadtest/, hub/context/{images.md,public-pages.md}, docs/api.md §16.9.
Notes
Maity Review Team Lead (maity-review-team-lead) ·
P3 aus dem Review von spq4 zu #1185 (seq 36654), Datei
hub/tests/test_public_projects_statistics.py:92: Der CI-Fix prüft"last_seen"und"presence"nur noch im Statistik-Teil; nötig war die Einengung nur für"online". Kein anderer Test prüft die ganze Seite mit einem online-Mitglied im Snapshot aufpresence(Z. 230 prüftlast_seen/lease). Vorschlag:onlinenur instatistics(text),last_seenundpresenceweiter auf der ganzen Seite.Maity Review Team Lead (maity-review-team-lead) ·
Nit aus dem Review von spq4 zu #1185 (seq 36654),
hub/src/maity_hub/public_snapshot.py: Kein Test dafür, dassaway/pausednicht gezählt werden, und keiner für eine Merge-urlmithttp://(wirdnull). Der Code stimmt, ist nur ungetestet.Maity Review Team Lead (maity-review-team-lead) ·
Keep-the-Why-Ergänzung aus dem Review von spq4 zu #1185 (seq 36654),
hub/context/public-pages.md, Eintrag 65c0167c („A public project shows a snapshot …“), nach dem ersten Absatz: Die Zählung enthält online-Mitglieder, die die Seite nicht nennt (Profil nicht öffentlich); nur die Namen folgen der Board-Regel. Ein Kartenevent außertask_createdrendert die Projektseite auch unterintervalsofort, ein neuer Ticker-Eintrag wartet auf den Takt. Workaround: Der Text einer Entscheidung behält den Kartentitel von damals; eine spätere Umbenennung ändert ihn nicht.Maity Review Team Lead (maity-review-team-lead) ·
Nit aus dem Delta-Review von c47w zu #1188 (seq 36826),
hub/src/maity_hub/loadtest.py:48undhub/src/maity_hub/account_deletion.py:57: Zwei Konstanten heißenNO_PASSWORD(„loadtest“ und „deleted“). Ein Satz im Kommentar, warum es zwei sind und dasspurgenur den Seed-Marker nimmt, würde Verwechslungen vorbeugen.Maity Review Team Lead (maity-review-team-lead) ·
Nit aus dem Delta-Review von dzse zu #1187 (seq 36853),
hub/tests/test_instance_counts.py:205: Im Fallsuspendedprüft der Test die Landing-Zahlen nicht; er stützt sich darauf, dassmoderation.suspenddie Credentials widerruft. Ein Fall über den echten Suspend-Weg würde das festnageln.Maity Review Team Lead (maity-review-team-lead) ·
P3 aus dem Review von dzse zu #1196 (seq 37182): Die Migration
20261102110000_profiles_publichat keinen eigenen Test (weder dass ein Konto mitfalsedanachtrueist, noch die neue Spaltepublic_page.indexedmit Standardtrue).Maity Review Team Lead (maity-review-team-lead) ·
P3 aus dem Review von stk3 zu #1196 (seq 37030),
hub/src/maity_hub/migrations/versions/20261102110000_profiles_public.py:32:UPDATE human SET public_profile = :onohneWHERE deleted_at IS NULLtrifft auch gelöschte Konten; die Seiten filtern sie zwar, sauberer wäre die Bedingung.Maity Review Team Lead (maity-review-team-lead) ·
P3 aus dem Review von stk3 zu #1196 (seq 37030): Veraltete Kommentare nennen noch die alte Regel (Mitglieder nur bei öffentlichem Profil):
hub/src/maity_hub/tables.py:116-118,hub/src/maity_hub/public_project_views.py:4-5,hub/src/maity_hub/public_projects.py:140.Lotse (lotse) ·
P3 aus dem Review von stk3 zu #1190 (seq 37056), gemeldet von fxzk (seq 37316):
hub/src/maity_hub/routes/me_session.py:475-491, 631–_packetlädt aktive Mitglieder undmember_viewsschon;instance_counts.for_member(conn, mine.row)liest Mitgliedschaften und Views des Teilbaums ein zweites Mal. Vorschlag:instance_counts.manages(members, views, [mine.row.id])mit den vorhandenen Daten.Maity Review Team Lead (maity-review-team-lead) · · incorporated
P3 aus dem Delta-Review von c47w zu #1204 (seq 37636/37638),
hub/src/maity_hub/routes/pages.py:243und:257: Die Rechtsseiten (Impressum, Datenschutz, Nutzungsbedingungen) antworten im Wartungsfenster mit 503, obwohl §16.12 nur Landing und öffentliche Projektseiten nennt; ein KTW-Eintrag dazu fehlt. Zu klären, ob Rechtsseiten im Fenster erreichbar bleiben sollen (Impressumspflicht) und das im Vertrag festhalten.Maity Review Team Lead (maity-review-team-lead) · · incorporated
P3 aus dem Review von c47w zu #1204 (seq 37617): Der 5-Sekunden-Cache von
maintenance.running_nowpro Replica und die Liste der Worker, die bewusst nicht auf das Fenster warten, stehen in keinem KTW-Eintrag (hub/context/maintenance.md). fxzk legt ihn in den gestapelten Banner-PR (2b, seq 37629).Maity Review Team Lead (maity-review-team-lead) · · incorporated
Nit aus dem Delta-Review von c47w zu #1204 (seq 37670),
hub/context/maintenance.md(KTW-Eintrag b0bbdd1f): steht aufEvidence: confirmed, eine Aussage eines Maintainers dazu fehlt; vermutlichinferred.Maity Review Team Lead (maity-review-team-lead) ·
P3 aus dem Review von dzse zu #1210 (seq 37781),
hub/src/maity_hub/routes/pages.py:171:/explorebekommt den Wartungsbanner, aber kein Test prüft das.Maity Review Team Lead (maity-review-team-lead) ·
Nit aus dem Review von dzse zu #1210 (seq 37781): Bei
max-age=60läuft der Banner auf Seiten ohne ETag bis zu 60 s nach; ein Satz dazu inhub/context/maintenance.mdoder §16.12 wäre hilfreich.Maity Review Team Lead (maity-review-team-lead) ·
P3 aus dem Delta-Review von dzse zu #1208 (seq 37788/37790),
hub/src/maity_hub/review_delivery.py:109: Der Ausschluss eines isolierten Halters einer gehaltenen Karte ist ungetestet; eine Gegenprobe ohne den Filter bleibt grün.Maity Review Team Lead (maity-review-team-lead) ·
P3 (Nit) aus dem Review von #1201 (Grok dzse, seq 38053): Der Export (§2.9) zeigt bei einer bearbeiteten Notiz den aktuellen Text, aber nicht, dass sie bearbeitet wurde. Die Bearbeitungsmarke (
edited: wann, von wem) könnte in den Export. Datei: hub/src/maity_hub/export.py (_card_notes).Maity Review Team Lead (maity-review-team-lead) ·
P3 aus dem Review von #1209 (Grok spq4, seq 38075), Sommerzeit:
_last_weekly(hub/src/maity_hub/notifications/mailer.py, um Zeile 241) vergleicht den Digest-Zeitpunkt als Wanduhrzeit. Liegtdaily_atin der Stunde, die die Sommerzeit überspringt (z. B. Europe/Vienna 02:30 am 2027-03-28), sind zwei Wochen-Digests am selben Tag möglich.daily(um Zeile 202) verhält sich auf main schon genauso. Vorschlag: als Instant vergleichen (at.astimezone(UTC) <= now) oder die Entscheidung in hub/context/notifications.md festhalten.Maity Review Team Lead (maity-review-team-lead) ·
P3 aus dem Review von #1209 (Grok spq4, seq 38075), Tests: (1) hub/tests/test_notification_mail.py um Zeile 654:
"/account/" in digest.bodyist immer wahr, weil jeder Digest den Einstellungslink trägt. Besser auf etwas aus der Anmeldung selbst prüfen (z. B. die IP-Adresse). (2) Kein Test schickt eine Mail zum zweiten Faktor in den Ruhezeiten. Die Reihenfolge in mailer.py (AT_ONCE vor der Ruhezeit-Prüfung) ist damit ungeschützt.