Notechondria

Version: 0.1.20 Build Date: 2026-04-15T00:00

What's Changed

Docs — per-app server split + storage model (URGENT)

  • The old single-file docs/server/backend.md is now an overview that delegates to three per-app deep dives, each with example request/response payloads:
    • docs/server/creators.md — accounts, sessions, OAuth, API keys, settings, identity-code verification.
    • docs/server/notes.md — notes, courses, planner events, calendar feeds, recycle bin, attachments, activity heatmap, version history. Includes the notes/services.py helper inventory.
    • docs/server/mcp.md — MCP tool surface, 21 tools, API-key auth, 39 tests.
  • New docs/development/storage_model.md documents how user data is laid out across PostgreSQL + R2 (backend) and SharedPreferences (frontend). Covers the seven keys per app (local_settings, local_drafts, local_courses, local_stats, local_cache, local_logs, session), the frontend-backend reconciliation points, and the "local_drafts vs local_cache" distinction.
  • docs/SUMMARY.md indexes the new per-app server docs + the storage-model doc.

Login window shows API base domain (3 apps)

  • The Login dialog's previously-empty or generic description line now reads Signing in to <host>, derived from the user's current api_base_url. Applies in editor / planner / portal via a shared _apiHostSubtitle(apiBaseUrl) helper and a new apiBaseUrl parameter on each app's _AuthHub.

Settings — API base URL locked when signed in (3 apps)

  • The API base URL TextField in Settings is now enabled: false when _isAuthenticated, wrapped in a Tooltip that explains "Log out before changing the API base URL. A logged-in token is only valid against its issuing backend." The input also shows a helper line Locked while signed in. Log out to change.

App preferences rename

  • The editor app's settings section previously titled "Editor preferences" is now "App preferences" — same content, same auto-save behavior, but neutral wording so the widget can be reused across editor / planner / portal once the "Global reusable components" refactor in docs/TODO.md lands.
  • frontend/AGENTS.md bullet updated accordingly.

Bug fixes (editor_app)

  • Session expired silently ("Initial load used offline fallback: Invalid token") — when the initial data load hits a DRF Invalid token / Authentication credentials were not provided / token_not_valid error, the app now clears the persisted session (_token, _profile, and notechondria.session) and logs Session expired — signed out. Please sign in again. instead of silently dropping into offline mode with a stale identity.
  • OAuth bind 401 with confusing "Use /api/v1/auth/bind/google/" backend message — the bind callback path in frontend/editor_app/lib/app_shell.dart _handleOAuthCallback used to fall through to the plain login endpoint with intent=bind when _token was null (session expired between clicking the button and the OAuth provider redirecting back). The backend rightly refused that with the pointer at the bind endpoint. The frontend now short-circuits intent == 'bind' && _token == null with a user-visible "Sign in first, then try linking the account again" snackbar, so the user gets a coherent error instead of an apparent backend bug.

Files Changed

Docs

  • docs/server/backend.md — slimmed to an overview pointing at the three per-app docs.
  • docs/server/creators.md — new (detailed creators app doc).
  • docs/server/notes.md — new (detailed notes app doc).
  • docs/server/mcp.md — new (MCP server doc).
  • docs/development/storage_model.md — new (storage model).
  • docs/SUMMARY.md — re-indexed server + development sections.

Frontend

  • VERSION — bumped 0.1.19 → 0.1.20.
  • frontend/editor_app/lib/core/helpers.dart, frontend/planner_app/lib/core/helpers.dart, frontend/portal_app/lib/core/helpers.dart_kAppVersion default bumped to match.
  • frontend/editor_app/lib/components/auth_dialogs.dart — added _apiHostSubtitle helper + apiBaseUrl parameter on _AuthHub; Login dialog uses the subtitle.
  • frontend/planner_app/lib/modules/settings.dart — same helper + parameter inline (planner keeps _AuthHub in this file, not in a separate components/ file).
  • frontend/portal_app/lib/modules/settings.dart — same.
  • frontend/editor_app/lib/modules/settings.dart — wired apiBaseUrl into _AuthHub; renamed "Editor preferences" to "App preferences"; wrapped the API base TextField in a Tooltip and set enabled: !_isAuthenticated.
  • frontend/planner_app/lib/modules/settings.dart — same lock-tooltip treatment on the API base TextField.
  • frontend/portal_app/lib/modules/settings.dart — same.
  • frontend/editor_app/lib/app_shell.dart — invalid-token detection
    • session clear in the initial-load path; bind-without-token short-circuit in _handleOAuthCallback.
  • frontend/AGENTS.md — reflects the "App preferences" rename.

Notes / follow-ups

  • The two bug fixes above are in editor_app only this round. Planner and portal have the same offline-fallback and bind callback paths (inlined in their respective app_shell.dart); they should get the same treatment in a follow-up round.
  • The "Global reusable components" URGENT TODO item (shared Sidebar/Navigation, Debug window, Login window, App preferences) is still pending — the rename and shared _apiHostSubtitle helper are the only steps toward it this round.
  • The splash animation / chemistry work and the debug-log terminal UI remain open in TODO.md.