mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-20 14:06:27 +00:00
plugin-sdk-v1.2.0
51 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9e4964ea4f |
feat(plugin-sdk): one-command publish (pack → release → preflight → PR)
Collapses the release into a single command: pack the artifact, tag + create the GitHub release, run the registry CI checks locally (preflight), and open the registry PR — stopping before it submits if preflight would fail, so a broken entry never becomes a doomed PR. `--sign` signs it; `--no-preflight` skips the gate. The individual pack/release/preflight/submit commands still exist. README + the Development/Publishing/Permissions wikis lead with `publish` now. |
||
|
|
9ce33921d2 |
feat(plugin-sdk): dev server, preflight, auto-PR submit, signing, wizard
Round out the author experience so the loop is create -> dev -> release/submit without hand-work or a round-trip through registry review. - `dev`: run a plugin locally with a real request loop and hot reload — no full TREK. Injects a ctx that enforces the manifest's granted permissions (an ungranted call throws, so you catch a missing grant), backs db:own with a real SQLite file (node:sqlite), serves routes under /api and page/widget UI at /ui, and reloads on save. Dependency-free (node:http + built-ins). - `preflight`: run the registry CI checks locally over the network (tag->commit, manifest parity, artifact sha256/size, native scan, README quality gate) so a green run predicts a green CI. - `submit`: fork TREK-Plugins, branch off current main, write/merge the entry, push, and open the PR — the last manual publishing step, automated. - `keygen`/`sign` + `--sign` on entry/release/submit: dependency-free Ed25519 author signatures over the artifact bytes, verified 1:1 against the server's TOFU check. Fills authorPublicKey + signature and guards against a key change. - `create` gains an interactive wizard (id/type/author/permissions) and flags. - README + Development/Publishing/Permissions wikis document the new flow. 24 tests pass (sign round-trips through a server-shaped verifier; zip reader; scaffold options; entry signing + key-change guard). |
||
|
|
648b4aab96 |
chore(plugin-sdk): make it npm-publishable so npx resolves for authors
The docs told authors to run `npx create-trek-plugin` / `npx trek-plugin`, but nothing published under those names, so npx couldn't resolve them. - Ship one package, `trek-plugin-sdk`, with a bin that matches the package name (`trek-plugin-sdk`) so `npx trek-plugin-sdk <command>` resolves with zero install. The dispatcher gained a `create` subcommand, so every step (create/validate/pack/entry/release) runs through that one entry point. The short `trek-plugin` / `create-trek-plugin` bins still work once installed. - Package hardening for publish: repository+directory (monorepo subdir), homepage/bugs/author/engines, publishConfig public, a prepublishOnly that builds + tests, and a LICENSE file. - A publish workflow: pushing a `plugin-sdk-v*` tag builds and publishes with the NPM_TOKEN repo secret. - Docs (SDK README + the four wiki pages) now use `npx trek-plugin-sdk <cmd>`, the invocation that actually resolves. |
||
|
|
ab0a67aa4c |
docs(plugins): rewrite the plugin wiki against the current code + tooling
The plugin wiki had drifted from the app and the SDK. Rewrote all four pages, verifying every command, permission, field, path and UI behaviour against source: - Plugins: activation is a toggle (no separate consent screen); install is the Discover tab (no "Browse plugins" button); you review permissions in the detail modal before installing; documents update + re-consent, the ⋯ menu, toolbar filters, capability chips and the health dot. - Plugin-Development: full manifest reference; ws:broadcast:trip/:user (there is no ws:broadcast:*); onLoad + onUnload; the trek:error bridge message and full context payload; trips.* only work in a route handler; asUserId is accepted-but-ignored; integration hooks are declared but not yet wired. - Plugin-Permissions: db:own also covers db.migrate; a host must appear as both an http:outbound:<host> permission and an egress[] entry or it's silently blocked; bare vs per-host outbound. - Plugin-Publishing: the new one-command flow (validate → pack → release → entry), size is a required entry field, signing reconciled with the schema, no reserved namespaces, and the --merge update path. |
||
|
|
711f6e9881 |
feat(plugins): sandbox hardening — OS permission model, egress choke point, bound acting user, author signatures
Closes the four gaps the security review surfaced: - OS permission model on the prod plugin child (Node --permission with fs-read scoped to the compiled server dir + the plugin's own code dir, no fs-write/child_process/worker/native). A plugin can no longer read trek.db or the .jwt_secret/.encryption_key files, nor shell out — the direct-fs and RCE escapes that bypassed the RPC layer. Opt-out via TREK_PLUGIN_PERMISSIONS=off. - Egress guard extended from fetch to the net.Socket connect choke point, so node:http/https/net/tls obey the declared-egress allowlist too (no declared egress = no outbound). Under the permission model there is no clean escape to an unwrapped runtime. Kernel/network-namespace containment remains the container step. - Trip reads are membership-checked against the acting user the HOST binds from the authenticated invocation, not an asUserId the plugin supplies; a job/onLoad (no user) can't read user-scoped trips. - Optional minisign (Ed25519) author signatures verified offline, TOFU-pinned (migration 158). Unsigned plugins install on sha256 alone; a signed plugin can't silently drop its signature or swap its author key. Server suite green (permission-model activation verified against the Koffi reference plugin on dev1). |
||
|
|
369672f701 | docs(plugins): clarify the fork-and-PR publishing flow | ||
|
|
0a5c8be83d |
docs(plugins): plugin wiki + reference plugin (M7)
- Wiki pages (sync to the GitHub wiki on push to main): Plugins overview + trust model, Plugin Development (SDK, definePlugin, ctx, routes/jobs, the client bridge, testing with the mock host), Plugin Permissions reference, and Publishing (registry PR + CI gates + provenance). Linked from the sidebar. - Reference plugin plugin-sdk/examples/trip-countdown: a complete, minimal- permission widget (reads trip data through ctx, renders in the sandboxed iframe via the bridge, filled-in README). Validated in the SDK test suite so it passes the exact gate authors face. |
||
|
|
5a007a1f0e |
feat(planner): integrate transit into the transport system as Automated mode
The add-transport dialog gains a Manual/Automated switch: Automated embeds the public-transit search (day picker + from/to + modes + preferences + results) right in the dialog, and the day header's tram button opens it directly in that mode. The standalone search modal is gone. Saved journeys get their own roomy journey view — the stop-by-stop itinerary (times, platforms, lines, headsigns, operators) together with the editable booking fields, delete, and a "Change route" action that re-runs the search pre-seeded with the journey's origin/destination and replaces the itinerary on save. The generic transport form no longer opens for transit entries, from the timeline or from the Transports tab, where journeys now sit in their own "Automated public transit" section with their line badges on the card. New i18n keys in every locale; wiki updated. |
||
|
|
3c87d37cd9 |
feat(planner): make transit journeys first-class entries (#1065)
A saved transit route is now its own reservation type instead of piggybacking on train/bus: it gets a tram icon and its own color everywhere, and the day timeline renders the itinerary inline — line badges in their official colors with walk segments, plus the transfer count and walking time — instead of a generic transport row. Clicking the row opens the itinerary view (journey summary, stop-by-stop legs with times, platforms, headsigns and operators) rather than the edit form; editing stays reachable from an Edit action inside that view. The transit type is registered across the timeline merge, transport modal, reservations panel, file manager, map overlays and detail panels, with a translated type label in every locale. |
||
|
|
45f1ff7799 |
feat(planner): public transit routing via Transitous (#1065)
Each day header gets a transit button (replacing the rename pencil, which moved next to the day name in the day detail panel). It opens a route search backed by Transitous/MOTIS — free, open data, no paid provider: from/to stop search with the day's own places as quick picks, depart/arrive time, mode filters (train, subway, tram, bus, ferry, cable car) and ranking by best route, fewer transfers or less walking. Results show local times, duration, transfers, walking time and line badges in their official colors, with a stop-by-stop breakdown per connection. Adding a connection saves it as a regular transport reservation — typed by its dominant leg, timed from the itinerary's wall-clock departure/arrival converted to station-local time (tz-lookup), with the origin, transfer stops and destination as endpoints and the compact legs in metadata.transit. It slots into the day timeline by time and inherits editing, deletion and drag-reordering from the existing transport machinery; the transport detail view renders the full itinerary. Re-saving a transit transport through the edit modal preserves the stored itinerary while the route is unchanged. The server proxies the Transitous API (JWT-guarded, rate-limited, identifying User-Agent, short response cache, strict mode whitelist); TRANSIT_API_URL lets self-hosters use their own MOTIS instance. New i18n keys in every locale, wiki page updated. Discussion #1065 |
||
|
|
5f77fa5cca |
feat(trips): trip invite links + optional trip binding on admin invites
Trip invite links (#1143): each trip can have one rotating invite link in its Share panel. An existing, logged-in user who opens /join/<token> is added to the trip as a member; an anonymous visitor is sent to the login page and returned to the invite afterwards — there is no registration from this link. Reading, rotating or disabling the link all require the share_manage permission. Admin invite trip binding (#1402): the admin create-invite dialog can now bind a registration invite to a trip. Someone who registers via that link is auto-added to the trip as a member (password and OIDC paths), inside the same atomic step that consumes the invite. Adds a trip_invite_tokens table and a nullable invite_tokens.trip_id, a shared owner-safe/idempotent add-by-id helper, the manage + join endpoints, the JoinTripPage and Share-panel section, the admin trip picker, and the new i18n keys across every locale. Wiki updated. Discussion #1143 |
||
|
|
7d87d87eec |
docs(wiki): add Collections addon page (#1081)
New wiki/Collections.md in the style of the other addon pages (lists, status, categories, adding/bulk-adding places, place detail, filters + bulk actions, fusion sharing with member roles, dashboard widget). Add it to the Addons overview table + the sidebar navigation. |
||
|
|
c7e4b2781b | docs(wiki): document force-offline, selective storage and conflicts | ||
|
|
9dd9057b7b |
feat(mcp): add bulk_update_places tool
Apply the same field values to many places in one call instead of one update_place per place — e.g. re-categorising 80 POIs at once. Adds the updatePlacesMany service (one transaction, trip-scoped, partial patch built on updatePlace) and the bulk_update_places MCP tool with the usual demo/access/place_edit guards and a place:updated broadcast per place. |
||
|
|
7173e82fe8 |
feat(feeds): subscribable ICS calendar feeds for trips
Adds TripIt-style live calendar subscriptions alongside the existing one-time .ics download. A trip (or all of a user's trips) exposes a secret, revocable feed URL that Google/Apple/Outlook poll to stay in sync. - Public read endpoints GET /api/feed/trip/:token.ics and /api/feed/user/:token.ics (no auth — the secret token is the credential), reusing the existing exportICS() generator and adding REFRESH-INTERVAL / X-PUBLISHED-TTL hints. - JWT-guarded token endpoints to generate (lazy, idempotent) and regenerate/revoke per-trip and per-user feed tokens; tokens stored in nullable feed_token columns. - All-trips feed excludes archived trips and trips ended >90 days ago. - UI: ICS toolbar button becomes a Download/Subscribe menu; modal offers one-click "Add to Google Calendar" (render?cid=webcal://) and a webcal:// link for Apple/Outlook, plus copy-link fallbacks. All-trips feed reachable from dashboard. - Feed base URL read from the existing APP_URL env var. Purely additive: new endpoints + two nullable columns, no breaking changes. Tests: server/tests/e2e/feeds.e2e.test.ts covers lazy token generate + idempotency, regenerate-invalidates-old, 401/404 auth+access, public feed content-type + hint injection, unknown-token 404, and the archived/>90-day all-trips exclusion. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
e34f40b686 |
feat(costs): Splitwise-like cost splitting
Add per-payer and per-member custom split amounts with Equally, Custom and Ticket split modes on top of the existing equal split, keep legacy "paid by" expenses working, and document the modes in the Budget Tracking wiki page. |
||
|
|
41c541828f |
fix(setup): warn when ADMIN_EMAIL/ADMIN_PASSWORD are ignored, ship reset-admin
The first-run seeder only applies ADMIN_EMAIL/ADMIN_PASSWORD on an empty database and then silently ignores them. People add the vars after the first boot, or pull a fresh image without clearing ./data, restart, and cannot log in with no hint why (#1339). The default is a generated password (not the .env.example placeholder), printed once in the first-run box. Now: warn loudly when the vars are set but a user already exists, and warn on a partial (one-of-two) config instead of quietly falling back. Also ship the reset-admin recovery script in the image -- it was never COPYed in despite the wiki referencing it. node server/reset-admin.js resets/creates admin@trek.local with a generated password (RESET_ADMIN_EMAIL/RESET_ADMIN_PASSWORD overridable), picks a free username so it cannot trip UNIQUE(username), and sets must_change_password. |
||
|
|
37f1fff367 | Merge main into dev after the v3.1.3 release | ||
|
|
0c1c534435 | docs(wiki): document the snap Docker + no-new-privileges startup failure | ||
|
|
005e0c109d |
fix(maps): make Overpass endpoints configurable and harden the POI search (#1309)
Builds on @Hardik-369's instance-specific User-Agent idea and reworks the rest of the #1309 fix: - keep the unique User-Agent (buildUserAgent) — a shared UA gets the public Overpass mirrors to rate-limit harder; it appends the configured instance URL and is applied to every Nominatim/Overpass/Wikimedia call - add OVERPASS_URL so an operator behind locked-down egress (e.g. a Kubernetes cluster) can point the explore search at an internal/self-hosted Overpass instance instead of the public mirrors - keep the per-endpoint timeout default at 12s but make it tunable via OVERPASS_TIMEOUT_MS for slow self-hosted instances; non-positive/invalid values fall back to the default rather than 502-ing every search at a 0ms cap - log each endpoint's failure reason before the 502 so blocked egress is diagnosable instead of a bare "Overpass request failed" Adds unit tests for the User-Agent, endpoint and timeout resolution plus the all-mirrors-down path, and documents the two new env vars in .env.example, the wiki and the Helm chart. |
||
|
|
382ec37142 | docs: dedupe development environment guide (#1320) | ||
|
|
92e3ebb4d5 | chore(wiki): ensure correctness for kitinerary installation | ||
|
|
49fb2fded2 | chore(wiki): make sure that all environement variables are properly documented | ||
|
|
ad893eb1cc |
Release 3.1.0 (#1185)
* Phase 0 — NestJS + Zod foundation harness (F1–F8) (#1050) Co-hosted NestJS app behind the existing Express server via a strangler-fig dispatcher, sharing the same better-sqlite3 connection and JWT httpOnly cookie. Additive and dormant: default routing stays on Express, Nest only serves its own /api/_nest diagnostics until a module opts in. F1 @trek/shared Zod contract package; F2 Nest bootstrap co-hosted (fall-through, single Dockerfile/port); F3 shared better-sqlite3 provider; F4 JWT cookie auth guard (+ @CurrentUser, admin guard); F5 Zod validation pipe + error-envelope parity; F6 Nest test + coverage gates; F7 per-prefix strangler toggle (env, default Express); F8 CI build/typecheck/test/coverage. Remaining F4/F6/F8 checklist items (trip-access + permission levels + MFA policy, e2e harness/seed + 80% gate, Nest↔Express parity test, Playwright PR-comment workflow) are tracked on the first consuming module cards (L1/A1/C1). * feat(weather): migrate /api/weather to the NestJS pilot module (L1) (#1053) First strangler migration (L1): /api/weather is served by a NestJS module. - @trek/shared/weather Zod contract; Nest controller byte-identical to the legacy Express route (paths, query params, status codes, { error } bodies, lang default, ApiError/500 passthrough). Service reuses getWeather/getDetailedWeather (+ shared cache; MCP tools unchanged). - Strangler routes /api/weather to Nest by default; the legacy Express route + its migration-time parity test were decommissioned in this PR. - Frontend (FE2): weatherApi typed against the @trek/shared WeatherResult contract. - Harness: reusable Nest-vs-Express parity harness, e2e harness (temp SQLite + seed/cookie helpers, real JwtAuthGuard), src/nest coverage gate raised to >=80%, src/nest test guide. - Verified end-to-end on a prod mirror (dev1): 401/400/200 via Nest with real Open-Meteo data, Express route gone. * fix(packing): multiply item weight by quantity in bag/total weight calcs (#898) Quantity now counts toward bag and total weights. Generalised to an itemWeight() helper used by every weight sum (bag totals + max, unassigned, grand total; sidebar + bag modal) with unit tests. * feat(i18n): add Korean (ko) translation (#977) Korean translation by @ppuassi, topped up to full en.ts key parity. Language registration follows separately. * feat(i18n): add Japanese (ja) translation (#829) Japanese translation by @soma3978, at full en.ts key parity, registered in supportedLanguages + TranslationContext. * Add Turkish (tr) translation + language registry (#1029) Turkish translation by @SkyLostTR, at full en.ts key parity, registered in supportedLanguages + TranslationContext. * i18n: register Korean + add Ukrainian translation (#1055) Korean translation by @ppuassi (#977) — now registered. Ukrainian by @JeffyOLOLO (#902) — lifted onto a clean branch. Both at full en.ts key parity (2258 keys). * chore: fix monorepo build pipeline and migrate shared to built package (#1056) * chore: fix monorepo build pipeline and migrate shared to built package - Root package.json: add workspace scripts (dev, build, test, test:cov, test:e2e) that delegate to actual scripts in shared/server/client workspaces - shared: add tsup build step (CJS + ESM dual output, .d.ts); consumers now import from the built dist instead of raw TS source via path aliases - server: replace tsc-alias with tsconfig-paths (tsc-alias mangled node_modules paths); fix MCP SDK path aliases to point to root node_modules (../node_modules) - server/scripts/dev.mjs: delay node --watch until tsc -w signals first-pass done, eliminating the spurious restart on every dev startup - client/vite.config.js + vitest.config.ts: remove @trek/shared path alias (no longer needed now that shared is a proper package) - Consolidate package-lock.json at the workspace root; drop per-workspace lock files * chore: fix test script to reflect root package.json * chore: add missing lint and prettier script in root package.json * fix(ci): build shared before tests; fix vitest MCP SDK alias paths vitest.config.ts aliases pointed at ./node_modules/ (server-local) but packages are hoisted to the root node_modules/ in the npm workspace — changed to ../node_modules/. CI jobs now install and build shared before running server/client tests so that @trek/shared's dist/ exists when vitest resolves the package. * fix(docker): update Dockerfile and CI for monorepo workspace structure Dockerfile: - Add shared-builder stage that produces @trek/shared dist before client and server stages need it - Each build stage carries root package.json + package-lock.json so npm can resolve @trek/shared as a workspace dependency - Production stage installs via workspace context (npm ci --workspace=server --omit=dev) so node_modules/@trek/shared symlinks to shared/dist correctly - Copy server/tsconfig.json into the image so tsconfig-paths/register can find the MCP SDK path aliases at runtime - CMD cds into /app/server before starting node so tsconfig-paths baseUrl resolves and ../node_modules points to /app/node_modules - Remove mkdir for /app/server (now a real dir); keep symlinks for uploads/data docker.yml version-bump: - Replace manual per-workspace cd+npm-version calls with single: npm version --workspaces --include-workspace-root --no-git-tag-version (mirrors the version:* scripts in root package.json) - git add now references root package-lock.json; adds shared/package.json .dockerignore: add shared/dist package.json: fix version:prerelease preid (alpha → pre) * fix(tests): use in-memory SQLite per worker in test mode vitest pool:forks spawns parallel worker processes that all called initDb() on the same data/travel.db, causing SQLite "database is locked" and "duplicate column name" races. When NODE_ENV=test each fork now gets an isolated :memory: DB so migrations run independently with no file contention. * chore(ci): add ACT guards to skip DockerHub steps in local act runs act sets ACT=true automatically. Guards added: - docker login: if: ${{ !env.ACT }} - build outputs: type=docker (local load) when ACT, push-by-digest when CI - digest export/upload: if: ${{ !env.ACT }} - merge job: if: ${{ !env.ACT }} - release-helm job (docker.yml): if: ${{ !env.ACT }} - version-bump git push (docker.yml): wrapped in [ -z "$ACT" ] shell guard Run locally with: ./bin/act -j build -W .github/workflows/docker.yml \ -P ubuntu-latest=catthehacker/ubuntu:act-latest * fix(ci): move ACT guards to step level; add guards to security.yml env context is invalid in job-level if conditions — moved all ACT guards down to individual steps. Also guards docker login + scout in security.yml so act can run the build-only part of that workflow. * fix(ci): skip git fetch and tag logic in act (no remote access in local containers) * Revert "fix(ci): skip git fetch and tag logic in act (no remote access in local containers)" This reverts commit |
||
|
|
b25eb18ea4 | wiki: small precision in dev env | ||
|
|
8410d7c4a5 | wiki: update dev env | ||
|
|
86ee8044da |
v3.0.22 Bug Fixes & Improvements (#1041)
Bundles the v3.0.22 bug fixes and improvements. See the release notes for the full list. |
||
|
|
117942f45e |
v3.0.21 Bug Fixes (#998)
* fix(journey): remove photo upload count limit and surface upload errors (#997) Removes the arbitrary 10-file cap on journey entry photo uploads and 20-file cap on gallery uploads. MulterErrors now return proper 4xx responses instead of 500, and the client surfaces the server error message via toast rather than silently trapping the user in the post editor overlay. * fix(planner): remove correct assignment when place assigned to same day multiple times When a place was assigned to the same day more than once, the "Remove from day" button in PlaceInspector always deleted the first assignment (Array.find on place.id) instead of the currently selected one. Now prefers selectedAssignmentId when available. Fixes #1005 * fix(map): enable 3D terrain for Mapbox outdoors style in trip planner wantsTerrain() only matched satellite styles, so the outdoors-v12 style was flat in the planner despite showing correct 3D terrain in the settings preview. Added outdoors-v12 to the allowlist; marker drift is already handled by syncMarkerAltitudes(). Fixes #1002 * fix(maps): send Referer header on Google API calls when APP_URL is set Supports HTTP referrer restrictions on GCP API keys. Documents the restriction types and photo troubleshooting steps in the wiki. |
||
|
|
e7211325df | Add asset.download permission to Photo Providers | ||
|
|
da3cba2de3 |
v3.0.19 Bug Fixes (#992)
* fix(mcp): replace relative oauth constent redirect by absolute redirect derived from APP_URL (#987) * feat(journey): convert HEIC/HEIF uploads to JPEG for cross-platform compatibility HEIC is an Apple-only format not recognised as an image by many browsers and platforms. heic-to (lazy-loaded) now converts HEIC/HEIF files to JPEG before upload in both the gallery and entry editor photo pickers. Embedded metadata (EXIF, GPS) may be lost during conversion — documented in the Journey Journal wiki page. * fix(journey): skip heic-to import for non-HEIC files to avoid test env failures * fix(notifications): prevent double-escaping HTML in password reset emails buildPasswordResetHtml passed a pre-built HTML block to buildEmailHtml, which then escaped it again — rendering raw tags as plain text in the email. |
||
|
|
25f326a659 |
v3.0.16 — bug fixes (#964)
* fix(mcp): MCP RFC compliant for more strict clients * fix(mcp): serve flat /.well-known/oauth-protected-resource for ChatGPT reconnect Clients such as ChatGPT probe the flat well-known URL on every fresh discovery cycle (i.e. after a full disconnect/reconnect where cached OAuth state is cleared). The SDK's mcpAuthMetadataRouter only serves the path-based form /.well-known/oauth-protected-resource/mcp, so the flat probe returned 404. Without the resource metadata, ChatGPT fell back to the issuer URL as the resource parameter (https://…/ instead of https://…/mcp). The authorize handler then rejected it with invalid_target and redirected back to ChatGPT's callback with an error — showing the user the TREK home page instead of the consent form. Add an explicit GET handler for the flat URL that returns the same protected resource metadata, so the resource URI is discovered correctly on the first probe. * fix(mcp): fix OAuth popup blank page — SW denylist and COOP header Service worker was intercepting /oauth/authorize navigate requests (not in denylist), serving index.html, and React Router's catch-all redirected to / instead of the SDK authorize handler. Helmet's default COOP: same-origin isolated the /oauth/consent popup from its cross-origin opener, making window.opener null and breaking the popup-based OAuth completion signal for ChatGPT and similar clients. * fix(ntfy): encode non-Latin-1 header values with RFC 2047 to prevent ByteString crash Todo/trip names containing chars like → or € (and non-Latin-1 locale templates for Czech, Chinese, Russian, etc.) caused the Fetch API to throw when setting the ntfy Title header. Apply RFC 2047 base64 encoded-word encoding for any header value containing chars above U+00FF; ntfy decodes this automatically. * docs(mcp): document Cloudflare bot detection blocking ChatGPT MCP requests Add Cloudflare WAF note to MCP-Setup and a full troubleshooting entry covering root cause (IP reputation + UA heuristics), free-plan limitation (disable Bot Fight Mode entirely, with explicit warning), and paid-plan WAF skip rule with the full expression syntax and path table for all MCP/OAuth/.well-known routes. * fix(pwa): detect upstream proxy auth challenges and recover gracefully Behind Cloudflare Zero Trust or Pangolin, cross-origin auth redirects on /api/* calls surface as CORS errors (error.response === undefined) that the existing 401 interceptor never catches, leaving the PWA stuck with network-error toasts instead of re-authenticating. New connectivity module probes /api/health every 30s using fetch with cache:no-store and inspects Content-Type to reliably detect whether the server is reachable vs intercepted by an upstream proxy. axios interceptor changes: - On !error.response + navigator.onLine: run probeNow(); if the health probe also fails (proxy is intercepting all requests), trigger a guarded window.location.reload() so the edge proxy can intercept the top-level navigation and run its auth flow (covers CF Access and Pangolin 302 mode) - On error.response status 401 with text/html body: same reload path, covering Pangolin header-auth extended compatibility mode which returns 401+HTML instead of a 302 redirect. TREK own 401s are always JSON so there is no collision with the existing AUTH_REQUIRED branch. - sessionStorage flag prevents reload loops; cleared on any successful response so the guard resets after re-auth. /api/health excluded from SW NetworkFirst cache (vite.config.js regex) and Cache-Control: no-store added server-side so probes always hit the network and cannot be served stale from the 24h api-data cache. LoginPage caches last-known appConfig in localStorage so the SSO button renders in OIDC+UN/PW dual mode even when the config fetch is intercepted by the proxy. Auto-redirect to IdP skipped when config comes from cache to avoid redirect loops while the proxy is challenging. Fixes discussion #836. * fix(files): add bottom-nav padding to files tab wrapper on mobile * fix(budget): expose toolbar on mobile so users can add budget categories * fix(pwa): unregister SW before proxy-reauth reload so Pangolin can challenge WorkBox's NavigationRoute served the cached SPA shell on window.location.reload(), meaning Pangolin/CF Access never saw the navigation and the app was left stuck showing stale offline data. Unregistering the SW first lets the navigation reach the network so the upstream proxy can run its auth flow. Also rebuilds server/public with corrected sw.js (health excluded from NetworkFirst, /oauth/ and /.well-known/ added to NavigationRoute denylist). * chore: remove committed build artifacts from server/public Dockerfile and Proxmox community script both rebuild client/dist and copy it into server/public at build time — committed artifacts were never used. Replace with .gitkeep and add server/public/* to .gitignore. * chore: add build-from-sources script |
||
|
|
418f3e0bb2 |
docs: add Portainer install guide and tag strategy to wiki
- Add wiki/Install-Portainer.md with stack setup, image tag strategy, update instructions, named volumes, and 7 annotated screenshots - Add tag strategy sections (latest / major / pinned) to Install-Docker.md, Install-Docker-Compose.md, and Updating.md - Add named volumes examples with Docker Compose volumes reference link to Install-Docker.md, Install-Docker-Compose.md, and Install-Portainer.md - Add Portainer update section with screenshots to Updating.md - Add Install-Portainer entry to _Sidebar.md |
||
|
|
22f3bf4bfc |
fix: add APP_VERSION fallback and HOST bind address env var (#952 #953) (#955)
* fix: add APP_VERSION fallback and HOST bind env var (#952 #953) - Read package.json version when APP_VERSION env var is absent so the startup banner shows the correct version for source/Proxmox installs - Add HOST env var to control the HTTP bind address; only applied when set so Docker deployments are unaffected (bind-all-interfaces default) - Parse PORT as Number() so malformed values like '10.0.0.72:3001' fall back to 3001 instead of silently misbehaving - Document HOST in .env.example, Environment-Variables wiki, and Install-Proxmox wiki with explicit warnings against using it in Docker * fix: correct package.json path in APP_VERSION fallback index.ts sits at server/src/ — one level up reaches server/package.json, not two (../../ overshot to the repo root where no package.json exists). |
||
|
|
256f38d8fa | docs: add budget documentation GIFs (create, add expense, final settlement) (#948) | ||
|
|
9592cc663f | docs: document wiki-only PR exemption from branch enforcement | ||
|
|
6072b969d6 |
Bug fixes - May 2nd 2026 (#941)
* fix: collab chat input hidden by mobile bottom nav bar Closes #939 * chore: prepare database for nest + typeorm * fix(ssrf): relax internal network resolution (#947) * docs(ssrf): update Internal-Network-Access wiki to reflect relaxed guard Loopback, link-local, and .local/.internal hostnames are now all overridable with ALLOW_INTERNAL_NETWORK=true (commit |
||
|
|
bb89d70a94 |
docs: document required permissions for Immich and Synology photo providers
Co-authored-by: Ben Haas <ben@benhaas.io> |
||
|
|
ad9f3887d8 |
docs: add wiki guide for adding places to day itinerary with GIFs
Co-authored-by: Tranko <tranko@gmail.com> |
||
|
|
12fc7f7b68 | docs: fix Proxmox update section to run inside LXC and add command | ||
|
|
5c3b89578d |
docs: add Proxmox VE LXC install guide and update CI ignore paths
- Add wiki/Install-Proxmox.md with full install/update/log instructions - Add Proxmox VE section to wiki/Updating.md - Add Install: Proxmox VE (LXC) to wiki/_Sidebar.md - Add "Proxmox Community Script" option to bug report install dropdown - Exclude GitHub meta files from triggering Docker CI workflow |
||
|
|
4923973380 | docs(wiki): add MCP OAuth troubleshooting entry for missing APP_URL | ||
|
|
2a37eeccb3 |
fix: hot fixes 23-04-2026 (#856)
* fix(packing): resolve avatar URL path in bag and category assignees (#854) packingService was returning raw avatar filenames from the DB instead of the full /uploads/avatars/<filename> path, causing broken profile images for users with uploaded avatars. * fix(budget): use Map.get() to fix category rename no-op (#855) * fix(security): relax Referrer-Policy and document HSTS_INCLUDE_SUBDOMAINS (#862) (#863) - Change Helmet default from no-referrer to strict-origin-when-cross-origin so browsers send the origin on cross-origin requests, allowing Google Maps API key restrictions by HTTP referrer to work correctly - Document HSTS_INCLUDE_SUBDOMAINS in all deployment artifacts: .env.example, docker-compose.yml, README.md, unraid-template.xml, charts/values.yaml, charts/configmap.yaml, wiki/Environment-Variables.md * fix(planner): prefetch budget items on trip page mount (#864) Loads budgetItems alongside reservations when TripPlannerPage mounts so the Budget category dropdown in ReservationModal and TransportModal shows pre-existing categories on first open, regardless of whether the Budget tab has been visited. Closes #861 * fix(reservations): prevent Invalid Date when end time is set without end date (#866) When reservation_end_time held a bare time string ("HH:MM"), fmtDate() produced Invalid Date on the reservation card. - Modal: when end date is blank but end time is filled, construct a same-day ISO datetime using the start date (prevents time-only strings from ever being persisted) - Panel: derive endDatePart via regex so date-only end values ("YYYY-MM-DD") still show the multi-day range, while bare time strings are skipped and handled correctly by the existing time column logic Closes #860 * fix(planner): format reservation end time instead of rendering raw ISO string (#867) Closes #859 * fix(planner): wire Route toggle into mobile day sidebar (#850) (#868) The per-booking Route icon was missing on mobile because the mobile DayPlanSidebar invocation in TripPlannerPage didn't pass visibleConnectionIds or onToggleConnection. Mobile PWA users couldn't activate reservation map overlays without forcing desktop mode. Also corrects the Map-Features wiki: fixes the setting name ("Booking route labels" not "Show connection labels"), documents the route_calculation requirement for travel-time pills, and explains that overlays are off by default and must be toggled per reservation. |
||
|
|
314486325e | fix: resolve dead wiki links across install and config pages | ||
|
|
8e8433fa9d |
docs: align Home.md + README addon list + Tags/Photo-Providers wording with dev state
- Home.md: addon list (9 real addons), MCP numbers (150+ tools, 30 resources, 27 scopes), admin-seeding text - README.md: expand addon list from 5 to 9 (Lists/Budget/Documents/Naver/MCP in, Dashboard widgets out) - Photo-Providers.md: 'Memories addon' -> photo provider toggles under Journey - Admin-Addons.md: Journey works without photo providers; they are optional sub-toggles - Tags-and-Categories.md: add Personal Tags section (user-scoped, MCP-only for now) |
||
|
|
758de855bf | docs: more common issues in troubleshooting | ||
|
|
840f5e82aa | docs: update contributing wiki page | ||
|
|
d59b3334dc | docs(wiki): add Contributing and Development-environment to sidebar and cross-links | ||
|
|
d2c44380a4 | doc: add missing pages in wiki | ||
|
|
d7d1493289 |
docs(wiki): document self-service password reset feature
Update Password-Reset.md and Login-and-Registration.md to reflect the
email-based forgot-password flow added in feat(auth):
|
||
|
|
1559ed12bd | fix(wiki): update mapbox scopes and url |