* 🐛 Add backend password validation with complexity rules and dictionary check
Enforce minimum 8-character password length, require at least 1 lowercase
letter, 1 uppercase letter, 1 digit, and 1 special character, and reject
common passwords using Passay library with a 10k-entry wordlist from
SecLists during registration and password change flows.
AI-assisted-by: mimo-v2.5-pro
* ✨ Improve user feedback
When the password is invalid, the user now gets extra indications to make it stronger, so it can be valid.
* 🐛 Fix remove unneeded common password check
The dictionary check is only relevant for passwords that meet all other requirements, but all 10,000 common passwords would fail the character requirements, so this check is not needed
---------
Co-authored-by: Luis de Dios <luis.dedios@kaleidos.net>
* ♻️ Rename nitrate config to admin-console
Rename user-facing configuration from 'nitrate' to 'admin-console':
- Feature flags: :nitrate -> :admin-console, :nitrate-bulk-create-profiles -> :admin-console-bulk-create-profiles
- Config keys: :nitrate-shared-key -> :admin-console-shared-key, :nitrate-backend-uri -> :admin-console-uri
- Shared-keys map entry: :nitrate -> :admin-console (setup.clj + main.clj)
- Env vars: PENPOT_NITRATE_SHARED_KEY -> PENPOT_ADMIN_CONSOLE_SHARED_KEY, PENPOT_NITRATE_BACKEND_URI removed (consolidated into PENPOT_ADMIN_CONSOLE_URI)
- Docker/nginx: PENPOT_NITRATE_URI -> PENPOT_ADMIN_CONSOLE_URI
Code namespaces, file paths, CSS classes, and i18n keys stay as-is.
AI-assisted-by: mimo-v2.5-pro
* ♻️ Rename initialize-user-in-nitrate-organization to initialize-user-in-organization
Part of the nitrate -> admin-console rename series. The function and all 9 references across 6 files have been renamed.
* ♻️ Rename :nitrate-bulk-create-profiles-not-allowed to :bulk-create-profiles-not-allowed
* ♻️ Inline nitrate-permissions into app.common.types.organization
- Delete app.common.types.nitrate-permissions and its test
- Move permission rules (allowed?, can-send-invitations?, etc.) into organization.cljc
- Harmonize all consumers to use alias cto for app.common.types.organization
- Update test runner and create organization_test.cljc
* 🎉 Improve reset to default flow
* 🎉 Add diff modal
* 🐛 Fix measurement shortcuts
* 🎉 Separate open-sections for each tab
* 🐛 Align button link icon
* 🎉 Reset only works after press save
* 🐛 Fix little things
* 🎉 Make the import export row to be fixed
* ♻️ Fix CI
* 🐛 Cancel shortcut is not appearing on disabled tab
* 🐛 Fix tests
* 🐛 Fix loop on personalized
* 🐛 Fix show measurements shortcut
The change-password form validated the existing password against the 8-character policy, locking out accounts whose current password predates it.
Closes#10626
Signed-off-by: Akshit Nassa <akshitnassa412@gmail.com>
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
Co-authored-by: Akshit Nassa <akshitnassa412@gmail.com>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
* ✨ Add MCP connection badge to the workspace toolbar
* ✨ Add MCP status button with single-tab connection control
* ♻️ Extract component for MCP indicator in the toolbar
* ♻️ Some improvements
---------
Co-authored-by: Luis de Dios <luis.dedios@kaleidos.net>
Render owned organizations in the delete-account modal with the same
org-avatar* component used across the dashboard, so logo and avatar
background are shown consistently and initials are extracted via
d/get-initials instead of a raw first-character substring.
Extends the get-owned-organizations-summary endpoint and the underlying
nitrate API schema to carry :avatar-bg-url and :logo-id, deriving
:custom-photo from logo-id with the public uri, matching the pattern
already used by set-team-org-api.
When the Stripe checkout fails to start, the subscription page now
shows an inline error in the Business Nitrate card under the CTA
instead of a toast. When the post-payment activation fails, the toast
message is updated to point users to support@penpot.app.
The nitrate-form modal also passed a URI object to
build-nitrate-callback-urls while the underlying append-query-param
relied on lambdaisland's u/parse, which only accepts strings. Switched
to the local u/uri helper so both strings and URI records work, so
failures opened from the modal land on the subscription page.