Commit graph

232 commits

Author SHA1 Message Date
Till JS
b91d4fb663 fix(help): add missing marked dependency
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 18:27:17 +01:00
Till JS
38c192b82c chore: update pnpm-lock.yaml
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 18:17:31 +01:00
Till JS
e7bcb230be refactor(auth): centralize auth stores — 21 apps use createManaAuthStore factory
Created createManaAuthStore in @manacore/shared-auth-stores that replaces
~350 lines of duplicated auth.svelte.ts per app with a ~10 line factory call.

The factory handles: SSO, passkeys, 2FA, magic links, token management,
password reset, sign up/in/out — everything the old stores did.

Each app only provides devBackendPort and optional onAuthenticated callback.

Before: 21 apps × ~350 lines = 6,800 lines of duplicated auth code
After:  21 apps × ~10 lines  = 182 lines total (97% reduction)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 18:04:27 +01:00
Till JS
5e05c532a2 fix(packages): fix type errors in consolidated packages + add missing files
- credits: fix mobile import paths (./operations → ../operations)
- feedback: fix createFeedbackService import (./feedback → ./api),
  recover missing types.ts from git history
- help: add package files (were untracked after consolidation)
- Update lockfile after package restructuring

All packages pass tsc --noEmit (excluding expected .svelte imports).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 17:53:34 +01:00
Till JS
d70ab97a66 refactor(packages): consolidate 4 help packages into @manacore/help
Merged shared-help-types + shared-help-content + shared-help-ui into
@manacore/help. Deleted shared-help-mobile (0 consumers).

Updated imports in all 20 web apps.

Package count: 53 → 49

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 17:36:32 +01:00
Till JS
8ccf8ff818 chore: misc fixes, new services, lockfile cleanup
Assorted changes from recent sessions:
- .gitignore: add mana-sync binary, Forgejo data
- chat/web: add isSidebarMode to navigation store
- clock/web: fix alarm page markup
- contacts/mukke/presi/questions: add svelte.config.js aliases
- context/web: add missing dependency
- manacore/landing: update pricing page
- manacore/web + todo/web: update mana dashboard pages
- planta/web: fix dashboard layout
- pnpm-lock.yaml: cleanup after backend removals
- docs/APP_GAP_ANALYSIS.md: new gap analysis doc
- services/mana-analytics: add Dockerfile
- services/mana-subscriptions: new Go subscription service

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 10:27:35 +01:00
Till JS
5c33962439 feat(local-first): migrate tags + task stores to reactive liveQuery across all apps
- Todo: Replace manual fetch/state stores with useLiveQuery() for tasks,
  projects, and tags. Components use Svelte context instead of store imports.
  Stores reduced to mutation-only services. Removes ~200 lines of manual
  state management. Enables multi-tab sync and auto-refresh on data changes.

- Tags (all 16 apps): Migrate from API-based createTagStore() to shared
  local-first IndexedDB ('manacore-tags'). Tags now work offline and in
  guest mode with default seed data. All apps share the same tag DB via
  tagLocalStore + useAllTags() + setContext pattern.

- Cleanup: Delete unused Todo API files (projects.ts, labels.ts,
  reminders.ts), remove dead labels store, clean up barrel exports.

Apps migrated: Todo, Zitare, Questions, Planta, Clock, Presi, Mukke,
Context, CityCorners, ManaDeck, Chat, Contacts, Calendar, Picture,
Storage, Photos

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 02:02:52 +01:00
Till JS
2c9a36828f feat(apps): migrate Calendar, Clock, Contacts, ManaDeck to local-first
Roll out @manacore/local-store to 4 more apps:

- Clock: alarms, timers, world clocks in IndexedDB with guest seed
- Calendar: calendars, events in IndexedDB with sample events
- Contacts: contacts in IndexedDB with 3 sample contacts
- ManaDeck: decks, cards in IndexedDB with onboarding flashcards

All apps: GuestWelcomeModal, login pill for guests, sync on auth.
Dev scripts: added dev:sync, dev:todo:server, dev:todo:local, dev:todo:full updated.

6 of 8 web apps are now local-first (Todo, Zitare, Clock, Calendar, Contacts, ManaDeck).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:10:07 +01:00
Till JS
b16e245fe3 feat(zitare): migrate to local-first with Dexie.js
- Favorites and lists stores rewritten to read/write IndexedDB
- Guest seed data: 3 pre-favorited quotes + sample list
- Layout: zitareStore.initialize(), sync on login, GuestWelcomeModal
- PillNav shows login button for guests (empty userEmail)
- No auth checks in stores — all writes are local

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 12:05:01 +01:00
Till JS
2e4bb9bad7 feat(local-first): add local-first architecture with Dexie.js, Go sync server, and Todo pilot
Implement the foundational local-first data layer for ManaCore apps:

- New @manacore/local-store package (Dexie.js IndexedDB, sync engine, Svelte 5 reactive queries)
- New mana-sync Go service (sync protocol, WebSocket push, field-level LWW conflict resolution)
- Todo app migrated as pilot: stores read/write IndexedDB, guest mode with onboarding seed data
- PillNavigation: prominent login pill for unauthenticated users
- SyncIndicator component showing local/syncing/offline status
- GuestWelcomeModal on first visit for Todo app
- Removed demo-mode auth_required checks from Todo components (all writes are now local)
- CSP fix for local development (localhost:3001, localhost:3050)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:17:58 +01:00
Till JS
7073756117 feat(auth): UX improvements for passkeys, 2FA, and password management
1. Passkey Conditional UI: autocomplete="username webauthn" on email
   field enables browser passkey suggestions in autofill dropdown
2. Trust Device checkbox: "Diesem Gerät 30 Tage vertrauen" option
   during 2FA verification (uses Better Auth trust_device cookie)
3. Local QR code generation: replaced external api.qrserver.com with
   local qrcode package for 2FA setup (no external dependency)
4. SecurityOnboarding component: post-registration wizard suggesting
   passkey setup to new users
5. ChangePassword component: reusable password change form with
   validation, visibility toggles, and changePassword() in authService

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:15:09 +01:00
Till JS
8692b0824e feat(storage): add structured logging with Pino
Setup nestjs-pino for structured JSON logging in production and
pretty-printed colorized logs in development. Health/metrics
endpoints excluded from auto-logging to reduce noise.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 13:18:58 +01:00
Till JS
8b5889e125 feat(storage): add Swagger/OpenAPI documentation
Setup @nestjs/swagger with auto-generated API docs at /api/docs.
Documents all 35 endpoints with bearer auth support.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 13:10:44 +01:00
Till JS
3091da914e feat(auth): add WebAuthn/Passkey support across all apps
Implements passwordless authentication via passkeys using @simplewebauthn:

Backend (mana-core-auth):
- New passkeys table in auth schema (credentialId, publicKey, counter, etc.)
- PasskeyService with registration/authentication flows and challenge storage
- 7 new API endpoints (register, authenticate, list, delete, rename)
- createSessionAndTokens helper for non-password auth flows
- Security event types for passkey operations

Client (shared-auth):
- signInWithPasskey() and registerPasskey() with dynamic @simplewebauthn/browser imports
- isPasskeyAvailable() browser capability check
- Passkey management methods (list, delete, rename)

UI (shared-auth-ui):
- Passkey button on LoginPage with key icon, shown when browser supports WebAuthn
- Divider between passkey and email/password form

App integration:
- All 19 web app auth stores have isPasskeyAvailable() and signInWithPasskey()
- All 19 web app login pages pass passkeyAvailable and onSignInWithPasskey props
- rpID=mana.how in production enables cross-app passkey usage (SSO-compatible)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 10:30:03 +01:00
Till JS
2d11ba6248 refactor(auth): remove all Google/Apple social login code
No external auth providers to keep authentication fully self-sovereign
and avoid dependency on third-party services. Removes Google Sign-In,
Apple Sign-In components, utilities, endpoints, translations, and
mobile dependencies across all apps and shared packages.

Google/Apple integrations for data sync (Contacts import, Calendar sync)
are intentionally preserved as they serve a different purpose.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 09:12:30 +01:00
Till JS
c7f2f9185f fix(citycorners): add missing leaflet.markercluster dependency
The package was dynamically imported in the map page but not declared
in package.json, causing production builds to fail.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 12:57:46 +01:00
Till JS
422b4f9fc9 fix(monitoring): add missing prom-client dependency to 4 backends
Nutriphi, Photos, Planta, and Presi backends had MetricsModule imported
but were missing the prom-client peer dependency, causing /metrics to
return 404 and VictoriaMetrics to report them as down (73% healthy).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 10:22:25 +01:00
Till JS
bdab272267 refactor(shared-help): extract shared translations, add Zitare + Mukke help pages
- Add defaultTranslationsDE/EN and getHelpTranslations() to shared-help-ui
  so apps only need to override the subtitle instead of duplicating ~80 lines
- Refactor all 6 existing help pages to use getHelpTranslations()
  (Contacts, Calendar, Todo, Storage, Chat, Picture)
- Add help page to Zitare (FAQ, features, contact — no shortcuts)
- Migrate Mukke from custom SettingsPage-based help to shared HelpPage
  (FAQ with audio formats, lyrics editor, playlists; features; shortcuts)

All 8 web apps now use the unified shared help system.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 09:26:26 +01:00
Till JS
f0233b8d31 feat(storage, chat, picture): add shared help pages
Add help pages to the remaining high-maturity production apps:

- Storage (84/100): FAQ (upload, sharing, versioning, trash, privacy),
  features (cloud storage, sharing, versioning, search), shortcuts
- Chat (82/100): FAQ (AI models, spaces, templates, comparison, privacy),
  features (multi-model, spaces, comparison, templates), shortcuts
- Picture (81/100): FAQ (generation, credits, moodboards, explore, privacy),
  features (AI generation, gallery, moodboards, explore), shortcuts

All 6 production web apps now have standardized help pages using the
shared help system.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 09:19:06 +01:00
Till JS
dd5c0d502f feat(calendar, todo): add shared help pages
Add help pages to Calendar and Todo web apps using the shared help system:

- Calendar: FAQ (events, recurring, sharing, sync, privacy), features,
  shortcuts, contact — with DE/EN/FR/IT/ES content support
- Todo: FAQ (quick add syntax, projects, kanban, recurring, privacy),
  features, shortcuts, contact — with DE/EN content

Both apps follow the Contacts reference implementation pattern.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 08:47:12 +01:00
Till JS
f2488f86fe feat(infra): add workspace dependency audit script
New script scans source imports vs package.json deps to catch missing
workspace dependencies that work locally but break in Docker.
Fixed: manadeck-web and presi-web missing shared-stores.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 22:36:11 +01:00
Till JS
db077aa404 fix(manacore): add missing date-fns dependency for Docker build
TasksTodayWidget imports date-fns but it wasn't in package.json,
causing Docker build failure.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:27:09 +01:00
Till JS
caa126f8de fix(zitare): add missing shared-utils dependency to web package
hooks.server.ts imports @manacore/shared-utils/analytics-server but
shared-utils wasn't listed as a dependency. pnpm doesn't create the
symlink without it, causing Rollup to fail during Docker builds.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:01:34 +01:00
Till JS
94d7e2bd02 feat(citycorners): add slugs, contacts, collections, clustering, rate limiting, soft deletes
1. SEO Slugs: Auto-generated from name (ä→ae, ö→oe, etc.), unique with
   -2/-3 suffix. Routes accept both UUID and slug. Seed data includes slugs.

2. Opening Hours + Contact: website, phone, openingHours fields in schema.
   Displayed on detail page, editable in add/edit forms.

3. Landing Page with API: Fetches locations from backend at build time,
   falls back to hardcoded JSON if API unreachable.

4. Frontend Tests: Vitest setup with api.test.ts (50 backend + web tests).

5. Marker Clustering: leaflet.markercluster for 10+ locations on map,
   direct markers for fewer.

6. Favorite Collections: New collections table with CRUD endpoints.
   Favorites page has tabs for favorites vs collections. Create, view,
   delete collections with location management.

7. Rate Limiting: In-memory guard (10 req/min) on write endpoints.
   Returns 429 with retryAfter.

8. Soft Deletes: deletedAt field, all reads filter deleted records.
   POST /locations/:id/restore endpoint for owners.

50 backend tests passing, 0 type errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 12:27:29 +01:00
Till JS
62c5dddab0 feat(project-doc-bot): migrate to shared-llm, remove OpenAI dependency
Migrate matrix-project-doc-bot from raw fetch to @manacore/shared-llm
and remove the unused openai npm package. The bot was already using
mana-llm and mana-stt (not OpenAI directly), but the code still had
raw fetch calls and the openai package installed.

Changes:
- generation.service.ts: raw fetch → llm.chat() via LlmClientService
- app.module.ts: add LlmModule.forRootAsync()
- Remove openai dependency (was unused in code)
- Update CLAUDE.md: document actual AI stack (mana-llm + mana-stt)
- Update TECH_STACK_INDEPENDENCE.md: mark Prio 1-3 as completed
  - Prio 1: Picture App → mana-image-gen 
  - Prio 2: Project Doc Bot → Ollama + mana-stt 
  - Prio 3: All LLM calls via mana-llm 
  - Self-hosted percentage: 75% → ~80%

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 10:44:56 +01:00
Till JS
44a9e02525 feat(manacore): add costs overview tab to credits page
Adds a "Kosten" tab showing all 40+ credit operations across all apps,
grouped by app with category filters (AI, Productivity, Premium) and
color-coded cost badges.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 10:10:44 +01:00
Till JS
e2f144962c feat: add unified @manacore/shared-llm package and migrate all backends
Create a shared LLM client package that provides a unified interface
to the mana-llm service, replacing 9 individual fetch-based integrations
with consistent error handling, retry logic, and JSON extraction.

Package (@manacore/shared-llm):
- LlmModule with forRoot/forRootAsync (NestJS dynamic module)
- LlmClientService: chat, json, vision, visionJson, embed, stream
- LlmClient standalone class for non-NestJS consumers
- extractJson utility (consolidates 3 markdown-stripping implementations)
- retryFetch with exponential backoff (429, 5xx, network errors)
- 44 unit tests (json-extractor, retry, llm-client)

Migrated backends:
- mana-core-auth: raw fetch → llm.json()
- planta: raw fetch + vision → llm.visionJson()
- nutriphi: raw fetch + regex → llm.visionJson() + llm.json()
- chat: custom OllamaService (175 LOC) → llm.chatMessages()
- context: raw fetch → llm.chat() (keeps token tracking)
- traces: 2x raw fetch → llm.chat()
- manadeck: @google/genai SDK → llm.json() + llm.visionJson()
- bot-services: raw Ollama API → LlmClient standalone
- matrix-ollama-bot: raw fetch → llm.chatMessages() + llm.vision()

New credit operations:
- AI_PLANT_ANALYSIS (2 credits, planta)
- AI_GUIDE_GENERATION (5 credits, traces)
- AI_CONTEXT_GENERATION (2 credits, context)
- AI_BOT_CHAT (0.1 credits, matrix)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 22:06:30 +01:00
Till JS
250e0b20af feat: add onboarding to 6 new apps and feature intro step to all 16 apps
Add onboarding with feature overview, preference selection, and tips to
Zitare, Mukke, Photos, Planta, SkillTree, and Questions. Insert a new
first "features" info step into all 10 existing onboarding flows so every
app now starts with a core-features overview page.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 21:58:14 +01:00
Till JS
df0b849408 feat: add org landing page builder service
New service that generates static Astro landing pages for organizations
and deploys them to Cloudflare Pages at {slug}.mana.how.

Components:
- Landing Builder Service (NestJS, port 3030) with Astro template
- Admin UI in Manacore web dashboard at /organizations/[id]/landing
- TeamSection + ContactSection for shared-landing-ui
- Two org themes (classic dark, warm light)
- LandingPageConfig types in shared-types
- Docker + CI/CD integration for Mac Mini deployment

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 13:20:10 +01:00
Till JS
71277ba7aa refactor(manadeck-mobile): migrate from custom auth to @manacore/shared-auth
Replace 900+ lines of custom auth implementation (authService, tokenManager,
deviceManager, safeStorage) with ~280 lines wrapping @manacore/shared-auth.
Auth now goes through mana-core-auth directly instead of manadeck backend.

Backward-compatible API: all consumers (stores, apiClient, hooks) work
without changes thanks to wrapper maintaining the same export interface.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 12:55:28 +01:00
Till JS
416e031f69 feat(matrix): add tests, E2EE warning, and dynamic homeserver config
- Make SSO loginToken homeserver configurable via VITE_MATRIX_HOMESERVER
- Add vitest setup with 14 unit tests for Matrix client functions
  (discoverHomeserver, checkHomeserver, loginWithToken)
- Show amber warning banner when E2EE is not available

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 12:18:07 +01:00
Till JS
71b9339310 refactor: move llm-playground from services/ to apps/playground/
The LLM playground is a SvelteKit web app (frontend), not a backend
microservice. Moving it to apps/ follows the monorepo convention where
all user-facing apps live under apps/.

- Moved services/llm-playground/ → apps/playground/apps/web/
- Renamed package from @mana-llm/playground to @playground/web
- Updated Dockerfile paths for new location
- Updated docker-compose.macmini.yml build context
- Removed unused concurrently dependency
- Added parent package.json

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 11:25:54 +01:00
Till JS
a2f8c32059 feat(citycorners): add PWA, i18n (DE/EN), and migrate landing to Tailwind
PWA: @vite-pwa/sveltekit with shared-pwa config, offline fallback page, service worker with standard caching preset.

i18n: svelte-i18n with DE/EN locale files, all UI strings translated, language switcher in PillNav, auth pages use shared-i18n translations.

Landing: Migrated from scoped CSS to Tailwind CSS with @astrojs/tailwind. Hero section, card grid, category filter buttons, detail page with timeline. Removed unused components (Welcome, ThemeToggle, update-locations.js).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 11:11:51 +01:00
Till JS
7910737dd9 fix(mana-media): use prom-client directly instead of shared metrics package
mana-media uses NestJS 11 while shared-nestjs-metrics targets NestJS 10,
causing DynamicModule type incompatibility. Use prom-client directly with
a simple MetricsController to expose /metrics endpoint.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 11:06:09 +01:00
Till JS
143112f77a feat(observability): add mana-search, mana-media, and Synapse to monitoring
- Add Prometheus scraping for mana-search (port 3020, already has metrics)
- Add Prometheus scraping for mana-media (port 3015, MetricsModule added)
- Add Prometheus scraping for Matrix Synapse (port 9002, already enabled)
- Add MetricsModule to mana-media with media_ prefix
- Update Dockerfile for mana-media to include shared-nestjs-metrics
- Replace hardcoded ServiceDown alert list with dynamic regex
  (.*-backend|mana-core-auth|mana-search|mana-media|synapse)
- Replace hardcoded backends.json query with dynamic regex
- Add Search, Media, Synapse to master-overview and system-overview dashboards

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 10:46:59 +01:00
Till JS
6fa6509fa5 feat(observability): add metrics and monitoring for all 15 backends
- Add MetricsModule to 8 backends missing it (photos, zitare, mukke,
  planta, picture, storage, presi, nutriphi)
- Enable Prometheus scraping for all 15 backends in prometheus.yml
  (was only 6, with 3 commented out and 6 missing entirely)
- Update ServiceDown alert rule to cover all 15 backends
- Update Grafana dashboards (backends, master-overview, system-overview)
  with all backend services in health panels
- Fix imprecise regex in application-details dashboard

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 09:09:04 +01:00
Till JS
c4385835ba chore: update pnpm-lock.yaml
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 19:16:47 +01:00
Till JS
e01b740dba refactor(analytics): centralize Umami tracking via env vars and shared utility
Move Umami analytics from hardcoded script tags in app.html to
server-side injection via hooks.server.ts. Website IDs are now
managed centrally in .env.development and distributed via
generate-env.mjs as PUBLIC_UMAMI_WEBSITE_ID.

- Add @manacore/shared-utils/analytics-server with injectUmamiAnalytics()
- Add UMAMI_WEBSITE_ID_* for all 17 web apps to .env.development
- Add PUBLIC_UMAMI_WEBSITE_ID mapping in generate-env.mjs for all web apps
- Update 10 existing hooks.server.ts to use shared utility
- Create 7 new hooks.server.ts (picture, planta, presi, photos, clock,
  questions, manadeck)
- Remove hardcoded Umami scripts from all 17 app.html files
- Add missing Umami tracking to Mukke and Questions
- Add shared-utils dependency to 6 web apps that lacked it
- Update ANALYTICS.md with architecture docs and "add new app" guide

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 18:27:31 +01:00
Till JS
9bdb997394 refactor(pwa): replace custom service workers with Vite PWA plugin and centralize offline page
Remove hand-written sw.js, offline.html, and manifest.json from todo/skilltree/zitare web apps
in favor of the Workbox-based service worker generated by @vite-pwa/sveltekit. This fixes an
issue where the custom SW could get stuck serving the offline fallback page even when the server
was reachable. Also extracts the duplicated offline page (~80 lines each across 19 apps) into a
shared OfflinePage component in @manacore/shared-ui with 3 props (appName, offlineMessage,
accentColor), reducing each app's offline route to an 8-line wrapper.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 18:16:43 +01:00
Till JS
ac3269bb3d chore: update pnpm-lock.yaml
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 21:26:05 +01:00
Till JS
c0c11c325a feat(whopixels): major refactor with 20 improvements across architecture, gameplay, UX, security, and i18n
Split monolithic RPGScene.js (1210 lines) into modular manager classes:
- WorldManager, PlayerManager, NPCManager, ChatUI, StorageManager,
  SoundManager, TouchControls

Key improvements:
- Constants config (GAME_CONFIG) replacing all magic numbers
- JSDoc types + jsconfig.json for IDE type-safety
- LocalStorage persistence for progress, stats, and custom avatars
- Synthesized sound effects via Web Audio API
- 26 NPCs (up from 10) in 3 categories
- Stats/leaderboard in main menu
- Pixel editor avatar integration with RPG game
- Mobile touch controls (virtual joystick + interact button)
- Chat UI with typing indicator and conversation history
- Interactive tutorial overlay for first-time players
- Floating question mark over NPCs in range
- Server hardened: rate limiting, input sanitization, CORS restrictions,
  API timeouts, conversation history cap
- Particle effect object pooling
- i18n framework with DE/EN and language switcher

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 15:26:40 +01:00
Till JS
481a88d25a feat(todo): add onboarding wizard — default view, display mode, tips
3-step onboarding using shared-app-onboarding package:
1. Default view: Today (recommended), Inbox, or Kanban Board
2. Display mode: Normal (with details) or Compact (title + priority only)
3. Tips: quick-add syntax, @project #label shortcuts, focus mode

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:15:08 +01:00
Till JS
16fe3aa61e feat(contacts): add onboarding wizard — sort preference, import option, tips
3-step onboarding using shared-app-onboarding package (same as calendar):
1. Sort order: first name vs last name
2. Import: Google, vCard/CSV, or skip — navigates to import page on completion
3. Tips: self-contact card, quick input, focus mode, tags

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 11:31:38 +01:00
Till JS
3ac976f600 feat(picture): migrate web app from Netlify to Docker/Mac Mini deployment
Switch from adapter-netlify to adapter-node for self-hosted Docker deployment.
Add missing Button and Card UI components, remove Netlify config files,
and add picture-backend + picture-web services to docker-compose and
Cloudflare tunnel routing (picture.mana.how).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:50:12 +01:00
Till JS
8c2aa261e8 perf(auth): replace bcrypt with bcryptjs (pure JS, no native build tools)
- Switch from bcrypt (native C++ addon) to bcryptjs (pure JavaScript)
- Remove python3/make/g++ build tools from Dockerfile builder stage
- bcryptjs is 100% hash-compatible with bcrypt
- Smaller builder image and faster Docker builds

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 19:46:16 +01:00
Till JS
41fbd2f035 feat(storage): improve shared-storage robustness, scalability, and DX
- Fix exists() to only catch 404/NotFound, rethrow real errors
- Add downloadStream() for memory-efficient large file downloads
- Add uploadMultipart() using @aws-sdk/lib-storage for large files
- Add automatic pagination to list() via continuation tokens
- Add CDN URL support (cdnUrl in BucketConfig, getCdnUrl() method)
- Reduce factory boilerplate with generic createStorage() function
- Add MinIO lifecycle rules for tmp/ prefixes (chat 90d, calendar 30d, picture 7d)
- Add vitest setup with 56 tests covering client, factory, and utils

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 18:52:34 +01:00
Till JS
fd0516f119 feat(presi): add DB indexes, Swagger docs, hardened validation (score 81→86)
- Add 7 database indexes on all query paths (userId, deckId, order, themeId)
- Add timestamps with timezone for all tables
- Enable Swagger/OpenAPI documentation at /api/docs
- Add ApiTags and ApiBearerAuth to all controllers
- Add ParseUUIDPipe on all ID parameters
- Harden DTO validation: string length limits, @IsIn for enums,
  @IsUrl for URLs, @ArrayMaxSize for arrays, @Min(0) for order fields
- Update audit to reflect improvements

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 22:35:11 +01:00
Till JS
e84e163c30 test(presi): add 72 tests, rate limiting, error boundary (score 55→81)
- Add 10 test files covering all 5 services and 5 controllers
- Add global ThrottlerGuard (100 req/min) via APP_GUARD
- Add SvelteKit +error.svelte error boundary
- Add Jest config and test dependencies
- Update audit to reflect improvements

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 22:24:38 +01:00
Till JS
97d5b13a38 feat(versioning): add semantic versioning and changesets to all apps
Assign version numbers based on app maturity: Calendar/Contacts/Todo (1.0.0),
Chat/Picture (0.3.0), 11 beta apps (0.2.0), Context/Planta/Questions (0.1.0),
Traces (0.0.1). Set up @changesets/cli for future version management.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 16:20:18 +01:00
Till JS
1d1489273d refactor(mukke): replace custom sidebar with shared PillNavigation
Replaces the custom sidebar layout with PillNavigation, SplitPaneContainer,
and app switcher from shared packages. Adds theme variants, keyboard
shortcuts (Ctrl+1-5), and consistent bottom-pill navigation matching
other apps like calendar and contacts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 15:49:59 +01:00