Commit graph

528 commits

Author SHA1 Message Date
6c6015f960 dev: Nachweise gesichtet, Vertragsübersicht BN-06, Deploy-Notiz v1.9.1
Screenshots und Verträge geprüft und in nachweise/ zusammengeführt;
Binärdateien per .gitignore ausgeschlossen (vertraulich, Kunden- und
Organisationsnummern, Größe). Vertragsübersicht mit Fassungen, Daten und
Drittlandgrundlagen. Versandfassung: DPF-Status Cloudflare vom 13.10.2026,
OpenAI-DPA unterzeichnet am 13.10.2026. Juli-Zahlen auf Live bestätigt.
Protokollzeile v1.9.0 im Git-Deploy-Dokument.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 11:22:15 +00:00
6647e420c8 build: Assets für v1.9.1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 11:22:10 +00:00
b3d2d1e5b4 web: Bildnachweis am Aufmacher auf Mobil nicht mehr vom Boost-Label verdeckt
Auf 390 px Breite lag das Schild „Gebuchte Platzierung“ über dem
Bildnachweis oben rechts. Der Nachweis sitzt auf Mobil jetzt unten rechts im
freien Rand unter der Meta-Zeile (ab sm unverändert oben rechts). Die
Erklärung am Schild ist rechtsbündig und stößt nicht mehr an den Bildrand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 11:22:10 +00:00
2d7e32b13c dev: Rollenprüfung BN-02 auf Live erledigt, Juli-Abfrage korrigiert
Nachher-Liste vom 13.10.2026: ein Admin-Konto mit Passkey und TOTP,
Super-Admin, keine Editoren, Zugänge außerhalb der Anwendung nur beim
Inhaber. Versandfassung D3 und Klärung U13 nachgezogen. Tinker-Befehl für
die Juli-Kampagnen nutzt status->value (Enum).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 10:37:57 +00:00
4bf22a81d0 admin: audit:admins mit Einzahl in der Zusammenfassung
„Gelistet ist 1 Konto“ statt „Gelistet sind 1 Konten“.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 10:37:57 +00:00
53da182d17 dev: Rechtspaket mit Nachweisordner, Archiv und Deploy-Notiz v1.9.0
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run
Versandfassung mit Codeabgleich vom 13.10. korrigiert (Zugriffsprotokoll
des Beweisarchivs als Ziel, Admin-Bestand, Juli-Mails mit Zahlen und
Empfängerregel, C2PA als geplant, Gate-Dialog heute), Anlage 6 abgelegt.
Neuer Ordner rechtliches/nachweise mit Checkliste, Juli-Mailtexten,
OpenAI-Endpunkten, BN-01-Vorlage und BN-02-Ablauf inklusive Notfallzugang.
Vorfassungen, Codeauswertung, To-do-Liste und Rückfragen nach
archive/rechtliches-2026-10. Deploy-Notiz archive/betrieb/deploy-v1.9.0.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 10:16:21 +00:00
2d74fd28c9 build: Assets für v1.9.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 10:16:21 +00:00
fce7baea2b admin: Boost vorzeitig beenden, Berechtigungsliste audit:admins
Admin ▸ Pressemitteilung zeigt laufende Boosts; „Boost beenden“ verlangt
einen Grund und billing:manage, beendet laufende und angeschlossene
Zeiträume, verwirft die Seiten-Caches und protokolliert „Boost beendet“.
Credits werden nicht zurückgebucht.

audit:admins listet alle Konten mit Rechten über den Kundenbereich hinaus
(Super-Admin, Rollen außer customer/api-only, direkte Permissions), auch
gesperrte und gelöschte, als Markdown mit 2FA, Passkeys, Tokens und letztem
Sitzungswiderruf. E-Mail standardmäßig nur mit Domain (Nachweis BN-02).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 10:16:21 +00:00
2150d4b7ae web: Boost als „Gebuchte Platzierung“ mit Erklärung gekennzeichnet
Label „Gebuchte Platzierung“ (en „Booked placement“) statt „Top-Platzierung“
auf Start- und Branchenseite. Die Erklärung „Das Unternehmen hat diesen Platz
gebucht …“ erscheint am Desktop beim Überfahren und auf Mobil per Tipp, ohne
den umgebenden Link zu öffnen; Screenreader lesen sie mit. Kopfzeile über dem
Aufmacher „Aktuell“ statt „Top-Auswahl“ (automatische Auswahl, keine
Redaktion). Preisseite nennt die Kennzeichnung (Rechtspaket U10).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 10:16:21 +00:00
8124d20946 dev: Deploy v1.8.0 im Git-Deploy-Protokoll, Hotfix v1.8.1 vorbereitet
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 07:37:33 +00:00
853dfe2131 web: „qualitätsgeprüft“ auch in Marken-Konfiguration und Tarif-Vorteilen ersetzt
Nachtrag zu v1.8.0, beim Prüfen nach dem Deploy gefunden: Meta-Beschreibungen
und Taglines der drei Marken (config/domains.php), Tarifvorteil „Starter“ im
PlanSeeder, Platzhalter im Admin. Der Wächtertest prüft jetzt auch config/
und database/seeders/. Live steht der Tarifvorteil in der Datenbank und wird
im Admin geändert (Seeder überschreibt sonst alle Tarifdaten).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 07:37:24 +00:00
2172d91d19 dev: Server-Logs auf 14 Tage umgestellt (Roadmap 5.13)
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 14:03:32 +00:00
da0b5bffbb dev: Server-Logs 52 → 14 Tage als Live-Aufgabe, Backup- und Monitoring-Fristen im Anwaltspaket
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 14:00:06 +00:00
a3663d5628 dev: Interessenabwägung Beweisarchiv (Entwurf), Anwaltspaket mit Hetzner Falkenstein und Backup-Rotation 14 Tage
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 13:52:28 +00:00
da011ccdbf dev: Entwurf Anwaltspaket Datenschutz (DSE 0.4, Fragen F1–F11)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 13:39:40 +00:00
9692de581d dev: Changelog-Entscheidungen O1–O13 und E19–E21, Roadmap v1.8-Stand
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 13:35:54 +00:00
62d00a6c9d tests: fester Test-APP_KEY in phpunit.xml
Die Suite hing vom lokalen APP_KEY ab (lokal ungültig, Roadmap 1.3).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 13:35:54 +00:00
ddff7dc989 web: Wortwahl „automatisierte Prüfung“ statt „qualitätsgeprüft“
Decision-Update Bildrechte 3.6 / Plan D.6: keine Siegel- oder
Redaktionszusage. Startseiten-Meta, CTA, Veröffentlichen-Seite (DE/EN),
Preisseite, Dashboard. „Qualitätsgeprüft seit 2012“ war sachlich falsch →
„Im Archiv seit :year“. Wächtertest gegen Rückfälle (Roadmap 3.7).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 13:35:54 +00:00
ccef83b952 api: Newsletter-Anmeldung über die API eingestellt (410)
Der Endpunkt legte Abos ohne Bestätigungsweg an, die Spezifikation versprach
ein Double-Opt-in; seit dem Go-Live kein Aufruf. Antwortet jetzt mit 410,
die Ability ist für neue Tokens nicht mehr wählbar (Roadmap 4.3).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 13:35:54 +00:00
002dc08b5c privacy: Löschfristen für Aktivitätsverlauf (395 Tage) und API-Zugriffsprotokoll (90 Tage)
Beide Tabellen hatten keine Frist; activity_events trägt Namen und Adressen
im Klartext, api_usage_logs IP und User-Agent. MassPrunable, täglich 04:05
über model:prune, Fristen in config/monitoring.php (Roadmap 4.2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 13:35:54 +00:00
d1b9ffdcf1 security: Breadcrumbs ohne Daten an GlitchTip, Übergangsmarke der Session-Sperre entfernt
- ErrorReportScrubber entfernt die Daten aller Breadcrumbs und bereinigt ihre
  Nachrichten; Livewire-Breadcrumbs standardmäßig aus — das SDK hängt dort
  Formularwerte und Properties an (Roadmap 4.9). Bestand in GlitchTip geprüft:
  keine Formular- oder Passwortdaten.
- SessionRevocation::legacyCachedMark() entfernt (Übergang bis v1.6.0)

Changelog: Sicherheit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 13:35:54 +00:00
29e68330ca feat(security): Sicherheitsseite zeigt dieses Gerät und die letzten Anmeldungen
Die Liste „Aktive Sessions“ las die sessions-Tabelle, Live speichert Sessions
in Redis — sie war immer leer. Jetzt: „Dieses Gerät“ (seit wann angemeldet)
und die letzten fünf Anmeldungen mit Anmeldeweg aus dem Aktivitätsverlauf,
ohne IP; Kachel „Anmeldungen in 30 Tagen“ (Roadmap 4.1).

Changelog: Verbessert
Public: Die Sicherheitsseite zeigt Ihre letzten Anmeldungen und wie Sie sich jeweils angemeldet haben.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 13:35:54 +00:00
53e3b270e0 dev: Vorgehen bei sensiblen Daten in der Historie dokumentiert, Roadmap 1.1/1.2 erledigt
- git-deploy.md Abschnitt G: Rotieren, Sichern, Umschreiben, Prüfen,
  Hash-Zuordnung, Push, Server, Forgejo/NAS, lokales Aufräumen
- Protokoll: Speicherbereinigung in Forgejo und auf dem NAS erledigt,
  keine weiteren Klone, Live-Schlüssel bereits rotiert
- Agenten-Regel: keine personenbezogenen Daten oder Schlüssel ins Repository
- Roadmap: 1.1 und 1.2 erledigt, Context7 und lokales MySQL-Root unter 1.3

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:53:24 +00:00
919b753f54 dev: Historienbereinigung auf Remotes und Server abgeschlossen
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:45:09 +00:00
421c0d92f9 dev: Historie von den Produktiv-SQL-Dumps bereinigt, lokale Dateien mit Personenbezug gelöscht
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run
- Zuordnung alter zu neuen Commit-Hashes in dev/archive/commit-map-2026-10-09.txt
- Git-Deploy-Protokoll: Eintrag und einmaliger Server-Abgleich (Tags mit
  --force holen, gc), Speicherbereinigung in Forgejo und auf dem NAS
- README und Roadmap 1.1/1.4 nachgeführt

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 11:30:49 +00:00
8e3554bf91 dev: Doku aufgeräumt, neue Roadmap als einzige Liste offener Punkte
- dev/roadmap.md neu: alle offenen Punkte aus Plänen, Audits und Protokollen,
  gegen Code und Git abgeglichen (Stand v1.7.0)
- Abgeschlossenes ins Archiv: 2026-09-01 → archive/2026-09-nutzergewinnung,
  2026-09-11-audit → archive/2026-09-audit, lagacy-rechnungen →
  archive/legacy-rechnungen, Deploy-Protokoll v1.1.0, Umami-Snippets,
  Go-Live-Roadmap vom 20.07.
- Aktiv bleiben eigene Ordner bildrechte/ (Plan Fassung 2, Decision-Update)
  und changelog/ (Decision-Update Changelog)
- dev/README.md als Ordnerkarte neu, Verweise und zwei Code-Kommentare auf
  die neuen Pfade

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 11:25:09 +00:00
35fd2f6e55 dev: Deploy v1.7.0 im Git-Deploy-Protokoll, Spamschutz-Nacharbeiten erledigt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 10:55:33 +00:00
b3bcc43c4c dev: Entwicklungsplan Spamschutz, Wiedervorlage der Nacharbeiten nach dem Deploy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:49:58 +00:00
010258a2ab build: Assets für v1.7.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:49:58 +00:00
06d2889a4d feat: Spamschutz für Kontakt-Widget und Registrierung mit Cloudflare Turnstile
- Turnstile für Gäste und unbestätigte Konten (TurnstileVerifier,
  <x-turnstile>); ist Cloudflare nicht erreichbar, wird durchgelassen und
  im Verlauf, in der Kontakt-Queue und in der Betriebsüberwachung markiert
- Inhaltsfilter des Kontaktformulars (fremde Links, Floskel mit
  Seitentitel, Zeichensalat, Sperrliste, Absenden unter 3 Sekunden);
  Treffer landen in der Spam-Quarantäne ohne Mail, Löschung nach 30 Tagen
- Admin: Filter „Spam“, Sammelaktion, „Kein Spam“ holt die Mail nach
- Registrierung lehnt Zufallsnamen ab; users:prune-bot-registrations
  (täglicher Lauf erst mit USERS_PRUNE_BOT_REGISTRATIONS=true)
- contact-messages:quarantine-spam für den Altbestand
- CSP erlaubt challenges.cloudflare.com, Log-Kanal spam
- Datenschutzerklärung: Abschnitt 6a Cloudflare Turnstile (Vorschlag)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:49:58 +00:00
61f449f483 dev: Deploy v1.6.1 im Git-Deploy-Protokoll
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 13:56:52 +00:00
75e206dc92 dev: Imagick als Server-Voraussetzung, Wiedervorlage der Restpunkte im Sicherheits-Entwicklungsplan
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 13:54:14 +00:00
b06f5a8659 build: Assets für v1.6.1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 13:54:14 +00:00
bbc2b6048f fix: Imagick in der Betriebsüberwachung, Scanner-Anfragen an Livewire als 400, abgebrochene Alpine-Übergänge nicht mehr melden
Auf Live fehlte die PHP-Erweiterung imagick: Herkunftsprüfung und
KI-Vorab-Check der Bilder scheiterten still und ließen jedes Bild durch.
AdminSystemHealth zeigt jetzt die Zeile „PHP-Erweiterung Imagick“ (rot bei
eingeschaltetem Vorab-Check, sonst gelb).

GlitchTip server-pressekonto, Issues 38 und 39: gebaute Livewire-Anfragen
setzen gesperrte Properties (portal/language im Meldungs-Feed und in der
Suche) oder schicken Uploads an Komponenten ohne Upload. Livewire weist sie
korrekt ab; statt 500 bzw. 419 (das als „Seite abgelaufen“ gemeldet wurde)
antworten sie jetzt mit 400 und werden nicht mehr gemeldet.

Browser (Issue 18): Alpine bricht x-transition-Übergänge mit
{isFromCancelledTransition: true} ab — keine Fehlermeldung mehr.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 13:54:14 +00:00
65086cafd2 dev: Deploy v1.6.0 im Git-Deploy-Protokoll
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 13:15:58 +00:00
077e522554 dev: Phase 4 im Sicherheits-Entwicklungsplan auf Stand v1.5.0/v1.6.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 13:02:49 +00:00
5dfd622141 security: Andere Geräte abmelden, IP-weites Login-Limit, dauerhafte Sperrmarke, Passwortregeln, CSP im Melde-Modus
Restliche Phase 4 aus dem Sicherheitsaudit 07.10.2026:

- Sicherheitsseite: „Andere Geräte abmelden“ rotiert remember_token und
  beendet alle anderen Sessions, die aktuelle bleibt (nicht während einer
  Impersonation).
- LoginIpThrottle: 20 Fehlversuche je IP in 15 Minuten über alle Konten.
  Gezählt über das Failed-Event, damit Livewire-Login und Fortifys
  POST /login denselben Zähler teilen; Erfolg setzt ihn nicht zurück.
- Sperrmarke für Sessions in users.sessions_revoked_at_ms statt nur im
  Cache — übersteht cache:clear. Die alte Cache-Marke zählt übergangsweise
  mit und kann im nächsten Release entfallen.
- Neue und geänderte Passwörter: mindestens 12 Zeichen, in Produktion
  zusätzlich uncompromised() (HIBP, k-Anonymität). Bestehende bleiben gültig.
- Content-Security-Policy-Report-Only in Produktion; Meldungen über
  /csp-report nach storage/logs/csp-*.log, je Meldung höchstens einmal pro
  Stunde, ohne Query und tokenartige Pfadsegmente.

Migration: users.sessions_revoked_at_ms (users hat FULLTEXT, 25 MB, Sekunden).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 13:02:49 +00:00
9c4962fbe0 build: npm-Advisories für shell-quote und source-map-js behoben
source-map-js 1.2.1 → 1.2.2 (GHSA-68fv-2mgg-jv7q). shell-quote per
overrides auf ^1.11.0 (installiert 1.12.0, GHSA-pqg4-j6r4-53mv u. a.):
concurrently legt 1.9.0 fest, auch in Version 10, und `npm audit fix`
stufte concurrently nur auf eine andere verwundbare Version herab. Beide
Pakete laufen nur in Entwicklung und Build, nichts davon im Browser.
`npm audit`: 0 Schwachstellen, Build unverändert.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 13:02:49 +00:00
798ae75e64 dev: Deploy v1.5.0 im Git-Deploy-Protokoll
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 12:18:24 +00:00
e77d9e7d09 feat: API-Zugang endet mit der Buchung, optionales Ablaufdatum für API-Tokens
Bisher blieb ein einmal erstellter Token gültig, auch wenn Abo bzw. Buchung
längst beendet waren. EnsureApiAccessIsBooked prüft jetzt bei jeder Anfrage
(v1 und /service/…-Altpfade), ob das Konto API-Zugang hat
(ApiAccessEligibilityService::hasApiAccess), sonst 403. Die Tokens bleiben
erhalten und funktionieren nach erneuter Buchung wieder.

Kunden können beim Erstellen optional ein Ablaufdatum setzen (bis 5 Jahre);
die Token-Liste zeigt „Gültig bis“ und einen Hinweis, wenn der Zugang
pausiert ist. sanctum:prune-expired räumt abgelaufene Tokens nach 30 Tagen
täglich ab. API-Doku (public/api/v1.yml) ergänzt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 11:41:24 +00:00
3def447f51 security: Proxy-Vertrauen nur noch lokal, HSTS in Produktion, Tests ohne echte ntfy-Pushes
Live-Prüfung 08.10.2026: nginx beantwortet die Anfragen direkt (kein CDN,
kein vorgeschalteter Proxy), die App vertraute aber jedem Proxy
(trustProxies at '*'). Jeder Client konnte per X-Forwarded-For seine IP
vorgeben und damit IP-Limits bei Login und Passwort-Reset umgehen sowie
IP-Protokolle fälschen. Jetzt steuert config/trustedproxy.php das Vertrauen:
lokal (Traefik) weiterhin '*', sonst keinem Proxy; ein späteres CDN kommt
über TRUSTED_PROXIES dazu.

HSTS fehlte auf Live. SecurityHeaders setzt Strict-Transport-Security auf
HTTPS-Antworten, standardmäßig nur in Produktion (max-age 1 Jahr, bewusst
ohne includeSubDomains/preload).

phpunit.xml leert MONITORING_NTFY_*, damit Testläufe keine echten
Push-Nachrichten mehr auslösen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 11:41:24 +00:00
f693226d4a dev: Deploy v1.4.0 und v1.4.1 im Git-Deploy-Protokoll, Release-Stand im Sicherheitsaudit und Entwicklungsplan
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 08:19:19 +00:00
af72810296 fix: Abgleich der Firmenrechte entzieht Bestandskonten ohne E-Mail-Bestätigung nicht mehr pauschal alle Rechte — memberships:resync-auto mit Probelauf und Notbremse
Auf Live meldete memberships:resync-auto nach v1.4.0 „vorher 19607, nachher 9":
syncMembershipsForEmail() entzog Konten ohne email_verified_at alle
automatischen Rechte, und 19.597 davon gehören Bestandskonten aus dem
Altsystem. Jetzt wird nur entzogen, was keine E-Mail-Grundlage mehr hat —
unabhängig vom Kontostatus (S-03 bleibt wirksam); neue Rechte weiterhin nur
für aktive, verifizierte Konten (F01).

memberships:resync-auto läuft in einer Transaktion, kennt --dry-run und rollt
zurück, wenn mehr als 5 % (mindestens 50) der Rechte wegfallen würden
(--force zum Erzwingen). Probelauf gegen die Live-Kopie: 19.607 → 19.316.
Wiederherstellung: storage/app/private/restore-company-user-auto-2026-10-07.sql
(nicht versioniert, INSERT IGNORE, idempotent).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 16:22:25 +00:00
8045ef18cc build: Assets für v1.4.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 16:09:35 +00:00
bae8347f6c security: Sicherheitsaudit 07.10.2026 (S-01–S-06) behoben, Passkeys und Zweitfaktor-Pflicht für Admins
Audit: dev/sicherheit/SICHERHEITSAUDIT-2026-10-07.md, Plan und Entscheidungen:
dev/sicherheit/ENTWICKLUNGSPLAN-SICHERHEIT-2026-10-07.md.

- S-01 Legacy-Rechnungen fremder Kunden nur mit billing:manage (auch Kundenroute).
- S-02 Kontaktzuordnung auf der Firmenanzeige verlangt companies:write, $id gesperrt.
- S-03 CompanyMembershipObserver: automatische Firmenrechte werden bei jeder
  Adress-/Zuordnungsänderung sofort neu bewertet; memberships:resync-auto.
- S-04 Passwortwechsel beendet alle anderen Sessions (PasswordChanger), Reset
  alle Sessions und offene Login-Links; Fortify PUT /user/password abgeschaltet.
  API-Tokens bleiben bestehen.
- S-05 Google: email_verified Pflicht, feste Bindung über die Provider-ID;
  Erstverknüpfung bestehender Konten außerhalb gmail/hd nur per Bestätigungslink
  in derselben Browser-Session.
- S-06 Frischer Identitätsnachweis (Passwort, App-Code, E-Mail-Code oder
  Passkey) vor E-Mail-Wechsel, erster 2FA-Einrichtung und Token-Erzeugung;
  Hinweis-Mails an die (bisherige) Kontoadresse.
- Entscheidung 5: Passkeys (Fortify, @laravel/passkeys) für alle; Super-Admins
  und Admins bestätigen die Session für den Admin-Bereich per Passkey oder
  App-Code (EnsureStrongAdminAuthentication, Notfallschalter
  AUTH_REQUIRE_STRONG_ADMIN); Reset des zweiten Faktors durch Super-Admins.

Neue Migration: create_passkeys_table. Suite 2.403 grün (1 übersprungen),
Larastan ohne Meldung.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 16:09:35 +00:00
fd8dd74d5f ops: Lokale Datenbank gegen fremde Testläufe absichern — DB_* nicht mehr als Container-Umgebung, Agenten-Regel, Testdatenbank-Pflicht im Baukasten
Am 07.10.2026 hat das RefreshDatabase eines frischen Demo-Projekts (Test der
Vorlagen aus dev/git-deploy-monitoring) die lokale Datenbank `pressekonto` auf
global-mysql vollständig geleert (Binärlog binlog.000009, Pos. 566161486).
Ursache: docker-compose.yml setzte DB_* als Container-Umgebungsvariablen, die
in Laravel Vorrang vor jeder .env haben; die phpunit.xml des Demo-Projekts
erzwang kein SQLite. Die eigene Suite war nicht beteiligt (force="true" und
Guard in tests/TestCase.php greifen; Gegenprobe mit MySQL-Variablen grün).

- docker-compose.yml: DB_* entfernt (Werte identisch in .env), wirksam nach
  Neuerstellen des Containers.
- Baukasten: „Testdatenbank absichern" (phpunit.xml mit force, Guard,
  Gegenprobe) als Pflicht vor RefreshDatabase.
- .ai/rules/general.md und CLAUDE.md: fremde/frische Laravel-Projekte nur mit
  SQLite :memory: testen; migrate hier erst nach migrate:status.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 16:09:25 +00:00
32e1349517 dev: Baukasten Git-Deploy und Betriebsüberwachung für andere Laravel-Projekte (dev/git-deploy-monitoring) — Anleitungen, Checkliste, Vorlagen für Laravel, deploy.sh und Monitoring-Server
Vorlagen in einem frischen Laravel 12 eingebaut (30 Tests grün), deploy.sh
gegen ein simuliertes Repository durchgespielt (Deploy, Abbruch bei
Migrationen, Drift, Rollback, fehlender Worker). GlitchTip-Aufbewahrung heißt
seit Version 6 GLITCHTIP_RETENTION_DAYS — in der Projekt-Doku korrigiert.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 09:45:16 +00:00
d083110b00 dev: Deploy v1.3.2 im Git-Deploy-Protokoll (Worker-Prüfung 4 s, Supervisor enabled)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 16:14:12 +00:00
3b4448ad4e dev: Worker-Ausfall 06.10. dokumentiert — Runbook ohne pauschales queue:retry all, Vorgehen bei stehendem Worker, externer Monitor erledigt (status.adametz.media)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 16:11:58 +00:00
c223daa563 deploy: Worker-Prüfung am Ende von deploy.sh — monitoring:queue-probe stellt einen Test-Job ein und wartet bis 60 s; ohne Worker Exit 3 mit Hinweis
Anlass 06.10.2026: Nach dem Deploy von v1.3.0 hat queue:restart den Worker
beendet, Supervisor lief nicht, über eine Stunde blieben KI-Prüfungen und
Mails liegen, ohne dass es auffiel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 16:11:58 +00:00