Product
|
Directus v12.5: Licensing Enhancements, Guardrails for the Public Policy, and a Preview Base URL
A safer way to edit your Public policy, licensing upgrades, a project-wide Preview Base URL, and stricter IP and TFA handling.

Bryant Gillespie
Staff Product Engineer

Editing the Public policy now comes with warnings and a confirmation step, a failed license renewal no longer takes your license down with it, and previews get a project-level base URL. Under the hood, Two Factor Authentication (2FA) enforcement, IP validation and schema building all got stricter.
Before we dive in, I want to highlight a few potential breaking changes you should be aware of:
Breaking Changes
🟡 2FA enforcement uses effective permissions: Policies with an IP allow list are now accounted for when enforcing 2FA, so 2FA is enforced within the allowed range. If you combine IP allow lists with 2FA, verify that the behavior matches what you expect.
🟡 License handling and /server/license response changed: A failed license request now keeps your current license in effect and is retried by a scheduled license check. The /server/license response no longer includes downgrade_reason. Read invalid_reason instead, which also reports why a license that is still in effect could not be renewed. In @directus/errors, LicenseManagedByEnvError, LicenseOfflineUnsupportedError, LicenseResolveIncompleteError and LicenseServiceUnavailableError are gone, along with their error codes. License request failures now surface as LICENSE_INVALID with a failure extension, or as the standard FORBIDDEN, INVALID_PAYLOAD, REQUESTS_EXCEEDED and SERVICE_UNAVAILABLE errors. License validation also now accepts only Directus keys and tokens.
🟡 Stricter IP validation: The ip-matching dependency has been removed, and policy ip_access and IMPORT_IP_DENY_LIST values are now validated more strictly. Subnets with a malformed prefix, such as 10.0.0.0/ 24 or 10.0.0.0/+24, are no longer accepted. Existing policies that already store such a value will fail every request for users with that policy, so check your stored values before upgrading.
🟡 Schema build settings changed: CACHE_SCHEMA_MAX_ITERATIONS has been removed. CACHE_SCHEMA_SYNC_TIMEOUT now also limits the schema build itself and defaults to 60000 ms. If you’ve set a lower value, make sure it’s long enough for your schema to finish building.
🟡 Corrected system type definitions: The types for directus_notifications, directus_permissions, directus_extensions, directus_fields, directus_activity, directus_collections and directus_revisions were updated to match the API, so TypeScript projects may see new compile errors.
You can see the full list of breaking changes in the changelog.
Licensing Upgrades
Previously, a failed license request could leave a project in an awkward state. Now, a failed request keeps your current license in effect and a scheduled check retries it. The app shows a warning explaining why the license couldn’t be renewed and when it lapses, so you have time to act before anything changes.
Two related fixes:
License boot no longer holds a lock for the entirety of startup.
License validation now accepts only Directus keys and tokens.
The bottom line: A temporary hiccup during license renewal no longer interrupts your project, and you get clear warning if something needs attention.
Guardrails for the Public Policy
The Public policy controls what anyone can read without logging in, which makes it one of the most consequential settings in a project. v12.5 adds two protections:
A persistent warning notice whenever you edit the Public policy.
A confirmation dialog when you save Public policy permission changes on system collections.
Neither stops you from doing what you intended. They make sure you meant to.
Preview Base URL
There’s a new Preview Base URL project setting. You can select it as a variable in a collection’s Preview URL, so you set the base address of your frontend once instead of repeating it in every collection. That makes it easier to point previews at a different environment later.
Manage Flows in Bulk
Following the Flows module in 12.4, the header bar now has buttons to set multiple selected Flows to active or inactive in one go.
Other Improvements
GraphQL: Fixed not-null fields with a default value being marked nullable in queries, and fields with falsey default values being marked required in create mutations.
Collections: Creating a collection with neither schema nor meta now returns a 400 validation error instead of a misleading 403.
OpenAPI: The spec version now changes only when the generated spec does.
Performance: New opt-in hash option for Redis memory improves cache clear performance.
Environment: The default environment values are now exported as
DEFAULTSfrom @directus/env.SDK: readActivity, deletePermission, readPermission, updatePermission, readItemPermissions, readNotification and readRevision now reject a null or undefined key or collection.
AI translations: Fixed duplicate target language rows when streaming multiple fields.
Check out the full release notes on GitHub for the complete changelog.
Directus v12.5 is Available Now
Update your instances to get the Public policy guardrails, more resilient licensing, Preview Base URL, and everything else in this release. Before you do, check your stored ip_access values and your CACHE_SCHEMA_* settings, and review the breaking changes above if you use the SDK types.
As always, back up your database before upgrading.
Ready to move faster?
30 minutes with a product specialist. See how Directus fits your stack.
KEEP EXPLORING
Explore the product context, implementation paths, and more guides from Directus.