* fix: use ACL ownership for prompt group cleanup on user deletion
deleteUserPrompts previously called getAllPromptGroups with only an
author filter, which defaults to searchShared=true and drops the
author filter for shared/global project entries. This caused any user
deleting their account to strip shared prompt group associations and
ACL entries for other users.
Replace the author-based query with ACL-based ownership lookup:
- Find prompt groups where the user has OWNER permission (DELETE bit)
- Only delete groups where the user is the sole owner
- Preserve multi-owned groups and their ACL entries for other owners
* fix: use ACL ownership for agent cleanup on user deletion
deleteUserAgents used the deprecated author field to find and delete
agents, then unconditionally removed all ACL entries for those agents.
This could destroy ACL entries for agents shared with or co-owned by
other users.
Replace the author-based query with ACL-based ownership lookup:
- Find agents where the user has OWNER permission (DELETE bit)
- Only delete agents where the user is the sole owner
- Preserve multi-owned agents and their ACL entries for other owners
- Also clean up handoff edges referencing deleted agents
* fix: add MCP server cleanup on user deletion
User deletion had no cleanup for MCP servers, leaving solely-owned
servers orphaned in the database with dangling ACL entries for other
users.
Add deleteUserMcpServers that follows the same ACL ownership pattern
as prompt groups and agents: find servers with OWNER permission,
check for sole ownership, and only delete those with no other owners.
* style: fix prettier formatting in Prompt.spec.js
* refactor: extract getSoleOwnedResourceIds to PermissionService
The ACL sole-ownership detection algorithm was duplicated across
deleteUserPrompts, deleteUserAgents, and deleteUserMcpServers.
Centralizes the three-step pattern (find owned entries, find other
owners, compute sole-owned set) into a single reusable utility.
* refactor: use getSoleOwnedResourceIds in all deletion functions
- Replace inline ACL queries with the centralized utility
- Remove vestigial _req parameter from deleteUserPrompts
- Use Promise.all for parallel project removal instead of sequential awaits
- Disconnect live MCP sessions and invalidate tool cache before deleting
sole-owned MCP server documents
- Export deleteUserMcpServers for testability
* test: improve deletion test coverage and quality
- Move deleteUserPrompts call to beforeAll to eliminate execution-order
dependency between tests
- Standardize on test() instead of it() for consistency in Prompt.spec.js
- Add assertion for deleting user's own ACL entry preservation on
multi-owned agents
- Add deleteUserMcpServers integration test suite with 6 tests covering
sole-owner deletion, multi-owner preservation, session disconnect,
cache invalidation, model-not-registered guard, and missing MCPManager
- Add PermissionService mock to existing deleteUser.spec.js to fix
import chain
* fix: add legacy author-based fallback for unmigrated resources
Resources created before the ACL system have author set but no AclEntry
records. The sole-ownership detection returns empty for these, causing
deleteUserPrompts, deleteUserAgents, and deleteUserMcpServers to silently
skip them — permanently orphaning data on user deletion.
Add a fallback that identifies author-owned resources with zero ACL
entries (truly unmigrated) and includes them in the deletion set. This
preserves the multi-owner safety of the ACL path while ensuring pre-ACL
resources are still cleaned up regardless of migration status.
* style: fix prettier formatting across all changed files
* test: add resource type coverage guard for user deletion
Ensures every ResourceType in the ACL system has a corresponding cleanup
handler wired into deleteUserController. When a new ResourceType is added
(e.g. WORKFLOW), this test fails immediately, preventing silent data
orphaning on user account deletion.
* style: fix import order in PermissionService destructure
* test: add opt-out set and fix test lifecycle in coverage guard
Add NO_USER_CLEANUP_NEEDED set for resource types that legitimately
require no per-user deletion. Move fs.readFileSync into beforeAll so
path errors surface as clean test failures instead of unhandled crashes.
* 🧯 fix: Remove revoked agents from user favorites
When agent access is revoked, the agent remained in the user's favorites
causing repeated 403 errors on page load. Backend now cleans up favorites
on permission revocation; frontend treats 403 like 404 and auto-removes
stale agent references.
* 🧪 fix: Address review findings for stale agent favorites cleanup
- Guard cleanup effect with ref to prevent infinite loop on mutation
failure (Finding 1)
- Use validated results.revoked instead of raw request payload for
revokedUserIds (Finding 3)
- Stabilize staleAgentIds memo with string key to avoid spurious
re-evaluation during drag-drop (Finding 5)
- Add JSDoc with param types to removeRevokedAgentFromFavorites
(Finding 7)
- Return promise from removeRevokedAgentFromFavorites for testability
- Add 7 backend tests covering revocation cleanup paths
- Add 3 frontend tests for 403 handling and stale cleanup persistence
* fix: require OTP verification for 2FA re-enrollment and backup code regeneration
* fix: require OTP verification for account deletion when 2FA is enabled
* refactor: Improve code formatting and readability in TwoFactorController and UserController
- Reformatted code in TwoFactorController and UserController for better readability by aligning parameters and breaking long lines.
- Updated test cases in deleteUser.spec.js and TwoFactorController.spec.js to enhance clarity by formatting object parameters consistently.
* refactor: Consolidate OTP and backup code verification logic in TwoFactorController and UserController
- Introduced a new `verifyOTPOrBackupCode` function to streamline the verification process for TOTP tokens and backup codes across multiple controllers.
- Updated the `enable2FA`, `disable2FA`, and `deleteUserController` methods to utilize the new verification function, enhancing code reusability and readability.
- Adjusted related tests to reflect the changes in verification logic, ensuring consistent behavior across different scenarios.
- Improved error handling and response messages for verification failures, providing clearer feedback to users.
* chore: linting
* refactor: Update BackupCodesItem component to enhance OTP verification logic
- Consolidated OTP input handling by moving the 2FA verification UI logic to a more consistent location within the component.
- Improved the state management for OTP readiness, ensuring the regenerate button is only enabled when the OTP is ready.
- Cleaned up imports by removing redundant type imports, enhancing code clarity and maintainability.
* chore: lint
* fix: stage 2FA re-enrollment in pending fields to prevent disarmament window
enable2FA now writes to pendingTotpSecret/pendingBackupCodes instead of
overwriting the live fields. confirm2FA performs the atomic swap only after
the new TOTP code is verified. If the user abandons mid-flow, their
existing 2FA remains active and intact.