Central Application Settings — Developer Guide
Core types
| Piece | Role |
|---|---|
App\Support\SystemSettingDefinitions | Catalog of keys, groups, types; obsolete key list; sensitive keys |
App\Services\Central\SystemSettingService | Cache, typed get/set, runtime config, public bootstrap, branding uploads, password defaults |
App\Services\Storage\FileUploadService | Disk-agnostic store/replace/delete/url for branding and future uploads |
SystemSettingController | Admin list/update, test-mail, branding upload |
PublicSettingsController | GET /public/settings, gated workspace registration |
EnsureTenantApplicationAvailable | Tenant API 503 when maintenance_mode |
App\Rules\PasswordRule | Centralized password policy from settings |
App\Mail\SystemSettingsTestMail | Test message using company/support branding |
Boot
AppServiceProvider::boot() calls:
$settings->applyRuntimeConfig();
$settings->configurePasswordDefaults();applyRuntimeConfig() overlays app.name, timezone, locale, session lifetime, Cashier currency, and mail via EmailManager (SMTP / Postmark / Mailgun / log / array / sendmail).
Password::defaults() and PasswordRule both read live settings (min length + special character).
Admin API
| Method | Path | Notes |
|---|---|---|
| GET | /api/central/v1/system-settings | Masked secrets |
| PUT | /api/central/v1/system-settings | { "settings": { "key": value } } |
| POST | /api/central/v1/system-settings/test-mail | { "email": "…", "settings"?: {…} } — structured result; optional unsaved draft |
| POST | /api/central/v1/system-settings/branding/{asset} | Multipart file → FileUploadService. Assets: logo, favicon, auth-image-login, auth-image-register, auth-image-forgot-password, auth-image-reset-password, auth-image-email-verify |
| GET | /api/central/v1/email-logs | Filter by status/provider/date/search |
| GET | /api/central/v1/email-logs/{uuid} | Show one log |
Permissions: system-settings.list, system-settings.update, email-logs.list, email-logs.view.
Empty / ******** secrets (mail_password, Postmark token, Mailgun secret) on update leave existing encrypted values unchanged.
Mail keys include mail_provider (canonical; mail_driver mirrored), SMTP fields, mail_reply_to, mail_timeout, provider credentials, and ops_notification_email. That mailbox receives new feedback, beta applications, and self-service workspace signups. It is not part of the public bootstrap. An empty value sends none of those alerts. Runtime apply lives in App\Services\Email\EmailManager.
Branding assets use the configured branding disk (FILESYSTEM_BRANDING_DISK, defaults to uploads). Logo/favicon under branding/logos / branding/favicons; auth panel images under branding/auth-images/{asset}. See object-storage.md.
Public bootstrap includes logo_url, favicon_url, button_color, and auth_image_*_url for guest auth pages.
Public API
| Method | Path | Notes |
|---|---|---|
| GET | /api/central/v1/public/settings | Bootstrap payload — no secrets |
| POST | /api/central/v1/public/register-workspace | 403 when registration disabled |
Frontend
| Piece | Role |
|---|---|
useSettingsStore | Bootstraps public settings; sets document.title, favicon, CSS --primary |
formatAppDate / formatAppDateTime | @/lib/datetime — PHP-style formats → dayjs |
/register | Registration-closed page when disabled |
| Tenant mode | Full-screen maintenance page when maintenance_mode |
Notifications / mail
Tenant + Central password-reset and invite notifications use:
companyName()for salutationsupportEmail()when set- Runtime mail From from settings
Schema / seed
- Migration
2026_07_12_160000_refactor_central_system_settingsmigratesprimary_color→button_colorand drops obsolete keys. SystemSettingsSeederseeds the catalog and deletes obsolete keys.
Tests
php artisan test --compact tests/Feature/Central/Settings/SystemSettingsTest.phpPlaywright: npm run test:e2e:settings in EloSync-Frontend.
Tenant workspace overrides: see tenant-settings-developer.md.