2026-02-04 23:31:53 +01:00
-- Consolidated schema (fresh install)
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
-- Generated: 2026-02-19
-- Includes all current tables, columns, indexes and seed data.
2026-02-04 23:31:53 +01:00
CREATE TABLE IF NOT EXISTS ` users ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` uuid ` CHAR ( 36 ) NOT NULL ,
` first_name ` VARCHAR ( 100 ) NOT NULL ,
` last_name ` VARCHAR ( 100 ) NOT NULL ,
2026-02-11 19:28:12 +01:00
` display_name ` VARCHAR ( 210 ) NOT NULL ,
2026-02-04 23:31:53 +01:00
` email ` VARCHAR ( 255 ) NOT NULL ,
` profile_description ` TEXT NULL ,
` job_title ` VARCHAR ( 160 ) NULL ,
` phone ` VARCHAR ( 50 ) NULL ,
` mobile ` VARCHAR ( 50 ) NULL ,
` short_dial ` VARCHAR ( 20 ) NULL ,
` address ` VARCHAR ( 255 ) NULL ,
` postal_code ` VARCHAR ( 20 ) NULL ,
` city ` VARCHAR ( 100 ) NULL ,
` country ` VARCHAR ( 100 ) NULL ,
` region ` VARCHAR ( 100 ) NULL ,
` hire_date ` DATE NULL ,
` email_verified_at ` DATETIME NULL DEFAULT NULL ,
2026-02-11 19:28:12 +01:00
` last_login_at ` DATETIME NULL DEFAULT NULL ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
` last_login_provider ` VARCHAR ( 20 ) NULL DEFAULT NULL ,
2026-02-04 23:31:53 +01:00
` password ` VARCHAR ( 255 ) NOT NULL ,
` locale ` VARCHAR ( 10 ) DEFAULT NULL ,
` totp_secret ` VARCHAR ( 255 ) DEFAULT NULL ,
` theme ` VARCHAR ( 10 ) NOT NULL DEFAULT ' light ' ,
` primary_tenant_id ` INT NULL ,
` current_tenant_id ` INT UNSIGNED NULL ,
` created_by ` INT UNSIGNED DEFAULT NULL ,
` modified_by ` INT UNSIGNED DEFAULT NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
` modified ` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP ,
` active ` TINYINT ( 1 ) NOT NULL DEFAULT 1 ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
` authz_version ` INT UNSIGNED NOT NULL DEFAULT 1 ,
2026-02-04 23:31:53 +01:00
` active_changed_at ` DATETIME NULL DEFAULT NULL ,
` active_changed_by ` INT UNSIGNED DEFAULT NULL ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_users_uuid ` ( ` uuid ` ) ,
UNIQUE KEY ` uniq_users_email ` ( ` email ` ) ,
KEY ` idx_users_primary_tenant_id ` ( ` primary_tenant_id ` ) ,
KEY ` idx_users_current_tenant_id ` ( ` current_tenant_id ` ) ,
KEY ` idx_users_created_by ` ( ` created_by ` ) ,
KEY ` idx_users_modified_by ` ( ` modified_by ` ) ,
KEY ` idx_users_active_changed_by ` ( ` active_changed_by ` ) ,
CONSTRAINT ` fk_users_created_by ` FOREIGN KEY ( ` created_by ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL ,
CONSTRAINT ` fk_users_modified_by ` FOREIGN KEY ( ` modified_by ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL ,
2026-03-11 20:14:04 +01:00
CONSTRAINT ` fk_users_active_changed_by ` FOREIGN KEY ( ` active_changed_by ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL
2026-02-04 23:31:53 +01:00
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` tenants ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` uuid ` CHAR ( 36 ) NOT NULL ,
` description ` VARCHAR ( 255 ) NOT NULL ,
` address ` VARCHAR ( 255 ) NULL ,
` postal_code ` VARCHAR ( 20 ) NULL ,
` city ` VARCHAR ( 100 ) NULL ,
` country ` VARCHAR ( 100 ) NULL ,
` region ` VARCHAR ( 100 ) NULL ,
` vat_id ` VARCHAR ( 50 ) NULL ,
` tax_number ` VARCHAR ( 50 ) NULL ,
` phone ` VARCHAR ( 50 ) NULL ,
` fax ` VARCHAR ( 100 ) NULL ,
` email ` VARCHAR ( 190 ) NULL ,
` support_email ` VARCHAR ( 190 ) NULL ,
` support_phone ` VARCHAR ( 50 ) NULL ,
` billing_email ` VARCHAR ( 190 ) NULL ,
` website ` VARCHAR ( 255 ) NULL ,
` privacy_url ` VARCHAR ( 255 ) NULL ,
` imprint_url ` VARCHAR ( 255 ) NULL ,
` primary_color ` VARCHAR ( 7 ) NULL ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
` default_theme ` VARCHAR ( 32 ) NULL ,
` allow_user_theme ` TINYINT ( 1 ) NULL ,
2026-02-04 23:31:53 +01:00
` status ` VARCHAR ( 20 ) NOT NULL DEFAULT ' active ' ,
` status_changed_at ` DATETIME NULL DEFAULT NULL ,
` status_changed_by ` INT UNSIGNED DEFAULT NULL ,
` created_by ` INT UNSIGNED DEFAULT NULL ,
` modified_by ` INT UNSIGNED DEFAULT NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
` modified ` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_tenants_uuid ` ( ` uuid ` ) ,
KEY ` idx_tenants_created_by ` ( ` created_by ` ) ,
KEY ` idx_tenants_modified_by ` ( ` modified_by ` ) ,
KEY ` idx_tenants_status_changed_by ` ( ` status_changed_by ` ) ,
2026-03-04 15:56:58 +01:00
CONSTRAINT ` chk_tenants_status ` CHECK ( ` status ` IN ( ' active ' , ' inactive ' ) ) ,
2026-02-04 23:31:53 +01:00
CONSTRAINT ` fk_tenants_created_by ` FOREIGN KEY ( ` created_by ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL ,
CONSTRAINT ` fk_tenants_modified_by ` FOREIGN KEY ( ` modified_by ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL ,
CONSTRAINT ` fk_tenants_status_changed_by ` FOREIGN KEY ( ` status_changed_by ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
2026-03-11 20:16:45 +01:00
SET @ fk_users_current_tenant_exists = (
SELECT COUNT ( * )
FROM information_schema . TABLE_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = DATABASE ( )
AND TABLE_NAME = ' users '
AND CONSTRAINT_NAME = ' fk_users_current_tenant '
AND CONSTRAINT_TYPE = ' FOREIGN KEY '
) ;
SET @ sql_add_fk_users_current_tenant = IF (
@ fk_users_current_tenant_exists = 0 ,
' ALTER TABLE `users` ADD CONSTRAINT `fk_users_current_tenant` FOREIGN KEY (`current_tenant_id`) REFERENCES `tenants` (`id`) ON DELETE SET NULL ' ,
' SELECT 1 '
) ;
PREPARE stmt_add_fk_users_current_tenant FROM @ sql_add_fk_users_current_tenant ;
EXECUTE stmt_add_fk_users_current_tenant ;
DEALLOCATE PREPARE stmt_add_fk_users_current_tenant ;
2026-03-11 20:14:04 +01:00
2026-02-04 23:31:53 +01:00
CREATE TABLE IF NOT EXISTS ` roles ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` uuid ` CHAR ( 36 ) NOT NULL ,
` description ` VARCHAR ( 255 ) NOT NULL ,
2026-02-11 19:28:12 +01:00
` code ` VARCHAR ( 50 ) DEFAULT NULL ,
` active ` TINYINT ( 1 ) NOT NULL DEFAULT 1 ,
2026-02-04 23:31:53 +01:00
` created_by ` INT UNSIGNED DEFAULT NULL ,
` modified_by ` INT UNSIGNED DEFAULT NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
` modified ` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_roles_uuid ` ( ` uuid ` ) ,
2026-02-11 19:28:12 +01:00
UNIQUE KEY ` uniq_roles_code ` ( ` code ` ) ,
KEY ` idx_roles_active ` ( ` active ` ) ,
2026-02-04 23:31:53 +01:00
KEY ` idx_roles_created_by ` ( ` created_by ` ) ,
KEY ` idx_roles_modified_by ` ( ` modified_by ` ) ,
CONSTRAINT ` fk_roles_created_by ` FOREIGN KEY ( ` created_by ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL ,
CONSTRAINT ` fk_roles_modified_by ` FOREIGN KEY ( ` modified_by ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` permissions ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` key ` VARCHAR ( 191 ) NOT NULL ,
` description ` VARCHAR ( 255 ) DEFAULT NULL ,
2026-02-11 19:28:12 +01:00
` active ` TINYINT ( 1 ) NOT NULL DEFAULT 1 ,
` is_system ` TINYINT ( 1 ) NOT NULL DEFAULT 0 ,
2026-02-04 23:31:53 +01:00
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
2026-02-11 19:28:12 +01:00
UNIQUE KEY ` uniq_permissions_key ` ( ` key ` ) ,
KEY ` idx_permissions_active ` ( ` active ` ) ,
KEY ` idx_permissions_system ` ( ` is_system ` )
2026-02-04 23:31:53 +01:00
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` departments ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` uuid ` CHAR ( 36 ) NOT NULL ,
` description ` VARCHAR ( 255 ) NOT NULL ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
` tenant_id ` INT UNSIGNED NOT NULL ,
2026-02-11 19:28:12 +01:00
` code ` VARCHAR ( 50 ) DEFAULT NULL ,
` cost_center ` VARCHAR ( 50 ) DEFAULT NULL ,
` active ` TINYINT ( 1 ) NOT NULL DEFAULT 1 ,
2026-02-04 23:31:53 +01:00
` created_by ` INT UNSIGNED DEFAULT NULL ,
` modified_by ` INT UNSIGNED DEFAULT NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
` modified ` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_departments_uuid ` ( ` uuid ` ) ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
KEY ` idx_departments_tenant ` ( ` tenant_id ` ) ,
2026-02-11 19:28:12 +01:00
KEY ` idx_departments_active ` ( ` active ` ) ,
2026-02-04 23:31:53 +01:00
KEY ` idx_departments_created_by ` ( ` created_by ` ) ,
KEY ` idx_departments_modified_by ` ( ` modified_by ` ) ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
CONSTRAINT ` fk_departments_tenant ` FOREIGN KEY ( ` tenant_id ` ) REFERENCES ` tenants ` ( ` id ` ) ON DELETE RESTRICT ,
2026-02-04 23:31:53 +01:00
CONSTRAINT ` fk_departments_created_by ` FOREIGN KEY ( ` created_by ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL ,
CONSTRAINT ` fk_departments_modified_by ` FOREIGN KEY ( ` modified_by ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` pages ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` uuid ` CHAR ( 36 ) NOT NULL ,
` slug ` VARCHAR ( 190 ) NOT NULL ,
` created_by ` INT UNSIGNED NULL ,
` modified_by ` INT UNSIGNED NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
` modified ` DATETIME NULL DEFAULT NULL ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_pages_uuid ` ( ` uuid ` ) ,
UNIQUE KEY ` uniq_pages_slug ` ( ` slug ` ) ,
KEY ` idx_pages_created_by ` ( ` created_by ` ) ,
KEY ` idx_pages_modified_by ` ( ` modified_by ` ) ,
CONSTRAINT ` fk_pages_created_by ` FOREIGN KEY ( ` created_by ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL ,
CONSTRAINT ` fk_pages_modified_by ` FOREIGN KEY ( ` modified_by ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` page_contents ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` page_id ` INT UNSIGNED NOT NULL ,
` locale ` VARCHAR ( 10 ) NOT NULL ,
` content ` LONGTEXT NULL ,
` created_by ` INT UNSIGNED NULL ,
` modified_by ` INT UNSIGNED NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
` modified ` DATETIME NULL DEFAULT NULL ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_page_locale ` ( ` page_id ` , ` locale ` ) ,
KEY ` idx_page_id ` ( ` page_id ` ) ,
KEY ` idx_page_contents_created_by ` ( ` created_by ` ) ,
KEY ` idx_page_contents_modified_by ` ( ` modified_by ` ) ,
CONSTRAINT ` fk_page_contents_page ` FOREIGN KEY ( ` page_id ` ) REFERENCES ` pages ` ( ` id ` ) ON DELETE CASCADE ,
CONSTRAINT ` fk_page_contents_created_by ` FOREIGN KEY ( ` created_by ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL ,
CONSTRAINT ` fk_page_contents_modified_by ` FOREIGN KEY ( ` modified_by ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` settings ` (
` key ` VARCHAR ( 64 ) NOT NULL ,
` value ` TEXT NULL ,
` description ` VARCHAR ( 255 ) NULL ,
` updated_at ` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` key ` )
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci ;
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
CREATE TABLE IF NOT EXISTS ` tenant_auth_microsoft ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` tenant_id ` INT UNSIGNED NOT NULL ,
` enabled ` TINYINT ( 1 ) NOT NULL DEFAULT 0 ,
` enforce_microsoft_login ` TINYINT ( 1 ) NOT NULL DEFAULT 0 ,
` sync_profile_on_login ` TINYINT ( 1 ) NOT NULL DEFAULT 0 ,
` sync_profile_fields ` TEXT NULL ,
` entra_tenant_id ` VARCHAR ( 64 ) NULL ,
` allowed_domains ` TEXT NULL ,
` use_shared_app ` TINYINT ( 1 ) NOT NULL DEFAULT 1 ,
` client_id_override ` VARCHAR ( 191 ) NULL ,
` client_secret_override_enc ` TEXT NULL ,
2026-03-10 22:48:10 +01:00
` auto_remember_mode ` TINYINT ( 1 ) NULL DEFAULT NULL ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
` modified ` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_tenant_auth_microsoft_tenant ` ( ` tenant_id ` ) ,
CONSTRAINT ` fk_tenant_auth_microsoft_tenant ` FOREIGN KEY ( ` tenant_id ` ) REFERENCES ` tenants ` ( ` id ` ) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
2026-03-25 07:26:04 +01:00
CREATE TABLE IF NOT EXISTS ` tenant_auth_ldap ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` tenant_id ` INT UNSIGNED NOT NULL ,
` enabled ` TINYINT ( 1 ) NOT NULL DEFAULT 0 ,
` enforce_ldap_login ` TINYINT ( 1 ) NOT NULL DEFAULT 0 ,
` host ` VARCHAR ( 255 ) NOT NULL DEFAULT ' ' ,
` port ` INT UNSIGNED NOT NULL DEFAULT 389 ,
` encryption_mode ` ENUM ( ' none ' , ' starttls ' , ' ldaps ' ) NOT NULL DEFAULT ' starttls ' ,
` verify_tls_certificate ` TINYINT ( 1 ) NOT NULL DEFAULT 1 ,
` base_dn ` VARCHAR ( 500 ) NOT NULL DEFAULT ' ' ,
` bind_dn_enc ` TEXT NULL ,
` bind_password_enc ` TEXT NULL ,
` user_search_filter ` VARCHAR ( 500 ) NOT NULL DEFAULT ' (&(objectClass=user)(sAMAccountName=%s)) ' ,
` user_search_scope ` ENUM ( ' sub ' , ' one ' ) NOT NULL DEFAULT ' sub ' ,
` bind_method ` ENUM ( ' search_then_bind ' , ' direct_bind ' ) NOT NULL DEFAULT ' search_then_bind ' ,
` bind_username_format ` VARCHAR ( 255 ) NULL ,
` unique_id_attribute ` VARCHAR ( 64 ) NOT NULL DEFAULT ' objectGUID ' ,
` attribute_map ` JSON NOT NULL DEFAULT ' {"first_name":"givenName","last_name":"sn","email":"mail","phone":"telephoneNumber","mobile":"mobile"} ' ,
` sync_profile_on_login ` TINYINT ( 1 ) NOT NULL DEFAULT 0 ,
` sync_profile_fields ` TEXT NULL ,
` allowed_domains ` TEXT NULL ,
` auto_remember_mode ` TINYINT ( 1 ) NULL DEFAULT NULL ,
` network_timeout ` INT UNSIGNED NOT NULL DEFAULT 5 ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
` modified ` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_tenant_auth_ldap_tenant ` ( ` tenant_id ` ) ,
CONSTRAINT ` fk_tenant_auth_ldap_tenant ` FOREIGN KEY ( ` tenant_id ` ) REFERENCES ` tenants ` ( ` id ` ) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
CREATE TABLE IF NOT EXISTS ` user_external_identities ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` user_id ` INT UNSIGNED NOT NULL ,
` provider ` VARCHAR ( 32 ) NOT NULL ,
` oid ` VARCHAR ( 128 ) NOT NULL ,
` tid ` VARCHAR ( 64 ) NOT NULL ,
` issuer ` VARCHAR ( 255 ) NOT NULL ,
` subject ` VARCHAR ( 255 ) NOT NULL ,
` email_at_link_time ` VARCHAR ( 255 ) NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_user_external_provider_tid_oid ` ( ` provider ` , ` tid ` , ` oid ` ) ,
UNIQUE KEY ` uniq_user_external_provider_iss_sub ` ( ` provider ` , ` issuer ` , ` subject ` ) ,
KEY ` idx_user_external_user ` ( ` user_id ` ) ,
CONSTRAINT ` fk_user_external_identity_user ` FOREIGN KEY ( ` user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
2026-02-04 23:31:53 +01:00
CREATE TABLE IF NOT EXISTS ` user_tenants ` (
` user_id ` INT UNSIGNED NOT NULL ,
` tenant_id ` INT UNSIGNED NOT NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` user_id ` , ` tenant_id ` ) ,
KEY ` idx_user_tenants_user ` ( ` user_id ` ) ,
KEY ` idx_user_tenants_tenant ` ( ` tenant_id ` ) ,
CONSTRAINT ` fk_user_tenants_user ` FOREIGN KEY ( ` user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE CASCADE ,
CONSTRAINT ` fk_user_tenants_tenant ` FOREIGN KEY ( ` tenant_id ` ) REFERENCES ` tenants ` ( ` id ` ) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` user_roles ` (
` user_id ` INT UNSIGNED NOT NULL ,
` role_id ` INT UNSIGNED NOT NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` user_id ` , ` role_id ` ) ,
KEY ` idx_user_roles_user ` ( ` user_id ` ) ,
KEY ` idx_user_roles_role ` ( ` role_id ` ) ,
CONSTRAINT ` fk_user_roles_user ` FOREIGN KEY ( ` user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE CASCADE ,
CONSTRAINT ` fk_user_roles_role ` FOREIGN KEY ( ` role_id ` ) REFERENCES ` roles ` ( ` id ` ) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` role_permissions ` (
` role_id ` INT UNSIGNED NOT NULL ,
` permission_id ` INT UNSIGNED NOT NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` role_id ` , ` permission_id ` ) ,
KEY ` idx_role_permissions_permission ` ( ` permission_id ` ) ,
CONSTRAINT ` fk_role_permissions_role ` FOREIGN KEY ( ` role_id ` ) REFERENCES ` roles ` ( ` id ` ) ON DELETE CASCADE ,
CONSTRAINT ` fk_role_permissions_permission ` FOREIGN KEY ( ` permission_id ` ) REFERENCES ` permissions ` ( ` id ` ) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
2026-03-13 21:11:48 +01:00
CREATE TABLE IF NOT EXISTS ` role_assignable_roles ` (
` role_id ` INT UNSIGNED NOT NULL ,
` assignable_role_id ` INT UNSIGNED NOT NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` role_id ` , ` assignable_role_id ` ) ,
KEY ` idx_rar_assignable ` ( ` assignable_role_id ` ) ,
CONSTRAINT ` fk_rar_role ` FOREIGN KEY ( ` role_id ` ) REFERENCES ` roles ` ( ` id ` ) ON DELETE CASCADE ,
CONSTRAINT ` fk_rar_assignable ` FOREIGN KEY ( ` assignable_role_id ` ) REFERENCES ` roles ` ( ` id ` ) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
2026-02-04 23:31:53 +01:00
CREATE TABLE IF NOT EXISTS ` user_departments ` (
` user_id ` INT UNSIGNED NOT NULL ,
` department_id ` INT UNSIGNED NOT NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` user_id ` , ` department_id ` ) ,
KEY ` idx_user_departments_user ` ( ` user_id ` ) ,
KEY ` idx_user_departments_department ` ( ` department_id ` ) ,
CONSTRAINT ` fk_user_departments_user ` FOREIGN KEY ( ` user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE CASCADE ,
CONSTRAINT ` fk_user_departments_department ` FOREIGN KEY ( ` department_id ` ) REFERENCES ` departments ` ( ` id ` ) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
2026-03-14 21:45:58 +01:00
CREATE TABLE IF NOT EXISTS ` user_bookmark_groups ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` user_id ` INT UNSIGNED NOT NULL ,
` name ` VARCHAR ( 100 ) NOT NULL ,
` icon ` VARCHAR ( 40 ) NOT NULL DEFAULT ' bi-folder ' ,
` sort_order ` SMALLINT UNSIGNED NOT NULL DEFAULT 0 ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
` modified ` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
KEY ` idx_ubg_user_sort ` ( ` user_id ` , ` sort_order ` ) ,
CONSTRAINT ` fk_ubg_user ` FOREIGN KEY ( ` user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` user_bookmarks ` (
2026-02-04 23:31:53 +01:00
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
` user_id ` INT UNSIGNED NOT NULL ,
2026-03-14 21:45:58 +01:00
` group_id ` INT UNSIGNED NULL ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
` name ` VARCHAR ( 120 ) NOT NULL ,
2026-03-14 21:45:58 +01:00
` url ` VARCHAR ( 500 ) NOT NULL ,
` sort_order ` SMALLINT UNSIGNED NOT NULL DEFAULT 0 ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
` modified ` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
2026-03-14 21:45:58 +01:00
UNIQUE KEY ` uniq_ub_user_url ` ( ` user_id ` , ` url ` ) ,
KEY ` idx_ub_user_sort ` ( ` user_id ` , ` sort_order ` ) ,
KEY ` idx_ub_user_group_sort ` ( ` user_id ` , ` group_id ` , ` sort_order ` ) ,
KEY ` idx_ub_group ` ( ` group_id ` ) ,
CONSTRAINT ` fk_ub_user ` FOREIGN KEY ( ` user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE CASCADE ,
CONSTRAINT ` fk_ub_group ` FOREIGN KEY ( ` group_id ` ) REFERENCES ` user_bookmark_groups ` ( ` id ` ) ON DELETE SET NULL
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
2026-03-19 22:09:44 +01:00
CREATE TABLE IF NOT EXISTS ` user_notifications ` (
` id ` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT ,
` recipient_user_id ` INT UNSIGNED NOT NULL ,
` tenant_id ` INT UNSIGNED NULL ,
` type ` VARCHAR ( 60 ) NOT NULL ,
` title ` VARCHAR ( 255 ) NOT NULL ,
` body ` VARCHAR ( 500 ) NULL ,
` link ` VARCHAR ( 500 ) NULL ,
` data ` JSON NULL ,
2026-03-20 00:05:03 +01:00
` dedupe_fingerprint ` CHAR ( 64 ) NULL ,
` dedupe_bucket ` INT UNSIGNED NULL ,
` dedupe_until ` DATETIME NULL DEFAULT NULL ,
2026-03-19 22:09:44 +01:00
` is_read ` TINYINT ( 1 ) NOT NULL DEFAULT 0 ,
` read_at ` DATETIME NULL DEFAULT NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
KEY ` idx_un_recipient_read_created ` ( ` recipient_user_id ` , ` is_read ` , ` created ` DESC ) ,
KEY ` idx_un_recipient_created ` ( ` recipient_user_id ` , ` created ` DESC ) ,
KEY ` idx_un_tenant_created ` ( ` tenant_id ` , ` created ` DESC ) ,
KEY ` idx_un_cleanup ` ( ` is_read ` , ` read_at ` ) ,
2026-03-20 00:05:03 +01:00
UNIQUE KEY ` uniq_un_dedupe_bucket ` ( ` recipient_user_id ` , ` dedupe_fingerprint ` , ` dedupe_bucket ` ) ,
2026-03-19 22:09:44 +01:00
CONSTRAINT ` fk_un_recipient ` FOREIGN KEY ( ` recipient_user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE CASCADE ,
CONSTRAINT ` fk_un_tenant ` FOREIGN KEY ( ` tenant_id ` ) REFERENCES ` tenants ` ( ` id ` ) ON DELETE SET NULL
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
CREATE TABLE IF NOT EXISTS ` tenant_custom_field_definitions ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` uuid ` CHAR ( 36 ) NOT NULL ,
2026-02-04 23:31:53 +01:00
` tenant_id ` INT UNSIGNED NOT NULL ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
` field_key ` VARCHAR ( 120 ) NOT NULL ,
` label ` VARCHAR ( 160 ) NOT NULL ,
` type ` VARCHAR ( 32 ) NOT NULL ,
` is_required ` TINYINT ( 1 ) NOT NULL DEFAULT 0 ,
` is_filterable ` TINYINT ( 1 ) NOT NULL DEFAULT 0 ,
` active ` TINYINT ( 1 ) NOT NULL DEFAULT 1 ,
` sort_order ` INT NOT NULL DEFAULT 100 ,
` created_by ` INT UNSIGNED DEFAULT NULL ,
` modified_by ` INT UNSIGNED DEFAULT NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
` modified ` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_tenant_custom_field_uuid ` ( ` uuid ` ) ,
UNIQUE KEY ` uniq_tenant_custom_field_key ` ( ` tenant_id ` , ` field_key ` ) ,
KEY ` idx_tenant_custom_field_tenant_active ` ( ` tenant_id ` , ` active ` , ` sort_order ` ) ,
KEY ` idx_tenant_custom_field_created_by ` ( ` created_by ` ) ,
KEY ` idx_tenant_custom_field_modified_by ` ( ` modified_by ` ) ,
CONSTRAINT ` fk_tenant_custom_field_tenant ` FOREIGN KEY ( ` tenant_id ` ) REFERENCES ` tenants ` ( ` id ` ) ON DELETE CASCADE ,
CONSTRAINT ` fk_tenant_custom_field_created_by ` FOREIGN KEY ( ` created_by ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL ,
CONSTRAINT ` fk_tenant_custom_field_modified_by ` FOREIGN KEY ( ` modified_by ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` tenant_custom_field_options ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` definition_id ` INT UNSIGNED NOT NULL ,
` option_key ` VARCHAR ( 120 ) NOT NULL ,
` label ` VARCHAR ( 160 ) NOT NULL ,
` active ` TINYINT ( 1 ) NOT NULL DEFAULT 1 ,
` sort_order ` INT NOT NULL DEFAULT 100 ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
` modified ` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_custom_field_option_key ` ( ` definition_id ` , ` option_key ` ) ,
KEY ` idx_custom_field_option_definition_active ` ( ` definition_id ` , ` active ` , ` sort_order ` ) ,
CONSTRAINT ` fk_custom_field_option_definition ` FOREIGN KEY ( ` definition_id ` ) REFERENCES ` tenant_custom_field_definitions ` ( ` id ` ) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` user_custom_field_values ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` user_id ` INT UNSIGNED NOT NULL ,
` definition_id ` INT UNSIGNED NOT NULL ,
` value_text ` TEXT NULL ,
` value_bool ` TINYINT ( 1 ) NULL ,
` value_date ` DATE NULL ,
` option_id ` INT UNSIGNED NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
` modified ` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_user_custom_field_definition ` ( ` user_id ` , ` definition_id ` ) ,
KEY ` idx_ucfv_definition ` ( ` definition_id ` ) ,
KEY ` idx_ucfv_option ` ( ` option_id ` ) ,
KEY ` idx_ucfv_bool ` ( ` definition_id ` , ` value_bool ` ) ,
KEY ` idx_ucfv_date ` ( ` definition_id ` , ` value_date ` ) ,
CONSTRAINT ` fk_ucfv_user ` FOREIGN KEY ( ` user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE CASCADE ,
CONSTRAINT ` fk_ucfv_definition ` FOREIGN KEY ( ` definition_id ` ) REFERENCES ` tenant_custom_field_definitions ` ( ` id ` ) ON DELETE CASCADE ,
CONSTRAINT ` fk_ucfv_option ` FOREIGN KEY ( ` option_id ` ) REFERENCES ` tenant_custom_field_options ` ( ` id ` ) ON DELETE SET NULL
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` user_custom_field_value_options ` (
` value_id ` INT UNSIGNED NOT NULL ,
` option_id ` INT UNSIGNED NOT NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` value_id ` , ` option_id ` ) ,
KEY ` idx_ucfvo_option ` ( ` option_id ` ) ,
CONSTRAINT ` fk_ucfvo_value ` FOREIGN KEY ( ` value_id ` ) REFERENCES ` user_custom_field_values ` ( ` id ` ) ON DELETE CASCADE ,
CONSTRAINT ` fk_ucfvo_option ` FOREIGN KEY ( ` option_id ` ) REFERENCES ` tenant_custom_field_options ` ( ` id ` ) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
2026-04-02 10:49:35 +02:00
CREATE TABLE IF NOT EXISTS ` module_migrations ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` module_id ` VARCHAR ( 64 ) NOT NULL ,
` filename ` VARCHAR ( 255 ) NOT NULL ,
` applied_at ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uq_module_migration ` ( ` module_id ` , ` filename ` )
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
CREATE TABLE IF NOT EXISTS ` user_api_tokens ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` uuid ` CHAR ( 36 ) NOT NULL ,
` user_id ` INT UNSIGNED NOT NULL ,
` name ` VARCHAR ( 120 ) NOT NULL DEFAULT ' ' ,
` selector ` CHAR ( 24 ) NOT NULL ,
` token_hash ` CHAR ( 64 ) NOT NULL ,
` tenant_id ` INT UNSIGNED NULL COMMENT ' Optional: scope token to specific tenant ' ,
` last_used_at ` DATETIME NULL DEFAULT NULL ,
` last_ip ` VARCHAR ( 45 ) NULL DEFAULT NULL ,
` expires_at ` DATETIME NULL DEFAULT NULL ,
` revoked_at ` DATETIME NULL DEFAULT NULL ,
` created_by ` INT UNSIGNED NULL ,
2026-02-04 23:31:53 +01:00
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
UNIQUE KEY ` uniq_user_api_token_uuid ` ( ` uuid ` ) ,
UNIQUE KEY ` uniq_user_api_token_selector ` ( ` selector ` ) ,
KEY ` idx_user_api_token_user ` ( ` user_id ` ) ,
KEY ` idx_user_api_token_tenant ` ( ` tenant_id ` ) ,
KEY ` idx_user_api_token_expires ` ( ` expires_at ` ) ,
CONSTRAINT ` fk_user_api_token_user ` FOREIGN KEY ( ` user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE CASCADE ,
CONSTRAINT ` fk_user_api_token_tenant ` FOREIGN KEY ( ` tenant_id ` ) REFERENCES ` tenants ` ( ` id ` ) ON DELETE SET NULL ,
CONSTRAINT ` fk_user_api_token_created_by ` FOREIGN KEY ( ` created_by ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL
2026-02-04 23:31:53 +01:00
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` mail_log ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` to_email ` VARCHAR ( 255 ) NOT NULL ,
` subject ` VARCHAR ( 255 ) NOT NULL ,
` template ` VARCHAR ( 100 ) NULL ,
` status ` VARCHAR ( 20 ) NOT NULL DEFAULT ' queued ' ,
` created_at ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
` sent_at ` DATETIME NULL DEFAULT NULL ,
` error_message ` TEXT NULL ,
` provider_message_id ` VARCHAR ( 255 ) NULL ,
PRIMARY KEY ( ` id ` ) ,
KEY ` idx_mail_log_status ` ( ` status ` ) ,
2026-03-04 15:56:58 +01:00
KEY ` idx_mail_log_to_email ` ( ` to_email ` ) ,
CONSTRAINT ` chk_mail_log_status ` CHECK ( ` status ` IN ( ' queued ' , ' sent ' , ' failed ' ) )
2026-02-04 23:31:53 +01:00
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
CREATE TABLE IF NOT EXISTS ` api_audit_log ` (
` id ` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT ,
` request_id ` CHAR ( 36 ) NOT NULL ,
` method ` VARCHAR ( 8 ) NOT NULL ,
` path ` VARCHAR ( 255 ) NOT NULL ,
` query_json ` TEXT NULL ,
` status_code ` SMALLINT UNSIGNED NOT NULL ,
` duration_ms ` INT UNSIGNED NULL ,
` error_code ` VARCHAR ( 100 ) NULL ,
` user_id ` INT UNSIGNED NULL ,
` tenant_id ` INT UNSIGNED NULL ,
` api_token_id ` INT UNSIGNED NULL ,
` token_tenant_id ` INT UNSIGNED NULL ,
` ip ` VARCHAR ( 45 ) NULL ,
` user_agent ` VARCHAR ( 255 ) NULL ,
` created_at ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_api_audit_request_id_created ` ( ` request_id ` , ` created_at ` ) ,
KEY ` idx_api_audit_created ` ( ` created_at ` ) ,
KEY ` idx_api_audit_status_created ` ( ` status_code ` , ` created_at ` ) ,
KEY ` idx_api_audit_user_created ` ( ` user_id ` , ` created_at ` ) ,
KEY ` idx_api_audit_tenant_created ` ( ` tenant_id ` , ` created_at ` ) ,
KEY ` idx_api_audit_path_created ` ( ` path ` , ` created_at ` ) ,
KEY ` idx_api_audit_error_created ` ( ` error_code ` , ` created_at ` ) ,
KEY ` idx_api_audit_token_created ` ( ` api_token_id ` , ` created_at ` ) ,
CONSTRAINT ` fk_api_audit_user ` FOREIGN KEY ( ` user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL ,
CONSTRAINT ` fk_api_audit_tenant ` FOREIGN KEY ( ` tenant_id ` ) REFERENCES ` tenants ` ( ` id ` ) ON DELETE SET NULL ,
CONSTRAINT ` fk_api_audit_token ` FOREIGN KEY ( ` api_token_id ` ) REFERENCES ` user_api_tokens ` ( ` id ` ) ON DELETE SET NULL
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
2026-03-04 15:56:58 +01:00
CREATE TABLE IF NOT EXISTS ` system_audit_log ` (
` id ` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT ,
` event_uuid ` CHAR ( 36 ) NOT NULL ,
` request_id ` CHAR ( 36 ) NULL ,
` channel ` VARCHAR ( 16 ) NOT NULL ,
` event_type ` VARCHAR ( 64 ) NOT NULL ,
` outcome ` VARCHAR ( 16 ) NOT NULL ,
` error_code ` VARCHAR ( 100 ) NULL ,
` actor_user_id ` INT UNSIGNED NULL ,
` actor_tenant_id ` INT UNSIGNED NULL ,
` target_type ` VARCHAR ( 64 ) NULL ,
` target_id ` INT UNSIGNED NULL ,
` target_uuid ` CHAR ( 36 ) NULL ,
` method ` VARCHAR ( 8 ) NULL ,
` path ` VARCHAR ( 255 ) NULL ,
` ip_hash ` CHAR ( 64 ) NULL ,
` user_agent_hash ` CHAR ( 64 ) NULL ,
` metadata_json ` TEXT NULL ,
` created_at ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_system_audit_event_uuid ` ( ` event_uuid ` ) ,
KEY ` idx_system_audit_created ` ( ` created_at ` ) ,
KEY ` idx_system_audit_event_created ` ( ` event_type ` , ` created_at ` ) ,
KEY ` idx_system_audit_actor_created ` ( ` actor_user_id ` , ` created_at ` ) ,
KEY ` idx_system_audit_target_created ` ( ` target_type ` , ` target_uuid ` , ` created_at ` ) ,
KEY ` idx_system_audit_request_created ` ( ` request_id ` , ` created_at ` ) ,
KEY ` idx_system_audit_outcome_created ` ( ` outcome ` , ` created_at ` ) ,
CONSTRAINT ` chk_system_audit_log_channel ` CHECK ( ` channel ` IN ( ' web ' , ' api ' , ' scheduler ' , ' cli ' ) ) ,
CONSTRAINT ` chk_system_audit_log_outcome ` CHECK ( ` outcome ` IN ( ' success ' , ' failed ' , ' denied ' ) ) ,
CONSTRAINT ` fk_system_audit_actor_user ` FOREIGN KEY ( ` actor_user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL ,
CONSTRAINT ` fk_system_audit_actor_tenant ` FOREIGN KEY ( ` actor_tenant_id ` ) REFERENCES ` tenants ` ( ` id ` ) ON DELETE SET NULL
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
CREATE TABLE IF NOT EXISTS ` import_audit_runs ` (
` id ` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT ,
` run_uuid ` CHAR ( 36 ) NOT NULL ,
` profile_key ` VARCHAR ( 32 ) NOT NULL ,
` status ` VARCHAR ( 16 ) NOT NULL ,
` source_filename ` VARCHAR ( 255 ) NULL ,
` mapped_targets_csv ` TEXT NULL ,
` rows_total ` INT UNSIGNED NOT NULL DEFAULT 0 ,
` created_count ` INT UNSIGNED NOT NULL DEFAULT 0 ,
` skipped_count ` INT UNSIGNED NOT NULL DEFAULT 0 ,
` failed_count ` INT UNSIGNED NOT NULL DEFAULT 0 ,
` error_codes_json ` TEXT NULL ,
` started_at ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
` finished_at ` DATETIME NULL DEFAULT NULL ,
` duration_ms ` INT UNSIGNED NULL ,
` user_id ` INT UNSIGNED NULL ,
` current_tenant_id ` INT UNSIGNED NULL ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_import_audit_run_uuid ` ( ` run_uuid ` ) ,
KEY ` idx_import_audit_started ` ( ` started_at ` ) ,
KEY ` idx_import_audit_status_started ` ( ` status ` , ` started_at ` ) ,
KEY ` idx_import_audit_profile_started ` ( ` profile_key ` , ` started_at ` ) ,
KEY ` idx_import_audit_user_started ` ( ` user_id ` , ` started_at ` ) ,
2026-03-04 15:56:58 +01:00
CONSTRAINT ` chk_import_audit_runs_status ` CHECK ( ` status ` IN ( ' running ' , ' success ' , ' partial ' , ' failed ' ) ) ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
CONSTRAINT ` fk_import_audit_user ` FOREIGN KEY ( ` user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL ,
CONSTRAINT ` fk_import_audit_tenant ` FOREIGN KEY ( ` current_tenant_id ` ) REFERENCES ` tenants ` ( ` id ` ) ON DELETE SET NULL
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` user_lifecycle_audit_log ` (
` id ` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT ,
` run_uuid ` CHAR ( 36 ) NOT NULL ,
` action ` VARCHAR ( 16 ) NOT NULL ,
` trigger_type ` VARCHAR ( 16 ) NOT NULL ,
` status ` VARCHAR ( 16 ) NOT NULL ,
` reason_code ` VARCHAR ( 64 ) NULL ,
` policy_deactivate_days ` INT UNSIGNED NOT NULL DEFAULT 0 ,
` policy_delete_days ` INT UNSIGNED NOT NULL DEFAULT 0 ,
` actor_user_id ` INT UNSIGNED NULL ,
` target_user_id ` INT UNSIGNED NULL ,
` target_user_uuid ` CHAR ( 36 ) NULL ,
` target_user_email ` VARCHAR ( 255 ) NULL ,
` snapshot_enc ` LONGTEXT NULL ,
` snapshot_version ` SMALLINT UNSIGNED NOT NULL DEFAULT 1 ,
` restored_at ` DATETIME NULL DEFAULT NULL ,
` restored_by_user_id ` INT UNSIGNED NULL ,
` restored_user_id ` INT UNSIGNED NULL ,
` created_at ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
KEY ` idx_user_lifecycle_created ` ( ` created_at ` ) ,
KEY ` idx_user_lifecycle_action_created ` ( ` action ` , ` created_at ` ) ,
KEY ` idx_user_lifecycle_status_created ` ( ` status ` , ` created_at ` ) ,
KEY ` idx_user_lifecycle_target_uuid_created ` ( ` target_user_uuid ` , ` created_at ` ) ,
KEY ` idx_user_lifecycle_run_uuid ` ( ` run_uuid ` ) ,
KEY ` idx_user_lifecycle_restored ` ( ` restored_at ` ) ,
2026-03-04 15:56:58 +01:00
CONSTRAINT ` chk_user_lifecycle_action ` CHECK ( ` action ` IN ( ' deactivate ' , ' delete ' , ' restore ' ) ) ,
CONSTRAINT ` chk_user_lifecycle_trigger_type ` CHECK ( ` trigger_type ` IN ( ' manual ' , ' cron ' , ' system ' ) ) ,
CONSTRAINT ` chk_user_lifecycle_status ` CHECK ( ` status ` IN ( ' success ' , ' skipped ' , ' failed ' ) ) ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
CONSTRAINT ` fk_user_lifecycle_actor ` FOREIGN KEY ( ` actor_user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL ,
CONSTRAINT ` fk_user_lifecycle_target ` FOREIGN KEY ( ` target_user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL ,
CONSTRAINT ` fk_user_lifecycle_restored_by ` FOREIGN KEY ( ` restored_by_user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL ,
CONSTRAINT ` fk_user_lifecycle_restored_user ` FOREIGN KEY ( ` restored_user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` scheduled_jobs ` (
` id ` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT ,
` job_key ` VARCHAR ( 64 ) NOT NULL ,
` label ` VARCHAR ( 120 ) NOT NULL ,
` description ` VARCHAR ( 255 ) NULL ,
` enabled ` TINYINT ( 1 ) NOT NULL DEFAULT 1 ,
` timezone ` VARCHAR ( 64 ) NOT NULL DEFAULT ' Europe/Berlin ' ,
` schedule_type ` VARCHAR ( 16 ) NOT NULL ,
` schedule_interval ` SMALLINT UNSIGNED NOT NULL DEFAULT 1 ,
` schedule_time ` CHAR ( 5 ) NULL ,
` schedule_weekdays_csv ` VARCHAR ( 32 ) NULL ,
` catchup_once ` TINYINT ( 1 ) NOT NULL DEFAULT 1 ,
` next_run_at ` DATETIME NULL DEFAULT NULL ,
` last_run_started_at ` DATETIME NULL DEFAULT NULL ,
` last_run_finished_at ` DATETIME NULL DEFAULT NULL ,
` last_run_status ` VARCHAR ( 16 ) NULL ,
` last_error_code ` VARCHAR ( 64 ) NULL ,
` last_error_message ` VARCHAR ( 255 ) NULL ,
` created_at ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
` updated_at ` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_scheduled_jobs_job_key ` ( ` job_key ` ) ,
KEY ` idx_scheduled_jobs_enabled_next ` ( ` enabled ` , ` next_run_at ` ) ,
2026-03-04 15:56:58 +01:00
KEY ` idx_scheduled_jobs_status ` ( ` last_run_status ` ) ,
CONSTRAINT ` chk_scheduled_jobs_last_run_status ` CHECK ( ` last_run_status ` IS NULL OR ` last_run_status ` IN ( ' running ' , ' success ' , ' failed ' , ' skipped ' ) )
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` scheduled_job_runs ` (
` id ` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT ,
` run_uuid ` CHAR ( 36 ) NOT NULL ,
` job_id ` BIGINT UNSIGNED NOT NULL ,
` job_key ` VARCHAR ( 64 ) NOT NULL ,
` trigger_type ` VARCHAR ( 16 ) NOT NULL ,
` status ` VARCHAR ( 16 ) NOT NULL ,
` actor_user_id ` INT UNSIGNED NULL ,
` started_at ` DATETIME NOT NULL ,
` finished_at ` DATETIME NULL DEFAULT NULL ,
` duration_ms ` INT UNSIGNED NULL ,
` error_code ` VARCHAR ( 64 ) NULL ,
` error_message ` VARCHAR ( 255 ) NULL ,
` result_json ` TEXT NULL ,
` created_at ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_sched_runs_run_uuid ` ( ` run_uuid ` ) ,
KEY ` idx_sched_runs_job_created ` ( ` job_id ` , ` created_at ` ) ,
KEY ` idx_sched_runs_status_created ` ( ` status ` , ` created_at ` ) ,
KEY ` idx_sched_runs_trigger_created ` ( ` trigger_type ` , ` created_at ` ) ,
2026-03-04 15:56:58 +01:00
CONSTRAINT ` chk_scheduled_job_runs_status ` CHECK ( ` status ` IN ( ' success ' , ' failed ' , ' skipped ' ) ) ,
CONSTRAINT ` chk_scheduled_job_runs_trigger_type ` CHECK ( ` trigger_type ` IN ( ' scheduler ' , ' manual ' ) ) ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
CONSTRAINT ` fk_sched_runs_job ` FOREIGN KEY ( ` job_id ` ) REFERENCES ` scheduled_jobs ` ( ` id ` ) ON DELETE CASCADE ,
CONSTRAINT ` fk_sched_runs_actor_user ` FOREIGN KEY ( ` actor_user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE SET NULL
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` scheduler_runtime_status ` (
` id ` TINYINT UNSIGNED NOT NULL ,
` last_heartbeat_at ` DATETIME NOT NULL ,
` last_result ` VARCHAR ( 32 ) NULL ,
` last_error_code ` VARCHAR ( 64 ) NULL ,
` updated_at ` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP ,
2026-03-04 15:56:58 +01:00
PRIMARY KEY ( ` id ` ) ,
CONSTRAINT ` chk_scheduler_runtime_status_last_result ` CHECK ( ` last_result ` IS NULL OR ` last_result ` IN ( ' ok ' , ' lock_not_acquired ' , ' unexpected_error ' ) )
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` request_rate_limits ` (
` id ` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT ,
` scope ` VARCHAR ( 64 ) NOT NULL ,
` subject_hash ` CHAR ( 64 ) NOT NULL ,
` hits ` INT UNSIGNED NOT NULL DEFAULT 0 ,
` window_started_at ` DATETIME NOT NULL ,
` blocked_until ` DATETIME NULL DEFAULT NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
` modified ` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_request_rate_scope_subject ` ( ` scope ` , ` subject_hash ` ) ,
KEY ` idx_request_rate_scope_blocked ` ( ` scope ` , ` blocked_until ` ) ,
KEY ` idx_request_rate_modified ` ( ` modified ` )
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
2026-02-04 23:31:53 +01:00
CREATE TABLE IF NOT EXISTS ` password_resets ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` user_id ` INT UNSIGNED NOT NULL ,
` code_hash ` VARCHAR ( 255 ) NOT NULL ,
` expires_at ` DATETIME NOT NULL ,
` attempts ` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT ' Failed verification attempts ' ,
` used_at ` DATETIME NULL DEFAULT NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
KEY ` idx_password_resets_user ` ( ` user_id ` ) ,
KEY ` idx_password_resets_expires ` ( ` expires_at ` ) ,
CONSTRAINT ` fk_password_resets_user ` FOREIGN KEY ( ` user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` email_verifications ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` user_id ` INT UNSIGNED NOT NULL ,
` code_hash ` VARCHAR ( 255 ) NOT NULL ,
` expires_at ` DATETIME NOT NULL ,
` attempts ` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT ' Failed verification attempts ' ,
` used_at ` DATETIME NULL DEFAULT NULL ,
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY ( ` id ` ) ,
KEY ` idx_email_verifications_user ` ( ` user_id ` ) ,
KEY ` idx_email_verifications_expires ` ( ` expires_at ` ) ,
CONSTRAINT ` fk_email_verifications_user ` FOREIGN KEY ( ` user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
CREATE TABLE IF NOT EXISTS ` user_remember_tokens ` (
` id ` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
` user_id ` INT UNSIGNED NOT NULL ,
` selector ` CHAR ( 24 ) NOT NULL ,
` token_hash ` CHAR ( 64 ) NOT NULL ,
` expires_at ` DATETIME NOT NULL ,
2026-02-11 19:28:12 +01:00
` expired_by_admin_at ` DATETIME NULL DEFAULT NULL COMMENT ' Expired by admin action ' ,
2026-02-04 23:31:53 +01:00
` created ` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
` last_used ` DATETIME NULL DEFAULT NULL ,
PRIMARY KEY ( ` id ` ) ,
UNIQUE KEY ` uniq_user_remember_selector ` ( ` selector ` ) ,
KEY ` idx_user_remember_user ` ( ` user_id ` ) ,
KEY ` idx_user_remember_expires ` ( ` expires_at ` ) ,
CONSTRAINT ` fk_user_remember_user ` FOREIGN KEY ( ` user_id ` ) REFERENCES ` users ` ( ` id ` ) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ;
2026-03-12 09:41:04 +01:00
INSERT INTO ` tenants ` (
` uuid ` ,
` description ` ,
` address ` ,
` postal_code ` ,
` city ` ,
` country ` ,
` region ` ,
` vat_id ` ,
` tax_number ` ,
` phone ` ,
` fax ` ,
` email ` ,
` support_email ` ,
` support_phone ` ,
` billing_email ` ,
` website ` ,
` privacy_url ` ,
` imprint_url ` ,
` primary_color ` ,
` default_theme ` ,
` allow_user_theme ` ,
` status ` ,
` created `
)
SELECT
UUID ( ) ,
' MusterMandant ' ,
' Musterstrasse 1 ' ,
' 10115 ' ,
' Berlin ' ,
' Deutschland ' ,
' Berlin ' ,
' DE123456789 ' ,
' 12/345/67890 ' ,
' +49 30 12345670 ' ,
' +49 30 12345679 ' ,
' info@mustermandant.de ' ,
' support@mustermandant.de ' ,
' +49 30 12345671 ' ,
' billing@mustermandant.de ' ,
' https://www.mustermandant.de ' ,
' https://www.mustermandant.de/datenschutz ' ,
' https://www.mustermandant.de/impressum ' ,
' #1A73E8 ' ,
' light ' ,
1 ,
' active ' ,
NOW ( )
2026-03-11 20:24:18 +01:00
WHERE NOT EXISTS ( SELECT 1 FROM tenants WHERE description = ' MusterMandant ' ) ;
2026-02-04 23:31:53 +01:00
2026-03-12 09:41:04 +01:00
UPDATE ` tenants `
SET
` address ` = COALESCE ( ` address ` , ' Musterstrasse 1 ' ) ,
` postal_code ` = COALESCE ( ` postal_code ` , ' 10115 ' ) ,
` city ` = COALESCE ( ` city ` , ' Berlin ' ) ,
` country ` = COALESCE ( ` country ` , ' Deutschland ' ) ,
` region ` = COALESCE ( ` region ` , ' Berlin ' ) ,
` vat_id ` = COALESCE ( ` vat_id ` , ' DE123456789 ' ) ,
` tax_number ` = COALESCE ( ` tax_number ` , ' 12/345/67890 ' ) ,
` phone ` = COALESCE ( ` phone ` , ' +49 30 12345670 ' ) ,
` fax ` = COALESCE ( ` fax ` , ' +49 30 12345679 ' ) ,
` email ` = COALESCE ( ` email ` , ' info@mustermandant.de ' ) ,
` support_email ` = COALESCE ( ` support_email ` , ' support@mustermandant.de ' ) ,
` support_phone ` = COALESCE ( ` support_phone ` , ' +49 30 12345671 ' ) ,
` billing_email ` = COALESCE ( ` billing_email ` , ' billing@mustermandant.de ' ) ,
` website ` = COALESCE ( ` website ` , ' https://www.mustermandant.de ' ) ,
` privacy_url ` = COALESCE ( ` privacy_url ` , ' https://www.mustermandant.de/datenschutz ' ) ,
` imprint_url ` = COALESCE ( ` imprint_url ` , ' https://www.mustermandant.de/impressum ' ) ,
` primary_color ` = COALESCE ( ` primary_color ` , ' #1A73E8 ' ) ,
` default_theme ` = COALESCE ( ` default_theme ` , ' light ' ) ,
` allow_user_theme ` = COALESCE ( ` allow_user_theme ` , 1 ) ,
` status ` = COALESCE ( ` status ` , ' active ' )
WHERE ` description ` = ' MusterMandant ' ;
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
INSERT INTO ` departments ` ( ` uuid ` , ` description ` , ` tenant_id ` , ` code ` , ` active ` , ` created ` )
2026-03-11 20:24:18 +01:00
SELECT UUID ( ) , ' Musterabteilung ' , t . id , ' MUSTER ' , 1 , NOW ( )
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
FROM tenants t
2026-03-11 20:24:18 +01:00
WHERE t . description = ' MusterMandant '
AND NOT EXISTS (
SELECT 1 FROM departments d
WHERE d . tenant_id = t . id
AND d . description = ' Musterabteilung '
) ;
INSERT INTO ` departments ` ( ` uuid ` , ` description ` , ` tenant_id ` , ` code ` , ` active ` , ` created ` )
SELECT UUID ( ) , ' Musterabteilung 2 ' , t . id , ' MUSTER2 ' , 1 , NOW ( )
FROM tenants t
WHERE t . description = ' MusterMandant '
AND NOT EXISTS (
SELECT 1 FROM departments d
WHERE d . tenant_id = t . id
AND d . description = ' Musterabteilung 2 '
) ;
2026-02-04 23:31:53 +01:00
2026-02-11 19:28:12 +01:00
INSERT INTO ` roles ` ( ` uuid ` , ` description ` , ` code ` , ` active ` , ` created ` )
SELECT UUID ( ) , ' Admin ' , ' ADMIN ' , 1 , NOW ( )
2026-02-04 23:31:53 +01:00
WHERE NOT EXISTS ( SELECT 1 FROM roles WHERE description = ' Admin ' ) ;
2026-03-11 20:24:18 +01:00
INSERT INTO ` roles ` ( ` uuid ` , ` description ` , ` code ` , ` active ` , ` created ` )
SELECT UUID ( ) , ' User ' , ' USER ' , 1 , NOW ( )
WHERE NOT EXISTS ( SELECT 1 FROM roles WHERE code = ' USER ' ) ;
2026-03-13 21:11:48 +01:00
INSERT INTO ` roles ` ( ` uuid ` , ` description ` , ` code ` , ` active ` , ` created ` )
SELECT UUID ( ) , ' Manager ' , ' MANAGER ' , 1 , NOW ( )
WHERE NOT EXISTS ( SELECT 1 FROM roles WHERE code = ' MANAGER ' ) ;
INSERT INTO ` roles ` ( ` uuid ` , ` description ` , ` code ` , ` active ` , ` created ` )
SELECT UUID ( ) , ' Auditor ' , ' AUDITOR ' , 1 , NOW ( )
WHERE NOT EXISTS ( SELECT 1 FROM roles WHERE code = ' AUDITOR ' ) ;
INSERT INTO ` roles ` ( ` uuid ` , ` description ` , ` code ` , ` active ` , ` created ` )
SELECT UUID ( ) , ' Support ' , ' SUPPORT ' , 1 , NOW ( )
WHERE NOT EXISTS ( SELECT 1 FROM roles WHERE code = ' SUPPORT ' ) ;
2026-02-04 23:31:53 +01:00
INSERT INTO ` users ` (
` uuid ` ,
` first_name ` ,
` last_name ` ,
2026-02-11 19:28:12 +01:00
` display_name ` ,
2026-02-04 23:31:53 +01:00
` email ` ,
2026-03-11 21:25:22 +01:00
` profile_description ` ,
` job_title ` ,
` phone ` ,
` mobile ` ,
` short_dial ` ,
` address ` ,
` postal_code ` ,
` city ` ,
` country ` ,
` region ` ,
` hire_date ` ,
2026-03-11 20:16:45 +01:00
` email_verified_at ` ,
2026-02-04 23:31:53 +01:00
` password ` ,
` locale ` ,
` totp_secret ` ,
` theme ` ,
` primary_tenant_id ` ,
` created_by ` ,
` created ` ,
` active ` ,
` active_changed_at ` ,
` active_changed_by `
)
SELECT
UUID ( ) ,
' Detlef ' ,
' Demo ' ,
2026-02-11 19:28:12 +01:00
' Detlef Demo ' ,
2026-02-04 23:31:53 +01:00
' demo@user.com ' ,
2026-03-11 21:25:22 +01:00
' Demo-Nutzer fuer Vorschau und Test der Adressbuchdarstellung. ' ,
' Sachbearbeiter ' ,
' +49 30 1234567 ' ,
' +49 171 2345678 ' ,
' 123 ' ,
' Musterstrasse 1 ' ,
' 10115 ' ,
' Berlin ' ,
' Deutschland ' ,
' Berlin ' ,
' 2024-01-15 ' ,
2026-03-11 20:16:45 +01:00
NOW ( ) ,
2026-02-04 23:31:53 +01:00
' $2y$12$KVCQvuy4Pl1aySBuzSpc7ehpZhAzYZkndDI9OaMi05E2P/Mhob5HO ' ,
' de ' ,
NULL ,
' light ' ,
2026-03-11 20:24:18 +01:00
( SELECT id FROM tenants WHERE description = ' MusterMandant ' LIMIT 1 ) ,
2026-02-04 23:31:53 +01:00
NULL ,
NOW ( ) ,
1 ,
NOW ( ) ,
NULL
WHERE NOT EXISTS ( SELECT 1 FROM users WHERE email = ' demo@user.com ' ) ;
2026-03-11 20:16:45 +01:00
UPDATE ` users `
SET ` email_verified_at ` = COALESCE ( ` email_verified_at ` , NOW ( ) )
WHERE ` email ` = ' demo@user.com ' ;
2026-03-11 21:25:22 +01:00
UPDATE ` users `
SET
` profile_description ` = COALESCE ( ` profile_description ` , ' Demo-Nutzer fuer Vorschau und Test der Adressbuchdarstellung. ' ) ,
` job_title ` = COALESCE ( ` job_title ` , ' Sachbearbeiter ' ) ,
` phone ` = COALESCE ( ` phone ` , ' +49 30 1234567 ' ) ,
` mobile ` = COALESCE ( ` mobile ` , ' +49 171 2345678 ' ) ,
` short_dial ` = COALESCE ( ` short_dial ` , ' 123 ' ) ,
` address ` = COALESCE ( ` address ` , ' Musterstrasse 1 ' ) ,
` postal_code ` = COALESCE ( ` postal_code ` , ' 10115 ' ) ,
` city ` = COALESCE ( ` city ` , ' Berlin ' ) ,
` country ` = COALESCE ( ` country ` , ' Deutschland ' ) ,
` region ` = COALESCE ( ` region ` , ' Berlin ' ) ,
` hire_date ` = COALESCE ( ` hire_date ` , ' 2024-01-15 ' )
WHERE ` email ` = ' demo@user.com ' ;
2026-02-04 23:31:53 +01:00
INSERT INTO ` user_tenants ` ( ` user_id ` , ` tenant_id ` , ` created ` )
SELECT u . id , t . id , NOW ( )
FROM users u
2026-03-11 20:24:18 +01:00
JOIN tenants t ON t . description = ' MusterMandant '
2026-02-04 23:31:53 +01:00
WHERE u . email = ' demo@user.com '
AND NOT EXISTS (
SELECT 1 FROM user_tenants ut WHERE ut . user_id = u . id AND ut . tenant_id = t . id
) ;
INSERT INTO ` user_departments ` ( ` user_id ` , ` department_id ` , ` created ` )
SELECT u . id , d . id , NOW ( )
FROM users u
2026-03-11 20:24:18 +01:00
JOIN departments d ON d . code = ' MUSTER '
JOIN tenants t ON t . id = d . tenant_id AND t . description = ' MusterMandant '
2026-02-04 23:31:53 +01:00
WHERE u . email = ' demo@user.com '
AND NOT EXISTS (
SELECT 1 FROM user_departments ud WHERE ud . user_id = u . id AND ud . department_id = d . id
) ;
INSERT INTO ` user_roles ` ( ` user_id ` , ` role_id ` , ` created ` )
SELECT u . id , r . id , NOW ( )
FROM users u
JOIN roles r ON r . description = ' Admin '
WHERE u . email = ' demo@user.com '
AND NOT EXISTS (
SELECT 1 FROM user_roles ur WHERE ur . user_id = u . id AND ur . role_id = r . id
) ;
2026-03-22 22:27:35 +01:00
-- ─── Demo user: Max Machtvoll (Manager) ───
INSERT INTO ` users ` (
` uuid ` ,
` first_name ` ,
` last_name ` ,
` display_name ` ,
` email ` ,
` profile_description ` ,
` job_title ` ,
` phone ` ,
` mobile ` ,
` short_dial ` ,
` address ` ,
` postal_code ` ,
` city ` ,
` country ` ,
` region ` ,
` hire_date ` ,
` email_verified_at ` ,
` password ` ,
` locale ` ,
` totp_secret ` ,
` theme ` ,
` primary_tenant_id ` ,
` created_by ` ,
` created ` ,
` active ` ,
` active_changed_at ` ,
` active_changed_by `
)
SELECT
UUID ( ) ,
' Max ' ,
' Machtvoll ' ,
' Max Machtvoll ' ,
' max@user.com ' ,
' Manager mit Weitblick und festem Griff am Steuer. ' ,
' Abteilungsleiter ' ,
' +49 30 9876543 ' ,
' +49 172 1111111 ' ,
' 201 ' ,
' Chefetage 7 ' ,
' 80331 ' ,
' Muenchen ' ,
' Deutschland ' ,
' Bayern ' ,
' 2023-06-01 ' ,
NOW ( ) ,
' $2y$12$KVCQvuy4Pl1aySBuzSpc7ehpZhAzYZkndDI9OaMi05E2P/Mhob5HO ' ,
' de ' ,
NULL ,
' light ' ,
( SELECT id FROM tenants WHERE description = ' MusterMandant ' LIMIT 1 ) ,
NULL ,
NOW ( ) ,
1 ,
NOW ( ) ,
NULL
WHERE NOT EXISTS ( SELECT 1 FROM users WHERE email = ' max@user.com ' ) ;
INSERT INTO ` user_tenants ` ( ` user_id ` , ` tenant_id ` , ` created ` )
SELECT u . id , t . id , NOW ( )
FROM users u
JOIN tenants t ON t . description = ' MusterMandant '
WHERE u . email = ' max@user.com '
AND NOT EXISTS (
SELECT 1 FROM user_tenants ut WHERE ut . user_id = u . id AND ut . tenant_id = t . id
) ;
INSERT INTO ` user_departments ` ( ` user_id ` , ` department_id ` , ` created ` )
SELECT u . id , d . id , NOW ( )
FROM users u
JOIN departments d ON d . code = ' MUSTER '
JOIN tenants t ON t . id = d . tenant_id AND t . description = ' MusterMandant '
WHERE u . email = ' max@user.com '
AND NOT EXISTS (
SELECT 1 FROM user_departments ud WHERE ud . user_id = u . id AND ud . department_id = d . id
) ;
INSERT INTO ` user_roles ` ( ` user_id ` , ` role_id ` , ` created ` )
SELECT u . id , r . id , NOW ( )
FROM users u
JOIN roles r ON r . description = ' Manager '
WHERE u . email = ' max@user.com '
AND NOT EXISTS (
SELECT 1 FROM user_roles ur WHERE ur . user_id = u . id AND ur . role_id = r . id
) ;
-- ─── Demo user: Bernd Benutzer (User) ───
INSERT INTO ` users ` (
` uuid ` ,
` first_name ` ,
` last_name ` ,
` display_name ` ,
` email ` ,
` profile_description ` ,
` job_title ` ,
` phone ` ,
` mobile ` ,
` short_dial ` ,
` address ` ,
` postal_code ` ,
` city ` ,
` country ` ,
` region ` ,
` hire_date ` ,
` email_verified_at ` ,
` password ` ,
` locale ` ,
` totp_secret ` ,
` theme ` ,
` primary_tenant_id ` ,
` created_by ` ,
` created ` ,
` active ` ,
` active_changed_at ` ,
` active_changed_by `
)
SELECT
UUID ( ) ,
' Bernd ' ,
' Benutzer ' ,
' Bernd Benutzer ' ,
' bernd@user.com ' ,
' Stinknormaler Benutzer. Macht seine Arbeit, trinkt seinen Kaffee. ' ,
' Sachbearbeiter ' ,
' +49 40 5551234 ' ,
' +49 173 2222222 ' ,
' 302 ' ,
' Normalweg 42 ' ,
' 20095 ' ,
' Hamburg ' ,
' Deutschland ' ,
' Hamburg ' ,
' 2024-03-10 ' ,
NOW ( ) ,
' $2y$12$KVCQvuy4Pl1aySBuzSpc7ehpZhAzYZkndDI9OaMi05E2P/Mhob5HO ' ,
' de ' ,
NULL ,
' light ' ,
( SELECT id FROM tenants WHERE description = ' MusterMandant ' LIMIT 1 ) ,
NULL ,
NOW ( ) ,
1 ,
NOW ( ) ,
NULL
WHERE NOT EXISTS ( SELECT 1 FROM users WHERE email = ' bernd@user.com ' ) ;
INSERT INTO ` user_tenants ` ( ` user_id ` , ` tenant_id ` , ` created ` )
SELECT u . id , t . id , NOW ( )
FROM users u
JOIN tenants t ON t . description = ' MusterMandant '
WHERE u . email = ' bernd@user.com '
AND NOT EXISTS (
SELECT 1 FROM user_tenants ut WHERE ut . user_id = u . id AND ut . tenant_id = t . id
) ;
INSERT INTO ` user_departments ` ( ` user_id ` , ` department_id ` , ` created ` )
SELECT u . id , d . id , NOW ( )
FROM users u
JOIN departments d ON d . code = ' MUSTER2 '
JOIN tenants t ON t . id = d . tenant_id AND t . description = ' MusterMandant '
WHERE u . email = ' bernd@user.com '
AND NOT EXISTS (
SELECT 1 FROM user_departments ud WHERE ud . user_id = u . id AND ud . department_id = d . id
) ;
INSERT INTO ` user_roles ` ( ` user_id ` , ` role_id ` , ` created ` )
SELECT u . id , r . id , NOW ( )
FROM users u
JOIN roles r ON r . description = ' User '
WHERE u . email = ' bernd@user.com '
AND NOT EXISTS (
SELECT 1 FROM user_roles ur WHERE ur . user_id = u . id AND ur . role_id = r . id
) ;
-- ─── Demo user: Petra Pruefblick (Auditor) ───
INSERT INTO ` users ` (
` uuid ` ,
` first_name ` ,
` last_name ` ,
` display_name ` ,
` email ` ,
` profile_description ` ,
` job_title ` ,
` phone ` ,
` mobile ` ,
` short_dial ` ,
` address ` ,
` postal_code ` ,
` city ` ,
` country ` ,
` region ` ,
` hire_date ` ,
` email_verified_at ` ,
` password ` ,
` locale ` ,
` totp_secret ` ,
` theme ` ,
` primary_tenant_id ` ,
` created_by ` ,
` created ` ,
` active ` ,
` active_changed_at ` ,
` active_changed_by `
)
SELECT
UUID ( ) ,
' Petra ' ,
' Pruefblick ' ,
' Petra Pruefblick ' ,
' petra@user.com ' ,
' Sieht alles. Vergisst nichts. Ihr Rotstift ist legendaer. ' ,
' Prueferin ' ,
' +49 69 4449876 ' ,
' +49 174 3333333 ' ,
' 403 ' ,
' Kontrollgasse 8 ' ,
' 60311 ' ,
' Frankfurt am Main ' ,
' Deutschland ' ,
' Hessen ' ,
' 2023-11-20 ' ,
NOW ( ) ,
' $2y$12$KVCQvuy4Pl1aySBuzSpc7ehpZhAzYZkndDI9OaMi05E2P/Mhob5HO ' ,
' de ' ,
NULL ,
' light ' ,
( SELECT id FROM tenants WHERE description = ' MusterMandant ' LIMIT 1 ) ,
NULL ,
NOW ( ) ,
1 ,
NOW ( ) ,
NULL
WHERE NOT EXISTS ( SELECT 1 FROM users WHERE email = ' petra@user.com ' ) ;
INSERT INTO ` user_tenants ` ( ` user_id ` , ` tenant_id ` , ` created ` )
SELECT u . id , t . id , NOW ( )
FROM users u
JOIN tenants t ON t . description = ' MusterMandant '
WHERE u . email = ' petra@user.com '
AND NOT EXISTS (
SELECT 1 FROM user_tenants ut WHERE ut . user_id = u . id AND ut . tenant_id = t . id
) ;
INSERT INTO ` user_departments ` ( ` user_id ` , ` department_id ` , ` created ` )
SELECT u . id , d . id , NOW ( )
FROM users u
JOIN departments d ON d . code = ' MUSTER '
JOIN tenants t ON t . id = d . tenant_id AND t . description = ' MusterMandant '
WHERE u . email = ' petra@user.com '
AND NOT EXISTS (
SELECT 1 FROM user_departments ud WHERE ud . user_id = u . id AND ud . department_id = d . id
) ;
INSERT INTO ` user_roles ` ( ` user_id ` , ` role_id ` , ` created ` )
SELECT u . id , r . id , NOW ( )
FROM users u
JOIN roles r ON r . description = ' Auditor '
WHERE u . email = ' petra@user.com '
AND NOT EXISTS (
SELECT 1 FROM user_roles ur WHERE ur . user_id = u . id AND ur . role_id = r . id
) ;
-- ─── Demo user: Hilfe Hilde (Support) ───
INSERT INTO ` users ` (
` uuid ` ,
` first_name ` ,
` last_name ` ,
` display_name ` ,
` email ` ,
` profile_description ` ,
` job_title ` ,
` phone ` ,
` mobile ` ,
` short_dial ` ,
` address ` ,
` postal_code ` ,
` city ` ,
` country ` ,
` region ` ,
` hire_date ` ,
` email_verified_at ` ,
` password ` ,
` locale ` ,
` totp_secret ` ,
` theme ` ,
` primary_tenant_id ` ,
` created_by ` ,
` created ` ,
` active ` ,
` active_changed_at ` ,
` active_changed_by `
)
SELECT
UUID ( ) ,
' Hilde ' ,
' Hilfe ' ,
' Hilfe Hilde ' ,
' hilde@user.com ' ,
' Erste Hilfe fuer alle Notfaelle. Kein Ticket bleibt unbeantwortet. ' ,
' Supportmitarbeiterin ' ,
' +49 221 7773210 ' ,
' +49 175 4444444 ' ,
' 504 ' ,
' Rettungsring 3 ' ,
' 50667 ' ,
' Koeln ' ,
' Deutschland ' ,
' Nordrhein-Westfalen ' ,
' 2024-07-01 ' ,
NOW ( ) ,
' $2y$12$KVCQvuy4Pl1aySBuzSpc7ehpZhAzYZkndDI9OaMi05E2P/Mhob5HO ' ,
' de ' ,
NULL ,
' light ' ,
( SELECT id FROM tenants WHERE description = ' MusterMandant ' LIMIT 1 ) ,
NULL ,
NOW ( ) ,
1 ,
NOW ( ) ,
NULL
WHERE NOT EXISTS ( SELECT 1 FROM users WHERE email = ' hilde@user.com ' ) ;
INSERT INTO ` user_tenants ` ( ` user_id ` , ` tenant_id ` , ` created ` )
SELECT u . id , t . id , NOW ( )
FROM users u
JOIN tenants t ON t . description = ' MusterMandant '
WHERE u . email = ' hilde@user.com '
AND NOT EXISTS (
SELECT 1 FROM user_tenants ut WHERE ut . user_id = u . id AND ut . tenant_id = t . id
) ;
INSERT INTO ` user_departments ` ( ` user_id ` , ` department_id ` , ` created ` )
SELECT u . id , d . id , NOW ( )
FROM users u
JOIN departments d ON d . code = ' MUSTER2 '
JOIN tenants t ON t . id = d . tenant_id AND t . description = ' MusterMandant '
WHERE u . email = ' hilde@user.com '
AND NOT EXISTS (
SELECT 1 FROM user_departments ud WHERE ud . user_id = u . id AND ud . department_id = d . id
) ;
INSERT INTO ` user_roles ` ( ` user_id ` , ` role_id ` , ` created ` )
SELECT u . id , r . id , NOW ( )
FROM users u
JOIN roles r ON r . description = ' Support '
WHERE u . email = ' hilde@user.com '
AND NOT EXISTS (
SELECT 1 FROM user_roles ur WHERE ur . user_id = u . id AND ur . role_id = r . id
) ;
2026-02-04 23:31:53 +01:00
INSERT INTO ` pages ` ( ` uuid ` , ` slug ` , ` created ` )
2026-03-12 14:09:06 +01:00
SELECT UUID ( ) , v . slug , NOW ( )
FROM (
SELECT ' imprint ' AS slug
UNION ALL SELECT ' privacy '
UNION ALL SELECT ' terms '
) AS v
WHERE NOT EXISTS ( SELECT 1 FROM pages p WHERE p . slug = v . slug ) ;
INSERT INTO ` page_contents ` ( ` page_id ` , ` locale ` , ` content ` , ` created ` )
SELECT p . id , ' de ' , ' {"blocks":[{"type":"header","data":{"text":"Impressum","level":2}},{"type":"paragraph","data":{"text":"Diese Seite ist eine Vorlage. Bitte tragen Sie hier die Pflichtangaben Ihres Unternehmens ein."}},{"type":"paragraph","data":{"text":"Angaben gemaess Paragraph 5 TMG: Firmenname, Rechtsform, vertretungsberechtigte Person, Anschrift, Kontakt und Registerangaben."}},{"type":"paragraph","data":{"text":"Inhaltlich verantwortlich: Name und Anschrift."}}]} ' , p . created
FROM pages p
WHERE p . slug = ' imprint '
AND NOT EXISTS (
SELECT 1 FROM page_contents pc WHERE pc . page_id = p . id AND pc . locale = ' de '
) ;
INSERT INTO ` page_contents ` ( ` page_id ` , ` locale ` , ` content ` , ` created ` )
SELECT p . id , ' en ' , ' {"blocks":[{"type":"header","data":{"text":"Imprint","level":2}},{"type":"paragraph","data":{"text":"This page is a template. Please add your mandatory company details here."}},{"type":"paragraph","data":{"text":"Provide legal publisher information, address, contact channels, company register data and authorized representatives."}},{"type":"paragraph","data":{"text":"Responsible for content: name and address."}}]} ' , p . created
FROM pages p
WHERE p . slug = ' imprint '
AND NOT EXISTS (
SELECT 1 FROM page_contents pc WHERE pc . page_id = p . id AND pc . locale = ' en '
) ;
INSERT INTO ` page_contents ` ( ` page_id ` , ` locale ` , ` content ` , ` created ` )
SELECT p . id , ' de ' , ' {"blocks":[{"type":"header","data":{"text":"Datenschutz","level":2}},{"type":"paragraph","data":{"text":"Diese Seite ist eine Vorlage. Beschreiben Sie hier transparent, welche personenbezogenen Daten verarbeitet werden."}},{"type":"paragraph","data":{"text":"Nennen Sie Rechtsgrundlagen, Speicherdauer, Empfaenger, Betroffenenrechte und Kontakt der Datenschutzstelle."}},{"type":"paragraph","data":{"text":"Pruefen Sie die Inhalte regelmaessig mit Ihrem Datenschutzbeauftragten."}}]} ' , p . created
FROM pages p
WHERE p . slug = ' privacy '
AND NOT EXISTS (
SELECT 1 FROM page_contents pc WHERE pc . page_id = p . id AND pc . locale = ' de '
) ;
INSERT INTO ` page_contents ` ( ` page_id ` , ` locale ` , ` content ` , ` created ` )
SELECT p . id , ' en ' , ' {"blocks":[{"type":"header","data":{"text":"Privacy","level":2}},{"type":"paragraph","data":{"text":"This page is a template. Explain which personal data is processed and for what purpose."}},{"type":"paragraph","data":{"text":"Document legal bases, retention periods, recipients, data subject rights and your privacy contact point."}},{"type":"paragraph","data":{"text":"Review this content regularly with your legal or privacy team."}}]} ' , p . created
FROM pages p
WHERE p . slug = ' privacy '
AND NOT EXISTS (
SELECT 1 FROM page_contents pc WHERE pc . page_id = p . id AND pc . locale = ' en '
) ;
INSERT INTO ` page_contents ` ( ` page_id ` , ` locale ` , ` content ` , ` created ` )
SELECT p . id , ' de ' , ' {"blocks":[{"type":"header","data":{"text":"Nutzungsbedingungen","level":2}},{"type":"paragraph","data":{"text":"Diese Seite ist eine Vorlage. Beschreiben Sie hier Zweck, Leistungsumfang und zulaessige Nutzung Ihres Angebots."}},{"type":"paragraph","data":{"text":"Ergaenzen Sie Regelungen zu Haftung, Laufzeit, Kuendigung, Gerichtsstand und anwendbarem Recht."}},{"type":"paragraph","data":{"text":"Lassen Sie die Inhalte vor Veroeffentlichung rechtlich pruefen."}}]} ' , p . created
FROM pages p
WHERE p . slug = ' terms '
AND NOT EXISTS (
SELECT 1 FROM page_contents pc WHERE pc . page_id = p . id AND pc . locale = ' de '
) ;
INSERT INTO ` page_contents ` ( ` page_id ` , ` locale ` , ` content ` , ` created ` )
SELECT p . id , ' en ' , ' {"blocks":[{"type":"header","data":{"text":"Terms of Service","level":2}},{"type":"paragraph","data":{"text":"This page is a template. Describe the service scope, intended use and user obligations."}},{"type":"paragraph","data":{"text":"Add clauses for liability, term, termination, governing law and jurisdiction."}},{"type":"paragraph","data":{"text":"Have this content reviewed by legal counsel before publishing."}}]} ' , p . created
FROM pages p
WHERE p . slug = ' terms '
AND NOT EXISTS (
SELECT 1 FROM page_contents pc WHERE pc . page_id = p . id AND pc . locale = ' en '
) ;
2026-02-04 23:31:53 +01:00
INSERT INTO ` page_contents ` ( ` page_id ` , ` locale ` , ` content ` , ` created ` )
SELECT p . id , ' de ' , NULL , p . created
FROM pages p
WHERE NOT EXISTS (
SELECT 1 FROM page_contents pc WHERE pc . page_id = p . id AND pc . locale = ' de '
) ;
2026-02-11 19:28:12 +01:00
INSERT INTO ` permissions ` ( ` key ` , ` description ` , ` active ` , ` is_system ` )
2026-02-04 23:31:53 +01:00
VALUES
2026-02-11 19:28:12 +01:00
( ' users.view ' , ' Can view users ' , 1 , 1 ) ,
( ' users.view_meta ' , ' Can view user status and meta ' , 1 , 1 ) ,
( ' users.view_audit ' , ' Can view user audit log ' , 1 , 1 ) ,
( ' users.create ' , ' Can create users ' , 1 , 1 ) ,
( ' users.update ' , ' Can update users ' , 1 , 1 ) ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
( ' users.access_pdf ' , ' Can generate onboarding access PDFs ' , 1 , 1 ) ,
2026-02-11 19:28:12 +01:00
( ' users.delete ' , ' Can delete users ' , 1 , 1 ) ,
( ' users.self_update ' , ' Can update own user ' , 1 , 1 ) ,
( ' users.update_assignments ' , ' Can update user assignments ' , 1 , 1 ) ,
( ' address_book.view ' , ' Can view address book ' , 1 , 1 ) ,
( ' tenants.view ' , ' Can view tenants ' , 1 , 1 ) ,
( ' tenants.create ' , ' Can create tenants ' , 1 , 1 ) ,
( ' tenants.update ' , ' Can update tenants ' , 1 , 1 ) ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
( ' tenants.sso_manage ' , ' Can manage tenant Microsoft SSO settings ' , 1 , 1 ) ,
2026-02-11 19:28:12 +01:00
( ' tenants.delete ' , ' Can delete tenants ' , 1 , 1 ) ,
( ' departments.view ' , ' Can view departments ' , 1 , 1 ) ,
( ' departments.create ' , ' Can create departments ' , 1 , 1 ) ,
( ' departments.update ' , ' Can update departments ' , 1 , 1 ) ,
( ' departments.delete ' , ' Can delete departments ' , 1 , 1 ) ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
( ' departments.import ' , ' Can import departments ' , 1 , 1 ) ,
2026-02-11 19:28:12 +01:00
( ' roles.view ' , ' Can view roles ' , 1 , 1 ) ,
( ' roles.create ' , ' Can create roles ' , 1 , 1 ) ,
( ' roles.update ' , ' Can update roles ' , 1 , 1 ) ,
( ' roles.delete ' , ' Can delete roles ' , 1 , 1 ) ,
( ' permissions.view ' , ' Can view permissions ' , 1 , 1 ) ,
( ' permissions.create ' , ' Can create permissions ' , 1 , 1 ) ,
( ' permissions.update ' , ' Can update permissions ' , 1 , 1 ) ,
( ' permissions.delete ' , ' Can delete permissions ' , 1 , 1 ) ,
( ' settings.view ' , ' Can view settings ' , 1 , 1 ) ,
( ' settings.update ' , ' Can update settings ' , 1 , 1 ) ,
2026-02-24 08:49:40 +01:00
( ' tenant.scope.global ' , ' Can bypass tenant scope globally ' , 1 , 1 ) ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
( ' imports.view ' , ' Can view imports ' , 1 , 1 ) ,
( ' imports.audit.view ' , ' Can view import audit logs ' , 1 , 1 ) ,
( ' jobs.view ' , ' Can view scheduled jobs ' , 1 , 1 ) ,
( ' jobs.manage ' , ' Can manage scheduled jobs ' , 1 , 1 ) ,
( ' jobs.run_now ' , ' Can run scheduled jobs manually ' , 1 , 1 ) ,
( ' user_lifecycle_audit.view ' , ' Can view user lifecycle audit logs ' , 1 , 1 ) ,
( ' users.import ' , ' Can import users ' , 1 , 1 ) ,
( ' users.import_assignments ' , ' Can assign tenant, role and department during user import ' , 1 , 1 ) ,
( ' users.lifecycle_restore ' , ' Can restore users from lifecycle audit ' , 1 , 1 ) ,
( ' custom_fields.manage ' , ' Can manage tenant custom field definitions ' , 1 , 1 ) ,
( ' custom_fields.edit_values ' , ' Can edit user custom field values ' , 1 , 1 ) ,
( ' api_docs.view ' , ' Can view API documentation ' , 1 , 1 ) ,
( ' docs.view ' , ' Can view developer documentation ' , 1 , 1 ) ,
2026-02-11 19:28:12 +01:00
( ' mail_log.view ' , ' Can view mail logs ' , 1 , 1 ) ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
( ' api_audit.view ' , ' Can view API audit logs ' , 1 , 1 ) ,
2026-03-04 15:56:58 +01:00
( ' system_audit.view ' , ' Can view system audit logs ' , 1 , 1 ) ,
( ' system_audit.purge ' , ' Can purge system audit logs ' , 1 , 1 ) ,
2026-03-11 22:18:54 +01:00
( ' api_tokens.manage ' , ' Can manage user API tokens ' , 1 , 1 ) ,
2026-03-13 21:11:48 +01:00
( ' stats.view ' , ' Can view statistics ' , 1 , 1 ) ,
feat: add read-only System Info admin page with health checks and module inventory
New page at /admin/system-info with three tabs:
- Overview: PHP version, SAPI, environment, 6 health checks (DB, schema,
storage, RBAC baseline, admin role, scheduler heartbeat)
- Modules: table of active modules with version, dependencies, permission count
- Permissions: active/inactive counts and per-source breakdown
Gated behind new system_info.view permission assigned to Admin role.
No mutations — purely diagnostic/observability.
Includes SystemHealthService, SystemInfoService, SystemHealthRepository
with interface, DI registration, i18n keys (de+en), idempotent DB update
script, and 17 new PHPUnit tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 15:08:02 +01:00
( ' system_info.view ' , ' Can view system info and health status ' , 1 , 1 ) ,
2026-03-20 00:05:03 +01:00
( ' roles.assign_all ' , ' Can assign all roles (bypass assignable-roles check) ' , 1 , 1 ) ,
( ' notifications.view ' , ' Can view and manage own notifications ' , 1 , 1 )
2026-02-11 19:28:12 +01:00
ON DUPLICATE KEY UPDATE
` description ` = VALUES ( ` description ` ) ,
` active ` = VALUES ( ` active ` ) ,
` is_system ` = VALUES ( ` is_system ` ) ;
2026-02-04 23:31:53 +01:00
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
INSERT INTO ` scheduled_jobs ` (
` job_key ` ,
` label ` ,
` description ` ,
` enabled ` ,
` timezone ` ,
` schedule_type ` ,
` schedule_interval ` ,
` schedule_time ` ,
` schedule_weekdays_csv ` ,
` catchup_once ` ,
` next_run_at `
)
VALUES (
' user_lifecycle_run ' ,
' User lifecycle run ' ,
' Runs automatic user deactivate/delete policy ' ,
1 ,
' Europe/Berlin ' ,
' daily ' ,
1 ,
' 02:15 ' ,
NULL ,
1 ,
NULL
)
ON DUPLICATE KEY UPDATE
` label ` = VALUES ( ` label ` ) ,
` description ` = VALUES ( ` description ` ) ;
2026-03-04 15:56:58 +01:00
INSERT INTO ` scheduled_jobs ` (
` job_key ` ,
` label ` ,
` description ` ,
` enabled ` ,
` timezone ` ,
` schedule_type ` ,
` schedule_interval ` ,
` schedule_time ` ,
` schedule_weekdays_csv ` ,
` catchup_once ` ,
` next_run_at `
)
VALUES (
' system_audit_purge ' ,
' System audit purge ' ,
' Purges system audit entries by retention policy ' ,
1 ,
' Europe/Berlin ' ,
' daily ' ,
1 ,
' 03:00 ' ,
NULL ,
1 ,
NULL
)
ON DUPLICATE KEY UPDATE
` label ` = VALUES ( ` label ` ) ,
` description ` = VALUES ( ` description ` ) ;
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
INSERT INTO ` scheduler_runtime_status ` (
` id ` ,
` last_heartbeat_at ` ,
` last_result ` ,
` last_error_code `
)
VALUES (
1 ,
NOW ( ) ,
' ok ' ,
NULL
)
ON DUPLICATE KEY UPDATE
` id ` = ` id ` ;
2026-02-04 23:31:53 +01:00
INSERT INTO ` role_permissions ` ( ` role_id ` , ` permission_id ` , ` created ` )
SELECT r . id , p . id , NOW ( )
FROM roles r
JOIN permissions p ON p . ` key ` IN (
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
' users.view ' , ' users.view_meta ' , ' users.view_audit ' , ' users.create ' , ' users.update ' , ' users.access_pdf ' , ' users.delete ' ,
2026-02-04 23:31:53 +01:00
' users.self_update ' , ' users.update_assignments ' ,
' address_book.view ' ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
' tenants.view ' , ' tenants.create ' , ' tenants.update ' , ' tenants.sso_manage ' , ' tenants.delete ' ,
' departments.view ' , ' departments.create ' , ' departments.update ' , ' departments.delete ' , ' departments.import ' ,
2026-02-04 23:31:53 +01:00
' roles.view ' , ' roles.create ' , ' roles.update ' , ' roles.delete ' ,
' permissions.view ' , ' permissions.create ' , ' permissions.update ' , ' permissions.delete ' ,
2026-02-24 08:49:40 +01:00
' settings.view ' , ' settings.update ' , ' tenant.scope.global ' ,
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
' imports.view ' , ' imports.audit.view ' , ' jobs.view ' , ' jobs.manage ' , ' jobs.run_now ' ,
' user_lifecycle_audit.view ' , ' users.import ' , ' users.import_assignments ' ,
' users.lifecycle_restore ' ,
' custom_fields.manage ' , ' custom_fields.edit_values ' ,
' api_docs.view ' , ' docs.view ' ,
2026-03-11 22:18:54 +01:00
' api_tokens.manage ' ,
2026-03-04 15:56:58 +01:00
' mail_log.view ' , ' api_audit.view ' , ' system_audit.view ' , ' system_audit.purge ' ,
feat: add read-only System Info admin page with health checks and module inventory
New page at /admin/system-info with three tabs:
- Overview: PHP version, SAPI, environment, 6 health checks (DB, schema,
storage, RBAC baseline, admin role, scheduler heartbeat)
- Modules: table of active modules with version, dependencies, permission count
- Permissions: active/inactive counts and per-source breakdown
Gated behind new system_info.view permission assigned to Admin role.
No mutations — purely diagnostic/observability.
Includes SystemHealthService, SystemInfoService, SystemHealthRepository
with interface, DI registration, i18n keys (de+en), idempotent DB update
script, and 17 new PHPUnit tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 15:08:02 +01:00
' stats.view ' , ' system_info.view ' ,
2026-04-02 17:48:27 +02:00
' roles.assign_all ' ,
' helpdesk.access ' , ' helpdesk.settings.manage '
2026-02-04 23:31:53 +01:00
)
WHERE r . description IN ( ' Admin ' , ' Administrator ' ) OR r . id = 1
ON DUPLICATE KEY UPDATE role_id = role_id ;
2026-03-04 15:56:58 +01:00
2026-03-20 00:05:03 +01:00
-- Notifications are user-scoped and should be visible to all active roles by default.
INSERT INTO ` role_permissions ` ( ` role_id ` , ` permission_id ` , ` created ` )
SELECT r . id , p . id , NOW ( )
FROM roles r
JOIN permissions p ON p . ` key ` = ' notifications.view '
WHERE r . active = 1
ON DUPLICATE KEY UPDATE role_id = role_id ;
2026-03-11 20:24:18 +01:00
INSERT INTO ` role_permissions ` ( ` role_id ` , ` permission_id ` , ` created ` )
SELECT r . id , p . id , NOW ( )
FROM roles r
JOIN permissions p ON p . ` key ` IN ( ' users.self_update ' , ' address_book.view ' )
WHERE r . code = ' USER ' OR r . description = ' User '
ON DUPLICATE KEY UPDATE role_id = role_id ;
2026-03-13 21:11:48 +01:00
-- Manager: user & department management
INSERT INTO ` role_permissions ` ( ` role_id ` , ` permission_id ` , ` created ` )
SELECT r . id , p . id , NOW ( )
FROM roles r
JOIN permissions p ON p . ` key ` IN (
' users.view ' , ' users.view_meta ' , ' users.create ' , ' users.update ' ,
' users.update_assignments ' , ' users.access_pdf ' , ' users.self_update ' ,
' users.import ' , ' users.import_assignments ' ,
' address_book.view ' ,
' departments.view ' , ' departments.create ' , ' departments.update ' ,
' roles.view ' ,
' custom_fields.edit_values '
)
WHERE r . code = ' MANAGER '
ON DUPLICATE KEY UPDATE role_id = role_id ;
-- Auditor: read-only + audit logs
INSERT INTO ` role_permissions ` ( ` role_id ` , ` permission_id ` , ` created ` )
SELECT r . id , p . id , NOW ( )
FROM roles r
JOIN permissions p ON p . ` key ` IN (
' users.view ' , ' users.view_meta ' , ' users.view_audit ' , ' users.self_update ' ,
' address_book.view ' ,
' tenants.view ' , ' departments.view ' , ' roles.view ' , ' permissions.view ' ,
' settings.view ' ,
' imports.view ' , ' imports.audit.view ' ,
' user_lifecycle_audit.view ' ,
' mail_log.view ' , ' api_audit.view ' , ' system_audit.view ' ,
' stats.view ' , ' jobs.view '
)
WHERE r . code = ' AUDITOR '
ON DUPLICATE KEY UPDATE role_id = role_id ;
-- Support: helpdesk / user support
INSERT INTO ` role_permissions ` ( ` role_id ` , ` permission_id ` , ` created ` )
SELECT r . id , p . id , NOW ( )
FROM roles r
JOIN permissions p ON p . ` key ` IN (
' users.view ' , ' users.view_meta ' , ' users.view_audit ' ,
' users.update ' , ' users.self_update ' ,
' address_book.view ' ,
' departments.view ' , ' roles.view ' ,
' api_tokens.manage ' ,
2026-04-02 17:48:27 +02:00
' custom_fields.edit_values ' ,
' helpdesk.access '
2026-03-13 21:11:48 +01:00
)
WHERE r . code = ' SUPPORT '
ON DUPLICATE KEY UPDATE role_id = role_id ;
-- Admin role can assign every role (also has roles.assign_all permission as fallback)
INSERT IGNORE INTO ` role_assignable_roles ` ( ` role_id ` , ` assignable_role_id ` )
SELECT admin_role . id , all_roles . id
FROM roles admin_role
CROSS JOIN roles all_roles
WHERE admin_role . description IN ( ' Admin ' , ' Administrator ' ) OR admin_role . id = 1 ;
-- Manager can assign USER and SUPPORT roles
INSERT IGNORE INTO ` role_assignable_roles ` ( ` role_id ` , ` assignable_role_id ` )
SELECT mgr . id , target . id
FROM roles mgr
JOIN roles target ON target . code IN ( ' USER ' , ' SUPPORT ' )
WHERE mgr . code = ' MANAGER ' ;
2026-03-11 21:11:19 +01:00
INSERT INTO ` settings ` ( ` key ` , ` value ` , ` description ` )
SELECT ' default_tenant_id ' , CAST ( t . id AS CHAR ) , ' setting.default_tenant '
FROM tenants t
WHERE t . description = ' MusterMandant '
LIMIT 1
ON DUPLICATE KEY UPDATE
` key ` = ` key ` ;
INSERT INTO ` settings ` ( ` key ` , ` value ` , ` description ` )
SELECT ' default_department_id ' , CAST ( d . id AS CHAR ) , ' setting.default_department '
FROM departments d
JOIN tenants t ON t . id = d . tenant_id
WHERE d . code = ' MUSTER '
AND t . description = ' MusterMandant '
LIMIT 1
ON DUPLICATE KEY UPDATE
` key ` = ` key ` ;
INSERT INTO ` settings ` ( ` key ` , ` value ` , ` description ` )
SELECT ' default_role_id ' , CAST ( r . id AS CHAR ) , ' setting.default_role '
FROM roles r
WHERE r . code = ' USER '
LIMIT 1
ON DUPLICATE KEY UPDATE
` key ` = ` key ` ;
INSERT INTO ` settings ` ( ` key ` , ` value ` , ` description ` )
SELECT ' api_cors_allowed_origins ' , CONCAT ( ' http://localhost:8080 ' , CHAR ( 10 ) , ' http://127.0.0.1:8080 ' ) , ' setting.api_cors_allowed_origins '
ON DUPLICATE KEY UPDATE
` key ` = ` key ` ;
2026-03-04 15:56:58 +01:00
INSERT INTO ` settings ` ( ` key ` , ` value ` , ` description ` )
VALUES
2026-03-11 21:11:19 +01:00
( ' app_title ' , ' CoreCore ' , ' setting.app_title ' ) ,
( ' app_locale ' , ' de ' , ' setting.app_locale ' ) ,
( ' app_theme ' , ' light ' , ' setting.app_theme ' ) ,
( ' app_theme_user ' , ' 1 ' , ' setting.app_theme_user ' ) ,
( ' app_registration ' , ' 1 ' , ' setting.app_registration ' ) ,
( ' app_primary_color ' , ' #105433 ' , ' setting.app_primary_color ' ) ,
( ' api_token_default_ttl_days ' , ' 90 ' , ' setting.api_token_default_ttl_days ' ) ,
( ' api_token_max_ttl_days ' , ' 365 ' , ' setting.api_token_max_ttl_days ' ) ,
( ' session_idle_timeout_minutes ' , ' 30 ' , ' setting.session_idle_timeout_minutes ' ) ,
( ' session_absolute_timeout_hours ' , ' 8 ' , ' setting.session_absolute_timeout_hours ' ) ,
( ' user_inactivity_deactivate_days ' , ' 180 ' , ' setting.user_inactivity_deactivate_days ' ) ,
( ' user_inactivity_delete_days ' , ' 365 ' , ' setting.user_inactivity_delete_days ' ) ,
2026-03-04 15:56:58 +01:00
( ' system_audit_enabled ' , ' 1 ' , ' setting.system_audit_enabled ' ) ,
2026-03-06 00:44:52 +01:00
( ' system_audit_retention_days ' , ' 365 ' , ' setting.system_audit_retention_days ' ) ,
2026-03-11 21:11:19 +01:00
( ' frontend_telemetry_enabled ' , ' 1 ' , ' setting.frontend_telemetry_enabled ' ) ,
2026-03-06 00:44:52 +01:00
( ' frontend_telemetry_sample_rate ' , ' 0.2 ' , ' setting.frontend_telemetry_sample_rate ' ) ,
2026-03-11 21:11:19 +01:00
( ' frontend_telemetry_allowed_events ' , ' ajax_error,warn_once ' , ' setting.frontend_telemetry_allowed_events ' ) ,
2026-03-10 22:48:10 +01:00
( ' microsoft_auto_remember_default ' , ' 0 ' , ' setting.microsoft_auto_remember_default ' ) ,
( ' remember_token_lifetime_days ' , ' 30 ' , ' setting.remember_token_lifetime_days ' )
2026-03-04 15:56:58 +01:00
ON DUPLICATE KEY UPDATE
2026-03-06 00:44:52 +01:00
` key ` = ` key ` ;
2026-03-20 00:05:03 +01:00
-- =============================================
-- Seed: sample notifications for demo user
-- =============================================
INSERT INTO ` user_notifications ` (
` recipient_user_id ` , ` tenant_id ` , ` type ` , ` title ` , ` body ` , ` link ` , ` data ` , ` is_read ` , ` read_at ` , ` created `
)
SELECT
u . id ,
( SELECT t . id FROM tenants t ORDER BY t . id LIMIT 1 ) ,
n . type , n . title , n . body , n . link , n . data , n . is_read , n . read_at , n . created
FROM users u
CROSS JOIN (
SELECT ' user.created ' AS type ,
' Neuer Benutzer: Max Mustermann ' AS title ,
NULL AS body ,
' admin/users/edit/00000000-0000-0000-0000-000000000001 ' AS link ,
' {"user_id":99} ' AS data ,
0 AS is_read ,
NULL AS read_at ,
DATE_SUB ( NOW ( ) , INTERVAL 5 MINUTE ) AS created
UNION ALL
SELECT ' user.created ' ,
' Neuer Benutzer: Erika Musterfrau ' ,
NULL ,
' admin/users/edit/00000000-0000-0000-0000-000000000002 ' ,
' {"user_id":98} ' ,
0 ,
NULL ,
DATE_SUB ( NOW ( ) , INTERVAL 30 MINUTE )
UNION ALL
SELECT ' user.deleted ' ,
' Benutzer geloescht: Karl Schmidt ' ,
NULL ,
NULL ,
' {"user_id":97} ' ,
0 ,
NULL ,
DATE_SUB ( NOW ( ) , INTERVAL 2 HOUR )
UNION ALL
SELECT ' system ' ,
' Systemwartung abgeschlossen ' ,
' Alle Dienste laufen wieder normal. ' ,
NULL ,
NULL ,
1 ,
DATE_SUB ( NOW ( ) , INTERVAL 3 HOUR ) ,
DATE_SUB ( NOW ( ) , INTERVAL 4 HOUR )
UNION ALL
SELECT ' user.created ' ,
' Neuer Benutzer: Anna Weber ' ,
NULL ,
' admin/users/edit/00000000-0000-0000-0000-000000000003 ' ,
' {"user_id":96} ' ,
1 ,
DATE_SUB ( NOW ( ) , INTERVAL 1 DAY ) ,
DATE_SUB ( NOW ( ) , INTERVAL 2 DAY )
) n
WHERE u . email = ' demo@user.com '
AND NOT EXISTS ( SELECT 1 FROM user_notifications un WHERE un . recipient_user_id = u . id ) ;