Commit Graph

423 Commits

Author SHA1 Message Date
jubnl 62453ebefa fix: harden prerelease workflow against races, orphan tags, and edge cases
- Add concurrency groups to both workflows to prevent parallel version-bump races
- Defer git tag push to merge job so orphan tags can't exist without a live image
- Pin build/merge jobs to the SHA captured in version-bump to prevent TOCTOU
- Guard auto-finalize in docker.yml against cross-major prereleases (requires bump=major + confirm_major=MAJOR)
- Add STABLE fallback to 0.0.0 for fresh repos with no stable tag
- Fix cleanup sort to extract numeric N via awk instead of fragile sort -t. -k4 -n
- Add 5-minute in-memory cache to checkVersion to avoid GitHub API rate limits
- Type GitHubPanel releases state; remove any cast on filter
- Quote all $VERSION/$MAJOR_TAG vars in imagetools create calls
2026-04-12 16:50:54 +02:00
jubnl e198791139 fix: address prerelease workflow review issues
- Remove stale mauriceboe/nomad tags from docker-dev.yml
- Fix APP_VERSION empty string fallback (?? -> ||)
- Fix compareVersions to handle -pre.N suffixes correctly
- Use highest existing N instead of tag count to avoid collision after cleanup
- Add cleanup step to keep only last 5 prerelease tags per base version
2026-04-12 16:39:50 +02:00
jubnl 981b667fbb feat: prerelease workflow with major version support and version propagation
- Add docker-dev.yml: prerelease CI for dev branch with minor/major bump
  inputs; auto-continues in-flight major line via existing pre tags;
  publishes floating major-pre Docker tag (e.g. 2-pre)
- Rewrite docker.yml version-bump: tag-based versioning, manual bump
  inputs (auto/patch/minor/major), major guarded by confirm_major=MAJOR,
  auto-finalizes in-flight prereleases; publishes floating major tag (e.g. 2)
- Inject APP_VERSION build-arg through Dockerfile so the running container
  knows its real version instead of reading package.json
- Server reads APP_VERSION env in authService/adminService; exposes
  is_prerelease in app config and update-check response; prerelease builds
  compare against GitHub prerelease releases rather than latest stable
- Client stores isPrerelease from config; navbar shows amber version badge
  on prerelease builds (left of dark-mode toggle); GitHubPanel filters out
  prerelease releases unless the running build is itself a prerelease
2026-04-12 16:26:44 +02:00
Maurice f323952012 feat: configurable week start day in Vacay (Monday or Sunday)
- New setting in Vacay Settings to choose Mon or Sun as week start
- DB migration adds week_start column to vacay_plans (default: Monday)
- Calendar grid and weekday headers adapt to the selected start day
- Weekend column highlighting works correctly for both modes
- Translations added for all 14 languages
2026-04-12 02:18:45 +02:00
Maurice 344b769583 fix: deduplicate places on Google Maps list re-import (#543)
Skip places that already exist in the trip (same name + coordinates
within ~10m) when re-importing a Google Maps list. Only new places
are added, preventing duplicates on repeated imports.
2026-04-12 01:45:32 +02:00
Maurice de157cb87b test: comprehensive Journey test suite — 89.5% new code coverage
Server (172 tests):
- journeyService unit tests (87 tests): CRUD, access control, sync, photos, contributors
- journeyShareService unit tests (20 tests): share links, token validation, public access
- journey integration tests (45 tests): all API routes, auth, permissions, edge cases
- Test helpers: journey factories, RESET_TABLES updated

Client (340+ tests):
- journeyStore tests (15 tests): all store actions and state management
- JourneyPage tests (20 tests): frontpage, create flow, suggestions, navigation
- JourneyDetailPage tests (94 tests): all sub-components, entry editor, settings,
  share links, contributors, gallery, map, trip linking
- JourneyPublicPage tests (18 tests): public view, tabs, restricted access
- JourneyBookPDF tests (6 tests): PDF generation
- BottomNav tests (9 tests): profile sheet, navigation
- PhotoLightbox tests (8 tests): keyboard nav, counter
- JourneyMap tests (12 tests): markers, polylines, zoom
- Component tests: moodConfig, stripMarkdown, MarkdownToolbar, JournalBody, MobileTopHeader
- DashboardPage tests (32 tests): spotlight card, quick actions, widget settings

SonarQube: exclude unused MemoriesPanel from coverage (dead code, moved to Journey)
2026-04-12 01:19:53 +02:00
jubnl 47d9cce936 fix(tests): update tests for granular auth toggles
- Add new fields to AppConfig type and buildAppConfig factory
- Update FE-PAGE-ADMIN-018: heading changed to "Authentication Methods"
- Update FE-PAGE-ADMIN-053: oidc_only toggle removed from OIDC panel
- Update FE-PAGE-LOGIN-007/017: mocks now include password_login/oidc_login
- Update ADMIN-SVC-049: updateOidcSettings no longer writes oidc_only
2026-04-11 20:33:51 +02:00
jubnl bfd2553d1e feat(auth): split OIDC_ONLY into granular auth toggles
Replaces the coarse oidc_only + allow_registration settings with four
independent toggles: password_login, password_registration, oidc_login,
oidc_registration. Each can be enabled/disabled individually in
Admin > Settings without affecting the others.

- Add resolveAuthToggles() in authService.ts as the central resolver;
  falls back to legacy oidc_only/allow_registration keys when new keys
  are absent (backward compat)
- OIDC_ONLY env var still works and overrides DB toggles for password_*,
  with a visual lock in the admin UI when active
- Server enforces lockout prevention: cannot disable all login methods
- oidc_login gate added to OIDC /login and /callback routes
- Remove oidc_only toggle from OIDC settings panel; replaced by the
  granular toggles in the Settings tab
- Add 6 new resolveAuthToggles() unit tests; fix AUTH-DB-033 error
  message assertion
- Update OIDC_ONLY descriptions in README, docker-compose, Helm values,
  Unraid template, and .env.example to clarify override semantics

Closes #492
2026-04-11 20:21:36 +02:00
Julien G. 2b1889b9a9 Merge pull request #567 from mauriceboe/fix/atlas-country-region-matching
fix(atlas): scope region name matching by country and expand country lookup tables
2026-04-11 19:50:30 +02:00
Maurice 468035fc3c fix: reorder migrations — OAuth (84-88) before Journey (89-96)
Dev DB already ran OAuth migrations at indices 84-88. The merge
incorrectly placed Journey migrations before OAuth, causing
'duplicate column: parent_token_id' crash on the dev server.
2026-04-11 19:48:43 +02:00
jubnl 467d35702b fix(atlas): scope region name matching by country and expand country lookup tables
- Fix #521: `isVisitedFeature()` now scopes name-based region matching to
  the feature's parent country (via `iso_a2`), preventing same-name regions
  in different countries (e.g. Luxembourg BE vs LU) from falsely lighting up
- Fix #489: Add ~50 missing countries to COUNTRY_BOXES, NAME_TO_CODE, and
  CONTINENT_MAP so the bounding-box fallback correctly identifies Georgia
  instead of falling through to Russia/Azerbaijan's overlapping boxes
2026-04-11 19:45:26 +02:00
Maurice 956c4270df merge: resolve conflicts with dev, fix 7 Snyk security issues
- Resolve translation conflicts (keep both journey + OAuth scope keys)
- Resolve migrations.ts (dev OAuth migrations + journey migrations)
- Fix hono directory traversal, response splitting, input validation (CVE-2026-39407/08/09/10)
- Fix @hono/node-server directory traversal (CVE-2026-39406)
- Fix nodemailer CRLF injection (upgrade to 8.0.5)
2026-04-11 19:11:21 +02:00
Maurice 13956804c2 feat: Journey addon — travel journal with entries, photos, public sharing & PDF export
- 5-table schema (journeys, entries, photos, trips, contributors) with migrations 87-91
- Trip-to-Journey sync engine with skeleton entries and photo sync
- Full CRUD API for journeys, entries, photos with Immich/Synology integration
- Timeline, Gallery and Map views with entry editor (markdown, mood, weather, pros/cons)
- Journey frontpage with hero card, stats and trip suggestions
- Public share links with token-based access and photo proxy
- PDF photo book export (Polarsteps-inspired)
- Dashboard redesign: mobile greeting, live trip hero, quick actions, unified card design
- BottomNav profile sheet with settings/admin/logout
- DayPlan mobile inline place picker
- TripFormModal members management
- Vacay calendar trip date indicator dots
- Fix contributor photo access (403) for journey Immich/Synology photos
- Trip deletion cleanup for journey skeleton entries
- i18n: 231 new keys across all 14 languages (native translations, no fallbacks)
2026-04-11 19:01:34 +02:00
jubnl eff3fcfe10 test: update expected event_types count after adding synology_session_cleared 2026-04-11 18:44:40 +02:00
jubnl 0257e0d842 feat: route Synology session-cleared notification through unified send()
Replace direct createNotification() call with notificationService.send()
so the notification respects user preferences and reaches all enabled
channels (in-app, email, webhook) instead of only WebSocket.

Registers synology_session_cleared as a proper NotifEventType (inapp-only)
and adds localized text for all 14 supported languages.
2026-04-11 18:36:50 +02:00
jubnl 7871c06059 feat: enhance Synology Photos integration with OTP, SSL skip, and better UX
- Fix endpoint path: users now provide full base URL (e.g. https://nas:5001/photo)
- Add OTP/2FA field for Synology login
- Add skip SSL verification option (DB column + checkbox UI)
- Add device ID (synology_did) column for session tracking
- Trigger in-app notification when Synology session is cleared
- Show disconnection banner in MemoriesPanel
- Add URL hint in provider settings
- Map Synology API error codes to human-readable messages
- Update i18n for all locales
2026-04-11 18:25:42 +02:00
Julien G. bcc37d6b7d Merge pull request #562 from mauriceboe/main
Align dev
2026-04-11 15:41:34 +02:00
github-actions[bot] 0f6be35870 chore: bump version to 2.9.13 [skip ci] 2026-04-11 13:26:44 +00:00
jubnl f47852d689 docs: improve FORCE_HTTPS, COOKIE_SECURE, TRUST_PROXY documentation
FORCE_HTTPS now documents all four effects (redirect, HSTS, CSP
upgrade-insecure-requests, secure cookie flag) and is clearly marked
optional. COOKIE_SECURE default updated to "auto" with explanation of
auto-derivation logic. TRUST_PROXY clarifies it's off in dev unless
set and is required for FORCE_HTTPS. charts/README.md gains FORCE_HTTPS
and TRUST_PROXY entries. README prose expanded to explain all three
vars and their interaction.
2026-04-11 15:26:19 +02:00
Julien G. 3b080ac116 Merge pull request #544 from mauriceboe/feat/mcp-oauth2-addon-gating
Implement OAuth 2.1 authentication for MCP, enforce addon gating
2026-04-11 14:39:50 +02:00
jubnl 7a22d742ab test: add comprehensive coverage for OAuth scopes, MCP, and core services
Adds new and expanded test suites across client and server to cover the
OAuth 2.1 scope system, MCP session manager, collab service, unified
memories helpers, OIDC service, budget slice, and OAuth authorize page.
Also extends SonarQube coverage exclusions to include bootstrapping files
(migrations, scheduler, main.tsx, types.ts) that are not meaningfully
testable.
2026-04-11 14:08:09 +02:00
jubnl 1585c472c2 fix(test): bumb default limit to reflect implementation 2026-04-11 02:32:17 +02:00
jubnl dd8d2ae54a chore(mcp): raise default session and rate-limit caps
Higher defaults reduce config friction for self-hosters while
staying within reasonable server limits.

- MCP_MAX_SESSION_PER_USER: 5 → 20
- MCP_RATE_LIMIT: 60 → 300 req/min
2026-04-11 02:29:11 +02:00
jubnl 535c06bb3f feat(mcp): granular OAuth scopes and per-client rate limiting
- Split `media:read` into `geo:read` and `weather:read` scopes
- Add dedicated `atlas:read/write` scopes (previously under `places`)
- Add dedicated `todos:read/write` scopes (previously under `collab`)
- Rate limiting now keyed by userId+clientId instead of userId alone
- Bind MCP sessions to the OAuth client that created them
- Log MCP tool calls to audit log with clientId
- Invalidate all MCP sessions on addon state change
- Reduce session sweep interval from 10min to 1min
- Update all translations with new scope labels
2026-04-11 02:06:32 +02:00
github-actions[bot] e290c7c522 chore: bump version to 2.9.12 [skip ci] 2026-04-10 05:51:22 +00:00
jubnl f20eb6639f chore(workflow): remove delete tag workflow 2026-04-10 07:50:51 +02:00
github-actions[bot] d0176d7ed6 chore: bump version to 2.9.12 [skip ci] 2026-04-10 05:44:33 +00:00
jubnl 8402f3bcfd chore: add workflow to delete Docker tags 2026-04-10 07:44:10 +02:00
github-actions[bot] 6caa966a52 chore: bump version to 2.10.0 [skip ci] 2026-04-10 05:36:13 +00:00
jubnl 4b1286d53c feat(admin): add OAuth sessions to MCP Access panel
Show active OAuth sessions (first) and static API tokens (second) in
the admin MCP Access tab. Admins can revoke any OAuth session, which
immediately terminates the live MCP transport for that client.

- Add admin-level listOAuthSessions / revokeOAuthSession in adminService
- Add GET /admin/oauth-sessions and DELETE /admin/oauth-sessions/:id routes
- Restructure AdminMcpTokensPanel into two sections; rename tab to MCP Access
- Fix stale writeAudit call in rotate-jwt-secret route (user_id → userId)
- Add admin.oauthSessions.* i18n keys across all 14 locale files
2026-04-10 06:47:35 +02:00
jubnl cc2a2ddca3 remove(oauth): drop browser-initiated DCR registration flow
OAuthRegisterPage and its server routes (GET /api/oauth/register/validate,
POST /api/oauth/register) are superseded by the RFC 7591 machine-to-machine
DCR endpoint (POST /oauth/register). Claude.ai and compliant MCP clients
register via RFC 7591, then go through the standard /oauth/authorize consent
screen for scope selection.
2026-04-10 06:23:07 +02:00
jubnl 4ad1ccf5dd fix(oauth): gate scope selection UI to DCR clients only
Settings-created clients have fixed scopes chosen at creation time and
should show a read-only scope list on the consent screen. Only DCR-registered
clients expose the interactive checkbox UI for user-controlled scope selection.
2026-04-10 06:03:52 +02:00
jubnl cb3aeda8e0 fix(oauth): add public RFC 7591 DCR endpoint at POST /oauth/register
Claude.ai's start-auth flow POSTs to the registration_endpoint advertised
in the discovery document, but no public handler existed at /oauth/register
(only /api/oauth/register with browser cookie auth). This caused a
start_error redirect immediately on every connect attempt.

- Add POST /oauth/register to oauthPublicRouter following RFC 7591
- Make oauth_clients.user_id nullable via a raw (no-transaction) migration
  so anonymous DCR clients can be created without a user context
- Update migration runner to support { raw: () => void } migrations for
  DDL that requires PRAGMA foreign_keys = OFF outside a transaction
- Update createOAuthClient to accept userId: number | null with a global
  cap (500) for anonymous DCR clients in place of the per-user limit
2026-04-10 05:42:18 +02:00
jubnl 9b1baaf7b8 feat(oauth): browser-initiated dynamic client registration (DCR)
Adds an OAuth 2.1 public client registration flow so MCP clients can
self-register via a user-facing consent page instead of requiring manual
setup in Settings.

Server:
- DB migration adds `is_public` and `created_via` columns to oauth_clients
- New GET /api/oauth/register/validate — validates DCR params, returns
  requested scopes; unauthenticated callers get loginRequired flag
- New POST /api/oauth/register — creates a public client, saves consent,
  and redirects with client_id (cookie auth required)
- `authenticateClient` / `refreshTokens` skip secret check for public
  clients (PKCE provides the security guarantee)
- `createOAuthClient` accepts options for isPublic/createdVia; public
  clients store an opaque secret hash instead of a usable secret
- `rotateOAuthClientSecret` blocked on public clients
- `isValidRedirectUri` extracted as a shared helper
- Discovery metadata now advertises registration_endpoint and auth method
  `none`; token/revoke endpoints no longer require client_secret for
  public clients

Client:
- New OAuthRegisterPage (/oauth/register) — loading → optional
  login-required gate → scope selection → done states
- New ScopeGroupPicker component — collapsible groups, indeterminate
  checkboxes, select-all per group or globally
- oauthApi.register.{validate,submit} added to api/client.ts
- apiClient exported so it can be reused outside api/client.ts
- IntegrationsTab tests fixed for new collapsible section structure
- collab_notes fallback changed from undefined to [] in MCP trip tools
2026-04-10 05:20:54 +02:00
jubnl 81a360f9a7 fix(mcp): bundle data with deprecation error and add verbatim instruction
Claude retried the tool silently and answered without mentioning the
notice. Two fixes:

1. Include actual trip data in the same isError response so no retry
   is needed and Claude has both the warning and the answer in one shot.

2. Reword the notice to instruct Claude to include the warning verbatim
   in its response before answering the user's question.
2026-04-10 03:15:18 +02:00
jubnl a74a6313dd fix(mcp): instruct Claude to retry tool call after deprecation notice
Claude stopped after surfacing the error rather than retrying.
Append an explicit instruction to retry the tool call so the user
gets both the deprecation warning and their actual answer.
2026-04-10 03:10:02 +02:00
jubnl 89a109560e fix(mcp): return deprecation notice as isError tool result
isError: true is the one MCP mechanism Claude.ai cannot ignore —
it is obligated to surface tool errors to the user.

On the first tool call of a static-token session, return only the
deprecation notice with isError: true (no data). The per-session
_noticeEmitted flag is set before returning, so the immediate retry
(or any subsequent call) goes through normally and returns real data.
2026-04-10 03:04:05 +02:00
jubnl ce36b550c3 fix(mcp): embed deprecation notice as JSON field instead of separate content item
Claude.ai filters out prepended content items as metadata but must
process top-level JSON fields as response data, making it far more
likely to surface the notice to the user.
2026-04-10 02:54:32 +02:00
jubnl 1187883c6b feat(mcp): always register list_trips & get_trip_summary; inject deprecation notice into tool results
Navigation tools:
- list_trips and get_trip_summary are now always registered for any
  OAuth session regardless of granted scopes — they are required for
  trip ID discovery before any scoped tool can be used
- get_trip_summary filters optional sections (budget, packing, collab,
  reservations) by the client's OAuth scopes when called without trips:read

Deprecation notice:
- Inject static token deprecation warning into the first tool result
  (list_trips or get_trip_summary) via a per-session closure so Claude
  is forced to surface it — the instructions field alone is only
  background context and is not proactively shown to the user

UI:
- OAuth client creation modal: add hint explaining the always-available
  tools, remove the "must select at least one scope" submit guard
- OAuth consent screen: add "Always included" section showing list_trips
  and get_trip_summary; handles zero-scope clients gracefully (empty
  permissions section is hidden)
2026-04-10 02:45:16 +02:00
jubnl cef86cbcd9 feat(mcp): add base server instructions for all MCP sessions
Injects a structured BASE_MCP_INSTRUCTIONS string into every session's
initialize response so Claude has data model, workflow, and behavioral
context without needing to infer it from tool names alone.

Covers: data model hierarchy (trip→day→place→assignment), key discovery
workflow (list_trips → get_trip_summary), correct place-to-itinerary
flow (search_place → create_place → assign_place_to_day), accommodation
creation order, access rules, date/time format, add-on feature list,
and common pitfalls (e.g. don't skip search_place, confirm before bulk
deletes).

Static token deprecation notice is appended on top when applicable.
2026-04-10 02:23:32 +02:00
jubnl bf23b2d2f2 fix(mcp): surface static token deprecation via server instructions
The deprecation warning was registered as an MCP prompt that clients
must explicitly fetch — it never fired automatically. Move it to the
ServerOptions.instructions field, which is returned in the initialize
response and automatically read by Claude and other MCP clients as
system context.
2026-04-10 02:18:06 +02:00
jubnl 7c0a0d5f39 security(oauth): harden OAuth 2.1/MCP implementation (Critical + High + Medium findings)
Address 14 security findings from internal review of the OAuth 2.1 + MCP layer:

Critical:
- C1: Scope-gate all MCP resources (trips, budget, packing, collab, atlas, vacay, etc.)
- C2: Wire token/session revocation into active MCP session lifecycle per (user, client_id)
- C3: Refresh-token replay detection via parent_token_id chain + cascade revoke on replay

High:
- H1: Validate PKCE code_challenge (43-char base64url) and code_verifier (43–128 chars) format
- H2: Rate-limit /oauth/token (30/min), /authorize/validate (30/min), /oauth/revoke (10/min)
- H3: Strip client metadata from unauthenticated /authorize/validate responses (oracle prevention)
- H4: Constant-time secret comparison via crypto.timingSafeEqual (prevents timing attacks)
- H5: Collapse all invalid_grant cases to a single generic message; log specifics server-side

Medium:
- M1: Set Cache-Control: no-store + Pragma: no-cache on token endpoint responses
- M2: Return 404 (not 200/403) on discovery + revoke endpoints when MCP addon is disabled
- M4: Audit-log all OAuth lifecycle events (create, consent, issue, refresh, revoke, replay)
- M5: Union consent scopes on re-authorization instead of replacing existing grants
- M7: Require httpOnly cookie auth (not Bearer JWT) on all state-mutating OAuth endpoints
- M8: Strict Bearer scheme check in MCP token verification

Refactoring:
- Extract MCP session management (sessions Map, revokeUserSessions, revokeUserSessionsForClient)
  into mcp/sessionManager.ts to break the circular dependency between oauthService and mcp/index
- Extract verifyJwtAndLoadUser helper in auth middleware, shared by authenticate and new
  requireCookieAuth middleware

Tests:
- Fix all existing integration tests broken by the security hardening (OAUTH-019 to OAUTH-032)
- Add 13 new integration tests covering M1, M2, H1, H3, H5, M5, M7, C3
- Add 14 new unit tests covering C2, C3, H1, H3, M5 behaviors in oauthService
2026-04-10 02:03:27 +02:00
jubnl 8212f3c023 feat(oauth): add trips:share scope and redesign consent screen
Introduce trips:share as a dedicated OAuth scope for managing public
share links, decoupled from trips:read and trips:write. Share link
tools (get/create/delete_share_link) now gate on canShareTrips()
instead of the generic read/write scopes. Scope added to both client
and server definitions with full test coverage.

Redesign the consent screen from a narrow single-column card
(max-w-sm) to a two-panel layout (max-w-2xl): app identity and
action buttons on the left, scrollable scope list on the right.
Responsive — stacks vertically on mobile.
2026-04-10 00:55:12 +02:00
jubnl 41f1dd9ce5 fix(oauth): select ot.user_id instead of u.id in getUserByAccessToken
u.id was returned by SQLite as `id` but the code read `row.user_id`,
which was undefined. This caused all MCP calls to resolve userId as
undefined, making list_trips return empty and canAccessTrip deny all
access when authenticated via OAuth 2.1.
2026-04-09 23:59:11 +02:00
jubnl 5b44fe68b1 fix(mcp): narrow OAuth scope to allowed intersection instead of rejecting
When a client requests scopes it is not permitted for, silently drop
them rather than failing the entire authorization flow. The token is
issued with only the intersection of requested and allowed scopes.

Also fix /authorize/validate to always return HTTP 200 so the consent
page can surface the actual error_description instead of a generic
axios failure message.
2026-04-09 23:48:05 +02:00
jubnl f2908fdd65 test(mcp): add tests for OAuth 2.1, addon gating, and budget reorder
Covers OAuth integration flow, scope enforcement, addon-gated tool access,
oauthService unit tests, and budget reorder/permission/reservation-sync scenarios.
2026-04-09 23:12:59 +02:00
jubnl 830f6c0706 feat(mcp): introduce OAuth 2.1 auth and enforce addon gating
OAuth 2.1 authentication for MCP:
- Add OAuth 2.1 authorization server with PKCE support (routes/oauth.ts)
- Add OAuth service for client CRUD, auth-code flow, and token management (services/oauthService.ts)
- Add typed scope definitions and enforcement helpers (mcp/scopes.ts)
- Add OAuth consent UI page (OAuthAuthorizePage.tsx)
- Add client-side scope labels and descriptions (api/oauthScopes.ts)
- Integrate OAuth token auth into MCP handler alongside existing static tokens
- All OAuth endpoints gated on `mcp` addon

Addon gating across MCP tools, resources, and prompts:
- Add typed ADDON_IDS constant (server/src/addons.ts) replacing all string literals
- Gate budget tools and resources (trip-budget, per-person, settlement) on `budget` addon
- Gate packing tools and resources (trip-packing, trip-packing-bags, trip-todos) on `packing` addon
- Gate todos tools on `packing` addon (mirrors web UI Lists tab behavior)
- Expand atlas gate to cover full tool body (bucket-list + country tools no longer leak)
- Expand collab gate to cover full tool body (collab notes no longer leak)
- Gate packing-list and budget-overview MCP prompts on their respective addons
- Gate get_trip_summary sections per addon; blank packing/budget/collab_notes/todos when disabled
- Remove trip-files resource and files field from get_trip_summary
- Replace all isAddonEnabled('literal') calls with ADDON_IDS constants

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:25:58 +02:00
Maurice 0df90086bf feat: include day activities and notes in iCal export (#375)
Timed activities are exported as individual calendar events with
start/end times and location. Untimed activities and day notes are
grouped into an all-day summary event per day with a structured
description listing places and notes.
2026-04-09 20:11:42 +02:00
Maurice 5c0d819fc1 feat: drag-and-drop reorder for budget categories and items (#479)
Add reordering support for budget categories and line items within
categories. Changes persist via new DB table (budget_category_order)
and existing sort_order column. Live sync via WebSocket budget:reordered
event. Use Map instead of plain objects for category grouping to
preserve insertion order with numeric category names.
2026-04-09 19:21:43 +02:00
Julien G. 89c10ccedb Merge pull request #540 from mauriceboe/feat/mcp-enhancement
feat(mcp): extract all MCP tools into dedicated modules and add shared helpers and add missing tools
2026-04-09 18:29:38 +02:00