Projekt BISO 3 - Handbuch
[inhalt]

Konfiguration

English Version

Scheduler (Cron)

BISO verwendet crunz als zentralen Task-Scheduler. Anstatt für jede wiederkehrende Aufgabe einen eigenen Cronjob einzurichten, wird nur ein einziger Cronjob benötigt. Der Scheduler prüft selbständig, welche Tasks fällig sind und führt diese aus.

Die Task-Dateien befinden sich im Verzeichnis webroot/backend/scheduler/tasks/. Einzelne Tasks werden je nach Konfiguration (Config) oder Parameter (Admin > Parameter) bedingt aktiviert.

Einrichtung Cronjob

Auf dem Kundensystem muss ein einziger Crontab-Eintrag eingerichtet werden, der jede Minute läuft:

* * * * *   www-data   /usr/bin/php /var/www/biso/webroot/biso-cli scheduler run

Hinweis: Der Pfad /var/www/biso/webroot/ muss an die jeweilige Installation angepasst werden.

Der Scheduler delegiert an crunz, welches die einzelnen Task-Dateien einliest und nur die zum jeweiligen Zeitpunkt fälligen Tasks ausführt. Überlappende Ausführungen werden durch preventOverlapping() verhindert.

CLI-Befehle

Befehl Beschreibung
php biso-cli scheduler list Alle registrierten Tasks mit Zeitplan anzeigen
php biso-cli scheduler run Fällige Tasks ausführen
php biso-cli scheduler run --force Alle Tasks sofort ausführen (unabhängig vom Zeitplan)
php biso-cli scheduler run --task=N Bestimmten Task nach Nummer ausführen

Neuen Task erstellen

Um einen neuen Scheduler-Task hinzuzufügen, wird eine neue PHP-Datei im Verzeichnis webroot/backend/scheduler/tasks/ erstellt. Der Dateiname muss auf Tasks.php enden (z.B. MeinNeuerTasks.php).

Grundstruktur einer Task-Datei:

<?php

use Crunz\Schedule;

require_once __DIR__ . '/../../../components/composer/kadenpartner/gaia/bootstrap.php';

$schedule = new Schedule();

// Bedingte Aktivierung (optional):
if (Param::get('mein_feature_aktiv', false)) {
    $schedule->run(PHP_BINARY . ' ' . Config::get('rootdir') . '/biso-cli mein-command')
        ->daily()->at('08:00')
        ->description('Beschreibung des Tasks')
        ->preventOverlapping()
        ->appendOutputTo(Config::get('tmpdir') . '/mein-task.log');
}

return $schedule;

Scheduling-Methoden Beispiele

Methode Beschreibung
->everyMinute() Jede Minute
->hourly() Stündlich
->hourlyAt('15') Stündlich um Minute 15
->daily() Täglich um Mitternacht
->daily()->at('08:00') Täglich um 08:00
->weekly() Wöchentlich
->weeklyOn(1, '13:30') Wöchentlich am Montag um 13:30 (0=Sonntag)
->monthly() Monatlich
->cron('30 8 * * Mon,Fri') Beliebiger Cron-Ausdruck

Best Practices

Logging

Jeder Task schreibt seine Ausgabe in eine eigene Log-Datei im Verzeichnis data/tmp/:

Mail (SMTP / E-Mail-Versand)

BISO versendet alle ausgehenden E-Mails zentral über MailManager (bzw. die PHPMailer-Subklasse BisoMailer) und ist damit der einzige Ort, an dem die SMTP-Konfiguration wirkt. Wird smtp_server leer gelassen, versendet BISO keine Mails (alle Aufrufe geben wahr zurück, ohne eine Verbindung aufzubauen).

Die folgenden Konfigurationswerte werden in der config.php gesetzt.

SMTP-Transport und Standard-Absender

Mit den fünf smtp_*-Schlüsseln wird die SMTP-Verbindung und der Standard-Absender konfiguriert. Die Werte werden beim Erzeugen der PHPMailer-Instanz einmalig gesetzt.

// config.php

// SMTP-Server (Hostname oder IP). Leer = kein Mailversand.
Config::set('smtp_server', 'mail.example.com');

// SMTP-Authentifizierung. Leer = offenes SMTP ohne Login.
Config::set('smtp_user', '');
Config::set('smtp_pass', '');

// Zusätzliche PHPMailer-Optionen. Beliebige PHPMailer-Properties
// können hier gesetzt werden (häufig verwendet: Port, SMTPAuth,
// SMTPSecure, SMTPOptions, SMTPDebug, ...).
Config::set('smtp_options', array(
    'Port' => 25,
    'SMTPAuth' => false,
    'SMTPSecure' => false,
    'SMTPOptions' => array(
        'ssl' => array(
            'verify_peer' => false,
            'verify_peer_name' => false,
            'allow_self_signed' => true,
        ),
    ),
));

// Standard-Absender-Adresse des Systems (From: bei intern
// ausgelösten Mails wie Termin-Einladungen, Cronjob-Benachrichtigungen,
// CMBB-TG-Fallabschluss-Mails).
Config::set('smtp_sender', 'admin@biso.ch');
Schlüssel Pflicht Bedeutung
smtp_server ja (für Versand) SMTP-Server (Hostname oder IP). Leer deaktiviert den gesamten Mailversand.
smtp_user bei Auth SMTP-Benutzername. Leer bei offenem SMTP.
smtp_pass bei Auth SMTP-Passwort.
smtp_options nein Array mit beliebigen PHPMailer-Properties (z.B. Port, SMTPAuth, SMTPSecure, SMTPOptions). Jeder Schlüssel wird auf der Mailer-Instanz gesetzt.
smtp_sender empfohlen Standard-Absender-Adresse für vom System intern ausgelöste Mails (Cronjobs, Termin-Einladungen, kantonale Delegate).

SMTP-Envelope-Override

Einige authentifizierte SMTP-Server verweigern Mails, deren SMTP-Envelope-Absender (MAIL FROM / PHPMailer-Property Sender) von der Mailbox des SMTP-Authentifizierungs-Benutzers abweicht. Standardmässig verwendet BISO für jede Mail die tatsächliche Benutzer-E-Mail-Adresse als Envelope. Mit den drei folgenden Schlüsseln lässt sich der Envelope - und optional auch der sichtbare From:-Header - durch eine fixe, systemeigene Adresse ersetzen.

Der Override wird zentral in BisoMailer::send() angewendet und wirkt damit für jeden Mailaufruf (regulärer Versand via MailManager::sendEmail() und direkte Aufrufer wie die VCalendar-Entities).

// config.php

// SMTP-Envelope (MAIL FROM / Sender) ersetzen. null/leer = kein
// Override (BISO verwendet die ursprüngliche Benutzer-Adresse).
Config::set('smtp_envelope_sender', 'noreply@example.com');

// Auch den sichtbaren "From:"-Header durch die Envelope-Adresse
// ersetzen. Der display name (FromName) des ursprünglichen Senders
// bleibt erhalten (Empfänger sieht z.B. "Max Muster <noreply@example.com>").
// false = "From:" bleibt die ursprüngliche Benutzer-Adresse.
Config::set('smtp_force_envelope_sender_as_from', true);

// Die ursprüngliche "From:"-Adresse als "Reply-To:" setzen, damit
// Antworten weiterhin den ursprünglichen Sender erreichen. Wirkt nur,
// wenn "From:" tatsächlich überschrieben wurde.
// false = kein Reply-To hinzufügen (Antworten gehen an die Envelope-Adresse).
Config::set('smtp_use_from_as_replyto', true);
Schlüssel Default Wirkung
smtp_envelope_sender null Fixe Envelope-Adresse. null deaktiviert alle drei Overrides.
smtp_force_envelope_sender_as_from false true ersetzt zusätzlich den sichtbaren From:-Header.
smtp_use_from_as_replyto false true fügt - nur bei tatsächlich überschriebenem From: - die ursprüngliche From:-Adresse als Reply-To: hinzu.

Verhaltensmatrix:

smtp_envelope_sender smtp_force_envelope_sender_as_from smtp_use_from_as_replyto Resultat
null egal egal Kein Override. From: und Envelope = ursprünglicher Sender.
gesetzt false false Envelope = fix, From: = ursprünglicher Sender.
gesetzt false true Envelope = fix, From: = ursprünglicher Sender (Reply-To redundant).
gesetzt true false Envelope und From: = fix, Displayname erhalten.
gesetzt true true und Original ≠ Envelope Envelope und From: = fix, ursprüngliche From:-Adresse als Reply-To:.
gesetzt true true und Original = Envelope Envelope und From: = fix, kein selbst-Reply-To (Deduplizierung).

Logging

Der Mailversand schreibt in den eigenen Logger mailer (siehe webroot/config.orig.php). Für gezielte Fehlerdiagnose empfiehlt sich ein eigenes Log-File:

// config.php:
Config::set('gaia.logging', [
    'mailer' => [
        'type' => 'file',                          // 'file' | 'console' | 'none'
        'level' => 'DEBUG',                        // 'DEBUG' | 'INFO' | 'WARNING' | 'ERROR'
        'console' => 'output',
        'logfile' => Config::get('tmpdir') . '/biso-mailer.log',
    ],
]);

Siehe auch

SMS-Konfiguration

BISO unterstützt verschiedene SMS-Provider. Die Auswahl erfolgt über die Konfigurationsoption sms_driver (siehe unten). Per Default ist der historische Mail-to-SMS-Gateway-Versand aktiv (sms_driver = 'email'), womit bestehende Installationen ohne Anpassung weiterlaufen.

Hinweis für bestehende Installationen: Die neue Provider-Architektur ist rückwärtskompatibel. Wird sms_driver nicht explizit gesetzt, bleibt das Verhalten identisch zur bisherigen Lösung (Mail-Gateway via sms_gateway_mail_domain / sms_gateway_mail_sender). Die Umstellung auf Swisscom REST-API, ASP SMS REST-API oder den Dummy-Treiber erfolgt durch Setzen der entsprechenden Konfigurationswerte.

Unterstützte SMS-APIs

Treiber Transport Konfiguration erforderlich Anwendungsfall
email (Default) SMTP-Mail an <mobile>@<sms_gateway_mail_domain> sms_gateway_mail_domain, optional sms_gateway_mail_sender Bestehende Bundes-SMS-Gateway-Lösungen (z.B. smsc.admin.ch), Kunden mit Mail-to-SMS-Bridge.
swisscom HTTPS POST an Swisscom Web-to-SMS REST-API sms_swisscom_api_key (Pflicht), optional sms_swisscom_api_url, sms_swisscom_sender, sms_swisscom_max_msg_parts, sms_swisscom_validity_minutes Kantone mit Swisscom-Vertrag, die reine REST-Anbindung verlangen.
aspsms HTTPS POST an ASP SMS JSON-API (/SendSimpleTextSMS) sms_aspsms_userkey (Pflicht), sms_aspsms_password (Pflicht), optional sms_aspsms_api_url, sms_aspsms_sender Kunden mit ASP-SMS-Vertrag (aspsms.ch), die den JSON-Endpoint von ASP nutzen.
dummy Kein Versand, nur Log-Eintrag Test- und DEV-Umgebungen.

Provider-Auswahl

In der config.php:

Config::set('sms_driver', 'email');   // default, rückwärtskompatibel
// oder
Config::set('sms_driver', 'swisscom');
// oder
Config::set('sms_driver', 'aspsms');
// oder
Config::set('sms_driver', 'dummy');   // für Tests / Staging

Konfiguration: Email-SMTP-Gateway (Treiber: email)

Config::set('sms_gateway_mail_domain', 'smsc.admin.ch');
Config::set('sms_gateway_mail_sender', 'info@kunde.ch');
Config::set('sms_ausloeser_username', 'admin');
Config::set('sms_versand_iso_encoding', true);   // Body nach ISO-8859-1 encoden

Bemerkungen:

Konfiguration: Swisscom REST-API (Treiber: swisscom)

Implementation gemäss Swisscom Benutzerhandbuch "Web to SMS" (Stand September 2025). Der SMS-Versand erfolgt via HTTPS-POST an die Swisscom Web-to-SMS REST-Schnittstelle. Die Authentifizierung erfolgt per API-Key im HTTP-Header HTTP_X_APIKEY.

Mindestens erforderlich ist der API-Key (Pflichtfeld). Alle anderen Werte haben sinnvolle Defaults gemäss Swisscom-Spezifikation.

Config::set('sms_driver', 'swisscom');

// Pflicht: API-Key aus dem SMMS-Portal
Config::set('sms_swisscom_api_key', '<api-key-aus-smms-portal>');

// Optional mit Default-Werten:
Config::set('sms_swisscom_api_url', 'https://web2sms.swisscom.com/v8/api/rest/sms');  // default
Config::set('sms_swisscom_sender', '<originator: 1-16 numerisch oder 1-11 alphanumerisch>');
Config::set('sms_swisscom_max_msg_parts', 5);          // 1-9, default 5
Config::set('sms_swisscom_validity_minutes', 720);     // 1-10080, default 720 (12h)
Konfigurationswert Typ Default Bedeutung
sms_swisscom_api_key string Pflicht. API-Key aus dem SMMS-Portal. Wird im HTTP-Header HTTP_X_APIKEY übermittelt.
sms_swisscom_api_url string https://web2sms.swisscom.com/v8/api/rest/sms REST-Endpoint. In der Regel nicht ändern.
sms_swisscom_sender string Originator gemäss Swisscom-Vertrag. Wird im JSON-Feld smsorig übermittelt.
sms_swisscom_max_msg_parts int 5 Maximale Anzahl SMS-Splits (1-9). Bei Überschreiten wird der Text abgeschnitten.
sms_swisscom_validity_minutes int 720 Gültigkeitsdauer der SMS im SMSC in Minuten (1-10080). Nach Ablauf erfolgt ein Nicht-Zustellbericht.

Übermittelte Felder

Pro SMS sendet BISO folgenden JSON-Body an Swisscom:

{
  "recipient": "+41790001122",
  "msg": "<SMS-Body, UTF-8, max. 1377 Zeichen>",
  "smsorig": "<aus sms_swisscom_sender oder Berater-Absender>",
  "maxMsgParts": 5,
  "validity": 720
}

BISO normalisiert Empfänger-Nummern aus dem internen 0041…-Format ins internationale E.164-Format +41…, wie es die Swisscom-API verlangt.

HTTP-Antworten

Hinweis: Delivery Reports (Zustellbestätigungen) und SMS-Antworten werden von Swisscom asynchron an einen im SMMS-Portal konfigurierten Antwortkanal (URL oder E-Mail) zugestellt. BISO konsumiert diese in dieser Version nicht.

Konfiguration: ASP SMS JSON-API (Treiber: aspsms)

Implementation gemäss ASPSMS JSON-API. Der SMS-Versand erfolgt via HTTPS-POST an den Endpoint /SendSimpleTextSMS. Authentifizierung und alle SMS-Parameter werden als JSON-Body übermittelt (kein Query-String).

Erforderlich sind Userkey und Password (Pflicht). Der Originator (Sender) ist optional und fällt auf BISO zurück, falls nicht gesetzt.

Config::set('sms_driver', 'aspsms');

// Pflicht: API-Credentials aus dem ASP-Konto
Config::set('sms_aspsms_userkey', '<userkey-aus-aspsms-konto>');
Config::set('sms_aspsms_password', '<password-aus-aspsms-konto>');

// Optional mit Default-Werten:
Config::set('sms_aspsms_api_url', 'https://json.aspsms.com');  // Basis-URL; default
Config::set('sms_aspsms_sender', '<originator: numeric oder alphanumeric, max. 11 Zeichen>');  // default: 'BISO'
Konfigurationswert Typ Default Bedeutung
sms_aspsms_userkey string Pflicht. API-Userkey aus dem ASP-Konto. Wird als JSON-Feld UserName übermittelt.
sms_aspsms_password string Pflicht. API-Password aus dem ASP-Konto. Wird als JSON-Feld Password übermittelt.
sms_aspsms_api_url string https://json.aspsms.com Basis-URL der ASP JSON-API. An diese URL wird der Suffix /SendSimpleTextSMS angehängt. In der Regel nicht ändern (z.B. für Test-Mandanten möglich).
sms_aspsms_sender string BISO Originator des SMS (Absender-Kennung). Numeric oder alphanumeric, max. 11 Zeichen. Wird als JSON-Feld Originator übermittelt.

Übermittelte Felder

Pro SMS sendet BISO folgenden POST-Request an ASP:

POST https://json.aspsms.com/SendSimpleTextSMS
Content-Type: application/json; charset=utf-8

{
  "UserName": "...",
  "Password": "...",
  "Originator": "BISO",
  "Recipients": ["+41790001122"],
  "MessageText": "..."
}
JSON-Feld Typ Wertebereich Bedeutung
UserName string API-Userkey (Pflicht).
Password string API-Password (Pflicht).
Originator string numeric oder alphanumeric, max. 11 Zeichen Absender-Kennung. Default: BISO.
Recipients string[] E.164-Format +41790001122 Empfänger-Mobilnummern als JSON-Array. BISO sendet je Nummer einen Request mit einem Array-Element und normalisiert Nummern aus Person::getMobileNumbers() ins E.164-Format +41….
MessageText string UTF-8 SMS-Body (UTF-8).

BISO normalisiert Empfänger-Nummern aus dem internen 0041… oder 079…-Format ins E.164-Format +41790001122, wie es die ASP JSON-API-Beispiele zeigen.

HTTP-Antworten

Erfolg wird ausschliesslich über den HTTP-Status ermittelt. Der JSON-Body der Antwort ({"StatusCode": …, "StatusInfo": …}) wird nicht ausgewertet.

Konfiguration: Dummy-Treiber (Treiber: dummy)

Config::set('sms_driver', 'dummy');

Keine zusätzliche Konfiguration erforderlich. Der Versand wird vollständig im Logger-Kanal sms protokolliert; es findet kein externer HTTP- oder Mail-Versand statt.

SMS-Erinnerung

SMS-Erinnerungen sind ein Spezialfall innerhalb der SMS-Konfiguration: sie werden zeitgesteuert vor einem Termin an die Kunden-Mobilnummer versendet.

Erinnerungs-Vorlagen

Folgende Parameter (Admin > Parameter) sind im Admin-Panel verfügbar:

Parameter Bezeichnung Bedeutung
sms_versand Mit Termin-SMS Termin-SMS Modul ein/aus
sms_notification_time Erinnerungs-Distanz in Stunden Definiert die zeitliche Distanz vor dem Termin, in der eine SMS-Erinnerung ausgelöst wird
sms_versand_manuell manuell Auslösen SMS kann über die Termin-Oberfläche manuell ausgelöst werden
sms_text_max_length SMS-Text Maximallänge Frontend-Textarea-Max-Länge (z.B. 160 Zeichen für 1 SMS). Default deaktiviert.
mit_sms_suppression SMS-Suppression aktivieren Aktiviert die Suppression via Treffpunkt und Besprechungsart (Default: false).
SMS-Texte

Die SMS-Texte selbst sind keine Parameter mehr, sondern Briefvorlagen vom Typ SMS (Werteliste > Briefvorlagen > Neu > SMS-Vorlage). Damit lassen sich pro Anwendungsfall mehrere Vorlagen führen und über Filterkriterien (Sprache, Alter, Kostenpflicht, Beratungsart, Fall-Typen, Regionalstellen) unterscheiden.

Jede SMS-Vorlage hat einen SMS-Typ (Spalte brief_typ, dieselbe wie bei Brief-Vorlagen):

SMS-Typ Verwendung
sms_termin Termin-Erinnerung (Cron-Job und manueller Versand am BF-Termin)
sms_workshop Erinnerung an Gruppentest-/Workshop-Termine
sms_brief_info Info-SMS bei Brieferstellung (Checkbox im Dokument-Versand)

Beim Versand wird die Vorlage gewählt, deren gesetzte Filter alle zutreffen. Treffen mehrere Vorlagen zu, gewinnt die spezifischste (die meisten zutreffenden Kriterien); es wird immer nur eine SMS verschickt. Haben zwei Vorlagen gleich viele Treffer, gewinnt die mit passendem Sprachfilter — so bekommt niemand einen Text in der falschen Sprache. Am besten kombiniert man überlappende Kriterien direkt in einer Vorlage (z. B. Regionalstelle und Sprache), dann ist die Auswahl eindeutig. Eine Vorlage ganz ohne Filter dient als Default. Gibt es keine passende Vorlage, wird keine SMS versendet und der Fehler im SMS-Log vermerkt.

Die Sprache wird nicht an der Vorlage eingestellt: eine SMS wird immer in der Sprache des Empfängers gerendert (Beratungssprache des Kunden, ersatzweise die des Beraters, sonst Deutsch) — also in derselben, gegen die auch der Sprachfilter prüft. Das wirkt sich auf Wochentags- und Monatsnamen (%A, %B) und auf die Anrede-Platzhalter aus. Für einen eigenen französischen Text legt man eine zweite Vorlage mit dem Sprachfilter "Kunde spricht Französisch" an.

Als Platzhalter steht derselbe Smarty-Umfang wie bei Email-Vorlagen zur Verfügung ({$kunde.*}, {$berater.*}, {$termin.*}, {$institution.*}, {$treffpunkt.*}, {$beratungsfall.*}, {$anrede.*}, {$mentor.*}, bei Workshops zusätzlich {$workshop_plan.*}). Im Formular fügen Auswahlboxen die Platzhalter an der Cursorposition ein.

Die früheren Parameter sms_versand_termin_vorlage[_fr], sms_versand_workshop_vorlage[_fr] und sms_versand_einladungsbrief_vorlage[_fr] wurden per DB-Migration in solche Vorlagen überführt. Die _fr-Variante wurde dabei zu einer Vorlage mit dem Sprachfilter "Kunde spricht Französisch", die deutsche zur filterlosen Default-Vorlage.

Die alten param-Zeilen bleiben vorerst als Backup in der Datenbank, werden aber nicht mehr gelesen und sind im Parameter-Formular nicht mehr sichtbar. Änderungen daran haben keine Wirkung — massgebend ist ausschliesslich die Vorlage.

Cron-Job für Erinnerungs-Versand

Damit die Termin-SMS an den konfigurierten Transport gesendet werden, muss in regelmässigen Abständen das CLI-Command biso-cli termin-sms --do-it ausgeführt werden.

Beispiel Linux Crontab:

0 *    * * *   www-data    /usr/bin/php /var/www/biso/webroot/biso-cli termin-sms --do-it

Alternativ kann der SmsReminderTasks-Crunz-Scheduler aktiviert werden (siehe webroot/backend/scheduler/tasks/SmsReminderTasks.php). Dieser ruft denselben CLI-Befehl stündlich auf.

Für Testversand in DEV/Staging empfiehlt sich sms_driver = 'dummy' (siehe oben).

SMS-Unterdrückung (Suppression)

(siehe oben, Parameter mit_sms_suppression).

Für Termine, bei denen kein SMS-Versand erwünscht ist, kann die Suppression pro Treffpunkt oder Besprechungsart aktiviert werden.

Zusätzlich existieren zwei Tabellen-Felder, die das Verhalten steuern:

Die Suppression gilt sowohl für die automatische Termin-Erinnerung als auch für die manuelle Auslösung über die Termin-Oberfläche. Im Brief-Info-SMS-Flow (sendBriefInfo) wird bei aktiver Suppression der Versand still übersprungen.

Logging

SMS-Versand-Ereignisse werden im separaten Logger-Kanal sms protokolliert. Die Logs landen im konfigurierten sms-Logger:

// config.php (siehe system_config.php für Defaults):
Config::set('LOGGING', [
    'sms' => [
        'type'    => 'file',
        'level'   => 'DEBUG',
        'console' => 'output',
        'logfile' => Config::get('tmpdir') . '/biso-sms.log',
    ],
]);

Nachbefragungs-Emails

Nach Fallabschluss können Fälle mit einem Nachbefragungs-Email beliefert werden. Dazu sind folgende Voraussetzungen notwendig:

Die Nachbefragung wird via Cron-Job z.B. täglich angestossen:

$ php webroot/biso-cli send-nachbefragung

Konfiguration

Folgende Konfigurationen sind für die Nachbefragung relevant:

Kunden-Spezialconfigs

Logging

Der Nachbefragungs-CLI-Job loggt seinen Output in ein separates Logging-Target:

SendNachbefragung

Die Logs können somit in ein eigenes Logfile oder auf die Konsole geleitet werden:

// config.php:
Config::set('LOGGING', [
    'SendNachbefragung' => [
        'type' => Logger::TYPE_CONSOLE,
        'level' => Logger::DEBUG,
    ]
]);

DB-Log-System

SQL

Das Log-System setzt eine zweite Datenbank mit der Tabelle Log voraus.

CREATE DATABASE biso_log
    WITH
    OWNER = bisoadm
    ENCODING = 'UTF8'
    LC_COLLATE = 'de_CH.utf8'
    LC_CTYPE = 'de_CH.utf8'
    TABLESPACE = pg_default
    CONNECTION LIMIT = -1

CREATE TABLE IF NOT EXISTS log
(
    id serial NOT NULL,
    logtime timestamp,
    context text,
    benutzer text,
    action text,
    record_id int,
    record text ,
    CONSTRAINT log_pkey PRIMARY KEY (id)
)

config.php

In der config.php muss man eine zweite DB-Connection log eintragen, und das Log-System für Schreiben (LOG_STORE) und Löschen (LOG_DESTROY) aktivieren:

Config::set('gaia.db',[
    'main' => [ /* .... */],
    'log' => [
        'driver' => 'pdo_pgsql',
        'dbname' => 'biso_log',
        'host' => 'db',
        'port' => 5432,
        'user' => 'xxxxxx',
        'password' => 'yyyyy',
        'schema' => 'biso'
    ],
])

Config::set('LOG_STORE', false);
Config::set('LOG_DESTROY', true);

Task-Queue (Queue Runner)

Siehe Background-Task-System für die vollständige Dokumentation.

Die Task-Queue wird durch den biso-Scheduler ausgeführt. Die Anzahl parallel laufender Worker ist konfigurierbar:

// config.php:
Config::set('crunz.scheduler.queue.workers', 3);

So werden bis zu 3 Worker-Prozesse pro Minute gestartet. Läuft ein Worker noch, verhindert preventOverlapping() eine zweite Instanz desselben Workers.

Monitoring (Health-Check)

BISO stellt eine anonyme HTTP-Route zur Verfügung, die von Monitoring-Tools (z.B. Docker, Kubernetes, Prometheus-Blackbox-Exporter, Nagios, Uptime-Kuma) periodisch aufgerufen werden kann, um die Verfügbarkeit der Applikation zu prüfen.

Route

GET /backend/status

Prüfungen

Die Route führt zwei Prüfungen gegen die in config.php unter gaia.db.main konfigurierte Datenbankverbindung aus:

  1. Die DB-Verbindung kann aufgebaut werden.
  2. Ein einfacher SELECT count(*) FROM param kann ausgeführt werden.

Schlagen eine oder beide Prüfungen fehl, liefert die Route HTTP 503 Service Unavailable.

Antwort

Bei erfolgreicher Prüfung (HTTP 200 OK):

BISO-Status: OK
DB connection to <dbname>: OK

Dabei ist <dbname> der in config.php konfigurierte dbname der main-Verbindung (z.B. bisodev in der lokalen Dev-Umgebung).

Bei Fehler (HTTP 503 Service Unavailable) wird OK durch ERROR ersetzt:

BISO-Status: ERROR
DB connection to <dbname>: ERROR

Verwendung mit Docker Compose

Die mitgelieferte docker-compose.yml definiert für die Services web85 und web83 einen healthcheck, der die Route alle 10 Sekunden aufruft:

healthcheck:
    test: ["CMD-SHELL", "curl -fsS http://localhost/backend/status || exit 1"]
    interval: 10s
    timeout: 5s
    retries: 3
    start_period: 30s

Der Status eines Containers lässt sich dann z.B. so abfragen:

docker compose ps
docker inspect --format '{{json .State.Health}}' <container>

Verwendung mit externen Monitoring-Tools

Externe Tools sprechen die Route über die öffentliche URL der BISO-Installation an, also z.B. https://biso.example.com/backend/status. Erwartet wird HTTP 200; jeder andere Statuscode (insbesondere 503) signalisiert "nicht verfügbar".

Kurze Tests von der Kommandozeile:

# Status und Body inspizieren
curl -i https://biso.example.com/backend/status

# Nur den HTTP-Statuscode auswerten
curl -fsS -o /dev/null -w "%{http_code}\n" https://biso.example.com/backend/status

Hinweis: Hinter einem Reverse-Proxy / Loadbalancer ist sicherzustellen, dass diese Route nicht durch Auth-Layer (z.B. OIDC-Redirect) blockiert wird. Der Proxy muss GET /backend/status ohne Auth-Requirement an den BISO-Web-Container weiterleiten.

OIDC / Single-Sign-On (Benutzer-Auto-Provisionierung)

Die Konfiguration des OIDC-Logins (Apache mod_auth_openidc, oidc.auto_provision, oidc.sync_existing, oidc.userinfo_endpoint, oidc.roles_claim, Log-Kanal) ist beschrieben unter OIDC Auto-Provisionierung. Die kundenspezifische Genfer Konfiguration (GINA, ID-Mapping oidc.ge.*) siehe Kanton Genf: OIDC/GINA-Benutzerprovisionierung.