Architecture Decision Record · Projektpartnerportal / Projekt-Alert

Projekt-Alert-Konsolidierung: solcom_project_offer_alert wird das einzige Alert-System

accepted 2026-07-02
TL;DR: Im Repo existieren zwei parallele Projekt-Alert-Systeme: der eingeloggt-only „Suchagent" (solcom_projektpartner_alert, Entity ppp_alert) und der anonym-fähige „Projekt-Alert" (solcom_project_offer_alert, Entity project_offer_alert). Die Stakeholder-Findings aus P2503-275 betreffen ausschließlich das zweite. Beide werden zu einem System konsolidiert: Modul B (solcom_project_offer_alert) ist die Basis — es beherrscht bereits beide Zielgruppen (anonym per Double-Opt-in, eingeloggt per Upsert) und sein Matcher arbeitet Freitext-basiert. Modul A wird stillgelegt und deinstalliert. Die Schlagwort-Eingabe wechselt von Taxonomy-Whitelist auf Freitext + kuratierte Vorschläge (neues Vocabulary alert_suggestion, Seed aus der redaktionellen Neos-Liste) — das ist Altsystem-Parität (Select2 tags:true). Anonyme verwalten ihren Alert künftig über Token-Edit-Links in jeder Mail. Die 12.912 aktiven Neos-Alerts (User- und Gast-Alerts) werden migriert; die Neos-Bool-Gruppen werden dabei bewusst zu flachen OR-Listen abgeflacht (ODER-Gruppen-UI ist explizit gestrichen). Kanonische URL bleibt /projektportal/projektalert — pfadgleich mit dem Altsystem.
Update 2026-07-03: Der Zielgruppen-Scope dieses ADRs wurde durch ADR-0056 geändert — der Projekt-Alert ist nur noch für registrierte Projektpartner:innen; anonyme Anlage entfällt, Gast-Alerts werden nicht migriert (Hard Cut). Der Kern dieses ADRs (ein System, Modul B als Basis, Freitext + kuratierte Vorschläge, Modul-A-Stilllegung, URL-Kanon) bleibt unverändert gültig.

Kontext

Der Stakeholder meldete in P2503-275 fünf Findings zum Projekt-Alert: kuriose Autocomplete-Vorschläge („anlagen^bau"), keine freie Schlagwort-Eingabe möglich, unklare Versandfrequenz, gleiche Schlagworte in Include und Exclude eintragbar, und keine Möglichkeit für nicht registrierte Nutzer, einen angelegten Alert wiederzusehen oder zu bearbeiten. Als Notlösung wurde Deaktivierung bis nach Go-Live (08.07.2026) angeboten.

Die Code-Analyse ergab eine Doppelstruktur, die im Glossar (CONTEXT.md) bis dahin als ein Begriff geführt wurde:

Modul A — „Suchagent"Modul B — „Projekt-Alert"
Modulsolcom_projektpartner_alertsolcom_project_offer_alert (Submodul von solcom_project_offer)
Entityppp_alert, genau eine pro Userproject_offer_alert, E-Mail + UUID-Token
Zielgruppenur eingeloggte Projektpartneranonym (Double-Opt-in) UND eingeloggt (Upsert, sofort bestätigt)
KriterienSkills (Taxonomy) + Einsatz-Regionen (Include)Include-/Exclude-Schlagworte + Exclude-Gebiete (Remote/AT/CH/PLZ 0–9/International)
VerwaltungForm mit Edit/Deletenur Abmelde-Token-Link, keine Edit-UI
Seite/projektportal/suchagent (403 für Anonyme)/projektportal/projektalert

Drei empirische Befunde bestimmen die Entscheidung:

  • Modul B ist eine unvollständige Neos-Portierung. Das Altsystem (Quelltext lokal unter temp/web54_extracted/…/Contenance.Solcom, DB-Spiegel via Drush-Key neos) hatte genau die Ehe, die hier entschieden wird: eine projectalert-Tabelle mit user- ODER guest-Bindung, Include-Tags, Exclude-Tags (notags), Exclude-Gebieten und Hash-Token-Verwaltung. 20.369 Bestands-Alerts, davon 12.912 aktiv (13.053 user-, 7.314 gast-gebunden) — die Stakeholder-Annahme „früher nur registriert" ist widerlegt.
  • Der B-Matcher braucht die Whitelist nicht. ProjectOfferAlertMatcher matcht per Substring gegen Projekt-Freitext (Titel, Requirements, Skills) und unterstützt sogar Bool-Gruppen (filter_skill_groups). Die Taxonomy-Whitelist ist reine Formular-UI. Das Altsystem erlaubte Freitext (Select2 tags:true) mit Vorschlägen aus einer redaktionell gepflegten Liste (28 Technology-Nodes).
  • Die „anlagen^bau"-Kuriositäten sind ein Datenqualitätsproblem, kein Formular-Bug. 21 skill-Terms mit ^/=/! entstanden, weil SkillTextSplit (Salesforce-Import) und der RSM-Import Multiwert-Strings nur an ,/; splitten — Alt-Suchsyntax-Strings landen als ganze Terms und tauchen in jedem Skill-Autocomplete auf. Die alte Modul-A-Neos-Migration (NeosAlertSource) war zudem gegen ein erfundenes Tabellen-Schema gebaut und ist gegen den realen Dump nie lauffähig gewesen.

Entscheidung

1. Modul B ist die Basis, Modul A wird stillgelegt

solcom_project_offer_alert wird das einzige Alert-System. Es bedient beide Zielgruppen bereits heute; von Modul A werden die Edit/Delete-UI-Mechanik für Eingeloggte und die Ein-Alert-pro-User-Garantie übernommen. solcom_projektpartner_alert wird deinstalliert (vorher Bestandsprüfung auf Staging/Prod), /projektportal/suchagent wird Redirect auf /projektportal/projektalert.

2. Schlagwort-Eingabe: Freitext + kuratierte Vorschläge

Include- und Exclude-Feld verlieren den Whitelist-Zwang: freie Chip-Eingabe (min. 2 Zeichen, max. 4 Begriffe — Neos-Parität), Autocomplete-Vorschläge kommen aus dem neuen, redaktionell gepflegten Vocabulary alert_suggestion (Seed: bereinigte Neos-Technology-Liste). User-Eingaben erzeugen keine Taxonomy-Terms — gespeichert werden Strings, wie B es bereits tut. Das verschmutzte skill-Vocabulary bleibt Projektlisten-Filter-Quelle, wird separat bereinigt und ist nicht mehr Vorschlagsquelle des Alerts.

3. Anonym-Verwaltung über Token-Edit-Links, Dedup enumeration-safe

Jede Mail (Bestätigung + Digest) enthält neben „Abmelden" einen „Alert bearbeiten"-Link (/projektportal/projekt-alert/bearbeiten/{token}) — Formular vorbefüllt, mit Löschen-Button. Mehrfach-Abos derselben E-Mail werden verhindert: bei bekannter Adresse keine UI-Meldung (Enumeration-Schutz), stattdessen E-Mail mit Edit-Link.

4. Migration: alle aktiven Neos-Alerts, Bool-Gruppen werden abgeflacht

Alle 12.912 aktiven Alerts (User- und Gast-Alerts) werden migriert, ohne erneutes Double-Opt-in — der Consent stammt aus dem Alt-Double-Opt-in und deckt den Bezug „bis zur Abbestellung". Die ODER-Gruppen-Struktur der Alt-Daten wird bewusst zu flachen OR-Listen abgeflacht (Site-Owner-Entscheidung: keine Gruppen-UI); Wildcards (*) werden gestrippt, Substring-Matching macht Präfix-Semantik implizit. states mappt 1:1 auf filter_excluded_locations (identische Exclude-Semantik). Gegen Massen-Versand nach Cut-over wird die Pro-Projekt-Dedup-Tabelle beim Migrieren mit dem Ist-Projektbestand vorbefüllt.

5. Versandlogik: Erklär-Copy statt Frequenz-Einstellung

Wie im Altsystem gibt es keine Frequenz-Wahl. Das Formular erklärt: E-Mail, sobald neue passende Projekte erscheinen, jedes Projekt nur einmal (Pro-Projekt-Dedup nach Neos-Vorbild). Das vorhandene frequency-Feld bleibt ungenutzt im Datenmodell. Ergänzend: Include/Exclude-Duplikat-Validierung und ein AJAX-Trefferzähler (nice-to-have).

Abgelehnte Alternativen

Projekt-Alert deaktivieren, Überarbeitung nach Go-Live (Stakeholder-Angebot)

Verworfen: Die Findings sind mit vorhandenen Bausteinen vor Go-Live lösbar; eine Deaktivierung würde 12.912 aktive Bestands-Abonnenten des Altsystems ohne Nachfolger lassen und Bestandswert vernichten.

Modul A als Basis, anonyme Schicht anbauen

Verworfen: ppp_alert ist hart an den User gebunden; E-Mail+Token-Support, Double-Opt-in und Gast-Kontaktdaten müssten neu gebaut werden — alles existiert in B bereits. Invasiver Entity-Schema-Umbau bei sechs Tagen Restlaufzeit.

Beide Systeme behalten, B punktuell härten

Verworfen: Zwei parallele Systeme mit überlappender Funktion sind dauerhafte Doppel-Pflege (zwei Matcher, zwei Cron-Strecken, zwei Formulare), verwirren Redaktion und Nutzer (Stakeholder fand nur B und vermisste genau das, was A konnte) und verdoppeln jede künftige Änderung.

B als Capture-Formular, Verwaltung nur in A nach Registrierung

Verworfen: Höchste Komplexität (Überführungslogik B→A beim ersten Login), erzwungene Registrierung widerspricht dem Altsystem-Verhalten mit 7.314 Gast-Alerts.

Taxonomy-Whitelist behalten und nur Terms bereinigen

Verworfen: Löst das Kern-Finding nicht („Kunde nimmt er nicht") — der Stakeholder-Wunsch nach freier Eingabe ist Altsystem-Verhalten, und der Matcher braucht die Whitelist ohnehin nicht.

ODER-Gruppen-UI aus Neos nachbauen

Verworfen (explizite Site-Owner-Entscheidung): Die Gruppen-Mechanik (bis zu 4 ODER-Felder mit UND-innerhalb) war erklärungsbedürftig und wird nicht fortgeführt. Kosten der Abflachung: alte UND-Verknüpfungen matchen breiter (mehr Mails, nie weniger) — mitigiert durch den Edit-Link in jeder Mail.

Gast-Alerts nur mit Re-Opt-in-Mail migrieren

Verworfen: DSGVO-seitig nicht erforderlich (Double-Opt-in im Altsystem durchlaufen, Consent-Text deckt Bezug bis zur Abbestellung); eine Re-Opt-in-Kampagne würde erfahrungsgemäß 50–70 % des aktiven Bestands verlieren und braucht eine zusätzliche Mail-Strecke vor Go-Live.

Konsequenzen

Positiv:

  • Ein System, ein Matcher, ein Formular — jede künftige Änderung genau einmal.
  • Alle fünf Stakeholder-Findings aus P2503-275 sind adressiert (Datenqualität, freie Eingabe, Frequenz-Transparenz, Duplikat-Validierung, Verwaltung für Anonyme).
  • Altsystem-Parität bei Eingabe (Freitext + Vorschläge) und URL (/projektportal/projektalert pfadgleich — Alt-Bookmarks bleiben gültig).
  • 12.912 Bestands-Abonnenten überleben den Relaunch ohne Bruch.

Risiken / Kosten:

  • Mail-Volumen: Abgeflachte UND-Gruppen matchen breiter; einzelne Alt-Abonnenten bekommen mehr Mails als gewohnt. Mitigation: Edit-Link in jeder Mail, Pro-Projekt-Dedup.
  • Token-Sicherheit: Bearbeiten/Löschen hängt allein am Token-Wissen (wie bisher Abmelden). Tokens sind UUIDs, Mails der einzige Kanal — akzeptiertes Modell, identisch zum Altsystem-Hash.
  • Migrations-Datenqualität: Alt-Daten enthalten Tippfehler und Alt-Suchsyntax; die Migration normalisiert defensiv, Probelauf gegen den vollen Dump ist Pflicht vor Staging.
  • Glossar-Drift: Der CONTEXT.md-Begriff „Suchagent / Projekt-Alert" (ein Alert pro Partner, nur registriert) war schon vor dieser Entscheidung von der Realität abgewichen; er wird mit diesem ADR neu gefasst.

Verifikation: Kernel-Tests (Matcher, Form-Validierung, Migration mit Fixtures aus echten Neos-Samples), Functional-Tests (Token-Routen), Browser-Verify auf DDEV + Staging inkl. Mail-Sink. Details: Plan 2026-07-02-001.

Offene Punkte

Bestandsprüfung ppp_alert auf Staging/Prod. Lokal existieren nur 2 Testeinträge; vor der Deinstallation von Modul A ist der echte Bestand via mw app exec zu prüfen und ggf. nach B zu überführen.
Customer-Lens-Review. Das Decision-Time-Review (drei Linsen) lief parallel zur ADR-Erstellung; materielle Einwände werden als Follow-up-ADR oder Plan-Korrektur nachgezogen.