
# Change Log
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [3.0.12] - 2026-10-09

### Fixed
- WEX-Export und KI-Senden: Hat der abweichende Ort bzw. Disponent (bzw. der eigene
  Standort) keine gültige WEX-ID, erscheint eine klare Fehlermeldung statt eines
  API-Fehlers.

## [3.0.11] - 2026-10-09

### Fixed
- Senden per KI-Pipeline: Office-ID wird jetzt wie beim WEX-Export aus dem gewählten
  Standort bzw. Berater ermittelt (statt immer aus dem Standort des eingeloggten Users);
  behebt "Der gewählte Wert für officeid ist ungültig" (HTTP 422).
- Fehlerantwort der CV-Pipeline-API wird zusätzlich ins Log geschrieben.

## [3.0.10] - 2026-10-08

### Fixed
- Datenschutzerklärung (Webseite): fehlendes Leerzeichen vor "Evidenzhaltung".

## [3.0.9] - 2026-10-08

### Changed
- Datenschutzerklärung (PDF und Webseite): "Evidenzhaltung" im Satz
  "Wenn Sie sich initiativ bei uns bewerben oder der Evidenzhaltung zustimmen, ..."
  fett hervorgehoben.

## [3.0.8] - 2026-10-08

### Changed
- Text der Datenschutzerklärung (PDF und Webseite) angepasst: "Wenn Sie sich
  initiativ bei uns bewerben oder der Evidenzhaltung zustimmen, ..."

## [3.0.7-beta] - 2026-10-06

### Changed
- Mailadresse-Hinweis in "Bewerber anlegen" und "Bewerber bearbeiten":
  "(optional bei ausländischen Bewerbern, verpflichtend bei KI-Verarbeitung)".

## [3.0.6-beta] - 2026-10-05

### Changed
- Login nur noch mit gültigem Standort: Benutzer ohne Standort bzw. ohne
  Office-ID (z. B. "Ausgetreten") können sich nicht mehr anmelden. Die
  Zugangsdaten bleiben erhalten. Statt "Fehler beim Anmelden" erscheint eine
  eigene Meldung ("Ihrem Benutzer ist kein Standort zugewiesen").

### Fixed
- Senden per KI-Pipeline: Die Office-ID wird nie mehr als 0 übergeben. Hat der
  Standort keine gültige WEX-ID, erscheint stattdessen eine Fehlermeldung.

## [3.0.5-beta] - 2026-10-05

### Added
- Handynummer-Feld: Länderauswahl zeigt Flagge und Vorwahl.
- Bestätigungs-Mails verwenden den Header des jeweiligen Unternehmens
  (TTI, Squadra, IFAS, Berger).

### Changed
- Die Auswahl "mit/ohne Evidenzhaltung" wird als `ppvc_pool`
  (`active`/`inactive`) an WEX und die KI-Pipeline übergeben.

## [3.0.4-beta] - 2026-10-05

### Added
- Zustimmung: Der Bewerber wählt bei der Datenschutz-Zustimmung zwischen
  "mit" (Standard) und "ohne Evidenzhaltung"; die Auswahl wird gespeichert
  und im Bewerber-Detail angezeigt.

## [3.0.3-beta] - 2026-10-05

### Added
- Handynummer-Feld mit Länderauswahl (Standard +43): Nummern wie
  `06641234567` werden automatisch zu `436641234567` geglättet, beim
  Bearbeiten wird die gespeicherte Nummer wieder in Vorwahl und Rest getrennt.

## [3.0.2-beta] - 2026-10-05

### Changed
- Login- und Passwort-Formulare sind auf Desktop vertikal zentriert.

## [3.0.1-beta] - 2026-10-05

### Fixed
- KI-Übergabe (CV-Pipeline): `jobID` wird jetzt mit 0 übergeben und
  `recruitmentsourceID` mit der ID der Quelle des Bewerbers (statt eines
  Text-Mappings).
- Lokaler Start unter Node 26 schlug fehl (`SlowBuffer` entfernt); durch
  Update der Abhängigkeiten `jwa`/`jws` behoben.

## [3.0.0-beta] - 2026-10-02

### Changed
- Umbau auf eine neue interne Code-Struktur: Der Datenbankzugriff läuft
  jetzt über ein modernes ORM statt über direkte SQL-Abfragen, als
  Grundlage für die weitere Entwicklung.
- Optisches Update: Farben, Benutzerliste und Tabellen orientieren sich
  jetzt stärker am einheitlichen Erscheinungsbild der TTI-Group-Tools
  (z.B. Anzahl Einträge pro Seite einstellbar, markenspezifische Farben
  statt einer festen Farbe für alle). Oben rechts steht jetzt der volle
  Name statt des Benutzerkürzels.

### Fixed
- Mehrere kleinere Stabilitätsverbesserungen in der Bewerberverwaltung
  und Benutzerverwaltung.

## [2.19.0] - 2026-10-02

### Changed
- Phase 7 (Nachtrag): letzter verbliebener `switch(mandant.id)`-Block für
  die Du-/Sie-Form in `routes/applicant-workflow.routes.js`
  (`sendDSGVO()`: DSGVO-Mail- und SMS-Text) durch echte Spalte
  `salutation` auf der `mandant`-Tabelle abgelöst (additive Migration
  `20261002-add-mandant-salutation.js`, Backfill: TTI/BERGER = "du",
  SQUADRA/IFAS = "sie" — entspricht exakt den bisherigen
  hartcodierten Branches). `model.getMandant()`, `Mandant.js` und das
  Sequelize-Modell `models/mandant.model.js` geben das neue Feld durch.

  Der zweite `switch(mandant.id)`-Block in derselben Datei
  (markenspezifischer Social-Media-SMS-Text nach WEX-Export) bleibt
  bewusst im Code — mehrzeilige Textcopy mit Links, kein einfaches
  Attribut.

  Der neue `switch` hat einen `default`-Fall: fehlt/unbekannt
  `salutation` (z.B. Migration nicht gelaufen, oder ein 5. Mandant ohne
  Backfill), wird jetzt geloggt und **nichts verschickt**, statt wie es
  der alte `switch(mandant.id)` ohne `default` sonst getan hätte —
  nämlich eine Mail ohne Consent-Link zu verschicken und sie trotzdem
  als versendet zu markieren.

  Verifiziert: Testsuite weiterhin grün (63 Tests, davon 3 neu für
  genau diesen Switch — du-Form, sie-Form, fehlende salutation —, vor
  dem Umbau gegen den alten `switch(mandant.id)`-Code geschrieben und
  gegen ihn laufen gelassen: die beiden Form-Tests waren schon vorher
  grün, der Fehlerfall-Test schlug davor erwartungsgemäß fehl).
  Migration gegen die lokale DB (= Prod-Dump) gelaufen, Backfill für
  alle 4 Mandanten gegen die alten switch-Werte verglichen (stimmt
  exakt), End-to-End-Check `model.getUser()` → `model.getMandant()` →
  `salutation` für Mandant 1 über die echte Kette, Boot-Test ohne
  Fehler.

## [2.18.0] - 2026-10-02

### Changed
- Phase 7: `switch(mandant.id)` für Mail-Postfach und Logo in `mailer.js`
  durch echte Spalten auf der `mandant`-Tabelle abgelöst
  (`mail_account`, `logo_file`, additiv per Migration
  `20261002-add-mandant-config-columns.js` befüllt — Werte entsprechen
  exakt den bisherigen hartcodierten Branches). Zusätzlich `slug`
  (additiv, informativ) und `domain` (additiv, **bewusst nicht
  befüllt** — umgebungsabhängig, `Mandant.getDomain()` fällt weiterhin
  auf `MANDANT_DOMAIN` zurück, solange die Spalte `NULL` ist) ergänzt.
  `model.getMandant()`/`Mandant.js` geben die neuen Felder durch.

  Die beiden verbleibenden `switch(mandant.id)`-Blöcke in
  `routes/applicant-workflow.routes.js` (DSGVO-Mailtext/SMS-Text
  Du-/Sie-Form, Social-Media-SMS-Text nach WEX-Export) bleiben bewusst
  im Code — das ist mehrzeilige Textcopy, keine einfachen Attribute,
  und damit außerhalb des Phase-7-Scopes.

  Verhaltensänderung bei fehlendem `mail_account`: `sendMail` loggt
  jetzt einen Fehler und verschickt nichts, statt (wie der alte
  `default`-Zweig) heimlich über das Postfach der Schwester-App
  `tti-service-designer` zu versenden — betrifft nur den theoretischen
  Fall eines unbekannten/fehlenden Mandanten, nie einen der 4
  bestehenden.

  Verifiziert: `tests/mailer.test.js` (9 neue Charakterisierungstests,
  vor der Umstellung geschrieben und grün, danach unverändert grün;
  58 Tests insgesamt), Migration gegen frische Test-DB (0-Zeilen-UPDATE
  kein Fehler) und gegen die lokale DB (= Prod-Dump) gelaufen, Backfill
  für alle 4 Mandanten stichprobenartig mit den alten switch-Werten
  verglichen, End-to-End-Check `model.getMandant()` → `mailer.getCid()`
  für alle 4 Mandanten, Boot-Test ohne Fehler.


- Phase 5: Session-Store von der In-Memory-`memorystore` (verliert bei
  jedem Neustart/Deploy alle Sessions) auf `connect-session-sequelize`
  umgestellt, DB-persistiert über die bestehende `models/`-Sequelize-
  Instanz aus Phase 2. Dafür musste Phase 2 zuerst in diese Branch-Linie
  gemerged werden (siehe unten). Zwingend zusammen damit:
  `saveUninitialized: false`, sonst würde jeder anonyme Hit auf die
  öffentlichen DSGVO-Consent-Seiten eine dauerhafte Session-Zeile
  erzeugen, obwohl dort nie etwas in der Session gespeichert wird.
  Die `Sessions`-Tabelle wird beim Start per `sessionStore.sync()`
  angelegt (wie bei tti-service-designer), nicht über
  `scripts/migrate.js` — das Schema gehört dem npm-Paket, nicht der App.
  In Tests (`NODE_ENV=test`, von Jest automatisch gesetzt) bleibt
  bewusst die alte In-Memory-Store aktiv, damit die Testsuite weiterhin
  ohne echte DB-Verbindung läuft.

  Per Skript gegen die lokale DB (= aktueller Prod-Dump) end-to-end
  verifiziert, inkl. echtem Prozess-Neustart (zwei separate
  `node`-Aufrufe): Login legt genau eine Session-Zeile an, ein
  komplett neuer Prozess bleibt mit demselben Cookie eingeloggt
  (das eigentliche Ziel dieser Phase), anonyme Aufrufe der
  Consent-Seite erzeugen keine zusätzliche Zeile, Logout entfernt die
  Passport-Login-Daten aus der Session (die Zeile selbst bleibt bis zum
  natürlichen Ablauf bestehen — Standard-Verhalten von
  express-session/Passport, war bei der alten In-Memory-Store nicht
  anders).

  Nebenbefund (nicht Teil dieser Phase, nicht gefixt): `GET
  /datenschutzerklaerung/:id` wirft für mindestens einen echten
  Bestandsdatensatz einen 500er, weil `model.getMandant` dort kein
  gültiges Mandant-Objekt bilden kann (vermutlich verwaist referenzierte
  Location/Mandant) — vorbestehender Datenqualitäts-/Null-Check-Bug,
  gleiche Fehlerklasse wie der bereits in Phase 3 dokumentierte Fund.

- **Branch-Zusammenführung**: `phase2-sequelize-migrations` wurde in
  diese Branch-Linie (`phase3-express5` → `phase4-wave-*` →
  `phase6-views` → `phase5-session-store`) gemerged, da Phase 5 die
  Sequelize-Instanz aus Phase 2 braucht. Dabei kollidierten
  `package.json`/`CHANGELOG.md`/`CLAUDE.md` wie erwartet (siehe
  UMBAU-PLAN.md); der doppelte CHANGELOG-Eintrag "2.7.0" wurde auf
  "2.6.1" umnummeriert.

### Added
- Nach weiterer Abstimmung noch zwei der zunächst explizit nicht
  übernommenen tti-service-designer-Elemente ergänzt, wo sie passen:
  - **Username in der Navigation**: `model.checkLogin` liefert jetzt
    zusätzlich `username` (vorher nur `{id, role}` in der Session). Nav
    und Offcanvas zeigen ihn an (wie bei tti-service-designer), ohne
    zusätzliche DB-Abfrage pro Request.
  - **`container-xxl`** auf den vier Tabellen-/Listenseiten
    (Benutzerverwaltung, beide Bewerber-Admin-Listen, "Meine
    Bewerber*innen") statt des schmaleren `container` — nutzt auf
    großen Screens mehr Breite für die vielspaltigen Tabellen.
  - **Bewusst weiterhin nicht übernommen**: der Lade-Spinner (löst bei
    tti-service-designer ein Alpine.js-spezifisches Problem, das es
    hier mangels Alpine.js nicht gibt) und die Dropdown-Gruppierung im
    Nav (bei nur 2 Admin-Links kein Vorteil gegenüber den bisherigen
    direkten Icon-Links).

## [2.15.0] - 2026-10-02

### Changed
- Phase 6: Alle Views von einer flachen `views/*.pug`-Liste nach
  `views/layout/` + `views/components/` + `views/pages/<feature>/`
  umgezogen, im Format von tti-service-designer (`extends`/`block
  content`-Vererbung statt `include header`). Pro Phase-4-Welle ein
  eigener `pages/`-Unterordner. `app.js` setzt jetzt `app.locals.basedir`,
  damit absolute `extends`/`include`-Pfade funktionieren.
  Inhalt überall unverändert übernommen.

### Fixed
- Zwei Tooltip-Inputs in der Bewerber-Anlegen-Seite nutzten noch das
  alte Bootstrap-4-Attribut `data-toggle="tooltip"`, das unter
  Bootstrap 5 nie initialisiert wurde (kein passender JS-Init vorhanden).
  Auf `data-bs-toggle`/`data-bs-placement` korrigiert, Tooltip-Init in
  `public/js/script.js` ergänzt.
- Die Navigation nutzte noch `ml-auto` (Bootstrap 4, unter Bootstrap 5
  wirkungslos) für die rechtsbündigen Nav-Einträge - beim Neuschreiben
  der Navigation in `views/layout/app.pug` auf `ms-auto` korrigiert.
- `pages/applicant-workflow/mail-sent-fail.pug` übergab den Fehlertext
  bisher als lokale Variable `message` (ein String). Seit `layout/app`
  jetzt zentral `components/alert` einbindet, hätte das eine leere,
  grüne "Erfolg"-Alertbox über der eigentlichen Fehlerseite erzeugt
  (`alert.pug` prüft nur `message !== undefined`, nicht die Form).
  Variable in `errorMessage` umbenannt (Route + Template), damit die
  Alert-Komponente sie ignoriert.

### Changed (kleine Vereinheitlichungen, bündig mit dem View-Umzug)
- Login-Seite hatte als einzige der Sidenav-Seiten nicht die
  `tti_universe_background`-Klasse - jetzt einheitlich überall gesetzt.
- Der Versions-Link ("V{version}" → CHANGELOG) stand bisher nur auf der
  Login-Seite, nicht auf den Passwort-Seiten - jetzt einheitlich auf
  allen dreien.

## [2.14.0] - 2026-10-02

### Changed
- Phase 4 (Strangler-Fig-Extraktion), Welle F (letzte Welle, höchstes
  Risiko): öffentliche DSGVO-Consent-Routen
  (`/datenschutzerklaerung(_2)/:id`) + Login/Logout
  (`/login`, `/logout`, `/login_failure`) nach
  `routes/public-consent.routes.js` + `services/public-consent.service.js`
  extrahiert. Reiner Struktur-Schritt (4a), Service ruft weiterhin
  unverändert `model.js` auf. Verhalten 1:1 erhalten und per vorab
  geschriebenen Charakterisierungstests abgesichert (das bereits seit
  Phase 3 bestehende `tests/app.test.js` deckte diese Routen schon ab,
  ergänzt um `tests/public-consent-and-auth.test.js` für `/logout` und
  `/login_failure`, 2 weitere Tests), die vor der Extraktion gegen das
  alte `index.js` grün liefen und danach unverändert grün blieben (49
  Tests insgesamt). Routenzahl weiterhin 29 (gegengerechnet). Echter
  Boot-Smoke-Test ohne Fehler.
- Damit ist Phase 4 (Struktur-Schritt 4a, alle sechs Wellen A–F)
  abgeschlossen: `index.js` enthält nur noch 3 Routen (`/`, `/dashboard`,
  `/init_passwords`), der Rest ist nach `routes/`+`services/` extrahiert.
  4b (Sequelize je Welle) ist für keine Welle begonnen.

## [2.13.0] - 2026-10-02

### Changed
- Phase 4 (Strangler-Fig-Extraktion), Welle E: Bewerber anlegen/bearbeiten
  (`/bewerber-anlegen`, `/createApplicant`, `/edit-applicant`), inkl.
  DSGVO-Mail/SMS-Versand und WEX-Export, nach
  `routes/applicant-workflow.routes.js` + `services/applicant-workflow.service.js`
  extrahiert. Reiner Struktur-Schritt (4a), Service ruft weiterhin
  unverändert `model.js` auf. Verhalten 1:1 erhalten (inkl. zweier
  vorbestehender Bugs, bewusst nicht gefixt: `editable` als impliziertes
  globales Objekt, und ein undefiniertes `loggedUser` im
  `frm_export`-Fehlerzweig bei `show_filter=1`) und per vorab
  geschriebenen Charakterisierungstests (`tests/applicant-workflow.test.js`,
  13 Tests) abgesichert, die vor der Extraktion gegen das alte `index.js`
  grün liefen und danach unverändert grün blieben (47 Tests insgesamt).

## [2.12.0] - 2026-10-02

### Changed
- Phase 4 (Strangler-Fig-Extraktion), Welle D: "Meine Bewerber*innen"-Listen
  (`/bewerber-ohne-versand`, `/manage_my_gdpr_not_accepted_applicants`,
  `/manage_my_gdpr_accepted_applicants`, `/manage_my_imported_applicants`)
  nach `routes/applicant-lists.routes.js` + `services/applicant-lists.service.js`
  extrahiert. Reiner Struktur-Schritt (4a), Service ruft weiterhin
  unverändert `model.js` auf. Verhalten 1:1 erhalten und per vorab
  geschriebenen Charakterisierungstests (`tests/applicant-lists.test.js`,
  6 Tests) abgesichert, die vor der Extraktion gegen das alte `index.js`
  grün liefen und danach unverändert grün blieben (34 Tests insgesamt).

## [2.11.0] - 2026-10-02

### Changed
- Phase 4 (Strangler-Fig-Extraktion), Welle C: Admin-Bewerberverwaltung
  (`/manage-applicants`, `/delete-applicant/:id`) nach
  `routes/applicant-admin.routes.js` + `services/applicant-admin.service.js`
  extrahiert. Reiner Struktur-Schritt (4a), Service ruft weiterhin
  unverändert `model.js` auf. Verhalten 1:1 erhalten und per vorab
  geschriebenen Charakterisierungstests (`tests/applicant-admin.test.js`,
  3 Tests) abgesichert, die vor der Extraktion gegen das alte `index.js`
  grün liefen und danach unverändert grün blieben (28 Tests insgesamt).

## [2.10.0] - 2026-10-02

### Changed
- Phase 4 (Strangler-Fig-Extraktion), Welle B: Passwort-Reset
  (`/passwort-vergessen`, `/passwort-wiederherstellen(/:hash)`) nach
  `routes/password-reset.routes.js` + `services/auth.service.js`, sowie
  `/settings` nach `routes/settings.routes.js` + `services/settings.service.js`
  extrahiert. Reiner Struktur-Schritt (4a), Services rufen weiterhin
  unverändert `model.js` auf. Verhalten 1:1 erhalten und per vorab
  geschriebenen Charakterisierungstests (`tests/settings.test.js`, 10 Tests)
  abgesichert, die vor der Extraktion gegen das alte `index.js` grün liefen
  und danach unverändert grün blieben (25 Tests insgesamt).

## [2.9.0] - 2026-10-02

### Changed
- Phase 4 (Strangler-Fig-Extraktion), Welle A: Benutzerverwaltung
  (`/create-user`, `/edit-user/:user_id`, `/users`) aus `index.js` nach
  `routes/user.routes.js` + `services/user.service.js` extrahiert,
  `isLoggedIn`/`isAdmin` nach `middlewares/auth.js`. Reiner Struktur-Schritt
  (4a) — der Service ruft weiterhin unverändert `model.js` auf, noch kein
  Sequelize. Verhalten 1:1 erhalten und per vorab geschriebenen
  Charakterisierungstests (`tests/user-admin.test.js`) abgesichert, die vor
  der Extraktion gegen das alte `index.js` grün liefen und danach
  unverändert grün blieben.

## [2.8.0] - 2026-10-01

### Changed
- Express 4 → 5 Upgrade (Phase 3). Codebasis war bereits kompatibel (keine
  Wildcard-/Regex-Routen, kein `app.del`/`req.param`/`app.param`, kein
  verschachteltes `req.query`) — keine Anpassungen an Routen/Middleware
  nötig. Verifiziert über: automatisierte Testsuite (weiterhin grün),
  manueller Boot-Smoke-Test aller wichtigen Routen inkl. Static-File-Serving,
  und `npm run build`.

## [2.7.0] - 2026-10-01

### Added
- Jest + Supertest Testsuite (`tests/app.test.js`, `npm run test:unit`) als
  Regressions-Sicherheitsnetz für den Express 4→5-Umstieg (Phase 3):
  deckt öffentliche DSGVO-Consent-Routen, Login-Erfolg/-Fehler, die
  `isLoggedIn`/`isAdmin`-Gates und Session-Persistenz über Requests hinweg ab,
  komplett gemockt (keine echte DB-/Mail-/SMS-Verbindung). `app.js` exportiert
  die Express-App jetzt und startet den Server nur noch bei direktem Aufruf
  (`node app.js`), damit Tests sie ohne Port-Bindung importieren können.

## [2.6.2] - 2026-10-01

### Added
- Sequelize + eigener Migrations-Runner (`scripts/migrate.js`,
  `npm run migrate`/`migrate:status`/`migrate:undo`) additiv eingeführt,
  nach Vorbild von `tti-service-designer`. `migrations/` enthält eine
  Baseline-Migration, die das bestehende Schema (introspektiert gegen
  eine lokale DB, die ein aktueller Produktions-Dump ist) per
  `CREATE TABLE IF NOT EXISTS` dokumentiert (kein `sequelize.sync()`).
  `models/` bildet `mandant`/`locations`/`users`/`applicants` 1:1 ab und
  wurde bis zu diesem Merge ausschließlich vom Migrations-Runner genutzt.
  `npm run git` führt `migrate` jetzt vor dem Webpack-Build aus.
  (Branch `phase2-sequelize-migrations`, ursprünglich als "2.7.0"
  committet, dann beim Merge in die Phase-3/4/6-Linie auf "2.6.1"
  umnummeriert — und jetzt beim Merge von `main` nochmal auf 2.6.2, da
  `main`s echter SMS-Crash-Hotfix inzwischen die reale Version 2.6.1
  trägt und bereits live deployed ist. Siehe den Eintrag direkt darunter.)

## [2.6.1] - 2026-10-02

### Fixed
- Produktionsvorfall: Ein fehlgeschlagener SMS-Versand (websms.com, hier
  durch falsche/abgelaufene Zugangsdaten ausgelöst) crashte wiederholt
  den kompletten Node-Prozess (`ERR_HTTP_HEADERS_SENT`, da `sendSMS()`
  bei einem Fehler selbst eine Response sendete, obwohl die drei
  aufrufenden Stellen — Bewerber anlegen mit SMS-Versand, erneuter
  DSGVO-Versand, WEX-Export — danach noch eine eigene Response senden).
  `sendSMS()` loggt Fehler jetzt nur noch, sendet keine eigene Response
  mehr. Akute Ursache (Zugangsdaten) wurde separat auf dem Server behoben.
  **Bereits live deployed auf `main`** (unabhängig vom restlichen Umbau,
  siehe UMBAU-PLAN.md). Der gleiche Fix wurde zusätzlich in diese
  Branch-Linie übernommen (siehe `routes/applicant-workflow.routes.js`,
  wo dieselbe Logik seit Phase 4 Welle E extrahiert liegt).

## [2.6.0] - 2026-10-01

### Added
- `ppvc_pool: "active"` wird jetzt mit an den WEX-Export übergeben
- Versionsanzeige/Changelog-Link auf der Login-Seite (`package.json`
  "version" ist jetzt Single Source of Truth)

### Changed
- Konsent-Mailtext/SMS-Text für alle Mandanten auf neue
  Talente-Pool-Formulierung umgestellt (Du-Form für TTI/BERGER,
  Sie-Form für SQUADRA/IFAS)
- Frontend-Build von Gulp auf Webpack umgestellt (wie
  tti-service-designer); gebaute CSS-Dateien sind nicht mehr im Git,
  werden beim Deploy frisch gebaut
- Deployment auf zwei Branches (`staging`/`main`) mit automatisiertem
  SSH-Deploy via GitHub Actions umgestellt (wie tti-service-designer)

### Security
- `production.env`/`staging.env` aus dem Git entfernt (enthielten
  Live-Zugangsdaten im Klartext)
- Debug-Mail mit kompletter Bewerber-PII bei jedem WEX-Export entfernt
- `/delete-applicant/:id` von GET auf POST umgestellt (CSRF)
- SQL-Injection-Lücke in zwei Mandanten-Queries geschlossen
  (String-Interpolation → parametrisierte Queries)
- SMS-Zugangsdaten und Session-Secret aus dem Quellcode in
  Umgebungsvariablen verschoben

## [2.5] - 2023-12-21

### Added
Mandanten- und Locationänderungsmöglichkeit vor WEX Export

## [2.4] - 2023-12-21

### Added
Erstellungsdatum, Bestätigungsdatum
Neue Felder bearbeitbar
Speichern ohne Versand von neuen Bewerben
Cronjobs für automatische Löschungen
Einbau von Icons im Header für Platzoptimierungen

### Changed
nicht bearbeitbare Felder auch so anzeigen
diverse weitere Änderungen in den Formularen

### DB Changes


## [2.3.2] - 2023-12-11

### Added
neue Kategorie: Ausländische Jobbörsen
JOBBRIDGE Stellenbörse

## [2.3.2] - 2023-11-13

### Added
iswipe Stellenbörse

## [2.3.1] - 2023-10-08

### Added
ABA jobs.workinaustria 

## [2.3] - 2023-09-27

### Added
- possibility to delete applicant as Administrator

## [2.2.6] - 2023-07-31

### Fixed
- Menu highlight on edit applicant
- 
- text changes

## [2.2.5] - 2023-07-31

### Fixed
- new User needs PW
- text changes

## [2.2.4] - 2023-07-07

### Changed
- changed menuorder
- addded Applicant ID to Wex imported status

### Fixed
- SMS Sending not working

## [2.2.3] - 2023-07-05

### Changed
- active Menu marked
- Email address is always editable
- email field not required any more

## [2.2.2] - 2023-07-04

### Fixed
- ExportToWex Error

## [2.2.1] - 2023-07-04

### Changed
- show Substitutionname if Applicant is substituted instead of color
- if substituted, export to wex is filled with original data for agentID and locationWexID
- minor css changes

## [2.2] - 2023-06-29

### Changed
- Make Username and Email for Users unique
### Added
- Development has own header color
- save application_id from WEX to Database
- possibility to disable or enable SMS messages

## [2.1] - 2023-06-27

### Fixed

- If WEX creates an error, no more successmessage is shown and applicant is not moved to sent 
- editing an applicant now shows the stored data 

### Changed

- moved Wex connection from curl to axios

## [2.0] - 2023-06-01

### Added

- possibility to declare another user to substitute
- substituted applicants are marked
- password forgot
- user creation
- sort and filter applicants
- edit recruiting channel and send to WEX
- .env for configurations

