The cleanup cron cleared export_file_id for every user with an export
as soon as one export expired, orphaning fresh export files. Scope the
update to the expired file ids.
Add auth.ldap.attribute.id. When set (e.g. objectGUID on AD, entryUUID
on OpenLDAP), users and teams are matched by that attribute instead of
the login name and the group DN, so renaming or moving them in the
directory no longer creates duplicate accounts or new teams without the
old shares.
AD's binary objectGUID is formatted as a canonical GUID string; other
attributes must be printable text. Existing accounts and teams are
switched to the new id on the next login. An empty option keeps the old
behaviour.
Teams synced from an external provider can be moved from one external
id to another without losing members or project shares. Teams whose new
id is already taken by another team are left untouched.
Support {userdn} and {username} placeholders in auth.ldap.groupsyncfilter.
When present, every matching group is a membership and the member
attribute is not fetched, so the cost scales with the user's own
memberships and nested AD groups can be resolved with
LDAP_MATCHING_RULE_IN_CHAIN. Filters without a placeholder keep the
previous client-side member matching.
The group search now uses paged results in both modes so directories
with more groups than the server's size limit no longer fail the login.
Browser extensions inject third-party images (e.g. yahoo.co.jp favicons)
into the page, and their load failures were reported as ours.
Refs FRONTEND-OSS-263
Console breadcrumbs keep the raw logged arguments until Sentry normalizes
the event, which happens after event processors run. A cyclic object in
there, such as the Vue router internals a browser extension logged, sent
redactSensitiveParams into infinite recursion and the event was lost.
Fixes FRONTEND-OSS-2M2
A bulk update with no fields fell through to the single-task path and
replaced every task wholesale with values, clearing description, dates,
priority and more on all of them. Reject it with a new
ErrBulkTaskFieldsRequired (4036) and document the accepted bulk fields.
Fixes#4109
is_favorite was taken from the cloned bulk values, so a bulk update that
didn't name it unfavorited every task the caller had favorited (or
favorited all of them when values carried is_favorite: true). Keep the
caller's favorite state unless is_favorite is named in fields, and
accept is_favorite as a bulk field.
updateReminders deletes and re-inserts a task's reminders from the
cloned bulk values, so any bulk update whose fields list didn't name
reminders wiped them. Keep the stored reminders unless reminders is
named in fields, and accept reminders as a bulk field.
updateSingleTask replaced a task's assignees unconditionally, so a v2
bulk update (PUT /tasks/bulk, also exposed as the MCP tasks_bulk_update
action) whose fields list did not include assignees deleted every
assignee from every task in the request - even though the fields
contract says only the named fields are written and the rest of each
task is left untouched.
Only replace assignees when no field list is given (single-task
updates, unchanged) or when 'assignees' is named in fields. 'assignees'
is now accepted as a pseudo-field in the bulk field list so callers can
still replace or clear assignees explicitly. Field validation now runs
before the assignee update, so an invalid field no longer mutates
assignees before erroring.
Fixes#4109
Mandatory scroll snapping on narrow screens snapped the board back after
each small auto-scroll step from sortablejs, so tasks could only be
dropped into buckets already visible. Disable snapping while dragging.
Fixes#4163
The task detail view saves on every color picker update. The API returns
hex_color without '#', so the picker re-emitted the normalized value
after each save. While dragging, out-of-order save responses kept
flipping the color, each echo triggering another save in an endless loop.
Fixes#4156
Once the hour input holds a complete hour (two digits, or a single digit
that cannot start a valid two-digit hour in the current 12h/24h format),
the hour is committed and focus moves to the minutes input. Both inputs
select their content on focus so typing replaces the value.
Tab from the hours input now lands on minutes directly. The step buttons
stay mouse-clickable; ArrowUp/ArrowDown on the inputs remain the keyboard
path.
Starting a timer always used the click time, discarding a start time the
user had picked in the form. Only an untouched start now falls back to
the click time.