- Remove cors from inject chain; resolve via getResource() inside
try-catch so DB failures don't cascade when resolving the cors
resource dependency chain (cors -> allowedHostnames -> rule -> DB)
- Use override:true on addHeader to prevent duplicate CORS headers
when init() already set them before the exception was thrown
- Degrades gracefully: if cors resolution fails, error response is
sent without CORS headers (same behavior as before this PR)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Http::error() handler was missing CORS headers, causing browsers to
block error responses (e.g. 403 PROJECT_PAUSED) with a generic CORS
error instead of showing the actual error message. This injects the cors
resource into the error handler and adds CORS headers before sending the
error response, matching the pattern already used in Http::init().
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove team deletion for sole owner+sole member case; let orphan teams
be cleaned up by Cloud's inactive project cleanup (safer, avoids
accidental data loss)
- Add explicit ordering by $createdAt so the most veteran member gets
ownership transfer, with limit(1) for clarity
- Remove confirm filter on primary user transfer in membership deletion
so all members (including unconfirmed) are considered
- Remove redundant ownership transfer from Deletes worker since the API
controller already handles it before queueing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevent unconfirmed (pending invite) members from being promoted to
owner or set as the team's primary user during membership/account
deletion by adding a Query::equal('confirm', [true]) filter to the
relevant findOne queries.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Instead of blocking account deletion when the user has confirmed team
memberships, handle memberships gracefully during deletion:
- Sole owner + sole member: delete the team and queue project cleanup
- Sole owner + other members: transfer ownership to the next member
- Non-owner / multiple owners: no special handling needed (worker cleans up)
Also update the Deletes worker to transfer the team's primary user
reference when removing a deleted user's memberships.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The users.php and messaging.php legacy controllers were missing the
userType field in their log output, creating an inconsistency with the
new audit user type distinction feature. Also adds missing mode field
to users.php logs endpoint.
https://claude.ai/code/session_01J9gKXwbHoLggsGwJi6KUnM
The old guard that threw when workerCount > instanceConnections was
removed during the DI migration, causing pool size to silently floor
to 1. This can lead to connection exhaustion on multi-core hosts.
Use Utopia\Messaging\Adapter\Email\SMTP instead of raw PHPMailer
for the smtp register, Mails worker, and Doctor task. This enables
swapping email adapters (e.g. Resend) via DI override in downstream
repos by type-hinting against the EmailAdapter base class.
addHeader() already accumulates multiple values for the same key into an
array internally, so calling it once per value is the correct approach.
Comma-joining violates RFC 6265 for Set-Cookie headers.