Security: - Clear the offline IndexedDB cache on sign-in (not only logout) so a previous user's persisted query cache and Yjs page bodies cannot leak to the next user on a shared device when the prior session ended without an explicit logout. Regressions: - Remove the double Yjs title write from the AI title-generation path: the title editor is bound to the Yjs `title` fragment and the server REST update reseeds it, so the local setContent raced that reseed and doubled/garbled the title. Conventions / i18n / docs: - Remove the unused showAiMenuAtom. - Register the 3 offline-fallback strings in en-US and ru-RU. - Fix the 5 broken links to the nonexistent docs/offline-sync-plan.md. Stability / simplification: - warmInfiniteAll now reports truncation (returns false) when it hits maxPages with a cursor still pending instead of silently succeeding. - space-tree make-offline catch logs the raw error and surfaces the real cause. - Move the Offline/Mobile/CORS CHANGELOG entries from the released 0.93.0 section into [Unreleased] (CORS is a documented breaking change). - Drop the pass-through sync-flag forwarders in use-page-collab-providers; set the atoms directly. - Collapse the three isSwaggerEnabled true-cases into it.each. Tests / architecture: - Extract collabTokenNeedsRefresh (pure) and cover all four token states. - Extract shouldPropagateTitleChange and cover the collab-origin skip; add a TitleEditor render test for the static-h1 vs collaborative-editor switch. - Add a use-auth test asserting the sign-in cache purge runs before login. - Add an OFFLINE_PERSIST_ROOTS guard test asserting every persisted root maps to an exported query-key factory; route make-offline's currentUser warm through a new userKeys factory. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3.8 KiB
3.8 KiB
Mobile app bootstrap
Purpose: this document records what has been bootstrapped in the repo to enable a mobile app for Gitmost, per the first-step checklist in docs/mobile-app-plan.md section 12.
What is in the repo now
- PWA: web app manifest plus a service worker generated by
vite-plugin-pwausing Workbox (strategies: "generateSW"— not hand-rolled). The SW is built for production only (devOptions: { enabled: false }) and usesregisterType: "prompt", so the user is asked to apply an update rather than it auto-updating; registration goes throughvirtual:pwa-register/react(useRegisterSW) inapps/client/src/pwa/pwa-update-prompt.tsx, mounted frommain.tsxand skipped inside the Capacitor native WebView. The SW precaches the app shell (globPatternsjs/css/html/...) and servesnavigateFallback: "index.html"for SPA routes, withnavigateFallbackDenylistexcluding the server-owned routes/api,/collab,/socket.io,/share/,/mcp, and/robots.txt.runtimeCachingkeeps/collab,/socket.io, and all/apiasNetworkOnly— offline reads are served by the persisted TanStack Query cache (IndexedDB) andy-indexeddbfor the page Yjs doc, not by an SW HTTP cache. This lets the existing responsive web UI be installed and run as a Progressive Web App. The offline/sync design (stages M0…M4) is summarized in mobile-app-plan.md. - Backend mobile auth: opt-in token return from the login flow. The login
request accepts a
returnTokenflag (must be sent as a JSON boolean) that makes the server include the auth token in the response body, and the server already accepts aBearertoken in theAuthorizationheader. Note the global response interceptor wraps every payload, so the native client reads the token atresponse.data.authToken(not at the top level). A native client can store this token (Keychain / Keystore) and send it asAuthorization: Beareron each request. - Explicit CORS allowlist: the server reads a
CORS_ALLOWED_ORIGINSenv variable for the allowed origins, and always allows the native WebView origins (capacitor://localhost,ionic://localhost,https://localhost) so the mobile shell can call the API. - Optional OpenAPI / Swagger: an opt-in OpenAPI/Swagger surface gated behind
the
SWAGGER_ENABLEDenv flag, useful for developing the native client. - Capacitor config: capacitor.config.ts at the
repo root. It targets the
apps/clientweb build output (apps/client/dist) for the Android bundled mode, and on iOS loads the client from a hosted server viaCAP_SERVER_URL(server.url) so the AGPL web client is not bundled into the.ipa(see mobile-app-plan section 9).
Remaining MANUAL / local steps (require Xcode / external accounts, out of scope here)
- Run
pnpm installto fetch the Capacitor packages and@nestjs/swagger. - Run
pnpm run client:buildto produce the web build inapps/client/dist. - Run
npx cap add iosand/ornpx cap add androidto generate the native platform projects (these live outside version control; see.gitignore). - Set
CAP_SERVER_URLfor the iOS build so the shell loads the hosted client (AGPL-clean), then runpnpm run mobile:build/cap sync. - Set up push notifications: APNs for iOS and FCM for Android.
- Obtain an Apple Developer account and the App Store / Play Console listings.
- Confirm the AGPL iOS distribution decision (mobile-app-plan section 9) before shipping anything to the App Store.
See also
For the full background, rationale, and the licensing analysis, see docs/mobile-app-plan.md (section 12 for the bootstrap checklist, section 9 for the AGPL / App Store licensing path).