* 🐛 Fix several issues in RPC command handlers
- Reject circular library references in link-file-to-library
- Add explicit team permission check in search-files
- Constrain search-term max length to 250 chars
- Include :deleted-at in file ETag for COND caching
- Move storage I/O outside DB transaction in create-file-thumbnail
AI-assisted-by: deepseek-v4-pro
* 📎 Check perms before circular link checks
* 🐛 Handle circular library reference error
Catch :circular-library-reference error from backend when linking
files to libraries. Show user-friendly toast notification instead of
propagating unhandled error. Add English and Spanish translations.
AI-assisted-by: qwen3.7-plus
An organization owner keeps read-only access to the teams of their
organization even when they are not a member, so removing them from a
team was navigating them away from content they are still allowed to
see, and they could walk right back in through the URL.
Publish a :team-role-change to :viewer for them instead of a
:team-membership-change, which reuses the existing real-time role
transition on both the dashboard and the workspace. Any other member is
notified as before.
Signed-off-by: Juanfran <juanfran.ag@gmail.com>
Server changes:
- Switch list ordering from DESC to ASC (oldest first)
- Flip cursor direction to > for forward pagination
- Add 'until' param for server-side upper-bound filtering
CLI changes:
- Add --from/--to flags mapping to server's since/until
- Streaming output for --all and --format ndjson
- Add --format ndjson option (one JSON object per line)
- Add --normalize-hints flag to strip dynamic values
- Add --output flag to write list results to file
- Add 'stats' subcommand with aggregations (signature, host,
tenant, version, source, kind, hour) reading from API, file, stdin
- stats input supports JSON, JSON array, and NDJSON formats
Test changes:
- Fix pagination assertions for ASC ordering
AI-assisted-by: mimo-v2.5-pro
The bulk profile creation endpoint creates already active profiles that
skip email verification and onboarding, so it should not be reachable on
production deployments. Add the `nitrate-bulk-create-profiles` flag,
disabled by default, and reject the call when it is not enabled.
Signed-off-by: Juanfran <juanfran.ag@gmail.com>
Implement RPC methods for querying server error reports with pagination
and filtering. Add CLI tool (tools/error-reports.mjs) for convenient
access with table and JSON output formats. Extract profile-id from audit
events and logging context for better error categorization. Build
improved HREF using request path when available.
AI-assisted-by: qwen3.7-plus
* 📎 Add postgresql client tool wrapper for devenv
* ♻️ Replace uuid-ossp defaults with gen_random_uuid() and add missing :id on insert
- Switch all DEFAULT uuid_generate_v4() to gen_random_uuid()
(built-in PG 13+, no extension required)
- Add explicit :id (uuid/next) to 4 db/insert! calls that were
relying on the DB default (team-profile-rel, project-profile-rel,
team-project-profile-rel)
- Drop uuid-ossp extension (no longer needed)
- Add missing uuid require to projects.clj and srepl/binfile.clj
AI-assisted-by: deepseek-v4-flash
---------
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
When ImageMagick fails to process an uploaded image (e.g., corrupted PNG
with invalid IHDR data), the backend was raising :type :internal with
:code :imagemagick-error, which mapped to HTTP 500. The frontend treated
this as a server error and displayed the full error page.
Changed exec-magick! to raise :type :validation with :code :invalid-image
instead. This flows through the existing :invalid-image handler in
errors.clj which returns HTTP 400. The frontend's handle-media-error and
process-error now catch this code and show a notification banner.
AI-assisted-by: qwen3.7-plus
* 🐛 Demote unable-to-retrieve-user-info OIDC error to warning level
401 responses from the OIDC userinfo endpoint (e.g. expired/revoked GitHub
token) are normal auth failures, not server errors. Logging at :error level
triggers the database and Mattermost error reporters unnecessarily.
AI-assisted-by: deepseek-v4-flash
* ✨ Add pure function tests for OIDC auth module
Add tests for: int-in-range?, valid-info?, qualify-prop-key, qualify-props,
provider-has-email-verified?, profile-has-provider-props?, redirect-response,
redirect-with-error, redirect-to-verify-token, and build-redirect-uri.
AI-assisted-by: deepseek-v4-flash
* ✨ Add HTTP-mock tests for fetch-user-info and fetch-access-token
Replace with-redefs with binding (cf/config is ^:dynamic).
Add tests for: fetch-user-info (success, 401, 500, request structure),
fetch-access-token (success, 400 error).
AI-assisted-by: deepseek-v4-flash
* ✨ Add get-info integration tests with partial mocking
Test all branches: token/userinfo/auto info sources, incomplete info,
role checks (satisfied and insufficient), state props merge,
sso-session-id from claims, and sso-provider-id for uuid providers.
AI-assisted-by: deepseek-v4-flash
* ✨ Add callback-handler integration tests with real tokens and session
Tests all main branches: error param, no profile (registration disabled),
profile blocked, provider mismatch, inactive profile, success flow,
and graceful handling of unable-to-retrieve-user-info exception.
Uses real tokens/generate, tokens/verify, and session/inmemory-manager.
AI-assisted-by: deepseek-v4-flash
- Remove conditional build from test scripts (frontend, common)
- Remove test:jvm from common package.json (JVM tests via clojure directly)
- Remove test from backend package.json (JVM tests via clojure directly)
- Unify common/scripts/test-quiet.js with frontend's BUILD_STEPS pattern
- Add execution discipline section to mem:testing (no piping, tee to file)
- Add READ mem:testing FIRST directives to module testing docs
AI-assisted-by: deepseek-v4-flash
get-teams-detail, get-org-invitations and delete-org-invitations lacked
::rpc/auth false, so wrap-nitrate-sso ran on them whenever params carried
an organization-id. For SSO-active orgs this rejected the org owner's
admin-console reads with a 401, since their Penpot session has no SSO
grant for the org. These are shared-key protected management calls made
on the org owner's behalf and never use profile-id, so they should not
require an end-user SSO session — matching their sibling endpoints.