Skip to content

Platform 4.0

Platform 4.0 adds the access module to the backend service and carries a round of security fixes across the service, the modules and the CMS. The versions are in Versions below.

  • Access module. entirius-django-access joins the service. Staff get roles: the built-in Administrator, Manager, Editor and Viewer, and custom roles made of read and write permissions per module area. A gate in front of the admin API answers a request without the needed permission with 403; it runs in enforce by default and has an observe mode that only logs. Machine clients get application tokens with scopes, an optional channel pin, rotation and an optional expiry, and every change is written to an audit log. The CMS has an Access panel for roles, staff, groups, applications and the audit log, hides the panels a user cannot read and shows a page the user may only read without its writing actions. How it fits together: Access and API Tokens.
  • One key system. With the access module installed, the storefront, erase, contact form, returns, reviews and vault keys are verified as access tokens. The keys an installation already has are imported as tokens with the same secret, so callers keep working.
  • AI toolbox switch. AI_TOOLBOX_ENABLED = False switches the AI toolbox off on purpose. Nothing fails and nothing alerts: the health check passes with the state disabled, AI drafts, rewrites and translations answer 503 AI_TOOLBOX_DISABLED before anything is written, and the CMS turns its AI actions off with one hint. What runs without the toolbox: AI Toolbox.
  • Modules without their siblings. No module in the registry of the service (modules.yaml) forces another one any more. Matrix, QMS, FAQ, delivery points and the shared utilities no longer crash when an optional sibling app is installed but not enabled.
  • API document. The OpenAPI document and its Swagger and ReDoc pages are served to staff only, unless the installation sets API_SCHEMA_PUBLIC = True. Operations that fell back to the default tag carry a named one, paginated lists are generated as list operations, and URL examples use api.example.com.
  • Public documentation. This portal is public at docs.entirius.com from this release. It describes the platform version shown in the header, and every later release gets an entry on Release Notes.
  • api/token/ counts failed logins per username and address, per address and per username. At a limit it answers 429 with Retry-After, also for a correct password.
  • The Django admin login form counts on the same counters. It accepted unlimited guesses before, also while api/token/ was blocked.
  • The default authentication of the REST framework is JWT only. It was unset, so a public route that declares no classes answered differently for a right and a wrong password sent as Authorization: Basic. The deployment check volkanos.E002 fails when Basic or session authentication is back in the defaults.
  • Setting an expiry on a token that is already expired is refused with 409. A new date used to make it valid again.
  • A per-process default cache is the error django_access.E012 under check --deploy: with such a cache a revoked grant keeps working in the other workers and the login limits multiply by the worker count.
  • Creating a staff account answers a taken username and a taken e-mail address with one 409 message that names neither the field nor the account.
  • The CMS staff login customer/tokens/ runs the failed-login guard of the access module when it is installed: 429 with Retry-After before the password is checked.
  • The signup response no longer echoes the password that was sent. It returned the whole request body.
  • PATCH customer/<uid>/profile/ saves the first name, last name and sex. It answered 200 and stored nothing.
  • customer/tokens/ answers 403 user_not_customer for a valid login without a customer profile. It answered 500.
  • The public order-agreement write is throttled per address. It had no throttle.
  • Where checkout is enabled, the same write needs an order of the URL’s channel whose billing or shipping e-mail is the one sent, and answers 404 otherwise. Any order id and any address were accepted before.
  • A second write for the same order records nothing twice. It used to fail with HTTP 500.
  • Legal text taken from stored page content is sanitised before it is returned. It was returned as stored, scripts and event handlers included.
  • Links in sanitised agreement HTML keep an href only without a scheme or with http, https or mailto.
  • The public order-agreement write refuses a cookies definition with HTTP 400.
  • The payment and pay-code throttles count the client, not the reverse proxy, once the number of trusted proxies is set. Behind a proxy the whole shop shared one allowance.
  • A PayU method without second_key is reported by the system check django_checkout.W001, and a notification refused for that reason is logged once per method.
  • The router roots of the v1 public and admin APIs ignore credentials. Under the framework defaults they answered differently for a right and a wrong password sent as Authorization: Basic.
  • Page HTML is sanitised on write: creating, updating and publishing a draft keep only the markup the CMS editor writes. Content stored earlier is sanitised the next time it is saved or published.
  • point_service.update_point applies only the listed point fields and refuses any other keyword. The admin API is unchanged.
  • The public v2 views ignore credentials. They evaluated Authorization: Basic outside any login throttle in a service that left the framework defaults.
  • POST /api/munin/v2/health/check/ runs live probes and needs the write level of munin.config. It was mapped to read. The cached GET /api/munin/v2/health/ stays readable.
  • The return views read the customer’s orders and returns of the URL’s channel only. A token pinned to one channel could read the same customer’s data of another one.
  • The returns listing sorts by created_at, modified_at or status only. The client’s field went to the query unchecked.
  • Testing a supplier feed needs the write level of suppliers.sources, and its limit is capped. A read-only role could fetch a feed with the stored credentials.
  • verify_captcha logs a warning for each decorated view when the captcha package is installed but not enabled, so an app dropped by mistake is visible.
  • Stored HTML is cleaned where it is rendered: the rich-text previews of the page builder and the legal texts of the Agreements panel.
  • The session cookies are set with SameSite=Strict, and with Secure when the CMS is served over https.
  • A URL from the server reaches a link only as http, https or mailto, and every link that opens a new tab carries rel="noopener noreferrer".
  • A production build ships no source maps and fails when VUE_APP_USERNAME or VUE_APP_PASSWORD is set.
  • In debug mode the login call and every access token call are logged as [redacted].
  • The visual and docs capture projects refuse a CMS or API address that is not a loopback host unless CMS_ALLOW_REMOTE=1 is set.

This is a major release for three reasons: the keys of the modules are replaced by access tokens, so an integrator creates and manages keys in a new place; the service accepts only JWT by default, no Basic or session login on the API; and the access module is a required dependency of the service. The steps below take a service from 3.x to this release. The general procedure: Versioning and Upgrades.

  1. Trusted proxies. Set DRF_NUM_PROXIES in the local settings before upgrading: 0 without a proxy, otherwise the number of trusted proxies in front of the service. Unset, check --deploy fails with volkanos.E001, and the throttles see the proxy as the one client of the whole shop. Notes: service changelog.
  2. REST framework settings. An environment that replaces REST_FRAMEWORK as a whole in its local settings keeps the DEFAULT_AUTHENTICATION_CLASSES key, or check --deploy fails with volkanos.E002.
  3. Shared cache. A deploy whose default cache is per-process fails check --deploy with django_access.E012. Set a shared cache.
  4. Access preflight. The access module needs PostgreSQL 15 or later. Before the first deploy, list the admin routes without an access area (manage.py access_routes --unmapped); an installation with its own Django apps deploys the first time with ACCESS_GATE_MODE = "observe" and switches to enforce once the log is clean. On first adoption every active staff user who is not a superuser gets the Manager role; access management stays with superusers until someone is granted Administrator, and the Django admin is open to superusers only. Notes: access upgrade notes.
  5. Legacy API keys. migrate imports the keys of the module key tables and AGREEMENTS_API_KEY as access tokens with the same secret. Check that every key arrived: manage.py access_import_legacy_keys --check exits 1 while one is missing. The per-module key commands refuse from now on and name access_token create. An imported erase key is pinned to its channel: it erases customers, orders and carts of that channel only. Notes: accounts changelog, checkout changelog.
  6. PayU second_key. Every PayU payment method (payu, payu_card, payu_blik) needs second_key, the second key of the POS in the PayU merchant panel, in its additional_data. A notification that cannot be verified is answered 403, so a method without the key confirms no payment. manage.py check --database default lists the methods that lack it as django_checkout.W001. Notes: checkout changelog, section Upgrade notes.
  7. Scripts and roles. A script that sends wrong passwords to api/token/ is answered 429 at the limit. A role with read only loses the supplier feed test and the live configuration-health check, which need the write level. The OpenAPI document needs a staff login unless API_SCHEMA_PUBLIC = True.
  8. CMS build. Remove VUE_APP_USERNAME and VUE_APP_PASSWORD from the production build environment and keep them in .env.development.local. Serve the CMS over https, or the session cookies are not Secure. Notes: CMS changelog.

Patch of 2026-10-13. The service pins entirius-django-matrix 4.4.1: products no longer go missing from the storefront API after a seed or a large import. Two fills of the read model that overlapped on one channel deleted each other’s rows. An installation that ran the first service version of this release and lists fewer products than its catalog rebuilds the read model once: Troubleshooting.

ComponentVersionReleases
Platform 4.0.1 entirius-service-volkanos
Backend service 4.0.1 entirius-service-volkanos
Admin CMS 3.2.0 entirius-pwa-cms
Access module 1.0.0 entirius-django-access

Every other module has the version the lock of the service pins: Module Catalog.

Versioning and Upgrades