Commit graph

1148 commits

Author SHA1 Message Date
Till JS
1104c0489d feat(todo): add Board View Editor UI for creating and editing views
- New ViewEditorModal with form fields for name, icon, groupBy, layout,
  and column configuration with inline color picker
- ViewSelector updated with "+" button to create views, three-dot menu
  and right-click to edit active/any view
- Auto-generated column presets for status, priority, dueDate groupBy
- Custom columns mode for manual task grouping
- Live preview showing column layout (kanban or grid)
- Two-step delete confirmation
- Glass-morphism styling, dark mode, responsive

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 17:35:43 +01:00
Till JS
9d3c1cb45a fix: calendar test failures + storage lint error
- Fix external-calendars tests: add svelte-i18n mock for toast i18n
- Fix useDragToCreate test: add DEFAULT_EVENT_DURATION_MINUTES mock
- Fix storage server unused variable lint error

Calendar: 151/151 tests now pass (0 failures)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:30:46 +01:00
Till JS
0181d3f546 feat(apps): create Hono compute servers for Chat, Mukke, Picture
Chat (3002): LLM completions (sync + SSE streaming), model list
Mukke (3010): S3 upload/download/cover URLs via shared-storage
Picture (3006): Replicate/local image gen, S3 upload

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:28:14 +01:00
Till JS
1aeb987cb6 refactor(packages): consolidate 3 feedback packages into @manacore/feedback
Merged shared-feedback-types + shared-feedback-service + shared-feedback-ui
into a single @manacore/feedback package. Updated imports in all 21 apps.

Before: 3 packages (types, service, ui) with cross-dependencies
After:  1 package with direct imports, no circular refs

Note: ESLint warnings from pre-existing unused vars in chat/mukke
servers are unrelated to this change.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:27:11 +01:00
Till JS
bf4d9cb9aa refactor(go-services): integrate shared-go into crawler + gateway, fix Dockerfiles
- mana-crawler: config → envutil, handler → httputil.WriteJSON
- mana-api-gateway: config → envutil, handlers → httputil.WriteJSON
- Fix Dockerfile COPY paths (remove stale -go suffix in all 4 services)
- All services now use packages/shared-go via replace directive

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:25:30 +01:00
Till JS
ba6dbf16c4 feat(apps): create Hono compute servers for Context, ManaDeck, Questions
Context (Port 3020): AI text generation with document context
ManaDeck (Port 3009): AI deck/card generation + image-to-cards
Questions (Port 3011): Web research via mana-search (3 depth levels)

All use @manacore/shared-hono for auth and credits. ~100-140 LOC each.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:23:00 +01:00
Till JS
d3d11e661d feat(apps): create Hono compute servers for Traces, Planta, NutriPhi
Add lightweight Hono + Bun servers for server-only compute endpoints.
CRUD is handled by mana-sync, these handle AI + file upload only.

Traces: AI guide generation, location sync (Port 3026)
Planta: Photo upload (S3), AI plant analysis (Port 3022)
NutriPhi: AI meal analysis (photo+text), recommendations (Port 3023)

Each uses @manacore/shared-hono for auth/health/errors. ~100-200 LOC.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:16:57 +01:00
Till JS
4d26196590 fix(tests): update calendar event tests for pure function API, delete orphaned todo tests
Calendar: Rewrite events.test.ts and events-recurrence.test.ts to test
pure functions (getEventsForDay, getEventsInRange, expandRecurringEvents)
from queries.ts instead of removed store methods.

Todo: Delete projects.test.ts and reminders.test.ts — the API files they
tested were removed in the local-first migration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:11:08 +01:00
Till JS
f628026b9e fix(build): add handleHttpError for missing favicon.png in 4 apps
Clock, Context, Chat, and Planta prerender failed because /offline
references /favicon.png which doesn't exist. Added handleHttpError
to svelte.config.js to ignore this during prerender.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:03:19 +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
5d02b0419d refactor(infra): remove citycorners + skilltree NestJS backends, clean up CI/CD
Both apps migrated to local-first (mana-sync handles CRUD).

- Delete apps/citycorners/apps/backend/ (37 files)
- Delete apps/skilltree/apps/backend/ (32 files)
- Remove from CI build jobs, change detection, summary
- Remove from package.json scripts (replaced with sync-based dev commands)
- Remove from setup-databases.sh push_schema calls
- Remove from generate-env.mjs backend env generation
- Remove from ensure-containers-running.sh

Total: 6 NestJS backends removed across all sessions (Zitare, Clock,
Presi, Photos, CityCorners, SkillTree). ~12,000 lines of boilerplate
eliminated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 10:24:23 +01:00
Till JS
79080d6654 fix(apps): use explicit AuthServiceInterface in all 21 auth stores, re-enable type-check
Replace ReturnType<typeof initializeWebAuth>['authService'] with the
explicit AuthServiceInterface in all 21 web app auth stores. This
ensures svelte-check sees all 37 auth methods instead of TS inferring
a truncated type (~27 methods visible).

Re-enabled type-check in 5 apps that were skipping it:
- chat/web: svelte-kit sync && svelte-check --threshold error
- clock/web: svelte-kit sync && svelte-check --threshold error
- context/web: svelte-kit sync && svelte-check --threshold error
- presi/web: svelte-kit sync && svelte-check --threshold error
- picture/mobile: tsc --noEmit

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 10:15:23 +01:00
Till JS
b37a451d29 refactor(stores): rewrite NutriPhi + Mukke stores to use IndexedDB
NutriPhi meals store: Replace apiClient calls with mealCollection
reads/writes. Daily summary now computed locally from IndexedDB.

Mukke library store: Replace backend API aggregations (albums, artists,
genres, stats) with local computation from songCollection.getAll().
Server-only operations (upload, cover URLs, metadata extraction) remain
as fire-and-forget API calls.

Store migration status: All 19 apps now use IndexedDB as primary
data source. Server API calls only remain for:
- File upload/download (S3 presigned URLs)
- Image generation (Replicate API)
- AI analysis (Gemini)
- Cover art URLs (S3 presigned)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 03:12:37 +01:00
Till JS
924c15277a feat(local-first): migrate remaining 6 apps to reactive useLiveQuery reads
Complete the useLiveQuery migration across all apps. Same pattern:
queries.ts with live query hooks, stores slimmed to mutation-only,
components use Svelte context for reactive reads.

Apps migrated:
- Picture: images, boards, boardItems (writable stores → liveQuery)
- Photos: albums, albumItems, favorites
- Planta: plants, plantPhotos, wateringSchedules, wateringLogs
- Questions: collections, questions
- Mukke: songs, playlists, playlistSongs, projects
- CityCorners: locations, favorites

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 02:42:13 +01:00
Till JS
30e124e609 feat(local-first): migrate 9 apps to reactive useLiveQuery reads
Replace manual $state + fetchX() pattern with Dexie liveQuery hooks
across 9 apps. All data reads now auto-update on IndexedDB changes
(local writes, sync, other tabs). Stores reduced to mutation-only.

Apps migrated:
- Zitare: favorites, lists
- Contacts: contacts
- Calendar: calendars, events
- Chat: conversations, templates
- Clock: alarms, timers, worldClocks
- ManaDeck: decks, cards
- Presi: decks, slides
- Context: spaces, documents
- Storage: files, folders

Pattern per app:
1. New queries.ts with useLiveQuery hooks + pure filter helpers
2. Stores slimmed to mutation-only (no $state arrays, no fetch methods)
3. Layout sets context via setContext() for child components
4. Components use getContext() for reactive reads

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 02:27:46 +01:00
Till JS
d7799ec95d refactor(photos): remove NestJS backend, use local-first + direct mana-media
The Photos NestJS backend was a proxy to mana-media that enriched
responses with local album/favorite/tag data. Now:

- Albums store → local-first via albumCollection + albumItemCollection
- Favorites → local-first via favoriteCollection (toggle in IndexedDB)
- Photo tags → local-first via photoTagCollection
- Photo listing/stats → direct mana-media API calls from frontend
- Upload → direct mana-media upload from frontend
- Delete → direct mana-media delete from frontend

Removed 27 TypeScript files, 1 Docker container, 1 port (3039).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 02:18:03 +01:00
Till JS
dd2f814cf3 refactor(presi): replace NestJS backend with lightweight Hono server
The Presi NestJS backend (40 source files, 50 deps) was a CRUD wrapper
around decks, slides, and themes — all now handled by local-first sync.

Only the share-link feature requires server-side state (public URLs
without auth), so a minimal Hono + Bun server replaces the entire
NestJS backend:

- apps/presi/apps/server/ — Hono server with share routes + GDPR admin
  Uses @manacore/shared-hono for auth (JWKS), health, admin, errors
- Web app API client stripped to share-only (was 270 lines → 90 lines)
- Removed from docker-compose, CI/CD, Prometheus, env generation
- NestJS backend deleted (40 TS files, 8 test specs, 3038 lines)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 02:08:40 +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
32939fbfb5 refactor(infra): remove zitare + clock NestJS backends, add shared-hono package
Both apps are fully local-first via Dexie.js + mana-sync. Their NestJS
backends were pure CRUD wrappers (20 + 31 source files) that are no
longer needed.

Changes:
- Add packages/shared-hono: JWT auth via JWKS (jose), Drizzle DB factory,
  health route, generic GDPR admin handler, error middleware
- Migrate zitare lists page from fetch() to listsStore (local-first)
- Rewrite clock timers store from API-based to timerCollection (Dexie)
- Update clock +layout.svelte CommandBar search to use local collections
- Remove zitare-backend + clock-backend from docker-compose, CI/CD,
  Prometheus, env generation, setup scripts
- Add docs/TECHNOLOGY_AUDIT_2026_03.md with full repo analysis

Net result: -2 Docker containers, -2 ports, -2728 lines of code

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 22:43:46 +01:00
Till JS
fa16f1fe38 feat(apps): add GPU server fallback to all LLM-using apps
Configure all apps with gpu-llm.mana.how as fallback when MANA_LLM_URL
is not set. This ensures apps can use the GPU server's local LLM models
(Ollama gemma3, qwen2.5-coder) instead of cloud providers.

Apps updated:
- Chat: LLM fallback to GPU server
- Context: LLM fallback (replaces Azure OpenAI dependency)
- NutriPhi: LLM + Vision fallback (replaces Google Gemini for food analysis)
- Planta: LLM + Vision fallback (replaces Google Gemini for plant analysis)
- ManaDeck: LLM + Vision fallback for card generation
- Traces: LLM fallback for AI city guides

Vision model default: ollama/gemma3:12b (multimodal, runs on RTX 3090)
Added VISION_MODEL to .env.development

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 22:21:20 +01:00
Till JS
02bd9d3117 feat(apps): integrate GPU services into Picture and Chat apps
Picture App:
- Update LocalImageGenService to use GPU server (gpu-img.mana.how)
- Add API key authentication (GPU_API_KEY)
- Increase timeout to 120s (VRAM may need model loading time)

Chat App:
- Add VoiceModule with STT/TTS integration via GPU server
- POST /api/v1/voice/transcribe — Upload audio, get text + word timestamps
- POST /api/v1/voice/synthesize — Send text, get audio response
- GET /api/v1/voice/health — Check GPU voice services availability
- Supports speaker diarization and language selection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 21:59:46 +01:00
Till JS
7754cf6e00 refactor(skilltree): replace custom idb storage with @manacore/local-store
Remove the custom IndexedDB implementation (idb package + services/storage.ts)
and rewrite skills + achievements stores to use @manacore/local-store collections.

Changes:
- Rewrite skills.svelte.ts: all CRUD via skillCollection/activityCollection
- Rewrite achievements.svelte.ts: all persistence via achievementCollection
- Delete services/storage.ts (282 lines of custom idb code)
- Remove idb dependency from package.json
- Simplify layout comments

The stores now follow the same pattern as all other migrated apps:
reads/writes go to IndexedDB (Dexie.js), sync happens automatically
via mana-sync when authenticated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 21:32:47 +01:00
Till JS
a31ccc6c62 feat(infra): add api.mana.how route + Prometheus scrape targets for Go services
- Cloudflare Tunnel: api.mana.how → localhost:3060 (Go API Gateway)
- Prometheus: scrape targets for mana-api-gateway:3060 and mana-matrix-bot:4000

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 21:27:04 +01:00
Till JS
8d880f1fb6 feat(apps): migrate Chat, Questions, Mukke, Context, Photos to local-first
Add IndexedDB data layer to 5 more Tier 2 apps, bringing the total to
17/22 apps with local-first architecture.

For each app:
- Create local-store.ts with typed collections and sync config
- Create guest-seed.ts with onboarding data for guest mode
- Update layout with AuthGate allowGuest={true} + local store init
- Add GuestWelcomeModal for first-visit experience

App-specific changes:
- Chat: Add store init to existing AuthGate, keep session-based guest mode
- Questions: Replace manual onMount auth with AuthGate wrapper
- Mukke: Add allowGuest to existing AuthGate, audio files stay server-side
- Context: Replace manual onMount auth with AuthGate, AI stays server-side
- Photos: Add allowGuest to existing AuthGate, photos stay on mana-media

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 21:17:56 +01:00
Till JS
819568c3df feat(infra): consolidate 21 Matrix bots into Go binary + add Go API gateway
Replace 21 separate NestJS Matrix bot processes (~2.1 GB RAM, ~4.2 GB Docker images)
with a single Go binary using plugin architecture (8.6 MB binary, ~30 MB RAM).

New services:
- services/mana-matrix-bot/ — Go Matrix bot with 21 plugins (mautrix-go, Redis sessions)
- services/mana-api-gateway-go/ — Go API gateway (rate limiting, API keys, credit billing)

Deleted:
- 21 services/matrix-*-bot/ directories
- packages/bot-services/ and packages/matrix-bot-common/
- Legacy deploy scripts and CI build jobs

Updated:
- docker-compose.macmini.yml: new Go services, legacy bots removed
- CI/CD: change detection + build jobs for Go services
- Root package.json: new dev:matrix, build:matrix, test:matrix scripts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 21:03:00 +01:00
Till JS
ce51fd5fe2 feat(apps): migrate Presi, Picture, Inventar, NutriPhi, Planta, Storage to local-first
Add IndexedDB data layer (Dexie.js via @manacore/local-store) to 6 more apps,
bringing the total to 12/22 apps with local-first architecture.

For each app:
- Create local-store.ts with typed collections and sync config
- Create guest-seed.ts with onboarding data for guest mode
- Update layout with AuthGate allowGuest={true} + handleAuthReady()
- Add GuestWelcomeModal for first-visit experience
- Add @manacore/local-store dependency

App-specific changes:
- Presi: Rewrite decks store from API to IndexedDB, conditional share button
- Picture: Rewrite gallery + boards pages to read from IndexedDB
- Inventar: Replace manual auth $effect with AuthGate, keep localStorage stores
- NutriPhi: Add onReady handler to existing AuthGate
- Planta: Add allowGuest + sync init to existing AuthGate
- Storage: Add local store init to existing handleAuthReady

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 17:35:38 +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
427195d6dc feat(todo): add Hono + Bun server for compute-only endpoints
New lightweight server replacing NestJS for server-side compute:
- RRULE expansion (next occurrence, validation, DoS protection)
- Reminders (CRUD with reminder time calculation)
- Admin (GDPR user data counts + deletion)
- JWT auth middleware + service key auth for admin
- Port 3019, ~10 packages vs ~50 for NestJS

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 12:40:28 +01:00
Till JS
d4c6f257b3 docs: add devlog for 2026-03-25 and update 2026-03-26
Add missing devlog for March 25 (analytics, help system, CityCorners,
ManaLink, infra). Expand March 26 devlog to include all 61 commits
(Storage sprint, Passkeys/2FA, Tags, Zitare) alongside architecture planning.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 12:33:06 +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
fe8f0a227d fix(pricing): update remaining content pages to Mana Quelle naming and new prices
Update branchen pages (privat, selbststaendige, vereine), memoro-de content,
and onboarding CreditsStep to use new Mana Quelle S-XXL tiers and Mana Trank prices.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:55:32 +01:00
Till JS
b85c32fcce feat(todo): wire up browser sync with Go server
- Auth store starts/stops sync on login/logout
- LocalStore queues all existing records for initial sync (guest→auth transition)
- LocalCollection.queueAllForSync() creates pending inserts for all local records
- Skips initial queue if sync cursor exists (already synced before)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:55:32 +01:00
Till JS
8f56feb115 feat(auth): session management UI and improved account lockout feedback
Session management:
- GET /auth/sessions and DELETE /auth/sessions/:id endpoints
- listSessions() and revokeSession() in shared-auth client
- SessionManager component: active sessions list with device info,
  "Aktuell" badge, revoke individual or all other sessions
- Integrated in ManaCore settings page

Account lockout UX:
- Dedicated amber lockout banner (distinct from generic rate-limit)
- "Konto vorübergehend gesperrt" with MM:SS countdown
- "Passwort zurücksetzen" link as alternative action
- formatCountdown helper for clean time display

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:55:32 +01:00
Till JS
2624e5a6b7 feat(pricing): migrate to Mana Quelle S-XXL subscription tiers with new Stripe products
Replace old 3-tier model (Plus/Pro/Ultra) with 5 size-based tiers (S/M/L/XL/XXL).
New naming: "Mana Quelle" for subscriptions, "Mana Trank" for one-time purchases.
Create new Stripe products and prices, archive old ones, update all UI and seed data.

Subscription tiers: S (500 Mana, 4.99€), M (1000, 9.99€), L (2000, 19.99€),
XL (4000, 39.99€), XXL (10000, 99.99€). Yearly: 20% discount.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:54:58 +01:00
Till JS
cc50c0c2ab feat(auth): add password strength indicator and magic links
Password strength (zxcvbn-ts):
- PasswordStrength component with 4-segment color bar and German feedback
- Lazy-loaded with 150ms debounce to avoid SSR/bundle issues
- Integrated into RegisterPage and ChangePassword components

Magic Links (passwordless email):
- Better Auth magicLink plugin (10-minute expiry)
- sendMagicLinkEmail() in email service (German template)
- Passthrough route for /magic-link/* endpoints
- sendMagicLink() in shared-auth client
- "Login-Link per E-Mail senden" button on all 20 login pages
- All 21 auth stores have sendMagicLink() method

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:23:09 +01:00
Till JS
86d1da3587 feat(inventar): add configurable inventory management app
SvelteKit web app with schema-less collections, 8 field types,
8 templates (electronics, books, furniture, etc.), 3 views (list/grid/table),
hierarchical locations, categories, full-text search, and localStorage persistence.
Includes ManaScore audit (28/100 Alpha), Dockerfile, SSO prep, and i18n (DE/EN).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:21:36 +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
0dfd603892 feat(auth): rate limit feedback, audit log UI, and E2E tests
Rate-limiting feedback:
- LoginPage detects 429/account-locked errors and shows countdown timer
- Submit button disabled during cooldown period

Audit log:
- GET /auth/security-events endpoint (JWT-protected) in auth controller
- getSecurityEvents() in BetterAuthService + shared-auth client
- AuditLog component with event type labels, relative dates, UA parsing
- Integrated in ManaCore settings page

E2E tests (passkey-2fa.e2e-spec.ts):
- Passkey registration/authentication flow tests
- Auth guard enforcement (protected vs public endpoints)
- 2FA passthrough route existence tests
- Edge cases (cross-user access, missing fields, token shape)

CSRF note: Already covered by Better Auth (SameSite + HttpOnly +
Trusted Origins). Token refresh already has 4-retry + offline detection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:58:56 +01:00
Till JS
91116bf0f1 feat(apps): integrate shared TagStrip into all 15 remaining apps
Migrated apps with existing local tags (photos, storage, picture):
- Replace local tag stores with createTagStore wrapper
- Add shared TagStrip to layouts with tag filtering support
- Storage: new tag store, /tags management page
- Picture: migrated from Svelte 4 writables to createTagStore

New TagStrip added to 12 apps without prior tag system:
- chat, citycorners, clock, context, manadeck, manacore, matrix,
  mukke, planta, presi, questions, zitare
- Each gets: tag store, Tags toggle pill in PillNav, TagStrip overlay,
  /tags management page, fetchTags on auth ready
- All backed by central mana-core-auth Tags API

All 18 apps now have:
- Tags pill in PillNav (toggles TagStrip overlay)
- Shared TagStrip component from @manacore/shared-ui
- Tag store using createTagStore from @manacore/shared-stores
- /tags management page
- Cross-app tags via central mana-core-auth

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:41:14 +01:00
Till JS
69aa837898 feat(contacts,calendar): integrate shared TagStrip and createTagStore
Contacts:
- Replace local TagStrip with shared TagStrip from @manacore/shared-ui
- Replace local tags store with createTagStore wrapper (backward-compatible)
- Change Tags nav item from link to toggle pill (shows/hides TagStrip overlay)

Calendar:
- Replace local TagStrip in UnifiedBar with shared TagStrip component
- Replace local event-tags store with createTagStore wrapper (backward-compatible)
- Both apps now use central mana-core-auth Tags API

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:05:50 +01:00
Till JS
ce900d5fd3 feat(todo): integrate shared TagStrip and createTagStore
- Add createTagStore factory to @manacore/shared-stores (Svelte 5 runes, backed by @manacore/shared-tags)
- Replace Todo's local TagStrip with shared TagStrip from @manacore/shared-ui
- Replace Todo's labels store with createTagStore wrapper (backward-compatible)
- Remove "Tags" tab from PillNav TabGroup, add it as toggle pill (like Filter)
- Tags pill toggles TagStrip overlay visibility instead of navigating to /tags
- TagStrip has "Tags verwalten" pill linking to /tags management page

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 20:51:55 +01:00
Till JS
1316ef57f3 feat(zitare): show author bio on quote cards
Add a small info icon next to the author name that toggles a short
biography when clicked. Bio text is displayed in the current quote
language with German as fallback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 20:48:33 +01:00
Till JS
40b55eb65f feat(zitare): add search and sort to category detail page
Add inline search field and sort-by-author option to category pages.
Also extract hardcoded German strings and respect display settings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 20:47:35 +01:00
Till JS
7c7e5eb010 feat(zitare): add favorites count badge and respect display settings
Show a count badge next to the favorites title and use the global
display settings for category/source visibility on quote cards.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 20:43:31 +01:00
Till JS
b7d1d2ec9a feat(zitare): add category filter chips to search results
Show clickable category pills below the search input when results
are available. Each chip shows the match count for that category.
Also respects display settings for category/source visibility.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 20:30:04 +01:00
Till JS
6107d572a1 feat(zitare): expand settings with display options
Add toggle switches for show/hide category and source, and a font
size selector (small/normal/large/extra large). Settings are persisted
via the existing settings store and applied to QuoteCard and home page.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 20:28:22 +01:00
Till JS
5bb96dbf2d feat(zitare): add maxlength validation to list create form
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 20:10:03 +01:00
Till JS
326acf0eaa fix(zitare): add error feedback for silent API failures
Show toast notifications when list CRUD operations and favorite
toggling fail, instead of silently swallowing errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 20:03:07 +01:00
Till JS
96ff16b7a7 feat(zitare): add loading states to list operations
Add spinner indicators and disable buttons during create, delete,
update, add quotes, and remove quote operations to prevent double
clicks and give visual feedback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 19:57:26 +01:00
Till JS
f5a9edcfb6 feat(auth): add TOTP two-factor authentication across all apps
Uses Better Auth's built-in twoFactor plugin for TOTP + backup codes:

Backend (mana-core-auth):
- twoFactor plugin in better-auth.config.ts (issuer: ManaCore)
- twoFactorEnabled field on users table, backupCodes as encrypted text
- 2FA redirect detection in signIn flow
- Passthrough controller forwards /two-factor/* to Better Auth
- Security event types for 2FA operations

Client (shared-auth):
- enableTwoFactor, disableTwoFactor, verifyTwoFactor, verifyBackupCode,
  generateBackupCodes methods with session-to-token exchange

UI (shared-auth-ui):
- LoginPage: 2FA code input view after password login, backup code toggle
- TwoFactorSetup: settings component with enable/disable/QR code/backup codes

App integration:
- All 19 auth stores have verifyTwoFactor() and verifyBackupCode()
- All 19 login pages pass onVerifyTwoFactor and onVerifyBackupCode callbacks
- ManaCore settings page has TwoFactorSetup component

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