NEW: [Auth] Time-based one-time password authentication factor. Requires 2FA app such as Authy, Google Authenticator, or YubiKey. See Authentication.md. [Cockpit] Cockpit integration. Requires TOTP enabled for admin. SSO is available as well. See Cockpit.md. [HTTP] HTTP Strict Transport Security header may be set for all websites under Account > Settings > SSL. Server defaults set in [httpd] => hsts_mode. Corresponding API methods into web:list_ssl, ssl_set, and ssl_remove. [Internal] Accounts logged in with TOTP include an "extended auth" flag. A new permission class, PRIVILEGE_EXTAUTH, is introduced to validate API permission against this mode. [pgsql] get_table_sizes()- report relation sizes within a database. [PHP] ionCube, SourceGuardian PHP 8.4 support. [Plans] "opcenter plan:edit". See Plans.md. [Postfix] New "maintenance" transport. Domains with a maintenance destination are temporarily deferred until removed. See Postfix.md. [PostgreSQL] v17 support. [Scopes] mysql.big-selects, control max_join_size enforcement in MariaDB. [UI] Inline SVG icons within menu items as 4th parameter. [UI] Session multipath. Supports several thousand concurrent sessions in same browser instance. Requires setting [frontend] => multipath_length to a non-zero integer. This represents the session id characters used in url generation. [upcp] Staggered updates are now possible. cp.update-offset Scope sets a duration in hours for release pipeline to remain clean to treat the release as "cured" and thus deployable. [WordPress] Language support. New API calls, {un,in}stall_language, language_status. FIXED: [API] General euid privilege de-escalation fixups. [Cloudflare] 2024-11-30, "Zone information in individual DNS records" deprecation. [Discourse] Various. Bump minimum v18 Node to 18.20. MaxMind API key new format. restart() assumes launched by Passenger. [file] purge() retains translated path cache. [Laravel] .env values containing a space require quotes. [Mail] Catch-all delivery for non-addon subdomains relies on irresolvable hostname. Refer to primary domain in siteinfo to generate username. [Manage Users] "Reset Password" user option has no effect. [PostgreSQL] socket peer authentication ignores effective UID. [Screenshots] Cloudflare Turnstile can force client to compute interminable code. Introduce a timeout ([screenshots] => request_timeout) to abort page render if encountered. [Storage Usage] Sites with over 1 million files may exhaust memory during file list generation. [Web Apps] App pending install reports future version path in event of docroot relink. [Web Apps] An overrode app type in a Manifest still reports initial app. CHANGED: [API] php:pool_set_policy() collapses multidimensional arrays if the PHP directive contains a dot. Note that nested settings prevail if a similar directive exists unnested. [API] Rename get_autoload_class_from_module() to simply get_class_from_module(). Addresses confusing scenario in which code would load internal module instead of surrogate during housekeeping routines. [Auth] Session cache duration matches logout limit. [Bootstrapper] Throttle concurrent make jobs if per-core load exceeds 125%. [Bootstrapper] Run mysql_upgrade if MariaDB were upgraded from a previous version during password recovery. [Laravel] Update Laravel to v7, Horizon to v4 for future OAuth2 support. Horizon upgrade will pose no potential breaking changes. Laravel v7 may introduce minor changes with custom applications. See https://laravel.com/docs/7.x/upgrade [Letsencrypt] Gracefully handle unlikely scenario record-exists() + remove-record() both repeatedly return true in certain scenarios like a wildcard CNAME in which the target also contains TXT records. [Logging] Forward exception stack. Requires passing original exception as final parameter to error()/warning()/info() macro. [Map] Possible to create ini, unbounded json, and textfile maps from strings. [Monit] Switch daemon from TCP to UDS. Workaround for firewall-cmd --panic-on scenarios that arise during firewalld reload if a list contains overlapping entries (cf. firewalld/firewalld#1343). [Opcenter] Rename reseller,reseller_id => reseller,id. A migration is included to perform this on the server. [PHP] pool_set_state() no longer restarts a deactivated pool pending socket activation. [Postfix] SMTP smuggling protection is always active. [Python] Move pyenv to apisnetworks/pyenv repository to patch out "pyenv rehash" usage until RHEL-22464 resolves. [Rampart] rampart.fail2ban-whitelist supports multiple IP addresses. [Subdomains] Creating a local subdomain creates all ancestors. [Subdomains] Restrict adding a global subdomain if its parent path is unresolvable. [UI] Logging out from a subordinate (hijacked) account destroys all parent sessions as well. [UI] Report if a quota is dynamic (project quota, see Resource enforcement.md), cgroup memory/CPU/proclimit dynamic (nested cgroup), and OOM events in Dashboard. [UI] Site Administrator may now be disenrolled from all services except panel login. Combine with TOTP/PHP privilege separation to boost security of an account. [web] rename_subdomain() preserve DNS settings on path rename. Refer to forums post #700. [Web Apps] Failure/success callback order is non-deterministic when shared in same PHP array. [WordPress] Changing user now updates FTP_USER. REMOVED: [API] user_enabled() deprecated in favor of user_permitted(), a logical complement to permit_user()/deny_user() module calls. [Auth] Explicit authentication prior to apnscpFunctionInterceptor instantiation unnecessary. afi creation will call Auth::handle() if needed using the registered handler for its active gate. [Postfix] proxymap intermediary adds unnecessary latency in singleton services - tlsmgr + postscreen. [Postfix] TLS server-side session cache obviated by session tickets. Introduce client-side session cache for smtp instances.