Commit graph

187 commits

Author SHA1 Message Date
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
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
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
2c25eea045 dev: Monitoring-Plan — Nachtrag fehlgeschlagene Anmeldungen (Befund, Auswertung) und Einrichtung des externen Monitors (Uptime Kuma, ntfy, zweite Ebene)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 15:30:29 +00:00
9f806de1af dev: Git-Deploy — FPM-Reload ohne Passwort getestet, PK_FPM_RELOAD ungesetzt lassen; Nginx-Fehlerlog ausgewertet, process_control_timeout bewusst nicht gesetzt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 15:24:55 +00:00
da9411bdab dev: Deploy v1.2.0 (Volt entfernt) im Git-Deploy-Protokoll
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 14:47:49 +00:00
2cde7284a1 livewire: Volt entfernt — Komponenten als Livewire-4-Single-File-Components, Route::livewire(), Livewire::test(); livewire/volt deinstalliert
- 83 Komponenten: Livewire\Volt\Component → Livewire\Component
- 73 Routen (admin, auth, customer): Volt::route() → Route::livewire()
- 88 Testdateien: Volt::test/actingAs → Livewire::test/actingAs
- VoltServiceProvider gelöscht; composer remove livewire/volt
- config/livewire.php auf v4-Schlüssel (component_layout, component_placeholder,
  component_locations, make_command: SFC ohne ⚡). Der alte Schlüssel layout war
  wirkungslos; alle gerouteten Komponenten setzen ihr Layout selbst.
- CLAUDE.md, AGENTS.md, boost.json, .cursorrules, Skill volt-development
- Roadmap: erledigt; Larastan erfasst SFCs weiterhin nicht (Blade-Dateien)

Suite 2.325 grün, einer übersprungen; Larastan und Pint ohne Meldung;
route:cache und view:cache laufen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 13:59:36 +00:00
5782297dca dev: Git-Deploy live seit v1.1.3 (06.10.2026) — Protokoll, Befunde der Umwandlung, Runbook §10 und GlitchTip-Doku angepasst
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 13:43:01 +00:00
3a6cb6a57e dev: GlitchTip-Doku auf Git-Deploy umgestellt (Release-Datei schreibt deploy.sh)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 13:17:19 +00:00
9e35c73d23 dev: GlitchTip-Dokumentation (dev/glitch-tip) — Überblick, Meldewege, API-Abruf, Ablauf zur Fehlerbehebung, Regeln, Protokoll der Einträge; Verweis in CLAUDE.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 13:12:41 +00:00
129de4fc76 deploy: Git-Deploy per Tag — dev/betrieb/deploy.sh, Ablauf und einmalige Umstellung in git-deploy.md, Runbook §10; public/build wird versioniert
- deploy.sh: bricht ohne Änderung ab bei Abweichung im Checkout oder neuen
  Migrationen ohne --migrations; down, Checkout, RELEASE, Composer, Caches,
  queue:restart, FPM, up; Rollback = derselbe Aufruf mit dem vorherigen Tag
- git-deploy.md: Forgejo-Zugang, Umwandlung von ~/pressekonto.com in einen
  Checkout von v1.1.0 ohne Dateiänderung, Release lokal, Prüfungen, Rollback
- Assets werden lokal gebaut und committet, auf dem Server kein Node

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 10:12:09 +00:00
dd688e5a7a dev: KAS-Passwort erledigt — SSH-Zugang des Altsystems geändert und deaktiviert, KAS-Hosting bleibt für die Postfächer
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 10:12:09 +00:00
1d7ce9e942 dev: Roadmap — Volt entfernen und auf Livewire-4-Single-File-Components umstellen (Umfang, Schritte)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 13:40:29 +00:00
01d68c2637 dev: Deploy v1.1.0 am 05.10.2026 live — Protokoll in Deploy-Checkliste, Entwicklungsplan (Blöcke 9/10) und Monitoring-Plan
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 13:36:44 +00:00
984d001380 chore: docs/ aus dem Repository — lebt im Obsidian-Vault (Devcontainer-Mount), Q-05 entschieden; entpackte Deploy-Pakete ignoriert
Die Dateien bleiben in der Historie und im Vault; git rm --cached, nichts
auf der Platte gelöscht.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 13:30:33 +00:00
2dda9ecc44 dev: Deploy-Checkliste — Server braucht kein Git
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 12:59:27 +00:00
c837ef954e dev: Deploy-Checkliste v1.1.0 — Paket gebaut, Entwicklerdateien aus der Paketliste ausgenommen
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 12:55:49 +00:00
8690165625 dev: Monitoring-Plan (Phasen 1–3, Entscheidungen M1–M9, Protokoll), Deploy-Checkliste v1.1.0, Runbook um Versionsdatei und Composer-Schritt ergänzt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 12:53:06 +00:00
448643b4d8 dev: Commit-Hashes der Blöcke 9 und 10 im Protokoll nachgetragen
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 13:09:13 +00:00
4a7e496d1b 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>
2026-10-02 13:09:01 +00:00
80536ab998 dev: Bildkennzeichnung — Deploy 1b live (Formular v2 an, Testkonto geprüft), Precheck und Gate bleiben aus
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-28 13:08:15 +00:00
05cd604a1e dev: Bildkennzeichnung — Deploy 1, 2 und 2b am 28.09.2026 live, Protokoll
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-28 13:04:26 +00:00
c6543eb680 dev: Entscheidungen E10–E18 vom Betreiber bestätigt (25.09.2026)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-25 15:24:10 +00:00
c38bcebf12 dev: Entwicklungsplan Block 8 — Abgleich Umsetzungsaudit 25.09., Entscheidungen E10–E18, Live-Schritte, Protokoll
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-25 14:27:12 +00:00
2a2215b3c3 audit: Nacharbeit Umsetzungsaudit 25.09.2026 — Bildfreigabe, Beweisarchiv, KI-Atomarität, Berichte (Block 8, N01–N05, N07, N08, N10–N21, 5.1, 5.2)
Bilder (N01, N05, N07, N08): gemeinsamer Freigabezustand
PressReleaseImage::isPubliclyDeliverable() für Seiten, OG und Medienroute
(Bestand bleibt sichtbar, v2 nur mit Bestätigung, Admin-Upload bis zum
Kundenklick nicht öffentlich); eigene Ability confirmImageRights nur für den
Kontoinhaber, ohne Super-Admin-Kurzschluss, Identität und ausstehende
Bestätigung auch im Service; Status-Regel unter der PM-Sperre; Cache-Flush
nach dem Commit außerhalb der Dateibereinigung; Snapshot nach Bestätigung an
veröffentlichter PM; Bestätigungstexte an die gezeigte Kennung gebunden.

Beweisarchiv (N02, N10, N11, N12, N13, 5.1): Tombstone unter Zeilensperre mit
erneuter Hold-/Fristprüfung; Dateioperationen ausgewertet, Commands mit
FAILURE; record() über .tmp + move; Marker archive_pending_at mit
archive:retry-pending und archive:sweep-orphans; Anonymisierung entfernt Bilder
über den Remover mit Antragsbezug; Draft-Purge räumt Medien nie
veröffentlichter abgelehnter Einreichungen; App-Kopien fallen mit dem
Archiv-Tombstone; label_corrected nur für veröffentlichte Bilder;
archive_entries.legal_request_id; FileDeletion-Helfer; Systemstatus-Checks.

KI und Hintergrund (N03, N04, N14, N20, N21): Ergebnis-UPDATE und Audit in
einer Transaktion; erwarteter Hash bis in reject()/holdForManualReview();
Ablaufmail per beanspruchtem Marker in einer Transaktion; strikte
Schemaprüfung der Vision-Antwort; Fortschrittsmarke ungecacht.

Berichte und Canonical (N15–N19, 5.2): lückenlose Alterskohorten;
Feed-Identität mit Portal und Sprache; Sitemap-Rolle in der Kundenansicht;
Indexverteilung auf einer Grundgesamtheit; Kopien nach Wegfall der
Erstquelle neu bewertet; Kategorie-Admin leert Seiten-Caches; Dry-Run
zählt alle Tabellen.

Gesamtsuite: 2.122 Tests grün, einer übersprungen; Larastan und Pint sauber.
Zwei Migrationen (nullable Spalten, INSTANT). N09 offen.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-25 14:26:49 +00:00
34fa342c7f tests/legal: Testdatenbank-Guard vor den DB-Traits, Flags in phpunit.xml gepinnt, Zustimmung an gezeigte Fassung gebunden (Umsetzungsaudit 25.09.: N22, N06, 5.3)
- Tests\TestCase prüft die Standardverbindung in setUpTraits(), also vor
  RefreshDatabase — bisher erst nach dem Refresh (N22). Eigener Test.
- phpunit.xml pinnt IMAGE_RIGHTS_V2, IMAGE_PRECHECK(_STAGE) und
  LEGAL_ACCEPTANCE_GATE auf die Vorgaben aus .env.example; die Suite hing
  sonst an der lokalen .env (Audit Abschnitt 6).
- Zustimmungsgate: die Livewire-Komponenten tragen die beim Rendern gezeigten
  Fassungen (Trait-Hook rendering); weicht die aktuelle Fassung beim Absenden
  ab, wird die Annahme abgelehnt und der neue Wortlaut gezeigt. Ein fehlendes
  Pflichtdokument ist bei aktivem Gate ein Konfigurationsfehler (N06).
- Audit vom 25.09., Decision-Update vom 22.09. und Plan Fassung 2 versioniert;
  die Antwortkopie „…-211.md" entfernt; U10-Formulierung im Plan präzisiert.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-25 13:35:14 +00:00
b5b70416f2 archive: Beweisarchiv — verschlüsselte Einträge, Legal Hold, Purge mit Tombstone, Restore-Abgleich, Auslöser und Admin-Seite (Bildkennzeichnung Block F)
- archive_entries (append-only) + archive_access_log; Disk archive außerhalb des Web-Roots; eigener ARCHIVE_KEY (archive:key), AES-256-CBC, SHA-256 am Eintrag
- EvidenceArchive: record/open/manifest/export (signiertes ZIP), setLegalHold/releaseLegalHold (Frist läuft neu), purgeDue, exportTombstones, reconcileAfterRestore
- PressReleaseArchiver: image_removed (Original, Snapshot, Bestätigungen), pm_depublished (letzter veröffentlichter Stand), gdpr_change (Anonymisierung, Korrekturen), label_corrected
- Hooks in Remover, depublish/archive/changeStatusFromAdmin/deleteFromAdmin, AnonymizationService, CorrectionService, ImageCorrectionService
- Scheduler archive:purge 03:20 und archive:export-tombstones 03:30; archive:reconcile-after-restore im Runbook
- Admin ▸ Management ▸ Beweisarchiv (Liste, Legal Hold mit Pflichtvermerk, Öffnen/Export nur mit Zweck)
- Scope-Wächter: neue Befehle nutzen withoutGlobalScope(PortalScope::class)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-22 10:04:21 +00:00
24184f1dec api: Bildupload v1 unter Formular v2 (Pflichtfelder, Kennung des Wortlauts, Bestätigung mit Token), Legacy-Bildupload abgeschaltet, API-Doku (Bildkennzeichnung Block C)
- StorePressReleaseImageRequest: copyright, rights_confirmed, confirm_text_version Pflicht; 422 mit aktueller Kennung; 16 MiB
- PressReleaseImageController über den gemeinsamen Uploader, Löschen über den Remover; Resource mit Portalkennzeichnung, Kundenangabe, Herkunft, Bestätigung und warnings[]
- POST /service/pressreleases/{id}/images antwortet 410 mit Hinweis auf v1 (E-B4)
- API-Seite und Sprachdateien: Felder und Rechtehinweis mit aktiver Textkennung; Paritätsdokument ergänzt

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-22 09:35:52 +00:00
6df36c90e9 dev: Roadmap Block 0 — 0.2 bis 0.6 als erledigt geführt (Stand Protokoll Teil 2)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 16:11:16 +00:00
2b5960b8a1 dev: Basiswert 0.1 abgeschlossen — Kohorte 28–55 Tage am Stichtag 21.09.2026 (Median 122 / 314), Nach-Deploy-Stand
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 15:54:53 +00:00
1c38c820f4 reports: Kohortenalter ab Stichtag statt ab --to; legacy:settle-unpaid kennt bereits ersetzte Quellen; dev: Basiswert 0.1 vom Live-System ausgewertet
view-distribution rechnete das Alter der Kohorten ab dem Enddatum des
Fensters, die Zähler stehen aber immer auf heute — mit einem --to in der
Vergangenheit waren alle Kohorten um die Verzögerung des Laufs zu jung.
Das Alter zählt jetzt ab dem Stichtag der Erhebung (Feld stichtag), junge
Kohorten fallen bei altem Enddatum leer aus.

settle-unpaid meldete beim zweiten Lauf einen Posten, dessen Quelle der
erste Lauf schon per MAN-Rechnung ersetzt hatte (superseded), als
Konflikt. Solche Quellen zählen jetzt als already_reissued.

Basiswerte Block 0: Live-Erhebung vom 21.09.2026 (gleiches Fenster,
Median 126/303 statt 98/200) eingetragen, Kohortenzeile mit Alters-
Versatz erklärt, letzter Schritt für 0.1 benannt (Lauf ohne --to).
Protokoll: Nach-Deploy-Schritte, Lesart von Audit und Rechnungslauf.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 15:32:32 +00:00
eb658020e5 press-releases: assign-canonicals leert Seiten- und Sitemap-Caches; dev: Live-Lauf 21.09.2026 protokolliert (9.221 Paare)
Der Nachlauf über den Bestand änderte rel=canonical und die Sitemap-Auswahl,
ließ aber gecachte Meldungsseiten (1 h stale) und Sitemap-Caches (1 h)
stehen. Nach einem Lauf mit Änderungen wird WebCaches::forgetPublicPages()
aufgerufen; der Test prüft das über den vorher gecachten Sitemap-Stand.

Protokoll Teil 11: Nachtrag Live-Deploy (hash-content 179.619,
duplicates-report 9.221 Paare / 1.468 seit 07/2026, assign-canonicals
9.223/9.221, basiswert-0.1.json auf dem Server), Anhang 2 1c.7/1c.8 mit
Live-Zahlen, Basiswerte 0.1 mit Hinweis auf die noch zu holende Datei.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 13:05:43 +00:00
2b042d6aa7 web: Datenschutzerklärung — Abschnitt 5a „Eigene Nutzungsstatistiken ohne Personenbezug", Frist 395 Tage (Roadmap 0.7)
Aufrufe/Teilen je Meldung, Abrufe durch Such-, KI- und Feed-Dienste,
Konversionsschritte: Umfang ohne IP, Zweck, Art. 6 Abs. 1 lit. f, Löschung
nach 395 Tagen in Abschnitt 13. Text vom Betreiber abgenommen (21.09.2026);
gilt für Hub und beide Portale. 0.7 in Roadmap und Protokoll abgehakt.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 10:40:10 +00:00
fc700677ff web: Abruf-Protokoll der RSS-Feeds — Reader-Dienst, gemeldete Abonnenten, Admin-Bericht, Panel (Roadmap 3.1)
- feed_fetches: jeder Feed-Abruf mit Art, Schlüssel, Portal, Sprache,
  erkanntem Reader (config/feeds.php, FeedReaderIdentifier), vom Dienst
  gemeldeter Abonnentenzahl und gekürztem User-Agent — keine IP. Schreiben
  per defer() nach der Antwort, auch bei Cache-Treffer.
- Aufbewahrung 395 Tage über press-releases:purge-events;
  FEED_FETCHES_RECORDED_SINCE.
- Admin ▸ Reports ▸ Indexierung & Abrufe: Block „Abrufe der RSS-Feeds"
  (Summen je Feed-Art, je Reader-Dienst, meistabgerufene Feeds;
  FeedFetchReport, Verdichtung in PHP für MySQL und SQLite).
- Panel „Auslieferung": Abrufe je Feed in 30 Tagen; RSS-Seite nennt die
  Zählung ohne IP.
- Tests: FeedFetchLogTest (5), IndexStatusCheckTest erweitert.
- dev/2026-09-01: Nachtrag Protokoll Teil 11, Roadmap 3.1; 0.7 gilt auch
  für Crawler- und Feed-Log.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 09:00:09 +00:00
ff75159b8f web: RSS-Feed je Newsroom, RSS-Übersichtsseite, „RSS" in der Topleiste (Roadmap 3.1, Nachtrag)
- /{edition}/newsroom/{slug}/feed: Sichtbarkeit wie die Newsroom-Seite
  (aktiv, nicht entfernt, mindestens eine Meldung), Prüfung vor dem Cache,
  301 bei zusammengeführter Firma; Autodiscovery und Link „RSS-Feed" auf
  der Newsroom-Seite; Hub leitet auf das Portal der Firma.
- /{edition}/rss (RssPageController, static.rss DE/EN): Was RSS ist, wie
  ein Reader funktioniert, Hauptfeed, alle Branchen-Feeds mit Adresse,
  Muster des Newsroom-Feeds, Hinweise. Portalseite mit Portal-Kontext,
  Hub → presseecho, in Sitemap und llms.txt.
- Topleiste, Burger-Menü und Footer verlinken RSS neben FAQ/Hilfe/API.
- FeedController in portal/category/newsroom aufgeteilt; Panel
  „Auslieferung" nennt zusätzlich den Newsroom-Feed.
- Tests: FeedTest (+3), RssPageTest (4), StaticPagesTest, VisibilityStatsTest.
- dev/2026-09-01: Nachtrag in Protokoll Teil 11 und Roadmap 3.1.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 08:27:14 +00:00
9d5e5a0b54 web: RSS-Feeds je Branche und je Portal (Roadmap 3.1); dev: Sichtung des Ordners, Protokoll-Teile umnummeriert
- /{edition}/feed und /{edition}/category/{slug}/feed (FeedController,
  RSS 2.0 mit atom:link self, dc:creator, category; jüngste 50 der Ausgabe,
  Branche inkl. aktiver Unterkategorien, nur visibleInArchive).
- Cache über WebPageCache (Key-Gruppe feed), Hub leitet per 301 aufs Portal
  (canonical.portal_only_content_routes).
- Autodiscovery über @yield('feed_links') auf Start-, Branchen- und
  Archivseiten, sichtbarer Link in der Archiv-Leiste, llms.txt nennt die
  Feed-Muster, Block „RSS-Feeds" im Panel „Auslieferung"
  (VisibilityStats::feedLinks).
- Übersetzungen unter web.rss (web.feed ist die Startseiten-Liste).
- Tests: FeedTest (7), VisibilityStatsTest erweitert.
- dev/2026-09-01: Sichtung 18.09. (Teil 11), zweite Teil-Serie des
  Protokolls jetzt 7–10 mit nachgezogenen Verweisen, Anhang 1 abgeglichen,
  E6 abgehakt, 2.6 extern, 1c.5/E8 wartet auf Daten, 3.1 abgehakt.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 13:57:09 +00:00
5122624687 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>
2026-09-18 13:00:48 +00:00
c26bdff681 admin: Bericht „Indexierung & Abrufe" — Rolle Erstquelle/Kopie, Quellenbefund, Crawler-Abrufe; Schlüsselpfad ab Projektwurzel
Der Bericht meldete auf Live „nicht konfiguriert", während der Lauf
längst Daten holte: der relative Pfad der Schlüsseldatei war im Cron
(Projektwurzel) lesbar, im Web-Request (public/) nicht. Relative Pfade
werden jetzt ab base_path() aufgelöst.

Die Verteilung trennt zusätzlich nach Rolle in der kanonischen Zuordnung
(1c.8): bei einer Kopie mit Verweis ist „ausgeschlossen" der erwartete
Befund. Neu: Quellenbefund über Erstquellen (welche Adresse Google führt,
fremde Hosts), Abrufe durch Such- und KI-Dienste je Dienst, Tag und
Meldung mit CSV. Herkunftsmarker als Join statt korreliertem EXISTS,
Aggregate 15 Minuten gecacht.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 12:53:22 +00:00
1c421c0377 dev: Umsetzungsaudit vom 18.09. abgelegt, Block 7 mit Abgleich, Entscheidungen E7–E9 und Protokoll im Entwicklungsplan
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 12:22:43 +00:00
c46dfd3b83 dev: Protokoll — Gesamtsuite grün, zwei zufallsabhängige Tests festgezurrt
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 10:56:21 +00:00
226fb8131a dev: Umsetzungsprotokoll und Live-Schritte zum Audit-Entwicklungsplan
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 10:41:58 +00:00
72432fdb82 web/api/ki: Soft Deletes wieder wirksam, Caches bei Firmenwechsel, KI-Ergebnis an Inhalt gebunden (Audit Block 3+4, Deploy D)
Block 3 — Sichtbarkeit, Löschung, Cache, Eingaben

F04: withoutGlobalScopes() ohne Argument entfernte neben dem PortalScope
auch den Soft-Delete-Filter. Öffentliche, Kunden-, API-, Vorschau- und
Medienpfade sowie die PressRelease-Helfer schreiben jetzt
withoutGlobalScope(PortalScope::class). Zwei Stellen, die der Audit nicht
kannte: die öffentliche Meldungsseite zeigte gelöschte Firmenkontakte mit
Name, Mail und Telefon; das Pressefach listete gelöschte Kontakte weiter
und ließ sie bearbeiten. Ein Architekturtest friert die 39 bewusst
verbliebenen Stellen (Admin, Importer, Befehle, Slug-Eindeutigkeit) ein.
Der Vorschau-Test prüfte bisher forceDelete statt delete.

F22: LOWER(email) machte auf companies (110k Zeilen) bei jedem Login einen
Vollscan; die Kollation ist ohnehin case-insensitiv. EmailQuery vergleicht
auf MySQL direkt über den Index, auf SQLite (Tests) weiter per LOWER.
Neuer Index contacts_email_idx.

F13: Firmen-Observer verwirft die öffentlichen Seiten-Caches bei
Löschung, Wiederherstellung und is_active-Wechsel auf jedem Weg; die
Newsroom-Seite prüft Sichtbarkeit vor dem Cache-Treffer; Kontakt-
Änderungen im Pressefach flushen. Der Tombstone-Test wärmte den Cache
vorher nicht und traf den Fehler nie.

F12: Gemeldete URLs werden über Host, Ausgabe und Slug aufgelöst
(ReportedUrlResolver); fremde Hosts zählen nicht, bei Doppelveröffentlichung
gewinnt die Erstquelle.

F11: per_page 1–100, status als Enum, language nur de/en, Kategorie muss
aktiv sein und zum Ziel-Portal passen. Legacy-Aliasse behalten ihren
Vertrag.

F23: Rückgabewert von put() wird geprüft; Logo erst speichern, dann
Datenbank, dann altes Logo löschen. Fehler enden als Feldfehler, nicht
als verlorenes Logo.

Block 4 — KI-Prüfung und Scheduler

F07: Klassifikation und Score tragen die Prüfsumme des Inhalts bei
Einplanung. Weicht sie beim Speichern ab, wird das Ergebnis verworfen
(ki_audits.discarded_at) und ein neuer Lauf eingeplant. Der Scheduler
veröffentlicht keine Meldung, deren jüngste Klassifikation nicht zum
aktuellen Text passt, sondern plant eine Prüfung mit Routing ein.

F18: Kontingent an den Kalendermonat gebunden (users.press_release_quota_period).
Verbrauch aus einem früheren Monat zählt null, auch ohne Reset-Cron; der
Reset ist idempotent und lässt den laufenden Monat in Ruhe.

F20: Der Publikations-Scheduler liefert bei technischen Fehlern einen
Fehler-Exit-Code, damit der Failure-Hook greift.

F17: KI-Jobs mit $timeout = 120, retry_after 150; Runbook ergänzt.

F19: Aggregation der Aufrufe unter einem Cache-Lock für alle Einstiege.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 10:40:48 +00:00
1d76f5a733 auth: Firmenrechte nur aus nachgewiesener Adresse, 2FA auf allen Login-Wegen (Audit Block 1, Deploy A)
Audit vom 11.09. gegen HEAD geprüft, Entwicklungsplan dazu unter
dev/2026-09-11-audit/ENTWICKLUNGSPLAN.md. Dieser Commit ist Deploy A:
die sechs kleinen Punkte aus Block 1 ohne Schemaänderung.

F01: Der Fortify-Endpunkt PUT /user/profile-information tauschte die
E-Mail sofort und setzte die Verifizierung zurück; der Login-Sync vergab
danach Firmenrechte allein nach E-Mail-Treffer. Feature abgeschaltet
(die Kunden-UI hat den pending_email-Prozess), und der Sync verlangt
jetzt ein verifiziertes, aktives Konto – für alle Aufrufer.

F02: Google-Login übergibt Konten mit bestätigtem TOTP in die Challenge,
wie Passwort- und Magic-Link-Login.

F03: showRecoveryCodes ist gesperrt; ein Client-Update konnte die
Recovery-Codes entschlüsseln lassen.

F08: Nutzer-Detailroute unter can:users:manage (persistente Livewire-
Middleware), Gutschriften autorisieren zusätzlich in der Action.

F09: Gate::before greift nur für aktive Super-Admins; deaktivierte
fallen auf die Gates mit is_active-Prüfung zurück.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 10:08:55 +00:00
edb2d49199 web: Portal-Inhalte sind auf dem Hub nicht mehr erreichbar (Anhang 2, E10)
Kategorien, Jahresarchive, Meldungen und Newsrooms liefen auch unter
pressekonto.com — die Ausgabe-Routen gelten für alle Hosts, und der
Portal-Kontext fällt dort auf businessportal24 zurück. Jetzt 301 auf das
Portal.

Meldung und Newsroom folgen ihrem eigenen Portal, nicht einer festen
Vorgabe; bei Doppelveröffentlichung (gleicher Slug auf beiden Portalen)
gewinnt die Erstquelle, sonst endete die Weiterleitung auf der Kopie.
Kategorie, Archiv und Suche gibt es auf beiden Portalen — dort entscheidet
canonical.portal_only_host.

Bewusst nicht weitergeleitet wird ein unbekannter Slug (sonst 301 in ein
404) und alles, was kein GET ist (ein 301 auf POST verliert die Anfrage —
Newsroom beanspruchen und Share-Zählung laufen weiter). Query-Parameter
bleiben erhalten.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 09:15:04 +00:00