dev: Umsetzungsaudits 29.09. und 02.10., Entwicklungsplan Blöcke 9 und 10 mit bestätigten Entscheidungen E19–E34 und Deploy-Plan, Runbook ergänzt
- UMSETZUNGSAUDIT-2026-09-29.md (Bestandsaufnahme) und -2026-10-02.md - ENTWICKLUNGSPLAN.md: Block 9 und 10, Entscheidungen E19–E34 vom Betreiber am 02.10.2026 bestätigt (E25 revidiert), Deploy-Plan A–E, Protokoll - deploy-runbook.md: vollständige Scheduler-Tabelle, Restore-Schritte mit --accept-unsigned/--without-export, Zugangsdaten aus Abschnitt 7 entfernt (stehen weiter in der Historie — Passwort wird rotiert) - Bildplan-Protokoll mit Korrektur zu „Altbestand geschützt" (A-05) - dev/README.md und dev/roadmap.md verweisen auf den aktuellen Stand - .env.example: neue Schlüssel aus Block 9/10 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
5ec252da12
commit
aa47e113fe
8 changed files with 787 additions and 21 deletions
|
|
@ -1,6 +1,6 @@
|
|||
# Entwicklungsplan zum Audit vom 11.09.2026
|
||||
|
||||
**Stand:** 18.09.2026 (Entscheidungen getroffen, Umsetzung läuft)
|
||||
**Stand:** 29.09.2026 (Blöcke 1–9 umgesetzt; Block 9 = Umsetzungsaudit 29.09., Deploy offen)
|
||||
**Grundlage:** [AUDIT.md](AUDIT.md) (geprüfter Commit `5d0570b`), abgeglichen mit HEAD `24c1bbf` auf `technik/betriebsfixes-2026-09`
|
||||
**Zweck:** Nur die Befunde, die am aktuellen Code belegt sind, in eine abarbeitbare Reihenfolge bringen. Jeder Punkt hat einen konkreten Fix, einen Regressionstest und eine Aufwandsklasse.
|
||||
|
||||
|
|
@ -281,6 +281,111 @@ Grundlage: [`UMSETZUNGSAUDIT-2026-09-25.md`](UMSETZUNGSAUDIT-2026-09-25.md) (22
|
|||
|
||||
**Nicht in dieser Nacharbeit:** N09 (Snapshot-Versionierung nach Credit-/KI-Korrektur und `put()`-Prüfung im Snapshot) — eigener Schritt, weil die Snapshot-Datei damit versioniert werden muss (Bildbytes plus Metadaten) und der Neuaufbau bei Korrektur mit der OG-Cache-Frage (5.2) zusammenhängt.
|
||||
|
||||
## Block 9 — Umsetzung des Umsetzungsaudits vom 29.09.2026
|
||||
|
||||
Grundlage: [`UMSETZUNGSAUDIT-2026-09-29.md`](UMSETZUNGSAUDIT-2026-09-29.md) (4 × P1, 22 × P2, P3-Liste, OPT-1 bis OPT-9). Auftrag des Betreibers vom 29.09.2026: Block 9 vollständig und die kleinen Punkte (P3, OPT) mit umsetzen. Umgesetzt am 29.09.2026 in vier parallelen Gruppen mit getrennter Dateihoheit (Rechte/KI/Jobs, Bild-Pipeline, Archiv, SEO/Berichte); Integration, Qualitätsgates und Doku im Anschluss. Jeder Befund zuerst als roter Regressionstest, dann der Fix.
|
||||
|
||||
### Stand je Befund
|
||||
|
||||
| Schritt | Befunde | Stand | Kern der Umsetzung |
|
||||
|---|---|---|---|
|
||||
| 9.1 | R-01, K-04 | erledigt | API-Zuordnung zu bestehender Firma nur für Owner/Mitglieder oder Allowlist (`NEWSROOM_API_ASSIGNMENT_USER_IDS`), Pivot `granted_via = api`, Befehl `company-memberships:api-assignments` (Liste, `--remove` mit Vorschau). OAuth-Verifikation eines offenen Kontos: Passwort `null`, `remember_token` neu, Sanctum-Tokens weg, alle Sessions widerrufen (`SessionRevocation` + Middleware `EnsureSessionIsNotRevoked`, weil Redis-Sessions nicht je Nutzer aufzählbar sind) |
|
||||
| 9.2 | K-01, B-01, B-02, B-03 | erledigt | Scheduler und `publish()` (Quellen `ki`/`scheduler`) respektieren `manual_review_required_at` (`ManualReviewRequiredException`); Feed, Card-Helfer und Nachweis-PDF nur mit `isPubliclyDeliverable()`; Livewire-Temp-Upload 16 MiB |
|
||||
| 9.3 | R-02/K-03, R-03, N19-Rest | erledigt | Aggregation und Merge ohne `updated_at`; neue Spalte `press_releases.content_changed_at`, `PressRelease::contentModifiedAt()` für lastmod, `dateModified`, `article:modified_time`; Sitemap und Legacy-`view_url` mit `/en/` für englische Meldungen; `archive()` gibt Kopien frei |
|
||||
| 9.4 | A-01, A-02, A-03 | erledigt | Auftragstabelle `archive_pending_jobs` (`ArchivePendingQueue::push()`/`completeWith()`), `archive_pending_at` nur noch Sammelmarker; Nachholer ohne Schlüssel FAILURE; Sweep verschiebt in Quarantäne (30 Tage), Pause per `--pause`/`--resume` bzw. automatisch beim Restore-Abgleich, `archive:reregister` aus `manifest.json` |
|
||||
| 9.5 | N09, B-04 bis B-07, A-04, A-06 | erledigt | Snapshot versioniert (Bytes- plus Metadaten-Hash, OG-Variante enthalten, `put()` geprüft, alle Fassungen ins Archiv); Bestätigung an Bild-ID und SHA gebunden; Entfernen unter Sperre mit frischem Stand; Korrektur archiviert über Auftrag; `precheck_withheld_at` getrennt von `withheld_at`; Depublikationsstand am Auftrag; Restore-Abgleich löscht Anwendungskopien |
|
||||
| 9.6 | K-02, R-04, R-05, E9-Schalter | erledigt | Kontingent-/Bildsperre im Scheduler als „blockiert" (Exit 0, einmaliger Verlaufseintrag), KI-Job ohne Retry; nach Kundenbestätigung erneut routen; `X-Pk-Ref` per HMAC signiert, Hard-Sperre nur bei gültiger Signatur; Unmerge setzt nur unveränderte Füllwerte zurück (`company_merge_moves.merged_value`); `NEWSLETTER_SENDING_ENABLED` (Standard aus) |
|
||||
| 9.7 | Q-01, Q-02, Q-06, P3, OPT | erledigt bis auf Q-05 | Testhelfer nach `tests/Pest.php` (Suite läuft parallel); Larastan voller Scope ohne Meldung; P3-Liste und OPT-1 bis OPT-9 umgesetzt (OPT-4 teilweise, Integritätshash bleibt bewusst); Q-07 war ein Fehlalarm (`IMAGE_PRECHECK_MODEL` steht auskommentiert in `.env.example`). **Q-05 (`docs/` lokal gelöscht, nicht committet) entscheidet der Betreiber.** |
|
||||
|
||||
Zusätzlich bei der Integration: `press-release-images:sweep-orphan-originals` wöchentlich (So 04:45) im Scheduler, löscht nichts, solange der Archiv-Sweep pausiert ist; `purge-events` von 03:20 auf 03:50; alle `withoutOverlapping()` mit kurzer Sperrdauer (`ScheduleConfigurationTest`); Scheduler-Tabelle im Runbook vollständig. **Im Runbook stand seit `665c94f` (21.07.2026) ein Passwort neben dem KAS-SSH-Zugang** — aus der Arbeitskopie entfernt; in der Git-Historie und auf `origin` bleibt es, deshalb rotieren (Betreiber).
|
||||
|
||||
### Entscheidungen (bei der Umsetzung getroffen, **vom Betreiber am 02.10.2026 bestätigt**, einschließlich der Revision von E25)
|
||||
|
||||
| Nr. | Befund | Entscheidung |
|
||||
|---|---|---|
|
||||
| E19 | R-01 | Allowlist per `.env`, Standard leer; ohne Eintrag verhält sich connektar wie vor 1a.4 (neue Firma je Einlieferung). Live: connektar = User 13993 |
|
||||
| E20 | K-04 | Passwort bei OAuth-Verifikation eines offenen Kontos verwerfen; Anmeldung danach über Google, Magic Link oder Passwort-Reset |
|
||||
| E21 | K-02 | Keine Autorenmail bei Kontingent- oder Bildsperre (keine passende Vorlage; Bildbestätigung wurde schon angefordert), nur Verlaufseintrag und Log |
|
||||
| E22 | K-08 | Google-Login ohne erzwungenes „Angemeldet bleiben"; `magic-login` ohne `guest`, fremde Links wie bisher |
|
||||
| E23 | E9 | Newsletter-Versand per Schalter aus, bis U05–U07 umgesetzt sind |
|
||||
| E24 | R-02 | `content_changed_at` ohne Backfill; Fallback `published_at` |
|
||||
| E25 | R-04 | ~~Unsignierte Rückläufer im Übergang `soft`, nach etwa 14 Tagen auf `policy`~~ — **revidiert 02.10.2026 (O01):** jeder nicht verifizierte Rückläufer, hart wie weich, nur zur Sichtung (`BOUNCE_UNSIGNED_KIND=policy`); `soft` nur als bewusste, fälschbare Ausnahme |
|
||||
| E26 | R-09 | Claim-Links je Firma und Tag 5 statt 3, gezählt erst nach Versand |
|
||||
| E27 | R-10 | `email_bounces` 395 Tage wie DSE 5a; die Sperrliste selbst bleibt. DSE erwähnt Rückläufer noch nicht (Betreiber/Anwalt) |
|
||||
| E28 | R-11 | Canonical-Portal über Kategorie-ID (1–14), Slug-Liste als Rückfall |
|
||||
| E29 | A-02 | Auftragstabelle statt Zeitstempel-Marker |
|
||||
| E30 | A-03 | Quarantäne 30 Tage statt Löschen |
|
||||
| E31 | A-15 | Schlüsselrotation über `ARCHIVE_PREVIOUS_KEYS`, Export-HMAC per HKDF; alte Exporte bleiben prüfbar |
|
||||
| E32 | B-05 | Entfernen eines veröffentlichten Bildes blockiert bei Archivfehler nicht (E15-Muster), Auftrag bleibt offen, Beweisdateien bleiben liegen |
|
||||
| E33 | B-09 | Admin als Eigentümer der Meldung bekommt im Bildmanager die Kundenregel |
|
||||
| E34 | B-10 | Eigener Magic-Link-Zweck `image_confirmation`, 72 h, einmalig |
|
||||
|
||||
### Deploy-Plan für die Blöcke 9 und 10
|
||||
|
||||
Gilt für beide Blöcke zusammen (Block 10 hat keine eigene Migration). In Klammern die Entscheidung bzw. der Befund, aus dem der Schritt folgt.
|
||||
|
||||
**A — Vor dem Deploy**
|
||||
|
||||
1. `.env` auf Live ergänzen:
|
||||
- `NEWSROOM_API_ASSIGNMENT_USER_IDS=13993` — connektar, auf Live gegenprüfen (`select id from users where email = 'info@connektar.de'`). Ohne Eintrag legt connektar wieder je Einlieferung eine neue Firma an (E19).
|
||||
- `NEWSLETTER_SENDING_ENABLED=false` — bleibt aus, bis U05–U07 umgesetzt sind (E23).
|
||||
- `BOUNCE_UNSIGNED_KIND=policy` — unsignierte Rückläufer nur zur Sichtung (E25 revidiert, O01).
|
||||
- Optional, Standardwerte greifen: `BOUNCE_SIGNING_KEY` (leer = aus `APP_KEY`), `BOUNCE_RETENTION_DAYS` (395, E27), `ARCHIVE_PREVIOUS_KEYS` (nur bei Schlüsselrotation, E31), `ARCHIVE_QUARANTINE_DAYS` (30, E30), `ARCHIVE_SWEEP_PAUSED`, `CONVERSION_MAIL_CLICK_THROTTLE_MINUTES` (30), `NEWSROOM_CLAIM_LINKS_PER_DAY` (5, E26).
|
||||
2. Hauptkategorien prüfen: `select id, slug from category_translations where locale = 'de' and category_id between 1 and 14` muss zu `config/canonical.php` → `portal_by_category_id` passen (E28). Weicht etwas ab, vor dem Deploy die Config anpassen — sonst ändert sich die Canonical-Zuordnung still.
|
||||
3. Uploadgrenzen: PHP `upload_max_filesize` und `post_max_size` sowie nginx `client_max_body_size` ≥ 16 MiB mit Puffer, z. B. 20M (B-03).
|
||||
4. DB-Backup ziehen; `ARCHIVE_KEY` liegt getrennt gesichert vor.
|
||||
|
||||
**B — Deploy**
|
||||
|
||||
5. Dateien hochladen (Branch `technik/betriebsfixes-2026-09`).
|
||||
6. `php artisan migrate --force` — acht Migrationen, alle additiv: `press_releases.content_changed_at` (INSTANT, E24), `company_merge_moves.merged_value`, `press_release_images.precheck_withheld_at` + Übernahme offener Sichtungen, Magic-Link-Zweck `image_confirmation` (E34), `archive_pending_jobs` (E29), `archive_entries.key_id` + Index `payload_path` (E31), `archive_access_log.admin_name/-email`. Dev-Kopie (MySQL): 0,7 s gesamt.
|
||||
7. `php artisan config:cache`, `php artisan view:clear && php artisan view:cache`, `php artisan schedule:clear-cache` (alte 24-h-Sperren von `withoutOverlapping`), `php artisan queue:restart`, FPM-Neustart.
|
||||
|
||||
**C — Direkt nach dem Deploy**
|
||||
|
||||
8. `php artisan archive:retry-pending` einmal von Hand — vorhandene Altmarker werden zu Aufträgen `legacy_marker` und laufen einmal (E29). Danach im Admin-Systemstatus die Kacheln `archive_key`, `archive_pending`, `archive_sweep` grün.
|
||||
9. `php artisan company-memberships:api-assignments` sichten; nur bei Treffern ohne Freischaltung `--remove` (zeigt vorher die Zeilen, E19).
|
||||
10. `php artisan press-releases:assign-canonicals` — setzt veraltete Verweise zurück und leert die Caches (R-06, E28).
|
||||
11. `php artisan press-release-images:sweep-orphan-originals` einmal als Trockenlauf; ab dann läuft er sonntags 04:45 scharf (B-11).
|
||||
12. `php artisan archive:sweep-orphans --dry-run` — auf Live war der Sweep am 28.09. leer; Funde wandern jetzt in die Quarantäne statt gelöscht zu werden (E30).
|
||||
13. `php artisan schedule:list` — 19 Tasks, darunter `press-release-images:sweep-orphan-originals` So 04:45 und `press-releases:purge-events` 03:50.
|
||||
|
||||
**D — Abnahme auf Live (Testkonto)**
|
||||
|
||||
14. Anmelden per Passwort, Magic Link und Google; danach einige Seiten aufrufen — die neue Session-Middleware läuft auf jedem Request (E20, E22, K-08). Ein bereits eingeloggter Nutzer, der einen eigenen Magic Link öffnet, landet auf dem Ziel.
|
||||
15. Titelbild mit 13–15 MiB über das Formular hochladen (B-03).
|
||||
16. `sitemap.xml` stichprobenartig: englische Meldungen unter `/en/press-release/…` (R-03); Meldungsseite: `article:modified_time` = Veröffentlichung bzw. letzte Textänderung, nicht der letzte Aufruf (E24).
|
||||
17. Admin ▸ Newsletter: Kampagne zeigt den Sperrhinweis, „Senden" ist aus (E23).
|
||||
18. Admin ▸ Mail-Sperrliste nach dem nächsten `mail:fetch-bounces`: unsignierte Rückläufer erscheinen als Richtlinie mit „(unsigniert)", sperren aber nicht (E25).
|
||||
|
||||
**E — Danach, außerhalb des Codes**
|
||||
|
||||
19. **KAS-Passwort rotieren** — stand bis 29.09. im Runbook und liegt in der Git-Historie und auf `origin`.
|
||||
20. **Datenschutzerklärung:** Rückläufer-Protokoll (`email_bounces`, 395 Tage) in Abschnitt 5a/13 aufnehmen (E27, Betreiber/Anwalt).
|
||||
21. Restore-Übung in isolierter Umgebung (DB alt/Disk neu, Disk alt/DB neu, beide alt) mit den neuen Schritten aus Runbook Abschnitt 9 (O04/O05).
|
||||
22. Protokoll unten um Deploy-Datum und Ergebnisse von 8–18 ergänzen.
|
||||
|
||||
Keine Kundenkommunikation nötig: E20 betrifft nur offene, nie verifizierte Selbstregistrierungen; E21 erzeugt bewusst keine Mail; E33 ändert nur die Admin-Sicht.
|
||||
|
||||
## Block 10 — Abgleich Umsetzungsaudit vom 02.10.2026
|
||||
|
||||
Grundlage: [`UMSETZUNGSAUDIT-2026-10-02.md`](UMSETZUNGSAUDIT-2026-10-02.md) (2 × P1, 6 × P2) zur noch nicht committeten Arbeitskopie von Block 9. Jeder Befund am 02.10.2026 am Code gegengeprüft: **alle acht valide**, keiner durch eine dem Audit unbekannte Entscheidung gedeckt. Alle als offensichtliche Fehler behoben; einzig O01 ändert eine Entscheidung (E25).
|
||||
|
||||
| ID | Ergebnis | Umsetzung |
|
||||
|---|---|---|
|
||||
| O01 (P1) | valide — die Signaturprüfung griff nur bei `hard`; `delayed` und zu `soft` umgestufte 4.x-Berichte zählten ungeprüft, drei gefälschte DSNs sperrten jede Adresse | Jede Art, die auf eine Sperre zählt, braucht die gültige empfängergebundene Signatur. Ohne: `bounces.unsigned_kind` (`BOUNCE_UNSIGNED_KIND`, Standard `policy`, nie hart), falsch signiert: immer `policy`. Folge: auch die Freitextberichte des KAS-Relays (ohne Original-Header) sperren nicht mehr selbst, sie landen zur Sichtung |
|
||||
| O02 (P1) | valide — `DB_URL` überschreibt Treiber und Datenbank erst beim Verbindungsaufbau | phpunit.xml leert `DB_URL` (env und server), der Guard in `TestCase::setUpTraits()` bricht bei gesetzter `url` ab |
|
||||
| O03 (P2) | valide — `published_ever_at` setzte erst der nachgelagerte Snapshot | `PressReleaseImage::markPublishedIfNowPublic()` in der Freigabetransaktion: Kundenbestätigung, Freigabe der Vorab-Sichtung, Korrektur-Freigabe |
|
||||
| O04 (P2) | valide — Restore-Abgleich fand die Zeile per ID | Zuordnung über den Payload-Pfad (UUID); gleiche ID mit anderem Payload = Konflikt, nichts angefasst, Exit ≠ 0 |
|
||||
| O05 (P2) | valide — fehlendes `hmac` galt als Altformat; `reregister` ignorierte `invalid` | Unsignierte Exporte nur mit `--accept-unsigned`; `archive:reregister` bricht bei ungültigem/unsigniertem Export ab, bei fehlendem Export nur mit `--without-export` |
|
||||
| O06 (P2) | valide — blockierte Meldungen belegten dauerhaft die vordere Seite | Cursor über `(scheduled_at, id)`, Limit zählt bearbeitete Meldungen, Blockaden nur auf ein Scan-Budget (10 × Limit) |
|
||||
| O07 (P2) | valide — Direktweg und Nachholer starteten mit geladener Instanz | `ArchivePendingQueue::claim()` (Zeilensperre, neu lesen) in `completeWith()` und `PendingArchiveRetry::retry()`; bereits erledigt = nichts tun, kein Fehlversuch |
|
||||
| O08 (P2) | valide — fehlende Snapshot-Datei wurde still ausgelassen | Datei weg: Verweis auf den `image_removed`-/`image_replaced`-Eintrag des Bildes (`archived_in`), sonst Exception, Auftrag bleibt sichtbar offen; Altbestand ohne Snapshot als `snapshot: none` gekennzeichnet |
|
||||
|
||||
Abschnitt 5 des Audits (Betriebsnachweise, Restore-Übung, Bildbetrieb, Fachfreigaben) bleibt offen wie dort beschrieben; Abschnitt 5.7 (veraltete „offen"-Notizen zu 1.8 und N09) ist unten im Protokoll korrigiert. Echte Parallelität (O03, O07) ist weiter nur logisch geschlossen, nicht mit zwei MySQL-Verbindungen nachgestellt (6.6).
|
||||
|
||||
**Runbook:** Restore-Schritte 2 und 3 um Pfad-Zuordnung, `--accept-unsigned` und `--without-export` ergänzt.
|
||||
|
||||
## Nicht aufgenommen
|
||||
|
||||
- **F21 Legacy-Import.** Befund korrekt (Vollladen der Pivot-Tabellen, kein Transaktionsschutz, Wiederanlauf ändert UUID und Slug). Der Importer läuft seit dem 16.07. nicht mehr und ist nicht im Scheduler. Falls das Altsystem noch einmal einen Delta-Lauf braucht: `importRow()` in `DB::transaction` und vorhandene PM über `(legacy_portal, legacy_id)` statt über die Importmap erkennen. Bis dahin steht nur diese Notiz.
|
||||
|
|
@ -361,11 +466,19 @@ Entscheidungen aus Block 8 (25.09.2026, bei der Umsetzung getroffen; **alle acht
|
|||
| 18.09.2026 | 7.2, 7.3, 7.4 | `ea68362` | Bedingtes UPDATE in beiden Jobs, Prüfung im Publish-Lock für `ki`/`scheduler`, `StaleClassificationException`; roter Re-Check einer Review-PM lehnt ab (gilt auch für den Admin-Re-Check, PMs mit `manual_review_required_at` ausgenommen); NULL-Periode = laufender Monat plus Backfill |
|
||||
| 25.09.2026 | Block 8: N22, N06 (Gate), 5.3 | `4e34c3d` | Guard in `setUpTraits()`, Flags in phpunit.xml gepinnt, Zustimmung an gezeigte Fassung gebunden, Audit/Decision-Update/Plan versioniert |
|
||||
| 25.09.2026 | Block 8: N01–N05, N07, N08, N10–N21, 5.1 a–e, 5.2 | `48129e9` | vier parallel geprüfte und umgesetzte Gruppen (Bilder, Archiv, KI/Hintergrund, Berichte); zwei Migrationen; 12 + 9 + 7 + 8 neue Tests |
|
||||
| 29.09.2026 | Block 9: 9.1–9.7 (R-01, K-01–K-09, B-01–B-14, N09, A-01–A-15, R-02–R-11, N17/N18/N19-Rest, Q-01/Q-02/Q-06, OPT-1–OPT-9, E9-Schalter) | — (nicht committet) | vier parallele Gruppen; acht Migrationen, auf der Dev-Kopie (MySQL) in 0,7 s; neue Befehle `company-memberships:api-assignments`, `archive:reregister`, `archive:verify-export`, `press-release-images:sweep-orphan-originals`; KAS-Passwort aus dem Runbook entfernt |
|
||||
| 02.10.2026 | Block 10: O01–O08 aus dem Umsetzungsaudit 02.10. | — (nicht committet) | alle acht Befunde valide und behoben; keine Migration; E25 revidiert (`BOUNCE_UNSIGNED_KIND=policy`); Runbook-Restore um `--accept-unsigned`/`--without-export` ergänzt |
|
||||
|
||||
Gesamtsuite nach Block 7: 1.930 Tests grün, einer übersprungen; PHPStan ohne Meldung; Pint sauber.
|
||||
|
||||
Gesamtsuite nach Block 8 (25.09.2026, HEAD `48129e9`, Befehl `php artisan test --compact` nach `config:clear`): 2.122 Tests grün, einer übersprungen; Larastan Level 4 ohne Meldung auf allen geänderten Dateien; Pint sauber. Offen: N09, Browser-/Tastaturabnahme, MySQL-/Worker-CI, die Messpunkte aus 5.2. Ein Test (`ApiPortalResolutionTest`) brauchte wegen der neuen Kategorieprüfung eine gemeinsame Kategorie statt einer zufälligen.
|
||||
|
||||
Gesamtsuite nach Block 9 (29.09.2026, Befehl `php artisan test --compact` nach `config:clear`): **2.265 Tests grün, einer übersprungen** — seriell (305 s) und erstmals auch parallel (`--parallel --processes=6`, 57 s); Larastan Level 4 über den vollen Scope ohne Meldung (vorher 1); Pint sauber. Offen: Q-05 (`docs/`), U05–U07 (Newsletter, per Schalter gesperrt), 6.6 MySQL-/Worker-CI, 7.6 Browserabnahme.
|
||||
|
||||
Gesamtsuite nach Block 10 (02.10.2026, `php artisan test --compact --parallel --processes=6` nach `config:clear`): **2.281 Tests grün, einer übersprungen** (95 s); Larastan Level 4 voller Scope ohne Meldung; Pint sauber.
|
||||
|
||||
Offen: U05–U07 nach E9 aufgeschoben; 7.6 (Fokusführung) manuell im Browser abnehmen.
|
||||
|
||||
*Stand 02.10.2026: 1.8 ist mit Block 9 (K-08, `LoginCompletion`) und N09 mit Block 9.5 erledigt; die beiden Absätze unten sind historisch.*
|
||||
|
||||
Offen aus dem Plan: 6.6 (MySQL-/Worker-Integrationstests) bleibt aufgeschoben; 1.8 nur als Google-Zweig, nicht als Service-Zusammenführung; 4.2 hatte die Prüfung in `publish()` nicht (siehe Block 7, U02). Nachträglich zwei zufallsabhängige Tests festgezurrt (Kategorie-Portal in den API-Tests, Titel in der MAN-PDF-Adresse). Gesamtsuite nach allen Commits: 1.891 Tests grün, einer übersprungen; PHPStan ohne Meldung.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue