* 🐛 Fix incorrect invitation token handling on register process
- Reject prepare-register-profile when an active profile already
exists for the requested email.
- Stop embedding an existing profile's :profile-id into the
prepared-register JWE. Profile resolution in register-profile is
now done exclusively by email lookup, never by a JWE claim.
- Add created? guard to the invitation-success branch in
register-profile, so existing profiles (active or not) cannot
reach session creation via anonymous registration.
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
* ♻️ Restructure invitation handling inside register-profile
Move the invitation-success branch into the created? sub-cond so it
sits alongside the other post-creation branches, making the control
flow consistent.
- Active new profile + matching invitation: mint session and return
:invitation-token (frontend redirects to :auth-verify-token).
- Not-yet-active new profile + matching invitation: embed the
invitation token inside the verify-email JWE and send the
verification email. When the user clicks the link, they get
logged in and the frontend completes the team-invitation flow.
- Extend send-email-verification! with an optional invitation-token
parameter propagated into the verify-email JWE claims.
- Update the frontend verify-email handler to navigate to
:auth-verify-token when the response carries :invitation-token.
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
* 🐛 Handle email-already-exists error on registration form
Add a specific handler for the [:validation :email-already-exists] error
code in the registration form's on-error callback. The backend raises
this error when an active profile already exists for the requested email,
but the frontend was falling through to the generic error message.
Now it shows the existing "Email already used" i18n message instead of
the generic "Something wrong has happened" toast.
* 🐛 Reset submitted state on registration form error
The on-error handler in the registration form was not resetting the
submitted? state, causing the submit button to remain disabled after
any error. The completion callback in rx/subs! only fires on success,
not on error.
Add (reset! submitted? false) at the beginning of the on-error handler
so the form becomes submittable again after any error, allowing the user
to fix their input and retry.
---------
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
* 🐛 Fix incorrect invitation token handling on register process
- Reject prepare-register-profile when an active profile already
exists for the requested email.
- Stop embedding an existing profile's :profile-id into the
prepared-register JWE. Profile resolution in register-profile is
now done exclusively by email lookup, never by a JWE claim.
- Add created? guard to the invitation-success branch in
register-profile, so existing profiles (active or not) cannot
reach session creation via anonymous registration.
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
* ♻️ Restructure invitation handling inside register-profile
Move the invitation-success branch into the created? sub-cond so it
sits alongside the other post-creation branches, making the control
flow consistent.
- Active new profile + matching invitation: mint session and return
:invitation-token (frontend redirects to :auth-verify-token).
- Not-yet-active new profile + matching invitation: embed the
invitation token inside the verify-email JWE and send the
verification email. When the user clicks the link, they get
logged in and the frontend completes the team-invitation flow.
- Extend send-email-verification! with an optional invitation-token
parameter propagated into the verify-email JWE claims.
- Update the frontend verify-email handler to navigate to
:auth-verify-token when the response carries :invitation-token.
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
* 🐛 Handle email-already-exists error on registration form
Add a specific handler for the [:validation :email-already-exists] error
code in the registration form's on-error callback. The backend raises
this error when an active profile already exists for the requested email,
but the frontend was falling through to the generic error message.
Now it shows the existing "Email already used" i18n message instead of
the generic "Something wrong has happened" toast.
* 🐛 Reset submitted state on registration form error
The on-error handler in the registration form was not resetting the
submitted? state, causing the submit button to remain disabled after
any error. The completion callback in rx/subs! only fires on success,
not on error.
Add (reset! submitted? false) at the beginning of the on-error handler
so the form becomes submittable again after any error, allowing the user
to fix their input and retry.
---------
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
Introduce a new OpenCode workflow skill that guides users through
backporting commits by applying diffs instead of using cherry-pick.
This is useful when cherry-pick is undesirable (e.g. divergent
histories, binary conflicts, or partial porting).
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
Two coupled defects made shape.applyToken(), token.applyToShapes() and
token.applyToSelected() silently no-op when invoked from JavaScript with
an array of strings (e.g. token.applyToShapes([rect], ["fill"])):
1. token-attr-plugin->token-attr only consulted its alias map when the
input was already a keyword; string inputs fell through unchanged,
causing downstream token-attr? to return false.
2. The inner schemas used plain [:set ...] which lacks the :decode/json
transformer for JS array -> Clojure set coercion. Switching to
Penpot's custom [::sm/set ...] lets the standard JSON decoder
pipeline handle the conversion automatically.
This is a backport of commit 1eac3e2be5f973359ad2ec9bac4e80a9d5a9e022
which fixes GitHub #9162.
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
Improve MCP instructions on design creation:
* Agents should make use of layouts when appropriate
* Agents should name all elements appropriately
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
Update agent configurations: change commiter mode to all, rename
engineer agent to "Penpot Engineer", and remove obsolete testing agent.
Add new read-only planner agent for architecture analysis and planning.
Add four new skills: bat-cat (syntax-highlighted cat clone), fd-find
(fast file finder), jq-json-processor (JSON processor), and ripgrep
(fast text search).
Add fd-find and bat packages to devenv Dockerfile.
Update .gitignore to exclude opencode package-lock and plans directory.
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
Expand the Pull Requests section with detailed guidance on PR title
format, description expectations, branch naming conventions, the review
process, and a list of PRs that will not be accepted. Also clarify the
'Discuss Before Building' rule to link to GitHub Issues and Discussions
and reference Taiga stories. Update the Table of Contents with nested
links for all new subsections.
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
* ✨ Remove the need to navigate to page for deletion operation
* 🐛 Fix multiple selection with applied-tokens on stroke-color
* 🐛 Fix button position on page header
---------
Co-authored-by: Andrey Antukh <niwi@niwi.nz>