auth: automatische Firmenzuordnung beim Wegfall der E-Mail-Grundlage entfernen statt senken (Block 7.13, U01, E7)
- Login-Sync löscht auto-Pivots ohne aktuellen Treffer; member wäre die Teamrolle mit Schreibrecht auf alle Firmen-PMs, keine Leserolle - hochgestufte manuelle Mitgliedschaften tragen granted_via=auto-upgrade und fallen auf member zurück; manual und owner bleiben unberührt - company-memberships:audit --classify stuft nur manual-Zeilen um - Plan: E2 revidiert, E7 entschieden, 1.5 und 7.13 nachgezogen Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
c26bdff681
commit
5122624687
4 changed files with 92 additions and 26 deletions
|
|
@ -77,7 +77,7 @@ Der Kern: Firmenrechte entstehen aus einer E-Mail-Übereinstimmung, die nie auf
|
|||
| 1.2 | `ContactAccessService::syncMembershipsForEmail()` verlangt `hasVerifiedEmail()` und `is_active`. Gilt für alle Aufrufer, nicht nur den Login-Listener. Test: unverifizierter Nutzer mit passender Firmenadresse erhält keinen Pivot; nach Verifikation schon. | S | keine |
|
||||
| 1.3 | Herkunft am Pivot speichern: Spalte `company_user.granted_via` (`auto`, `manual`, `owner`). Migration klein, Tabelle klein. Bestehende Zeilen: `manual`, wenn sie nicht durch den Sync erklärbar sind (siehe 1.4). | S | E2 |
|
||||
| 1.4 | Bestandsprüfung als Befehl mit `--dry-run`: alle `responsible`-Pivots, deren Nutzer-Mail heute weder zur Firma noch zu einem Kontakt der Firma passt. Ausgabe als Liste, keine Löschung. Danach Entscheidung je Zeile. | S | 1.3 |
|
||||
| 1.5 | Entzug beim Login-Sync: `auto`-Pivots mit `responsible`, die keinen aktuellen E-Mail-Treffer mehr haben, auf `member` senken. `manual` und `owner` bleiben unberührt. Test: Kontakt löschen oder Adresse ändern, erneut anmelden, Schreibrecht ist weg. | M | 1.3, E2 |
|
||||
| 1.5 | Entzug beim Login-Sync: `auto`-Pivots mit `responsible`, die keinen aktuellen E-Mail-Treffer mehr haben, entfernen (E7, revidiert E2: `member` ist keine Leserolle). Hochgestufte manuelle Mitgliedschaften (`auto-upgrade`) fallen auf `member` zurück; `manual` und `owner` bleiben unberührt. Test: Kontakt löschen oder Adresse ändern, erneut anmelden, Schreibrecht auf fremde Firmen-PMs ist weg. | M | 1.3, E7 |
|
||||
| 1.6 | `security.blade.php`: `#[Locked]` auf `showRecoveryCodes`; die Codes nur im Render nach einer Action ausgeben, nicht aus einer Property. Test: `set('showRecoveryCodes', true)` scheitert. | S | keine |
|
||||
| 1.7 | Erneuter Nachweis vor `disableTwoFactorAuthentication()`, `regenerateRecoveryCodes()` und `updateEmail()`: aktueller TOTP-Code oder Recovery-Code. Das funktioniert auch für Konten ohne Passwort. Test: ohne Code 422, mit Code Erfolg. | M | E3 |
|
||||
| 1.8 | `GoogleController.php:50`: 2FA-Zweig aus `MagicLinkConsumeController.php:73-81` übernehmen; danach die drei Login-Abschlüsse in einen Service ziehen. Test in `GoogleLoginTest`: Konto mit TOTP endet als Gast auf der Challenge. | S | keine |
|
||||
|
|
@ -87,7 +87,7 @@ Der Kern: Firmenrechte entstehen aus einer E-Mail-Übereinstimmung, die nie auf
|
|||
**Entscheidungen**
|
||||
|
||||
- **E1** Fortify-Profiländerung abschalten (empfohlen) oder auf den `pending_email`-Prozess umbiegen. Abschalten ist ein Einzeiler und schließt den Einstieg vollständig; niemand nutzt den Endpunkt.
|
||||
- **E2** Entzugsregel: auto-vergebene `responsible` ohne aktuellen Treffer werden beim nächsten Login auf `member` gesenkt (empfohlen), oder komplett entfernt. Absenken ist reversibel und verliert keine manuellen Rechte.
|
||||
- **E2** Entzugsregel: auto-vergebene `responsible` ohne aktuellen Treffer werden beim nächsten Login auf `member` gesenkt (empfohlen), oder komplett entfernt. Absenken ist reversibel und verliert keine manuellen Rechte. *Revidiert durch E7 am 18.09.2026: `member` ist die Teamrolle mit Schreibrecht auf alle Firmen-PMs; die Zuordnung wird entfernt.*
|
||||
- **E3** Nachweisform für Sicherheitsaktionen: TOTP-/Recovery-Code (empfohlen, funktioniert für alle Kontotypen) oder Passwort mit Sonderweg für passwortlose Konten.
|
||||
|
||||
**Abnahme:** Die Kette aus F01 (fremde Adresse setzen, neu anmelden, zurückwechseln) ist als Test in `ContactAccessTest` abgebildet und hinterlässt keinen Pivot. Alle Login-Wege (Passwort, Magic Link, Google) landen bei aktivem TOTP auf der Challenge. Ergebnis von 1.4 ist gesichtet.
|
||||
|
|
@ -225,7 +225,7 @@ Nicht aufgenommen aus Block 7: U05–U07, weil das Kampagnenmodul nicht in Betri
|
|||
| 7.10 | 7.1 | S | `--classify` zeigt vorher die betroffenen Zeilen (Anzahl, Stichprobe) und nimmt mit `--before=` nur Pivots vor dem Deploy. `ConfirmEmailChangeController` stößt den Sync an. |
|
||||
| 7.11 | 7.5 | S | `ReleaseDetailPageData` sortiert wie der Resolver (Erstquelle zuerst, dann ID). |
|
||||
| 7.12 | 7.4, 7.7 | S | Protokoll korrigieren: 40 Ausnahmen, `--classify` statt `--dry-run`, 1.8 teilweise, Rechnungslauf mit Kappe 500 pro Lauf, E6 Gleichheitsfall. |
|
||||
| 7.13 | U01 | M | Nach E7. Empfehlung: automatische Zuordnung beim Wegfall der Grundlage entfernen statt senken. |
|
||||
| 7.13 | U01 | M | Nach E7: automatische Zuordnung beim Wegfall der Grundlage entfernen statt senken; neuer Pivot-Wert `auto-upgrade` für hochgestufte manuelle Mitgliedschaften. |
|
||||
|
||||
**E6, Gleichheitsfall:** Endet der Vertrag genau am letzten Tag der Periode (`grandfathered_until = current_period_end`), wird die Periode noch berechnet. Das ist die Regel „Rechnung, wenn die Periode nicht über das Vertragsende hinausreicht“. Bestätigt am 18.09.2026 mit E6.
|
||||
|
||||
|
|
@ -250,7 +250,7 @@ Tatsächlich umgesetzt am 18.09.2026 in fünf Commits auf `technik/betriebsfixes
|
|||
| C | Block 1, Punkte 1.3, 1.4, 1.5, 1.7 | `62202a4` | `company_user.granted_via` |
|
||||
| D | Block 3 und Block 4 | `f235156` | `contacts_email_idx`; `ki_audits.content_hash/discarded_at`; `users.press_release_quota_period` (COPY, Sekunden) |
|
||||
| E | Block 5 und Block 6 | `375f4df` | `user_payment_options.billing_hold_reason/-at` |
|
||||
| F | Block 7 (ohne 7.13) | `235d392`, `1cd9fd1`, `ea68362` | `user_payment_options.grandfathering_expired_at/-notified_at`; Backfill `users.press_release_quota_period` (DML, Sekunden); Newsletter-Bereinigung angepasst (noch nicht live) |
|
||||
| F | Block 7 | `235d392`, `1cd9fd1`, `ea68362`, 7.13 siehe Protokoll | `user_payment_options.grandfathering_expired_at/-notified_at`; Backfill `users.press_release_quota_period` (DML, Sekunden); Newsletter-Bereinigung angepasst (noch nicht live) |
|
||||
|
||||
Migrationen berühren `press_releases` und `press_release_search` nicht.
|
||||
|
||||
|
|
@ -271,12 +271,12 @@ Am 18.09.2026 alle sechs nach Empfehlung entschieden. Umsetzung ab demselben Tag
|
|||
| Nr. | Frage | Entscheidung |
|
||||
|---|---|---|
|
||||
| E1 | Fortify-Profiländerung abschalten oder umbiegen | abschalten |
|
||||
| E2 | Auto-Rechte bei Wegfall der Grundlage senken oder entfernen | auf `member` senken |
|
||||
| E2 | Auto-Rechte bei Wegfall der Grundlage senken oder entfernen | auf `member` senken – **revidiert durch E7** |
|
||||
| E3 | Nachweis vor Sicherheitsaktionen | TOTP- oder Recovery-Code |
|
||||
| E4 | Newsletter-Versandreihenfolge fachlich relevant | nein |
|
||||
| E5 | Kontingentperiode | Kalendermonat |
|
||||
| E6 | Letzte MAN-Periode am Vertragsende | keine Rechnung mehr |
|
||||
| E7 | U01: automatische Zuordnung bei Wegfall der Grundlage | **offen.** Empfehlung: Zuordnung entfernen. `member` ist die normale Teamrolle mit PM-Schreibrechten; eigene PMs bleiben über die Autorenschaft erreichbar. Alternative Leserolle wäre eine neue Rolle (L). |
|
||||
| E7 | U01: automatische Zuordnung bei Wegfall der Grundlage | Zuordnung entfernen (18.09.2026). `member` ist die normale Teamrolle mit PM-Schreibrechten; eigene PMs bleiben über die Autorenschaft, Eigentum, manuelle Rechte und weiterhin passende Adressen bleiben. Eine automatisch hochgestufte manuelle Mitgliedschaft fällt auf `member` zurück. |
|
||||
| E8 | U09: ungenutzte Fortify-2FA-Verwaltungsrouten | abschalten, folgt aus E3 |
|
||||
| E9 | U05–U07: Newsletter-Wiederaufnahme und Doppelversand | aufgeschoben, bis das Kampagnenmodul in Betrieb geht; bis dahin nur Abmeldung und Sperrliste live (Nutzer, 18.09.2026) |
|
||||
|
||||
|
|
@ -298,6 +298,6 @@ Am 18.09.2026 alle sechs nach Empfehlung entschieden. Umsetzung ab demselben Tag
|
|||
|
||||
Gesamtsuite nach Block 7: 1.930 Tests grün, einer übersprungen; PHPStan ohne Meldung; Pint sauber. Ein Test (`ApiPortalResolutionTest`) brauchte wegen der neuen Kategorieprüfung eine gemeinsame Kategorie statt einer zufälligen.
|
||||
|
||||
Offen: 7.13 (U01) wartet auf E7; U05–U07 nach E9 aufgeschoben; 7.6 (Fokusführung) manuell im Browser abnehmen.
|
||||
Offen: U05–U07 nach E9 aufgeschoben; 7.6 (Fokusführung) manuell im Browser abnehmen.
|
||||
|
||||
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