The Logto SDK needs the full callback URL (not just searchParams) to
verify it matches the redirect URI registered during sign-in.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The (app)/layout.tsx was calling cookieStore.set() which is forbidden in
Server Components under Next.js 16 (only allowed in Server Actions and
Route Handlers). This caused a 500 error immediately after Logto login.
Also includes: mobile sync client improvements, i18n updates, web API
rate limiting, Bearer token support for mobile clients, and Dockerfile
optimizations.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Custom server (server.ts) wrapping Next.js + ws on same port
- Ticket-based auth: validates ephemeral nonce from /api/ws-ticket
- Origin validation against allowlist
- Session revalidation every 15 min (sends auth_expired, closes)
- Heartbeat every 30s (ping/pong, terminates dead connections)
- broadcastToUser() for API routes to notify connected clients
- Shared ticket store between API route and WS server via globalThis
- Health endpoint now reports active WS connections
- Dockerfile updated to use custom server
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Lists, Tasks, Tags CRUD endpoints with soft-delete
- Sync endpoints (GET since + POST batch with idempotency keys)
- WS ticket endpoint (ephemeral nonce, 30s TTL, single use)
- Auth middleware on all endpoints via getAuthenticatedUser()
- BOLA prevention: userId check on every entity operation
- Zod strict schemas for input validation
- Filters and sorting on task listing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Logto config matching la-compagnie-maximus pattern
- API routes: sign-in, callback, sign-out
- Next.js middleware protecting all routes except /auth and /api
- Auth helper to extract userId (sub) from Logto context
- Login page with Compte Maximus branding
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Create src/shared/ with platform-agnostic types and helpers for
mobile/web code sharing. Add updatedAt to tags schema for sync.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Export WIDGET_NAMES from widgetSync.ts and import in widgetTaskHandler.ts
- Remove renderWithState call before forceWidgetRefresh to avoid double-render
- Use shared WIDGET_NAMES in widgetSync.ts refresh loop
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Only TOGGLE_SUBTASK needs forceWidgetRefresh() because ListView caches
items. TOGGLE_COMPLETE and TOGGLE_EXPAND already work with renderWithState()
alone since they perform structural changes (remove item / toggle children).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Android ListView caches its items, so visual-only changes (like
toggling a subtask checkbox) were not reflected without calling
requestWidgetUpdate() to invalidate the cache. Added forceWidgetRefresh()
helper that calls requestWidgetUpdate() for all 3 widget sizes after
TOGGLE_SUBTASK, TOGGLE_COMPLETE, and TOGGLE_EXPAND handlers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Merge widget:tasks, widget:isDark, and widget:expandedTaskIds into a
single widget:state key to reduce AsyncStorage I/O from 3 reads to 1.
Add 2s debounce on TOGGLE_EXPAND to prevent double-tap from collapsing
the subtask list. Legacy keys are migrated on first read.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Long-press a subtask to edit its title inline. Tap X to delete
with confirmation. Tap still toggles completion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace aggressive >=major overrides (picomatch>=4, brace-expansion>=2, etc.)
with npm audit fix which patches each dependency within its compatible semver
range: picomatch 2.3.2/3.0.2/4.0.4, brace-expansion 1.1.13/2.0.3/5.0.5,
undici 6.24.1, node-forge 1.4.0, tar 7.5.13, yaml 1.10.3/2.8.3.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previous preview build (v1.2.5) used versionCode 5 via production
autoIncrement, but app.json was still at 4. Android refuses to install
an APK with a lower versionCode than the currently installed one.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add safety limit of 30 rendered tasks in the widget to avoid Android
memory constraints. Also add cross-reference comment for the implicit
AsyncStorage coupling with useSettingsStore.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change default widgetPeriodWeeks from 2 to 0 (all tasks) so that the
issue is resolved out of the box without requiring the user to discover
the new setting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of removing the time filter entirely, let users choose the
widget display period (1 week, 2 weeks, 4 weeks, or all tasks) from
Settings. Default remains 2 weeks for backward compatibility.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove the 2-week date filter from widget task query so tasks with
distant due dates are included. Remove the maxItems truncation from
the scrollable ListWidget so the displayed list matches the counter.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace `finally` with `catch` in [id].tsx handleSave so goBack is
not called when updateTask/setTagsForTask fails
- Extract shared goBack helper into src/lib/navigation.ts
- Both [id].tsx and new.tsx now import goBack from the shared module
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace all router.back() calls with a goBack() helper that checks
router.canGoBack() first and falls back to router.replace('/') when
there is no screen to return to. In the task edit screen, change
catch to finally so the save button always resets its disabled state
even if updateTask/setTagsForTask throws.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The ListWidget (Android ListView) introduced for scrolling takes all
available vertical space, pushing the footer add button off-screen.
Move the + button into the header row where it remains always visible
regardless of the task list scroll state.
Related to #19
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add asc(tasks.completed) as the primary sort key in getOrderClauses()
so completed tasks always appear after active ones regardless of the
chosen sort mode (position, priority, dueDate, title, createdAt).
Also apply the same completed-first ordering to:
- getSubtasks() in tasks.ts
- noDateTasks query in widgetSync.ts
- subtasks query in widgetSync.ts
Ref: simpl-liste#15
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The transitive dependency chain drizzle-kit -> @esbuild-kit/esm-loader ->
@esbuild-kit/core-utils pulled in esbuild@0.18.20 which is vulnerable to
GHSA-67mh-4wv8-2f99. Adding an npm override forces all nested esbuild
instances to use ^0.25.0, resolving all 4 moderate audit findings.
Ref: simpl-liste#16
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace FlexWidget with ListWidget for the task list in medium and
large home screen widgets, enabling scroll when items exceed the
widget display area.
Fixes#11
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>