Webhook target checks, enumeration-safe sign-up, API validation, and organisation and dashboard access fixes.
**Webhook target checks, enumeration-safe sign-up, API validation, and
organisation and dashboard access fixes.**
Upgrading needs no migration. Two behaviour changes to be aware of:
webhooks pointing at private or internal addresses stop being delivered
(each attempt is logged as failed), and new sign-ups are no longer
signed in until they click the verification link.
Security
- Webhooks: target URLs must be
http(s)and resolve only to public addresses. Loopback, private networks (RFC 1918,fc00::/7), link-local (incl.169.254.169.254), CGNAT, multicast, reserved and IPv4-in-IPv6 forms are refused, in any notation (decimal, octal, hex), and cloud metadata endpoints are always refused. The check runs when a webhook is saved (Settings pane toast, API400) and again before every delivery; a blocked delivery is logged as failed and nothing is sent. Requests go to the exact address that passed the check (DNS-rebinding safe, TLS still verified against the hostname), ignore proxy settings, and never follow redirects (a3xxis logged as a failed delivery). New settingWEBHOOK_ALLOW_PRIVATE_TARGETS(env var, default off) allows private targets for local testing only (apps/api/url_safety.py). - Sign-up: the registration form no longer says "A user with that email already exists." Signing up with a registered address creates nothing and emails the owner ("someone tried to sign up with your address; sign in or reset your password"); the visitor sees the same "Check your email" page as a new sign-up (
/accounts/register/done/). New accounts are signed in by the verification link instead of right after sign-up. The password-reset confirmation page now reads "If an account exists for the email address you entered…". - Organisations: only owners can grant the owner role, by role change or invitation; admins can no longer promote themselves. The last owner can't step down until someone else is an owner.
- Organisations: pending invitations on the Members page are listed for owners and admins only.
- Staff-only pages: the CRM, eCommerce and SaaS dashboards, the charts showcase, the onboarding wizard and the forms, widgets, datatable, API-docs and maps showcase pages are staff-only on the server, not just hidden in the sidebar (anonymous → login, non-staff → 403). New
NavItemAccessMixin/@nav_access_requiredenforce a page'sNavItem.requires_staffflag. The marketing pages and the coming-soon, maintenance and 503 pages stay public by design. Giveis_staffto any account that should keep these pages.
Fixed
- API:
POST /api/v1/products/withoutcategory_id, or with an unknown one, returns400 {"detail": "category_id: …"}instead of a 500. Products created through the API get a unique slug from their name (the second one used to fail with a 500). Model rules (choices, lengths, non-negative stock, decimal size, valid email) are checked on product create, customer create/PATCH and webhook create, and PATCHing a customer field tonullis a 400. - Docs: webhook delivery was documented as "retried with exponential backoff"; it is one attempt per event and webhook (5-second timeout), every attempt in the delivery log. The API docs, README and Settings copy now say so and explain how to add retries with a task queue.
- Confirmations and auto-submit under the CSP: inline
on*=handlers never ran under the nonce-only Content-Security-Policy, so delete/void confirmations were skipped (forms submitted straight away), the language picker and organisation role select did nothing, and the toast demo and offline "Try again" were dead. Templates now usedata-confirm,data-autosubmitanddata-reload, handled by delegated listeners instatic/js/app.js. - MultiSelect widget: chips and options render again. Widget JSON in Alpine
x-dataattributes (and thejson_dumpsfilter) is no longer marked safe, so a label with a quote can't break the attribute. - Table search fires on any input (paste, autofill), not only on key presses.
- Command palette: label matches rank above keyword-only matches, so "ord" opens Orders rather than the eCommerce dashboard.
- E2E suite: the cache is cleared between tests so the login throttle no longer fails the second half of the run, and tests that had drifted from the UI and seed data (datatable counts, CSV download, archived customer, mail recipient combobox, Spanish sidebar label) are updated.
- Version synced to 0.1.4 in
pyproject.toml,package.json, and the lockfiles.