TaskAttachment.ReadOne now swallows ErrAccountDisabled/ErrAccountLocked
from the creator lookup, matching the existing ErrUserDoesNotExist
swallow. Without this, deleting a disabled user that owned a project
with task attachments would fail when the cascade re-loaded the
attachment to delete it.
The pseudo-element that extends the checkbox hit target also covered
label text content, which broke Playwright actionability checks for
clicks on text inside wider FancyCheckbox labels (e.g. the "Show
Archived" toggle on the projects list page).
Move the rule out of BaseCheckbox and into SingleTaskInProject's deep
override, where the label slot is already hidden via display: none, so
no neighboring content can be intercepted.
A pseudo-element on the label provides a 44x44 minimum hit area
centered on the visible icon. Visible size and surrounding layout
are unchanged. Addresses misclicks on the task list view checkbox
where ~50% of taps would open the task detail instead of toggling
done.
The flatpickr time inputs hardcoded `time_24hr: true`, so users who
selected the 12-hour format in their settings still got a 24-hour
picker — even though the displayed dates respected the preference.
Bind `time_24hr` to the existing `useTimeFormat` composable in:
- DatepickerInline (start/end/due dates and absolute reminders)
- DeferTask (defer due date)
- ApiTokenForm (API token expiry)
Reported at https://community.vikunja.io/t/4492.
Removes the `service.enablebotusers` config flag, the matching
`bot_users_enabled` field on /info, and the now-unused
`ErrBotUsersDisabled` error. Bot user routes and the frontend
settings tab are now always available.
https://claude.ai/code/session_01VhAR6xnoCdG1fpX52bzaCC
User search previously filtered bots only when they happened to match the
search string. That produced two bad behaviours:
1. Bots owned by other users could surface on an exact-username match,
leaking them into assignee pickers and similar UI.
2. A user could not reliably find their own bots by typing a partial
name, so bots became awkward to assign to tasks.
Change ListUsers to treat bot ownership explicitly: the existing match
branch excludes rows owned by someone else, and a second branch always
returns bots owned by the calling user. The own-bots branch also
respects any AdditionalCond passed in so project-scoped listings don't
start leaking bots from outside the project.
Bot users now render with a cool-toned (blue/cyan/violet/teal/indigo)
marble variant so they're visually distinguishable from human users.
Marble's rendering logic is parameterized with a palette; the route
forces the bot palette whenever the resolved user is a bot, overriding
whatever avatar provider they'd otherwise inherit.
The JWT skipper bypassed validation entirely for /token/test when the
bearer was an API token, leaving "user" unset in the context. CheckToken
then type-asserted it to *jwt.Token and panicked.
Validate the API token in the skipper but skip the route permission
check (since /token/test is not exposed in the API token route registry,
no token can hold explicit permission for it). Drop the now-redundant
JWT assertion in CheckToken — auth has already passed by the time the
handler runs.
The Modal mounts the <dialog> via v-if and calls showModal() in a
follow-up flush, so v-focus runs while the dialog is still closed and
its focus() call is dropped. The existing rAF retry was gated on
quick-add mode, leaving Ctrl+K in the regular app with no focused
input. Run the retry whenever the quick actions become active and keep
the command pre-selection scoped to quick-add mode.
Stylelint 17.9.0 resolves customSyntax modules relative to the
stylelint package, so the transitive postcss-html pulled in via
stylelint-config-recommended-vue is no longer reachable and lint
fails with "Could not find postcss-html".
During E2E testing with Playwright (via `mage test:e2e`), the frontend is built using Vite with `--mode development`. However, Vite hardcodes `process.env.NODE_ENV` to `production` during the build step, which causes `import.meta.env.DEV` to statically evaluate to `false`.
Because the `v-cy` custom testing directive relied on the `DEV` flag, it silently evaluated to false and failed to render the `data-cy` attributes into the DOM during the test build. This caused test failures because Playwright could not locate the elements.
Changing the check to explicitly evaluate `import.meta.env.MODE === 'development'` successfully bypasses the Vite build behavior, ensuring that `data-cy` testing attributes are consistently rendered during E2E tests.
For more context on Vite's build behavior regarding `DEV` and development mode, see:
https://github.com/vitejs/vite/discussions/14083