Commit graph

350 commits

Author SHA1 Message Date
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
0c479b3e88 feat(tags): implement cross-app tag system with groups and entity links
Backend (mana-core-auth):
- Add tag_groups table (name, color, icon, sortOrder per user)
- Add tag_links table (tagId + appId + entityId + entityType, cross-app)
- Extend tags table with groupId and sortOrder fields
- Tag Groups API: CRUD + reorder at /tag-groups
- Tag Links API: link/unlink/bulk/sync/query at /tag-links
- Tags API: updated DTOs for groupId/sortOrder

Frontend client (@manacore/shared-tags):
- Add TagGroup, TagLink types and response types
- Add tag group methods: getGroups, createGroup, updateGroup, deleteGroup, reorderGroups
- Add tag link methods: linkTag, bulkLinkTags, unlinkTag, getTagsForEntity, syncEntityTags

Shared UI (@manacore/shared-ui):
- Add TagStrip component with glass-pill styling, tag filtering, management link
- Consistent look across all apps (replaces 3 app-specific implementations)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 20:43:34 +01:00
Till JS
2b0b902ba3 fix(credit-operations): point package exports to compiled dist/ instead of raw src/
The package.json was pointing main/exports to src/index.ts which crashes in production
Docker containers where Node runs CJS and can't handle ESM export tokens.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 20:03:22 +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
Till JS
13681df76c feat(shared): add helpHref/themesHref to PillNav, shared Mana & Privacy FAQs
- PillNavigation: add helpHref and themesHref props with help icon in account dropdown
- PillDropdown: add help icon (question mark circle) to iconPaths
- shared-help-types: add getManaFAQs/getManaFeature for shared Mana credit FAQs
- shared-help-types: add getPrivacyFAQs for shared privacy/GDPR/tech independence FAQs
- ManaScore: add Help-Seite and Feedback-Seite as UX criteria, shared-help-ui and
  shared-feedback-ui as Core cross-app packages

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 14:28:38 +01:00
Till JS
c4d55209a4 feat(auth): add PasskeyManager component and production config
- PasskeyManager.svelte: reusable component for listing, registering,
  renaming, and deleting passkeys (German defaults, fully translatable)
- Production env: WEBAUTHN_RP_ID=mana.how and WEBAUTHN_ORIGINS for all
  *.mana.how subdomains in docker-compose.macmini.yml
- Local DB: passkeys table created via direct SQL

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 10:49:57 +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
3376b044bc fix(auth): resolve hardcoded localhost in user-settings across all web apps
The createUserSettingsStore was receiving a static auth URL evaluated at
module load time, before window.__PUBLIC_MANA_CORE_AUTH_URL__ was
injected by hooks.server.ts. In production this caused CSP violations
as settings API calls went to localhost:3001 instead of auth.mana.how.

Changes:
- Accept string | (() => string) for authUrl in shared-theme config
- Resolve authUrl lazily at fetch time instead of module load
- Fix fallback to empty string in non-dev environments (was localhost)
- Pass getAuthUrl as getter function in all 17 web apps

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 12:40:30 +01:00
Till JS
1fe8f8902d feat(analytics): add custom event tracking to NutriPhi and ManaDeck
Add NutriPhiEvents (mealAdded, mealDeleted, photoAnalyzed, textAnalyzed,
goalsUpdated, favoriteSaved, favoriteUsed) to shared analytics utils.
Add deckDeleted and cardDeleted to ManaDeckEvents. Wire up event calls
in NutriPhi meals store and ManaDeck deck/card stores.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 12:12:01 +01:00
Till JS
12b3c4f0f3 feat(analytics): add custom event tracking to Context, SkillTree, Planta, Questions
Add app-specific Umami event helpers and integrate tracking into:
- Context: 6 events (document create/delete/pin, space create/delete, AI generated)
- SkillTree: 3 events (skill create/delete with branch, XP added with level-up)
- Planta: 4 events (plant analyzed/created/deleted, plant watered)
- Questions: 5 events (question create/delete, research started, collection create/delete)

Updates ManaScore analytics from 3/5 to 4/5 for all four apps.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 10:13:05 +01:00
Till JS
3075e515bd feat(analytics): add custom event tracking to Photos app
Add PhotosEvents helper (8 events) and integrate tracking into:
- Photos store: favorite toggle, delete, filters applied
- Albums store: create, delete, add/remove photos
- Upload page: photo uploaded

Updates ManaScore analytics from 3/5 to 4/5 (customEvents: true).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 09:59:42 +01:00
Till JS
bade0a17db feat(analytics): add custom event tracking to Storage app
Add StorageEvents helper (11 events) and integrate tracking into:
- Files store: download, delete, favorite, view mode toggle
- Shared page: share link copy/delete
- Trash page: restore, empty trash
- Search page: search performed with results count

Updates ManaScore analytics from 3/5 to 4/5 (customEvents: true).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 09:34:07 +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
d2264f5360 feat(analytics): add Analytics Maturity metric to ManaScore and custom event tracking to 4 apps
Add new "Analytics Maturity" extended metric to ManaScore schema with 5 checks:
pageViewTracking, customEvents, authTracking, landingTracking, publicDashboard.
Populate analytics data across all 20 audit files. Document the metric in about.md.

Add app-specific Umami custom event helpers and integrate tracking into:
- ManaCore: 13 events (nav, onboarding, dashboard widgets, credits, settings)
- Presi: 12 events (deck/slide CRUD, presentation start/exit, sharing)
- Zitare: 9 events (quotes, favorites, categories, search, lists, language)
- Mukke: 12 events (upload, library, playlists, projects, editor export)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 09:20:59 +01:00
Till JS
cacf8d7cc1 perf(shared-nestjs-auth): local JWKS verification instead of HTTP call
Replace HTTP POST to /api/v1/auth/validate with local JWT verification
using jose + createRemoteJWKSet. Eliminates ~5-20ms HTTP roundtrip per
API request across all backends. JWKS cached automatically by jose.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 08:57:24 +01:00
Till JS
336cfedd0b refactor(auth): centralize appReady pattern into AuthGate component
Replace copy-pasted appReady/loading/redirect logic in all 13 layouts
with a shared AuthGate component. Supports guest mode, onReady callback
for app-specific data loading, and configurable login redirect.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 08:30:31 +01:00
Till JS
42dd7d2a7a fix(shared-help): harden help system with XSS protection, i18n, type safety, and reference implementation
- Add HTML sanitization via isomorphic-dompurify in parser layer to prevent XSS
- Replace all hardcoded English strings with translations (FAQSection, KeyboardShortcuts, ChangelogEntry/Section)
- Remove unsafe `as` type casting in loader.ts, use Zod-inferred generics instead
- Add error logging in content loader (replaces silent catch blocks)
- Fix HelpSearch blur handling (mousedown+preventDefault instead of setTimeout hack)
- Add ARIA attributes to HelpSearch for accessibility
- Derive FAQ categories from items instead of hardcoding all 6
- Fix null-safety in GettingStartedGuide.svelte
- Fix unused appId variable in HelpPage.svelte, add scroll-reset on tab switch
- Rebuild Contacts help page as reference implementation using shared HelpPage component
- Add README with quick-start guide, props docs, and translations template

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 22:38:46 +01:00
Till JS
bf7517d24d feat(auth): add SessionExpiredBanner to all remaining web apps
Added to: clock, photos, storage, mukke, planta, picture, skilltree,
nutriphi, chat. Now all 13 web apps show a re-login banner when
token refresh permanently fails.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 22:35:13 +01:00
Till JS
5286404129 feat(parsers): add intelligent quick-create parsers for 6 apps with multilingual support
- Base parser: multilingual (DE/EN/FR/ES/IT) date, time, weekday, month parsing
- Base parser: fuzzy/typo tolerance (Levenshtein), recurrence (RRULE), relative time
- Base parser: timezone extraction, date ranges, ordinal dates, confidence scoring
- Base parser: past dates (gestern/yesterday), this/next week distinction
- Base parser: compose helper (createAppParser), multiple @references
- Calendar: event-parser with duration, time ranges, location, all-day, calendar ref
- Calendar: wire up UnifiedBar with onCreate/onParseCreate for quick event creation
- Todo: task-parser multilingual priority keywords (urgent/important/normal/later)
- Planta: plant-parser with acquisition keywords (gekauft/bought/acheté)
- Mukke: song-parser with Artist-Title format, BPM, genre, playlist/project creation
- NutriPhi: meal-parser with meal type detection, add QuickInputBar to layout
- All parsers: 210 tests across 7 test suites, all passing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 22:18:05 +01:00
Till JS
d6440664ac feat(auth): add session expired banner when token refresh fails
Users now see an amber banner with a re-login button instead of a
broken empty page when their session expires. Uses pub/sub events
from tokenManager, integrated in todo, calendar, zitare, contacts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:24:28 +01:00
Till JS
d0802362d7 refactor(shared-auth): single fetch interceptor for multiple URLs
setupFetchInterceptor now accepts a urls[] array instead of wrapping
globalThis.fetch twice (once for auth URL, once for backend URL).
Backward compatible - backendUrl still works, mapped to urls internally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:26:03 +01:00
Till JS
c21347351a fix(credit-operations): export TypeScript source directly
Allows Vite/SvelteKit to import the package without a prior build step,
matching the pattern used by other shared packages like shared-credit-ui.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 11:31:20 +01:00
Till JS
c27f6f88f0 feat(shared-ui): add focusTrap action and apply to shared Modal
Create reusable Svelte action for focus trapping in modals/dialogs.
Traps Tab/Shift+Tab within element and restores focus on destroy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 10:04:04 +01:00
Till JS
56ffcbac39 feat: add Ollama memory optimization, LLM metrics, and chat streaming
Three improvements to the unified LLM infrastructure:

1. Ollama memory optimization (scripts/mac-mini/configure-ollama.sh):
   - OLLAMA_KEEP_ALIVE=5m → models unload after 5min idle (saves 3-16GB RAM)
   - OLLAMA_NUM_PARALLEL=1 → predictable memory usage
   - OLLAMA_MAX_LOADED_MODELS=1 → max 1 model in RAM at a time

2. Request-level metrics in @manacore/shared-llm:
   - LlmRequestMetrics interface (model, latency, tokens, fallback detection)
   - LlmMetricsCollector class with summary stats (for health endpoints)
   - Optional onMetrics callback in LlmModuleOptions
   - Automatic metrics emission in chatMessages() (success + error)

3. Chat streaming (token-by-token SSE):
   - Backend: POST /chat/completions/stream SSE endpoint
   - OllamaService.createStreamingCompletion() via llm.chatStreamMessages()
   - ChatService.createStreamingCompletion() with upfront credit consumption
   - Web: chatApi.createStreamingCompletion() SSE consumer
   - Chat store: sendMessage() now streams tokens into assistant message
   - UI updates reactively as each token arrives

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 09:41:33 +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
3b883af064 feat(manacore): improve todo dashboard widgets and fix port mismatch
- Fix todo dev port in APP_URLS (5188, was swapped with inventory 5189)
- Use APP_URLS for all links instead of hardcoded localhost ports
- TasksTodayWidget: add priority dots, subtask progress, label tags,
  completed/total counter, clickable task links
- TasksUpcomingWidget: add priority dots, label tags, overdue/today
  date highlighting with colored badges, clickable task links
- Extend Task type with labels and subtasks for richer widget display

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 21:48:29 +01:00
Till JS
9edd1c6e2e feat(shared-ui): locale-aware highlighting + success feedback for InputBar
1. Extract hardcoded German highlight patterns into locale-specific sets
   (de, en, fr, it, es). InputBar accepts `locale` or custom
   `highlightPatterns` prop, defaulting to German for backward compat.

2. Add visual success feedback after creating: input bar flashes green
   with a checkmark icon for 1.2s, confirming the action was successful.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 20:55:31 +01:00
Till JS
45db42720c fix(todo): pixel-perfect skeleton loaders, PillNav tab group, and SSR head fix
- Rewrite TaskListSkeleton to match notepad design (spiral holes, red margin line, cream background)
- Rewrite TaskItemSkeleton as flat rows with border-bottom instead of card style
- Rewrite KanbanColumnSkeleton with glassmorphism and pill-shaped task cards
- Update KanbanBoardSkeleton with matching border-radius and dark mode support
- Group navigation pills (Liste/Kanban/Tags) into PillTabGroup for clear UX distinction from toggle pills (Filter)
- Add Phosphor icon support to PillTabGroup component
- Fix %sveltekit.head% appearing as literal text in production by removing duplicate placeholder from HTML comment
- Disable PWA service worker in dev mode

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 20:51:41 +01:00
Till JS
e00e6ee8b7 feat(shared-ui): add deferred search mode to QuickInputBar
Instead of auto-searching on every keystroke (causing flickering loader),
show two static options: "create task" and "search". Search only runs
when explicitly selected, reducing API calls and improving UX.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 20:48:01 +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
b76746229e chore: remove @manacore/shared-supabase package
Package was unused — no imports found across the entire codebase.
All apps have migrated to direct PostgreSQL (Drizzle ORM) for backends
and mana-core-auth API for mobile/web clients.

Removes package and all documentation references.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 12:07:14 +01:00
Till JS
7691f66cbb refactor(todo): move Feedback, Themes, Spiral to profile dropdown
Move secondary navigation items (Themes, Spiral) from the main pill
nav bar into the user profile dropdown menu. Feedback and Settings
were already there. This declutters the main nav to just core views:
Liste, Kanban, Filter, Tags.

Add themesHref and spiralHref optional props to PillNavigation
component so any app can show these in the user dropdown.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 11:10:41 +01:00
Till JS
677a499c93 feat(contacts): integrate spiral-db for visual contact network
Add spiral-db integration to Contacts as the third app using
pixel-based spiral visualization. Contacts are encoded with
name, company, city, and email/phone flags.

Changes:
- Add createContactSchema() to spiral-db with bool fields for
  hasEmail/hasPhone and nullable company/city
- Create Svelte 5 spiral store with importContacts from contactsStore
- Add SpiralCanvas component and /spiral route
- Wire up navigation (Ctrl+5) with auto-import on mount
- Favorites show as starred entries with gold border

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 11:02:19 +01:00
Till JS
1c5c2446f6 feat(citycorners): add city guide app for Konstanz with full monorepo integration
New project with three apps:
- Landing (Astro): static site with SVG illustrations, location data
- Backend (NestJS, port 3025): CRUD API for locations + favorites, Drizzle ORM, auth via mana-core-auth
- Web (SvelteKit, port 5196): Tailwind 4, PillNav, auth (login/register/SSO), Leaflet map, favorites with optimistic updates, theme/settings

Infrastructure: DB init SQL, setup-databases.sh, generate-env.mjs, root package.json scripts, Dockerfiles, docker-compose.macmini.yml (backend:3025, web:5022), Cloudflare wrangler.toml.

Branding: registered in shared-branding (AppId, APP_BRANDING, APP_ICONS, MANA_APPS, CitycornersLogo).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 10:56:26 +01:00
Till JS
5bcbb4b71d feat(zitare): integrate spiral-db for visual quote storage
Add spiral-db integration to Zitare as the second app (after Todo) to
use pixel-based spiral data visualization. Favorites are encoded as
colored pixels in a spiral pattern and can be exported/imported as PNG.

Changes:
- Add createQuoteSchema() to spiral-db with fields for category,
  language, author, text, and quoteId
- Create Svelte 5 spiral store with importFavorites, CRUD, PNG export
- Add SpiralCanvas component for interactive visualization
- Add /spiral route with stats, records list, and actions
- Wire up navigation (Ctrl+6) and auto-import favorites on mount

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 10:44:39 +01:00
Till JS
7c1e2aca49 chore: remove remaining Hetzner references across codebase
Deleted:
- DOCKER_REGISTRY_SETUP.md, QUICK_START_CICD.md (legacy CI/CD docs)
- docs/ULOAD-DEPLOYMENT.md (Hetzner VPS deployment guide)
- scripts/get-ssh-key.sh, scripts/remove-coolify-references.sh (legacy scripts)

Updated Hetzner → MinIO references in:
- shared-storage (package.json, README, client.ts, types.ts)
- App CLAUDE.md files (mukke, storage, planta, picture)
- .claude/GUIDELINES.md, sveltekit-web.md guideline
- TROUBLESHOOTING.md, SETUP_TEMPLATES.md (replaced IPs with placeholders)
- GIT_WORKFLOW.md, COMMANDS.md
- services/matrix-project-doc-bot/CLAUDE.md

Remaining Hetzner mentions are in historical devlogs/audits and docs
that list Hetzner as a hosting alternative (not as active infrastructure).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 10:30:26 +01:00
Till JS
d4d08cc68b fix(spiral-db): add test suite and fix critical bugs
Add comprehensive test suite (174 tests) covering encoding, schema,
image, database CRUD, and PNG round-trip. Fix critical bugs:

- PNG compression: replace non-functional zlibCompress with pako.deflate
- PNG import: add CRC validation, support all filter types (Sub/Up/Avg/Paeth)
- Input validation: validate records against schema before insert
- Index overflow: dynamic dataStartRing prevents index/data ring overlap
- Image expansion: expand before writes instead of after to prevent OOB
- update() read bug: search index from end to find latest entry, not deleted one
- String encoding: enforce 511-byte max length
- Index ring count: use 6 bits (2 pixels) instead of 3 bits for >7 ring support

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 09:52:18 +01:00
Till JS
807c5da26e fix(mukke): add media-src to CSP for audio playback from MinIO
Add mediaSrc option to shared security headers and configure mukke
to allow audio loading from minio.mana.how (S3 presigned URLs).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 09:40:56 +01:00
Till JS
55e4f7b5cc fix(shared-ui): fix transparent context menu background
Use existing --color-surface-elevated CSS variable instead of
non-existent --color-surface-elevated-3. Add box-shadow for depth.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 09:37:53 +01:00
Till JS
dd477d5fda feat(analytics): expand umami tracking in todo, calendar, and contacts apps
Todo:
- Track projectCreated, projectDeleted, labelCreated
- Track taskUncompleted
- Track quickAddUsed via QuickInputBar

Calendar:
- Track eventUpdated, eventDeleted
- Track calendarCreated, calendarDeleted

Contacts:
- Track contactUpdated, contactDeleted, contactFavorited, contactArchived
- Track searchPerformed in SearchModal
- Track contactExported in ExportModal
- Track contactImported for both Google and file (vCard/CSV) imports

Also extends analytics event helpers with new event types.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 09:27:30 +01:00
Till JS
31b84bbcf4 fix(todo): use Spiral icon for Spiral nav item instead of Sparkle
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 09:07:51 +01:00
Till JS
abc7f95601 fix(todo): fix FAB close button hidden behind PillNav and move settings/mana to account dropdown
- Raise FAB z-index from 50 to 1002 so close button is clickable above PillNav (z:1000)
- Remove Settings from standalone nav items (already in account dropdown)
- Move Mana button from standalone pill into account dropdown

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 08:57:15 +01:00
Till JS
bae5bb99ea fix(error-tracking): switch to ESM output for SvelteKit compatibility
Change tsconfig module from commonjs to ES2020 and moduleResolution to
bundler so browser.js exports ESM that Vite/Rollup can tree-shake.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 08:44:47 +01:00
Till JS
7cad4073d4 feat(error-tracking): add browser error tracking to all 19 SvelteKit web apps
Add @sentry/browser integration via shared-error-tracking/browser export
and hooks.client.ts in every web app for client-side error reporting to GlitchTip.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 19:16:21 +01:00
Till JS
287bbed86e feat(analytics): add automatic CTA tracking to all 10 landing pages
Create Analytics.astro component in @manacore/shared-landing-ui that
automatically tracks CTA clicks and pricing section views via Umami.

The component uses event delegation and auto-detection of section
context (hero/pricing/footer) from section IDs or DOM position,
requiring zero changes to existing landing page content.

Tracked events: cta_click (with location), pricing_viewed,
pricing_plan_selected (with plan name)

Added to all 10 landing page Layout.astro files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 19:13:24 +01:00
Till JS
f5ee3aae20 feat(security): add unified CSP headers to all 17 web apps
Create @manacore/shared-utils/security-headers with setSecurityHeaders()
utility that sets standard security headers (CSP, X-Frame-Options,
X-Content-Type-Options, Referrer-Policy, Permissions-Policy).

CSP includes stats.mana.how (Umami) and glitchtip.mana.how by default.
Each app passes its own connectSrc origins (auth URL, backend URL, etc.).

Previously only Calendar and Storage had CSP headers - now all 17 web
apps have consistent security headers via the shared utility.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 18:53:40 +01:00
Till JS
f043db2b05 feat(analytics): add automatic auth event tracking via shared-auth
Add inline Umami tracking to @manacore/shared-auth authService for
login, signup, logout, SSO, and social auth events. Tracks both
success and failure with auth method metadata.

This automatically covers all web apps without any per-app code
changes. No-ops silently in environments without Umami (mobile, SSR).

Tracked events: login, login_failed, signup, signup_failed, logout,
password_reset_requested (with method: email/google/apple/sso)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 18:44:03 +01:00
Till JS
2c26fce736 fix: replace all manacore.app URLs with mana.how
The production domain is mana.how, not manacore.app. Updated all
references across shared-branding APP_URLS, app configs, landing pages,
docs, help content, calendar iCal UIDs, and deploy scripts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 18:40:37 +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