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>
- 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>
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>
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>
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>
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>
Shared Go utilities for all ManaCore Go services:
- httputil: WriteJSON, WriteError, DecodeJSON
- envutil: Get, GetInt, GetBool, GetSlice
- 8 tests, all passing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Status updates:
- shared-hono: credits client added (replaces nestjs-integration)
- Store migrations: all 19 apps confirmed using IndexedDB
- mana-sync: already generic (no app-specific config needed)
- App backends: 12 NestJS backends assessed — all have server-side
logic (AI, upload, external APIs) that can't be replaced by sync.
CRUD is handled by mana-sync, backends only needed for compute.
Pragmatic approach: keep running, migrate incrementally.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add credits.ts to @manacore/shared-hono as replacement for
CreditClientService from @mana-core/nestjs-integration.
Exports: getBalance, validateCredits, consumeCredits, refundCredits
Calls mana-credits service via MANA_CREDITS_URL + X-Service-Key.
Same API surface as the NestJS version but as pure functions
instead of an @Injectable() service class.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
TypeScript's ReturnType<> inference truncates large object literals,
showing only ~27 of 37 methods. This caused 5 apps to skip type-check
because verifyTwoFactor, signInWithPasskey, sendMagicLink, etc. were
invisible to consumers.
Fix: Define explicit AuthServiceInterface with all 37 methods and use
it as the return type of createAuthService(). This ensures all methods
are visible regardless of object literal size.
Verified: chat/web and presi/web now pass svelte-check for auth methods.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
Remove the entire NestJS-based mana-core-auth service (~36,000 lines
including tests, config, and package files). The new mana-auth service
(Hono + Bun, ~1,900 LOC) is the complete replacement on the same port.
Deleted:
- services/mana-core-auth/ — 169 files, 36,123 lines
(NestJS 10, Express, class-validator, all NestJS infrastructure)
Updated:
- docker-compose.macmini.yml: mana-auth now builds from services/mana-auth
with Bun healthcheck, simplified env vars (no Redis, no DuckDB needed)
- CLAUDE.md: mana-core-auth → mana-auth in services list
- Overview plan: marked Phase 4+5 as DONE, updated next steps
The ManaCore auth ecosystem is now:
- mana-auth (3001) — Auth, JWT, SSO, OIDC, Guilds, API Keys, GDPR
- mana-credits (3061) — Credits, Gifts, Guild Pools, Stripe
- mana-user (3062) — Settings, Tags, Storage
- mana-subscriptions (3063) — Plans, Billing, Invoices
- mana-analytics (3064) — Feedback, Voting
Total: ~6,600 LOC across 5 Hono+Bun services
Replaces: ~20,000 LOC in 1 NestJS service (67% reduction)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Forgejo v11 on port 3041 (git.mana.how via Cloudflare Tunnel)
- Forgejo Runner for CI/CD (GitHub Actions compatible)
- Built-in Docker registry and LFS support
- Registration disabled (admin-only)
- SSH access on port 2222
- Go Services CI workflow (.forgejo/workflows/go-services.yml)
- Setup script: scripts/mac-mini/setup-forgejo.sh
Replaces GitHub dependency for CI/CD. GitHub can remain as
mirror/backup while Forgejo becomes the primary Git host.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Complete the mana-auth Hono service with all remaining endpoints
from mana-core-auth.
Added:
- routes/auth.ts: Full auth flow (register, login, logout, validate,
password reset, profile, change-password, account deletion,
security events) with lockout + security event logging
- routes/guilds.ts: Guild CRUD, member management, invitations
(delegates to Better Auth org plugin + mana-credits for pools)
- routes/api-keys.ts: API key generation, listing, revocation,
validation (sk_live_* format, SHA-256 hashed)
- routes/me.ts: GDPR data export/delete (Articles 17 & 20)
- services/security.ts: SecurityEventsService (fire-and-forget audit)
+ AccountLockoutService (5 failures/15min → 30min lockout)
- services/api-keys.ts: Key generation, validation, scope checks
Updated:
- index.ts: Wire all routes with proper middleware (JWT, service auth)
Service now has ~1,900 LOC covering all functionality from the
original ~11,500 LOC NestJS mana-core-auth (83% reduction).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rewrite the central authentication service from NestJS to Hono + Bun.
Uses Better Auth's native fetch-based handler — no Express conversion.
Key architecture changes:
- Better Auth handler mounted directly on Hono (app.all('/api/auth/*'))
- No NestJS DI, modules, guards, decorators — plain TypeScript
- JWT validation via jose (same as extracted services)
- Email via nodemailer (simplified, German templates)
- ~1,400 LOC vs ~11,500 LOC in NestJS (88% reduction)
Service structure:
- auth/better-auth.config.ts — copied from mana-core-auth (framework-agnostic)
- auth/stores.ts — in-memory stores for email redirect URLs
- email/send.ts — nodemailer email functions
- middleware/ — JWT auth, service auth, error handler (shared pattern)
- db/schema/ — copied from mana-core-auth (Drizzle, framework-agnostic)
Port: 3001 (same as mana-core-auth — drop-in replacement)
Database: mana_auth (same DB, same schemas)
Better Auth plugins: Organization, JWT (EdDSA), OIDC Provider,
Two-Factor (TOTP), Magic Link
Note: This is the initial version. Guilds, API keys, Me (GDPR),
security (lockout/audit), and admin endpoints will be added
incrementally. The old mana-core-auth remains until fully replaced.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract feedback, analytics, and AI modules from mana-core-auth into
standalone mana-analytics service (Hono + Bun, Port 3064).
New service (services/mana-analytics/):
- User feedback CRUD with voting
- AI-powered feedback title generation via mana-llm
- Simplified from DuckDB analytics to pure PostgreSQL
- ~550 LOC
Removed from mana-core-auth:
- feedback/ module (6 files)
- analytics/ module (4 files)
- ai/ module (3 files)
- db/schema/feedback.schema.ts
mana-core-auth now contains ONLY pure auth:
- Better Auth (JWT, Sessions, 2FA, Passkeys, OIDC, Magic Links)
- Organizations/Guilds (membership management)
- API Keys, Security, Me (GDPR), Health, Metrics
- Ready for Phase 5: Hono rewrite
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
Extract subscription billing into standalone mana-subscriptions service
(Hono + Bun, Port 3063). Also removes Stripe module from mana-core-auth
since subscription webhooks are the last consumer.
New service (services/mana-subscriptions/):
- Plans CRUD, subscription management, Stripe Checkout + Portal
- Invoice tracking, webhook handlers for sub/invoice events
- Internal API for plan limits (consumed by guilds service)
- ~990 LOC (vs ~1,700 in NestJS incl. Stripe module)
Removed from mana-core-auth:
- subscriptions/ module (6 files)
- stripe/ module (4 files) — no longer needed in auth
- db/schema/subscriptions.schema.ts
- guilds.service.ts: replaced direct DB plan limit query with
HTTP call to mana-subscriptions internal API
mana-core-auth now contains only:
- Auth (Better Auth, JWT, Sessions, 2FA, Passkeys, OIDC)
- Organizations/Guilds (membership only, no credits/plans)
- API Keys, Security, Me (GDPR), Health, Metrics
- Feedback + Analytics (next extraction target)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
- 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>
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>
Clock app was migrated to local-first (mana-sync), remove stale
depends_on and environment references to clock-backend.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary document covering:
- Local-first status for all 19/22 apps (which stores are done vs pending)
- Service extraction progress (mana-credits, mana-user done)
- What's left to extract (subscriptions, analytics)
- Phase 5 plan (auth Hono rewrite)
- All commits from this session
- Prioritized next steps
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- mana-sync on port 3051 (Go sync server for local-first apps)
- mana-notify-go on port 3040 (Go notification service)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Required for Docker Desktop Mac (TLS proxy) and sites with
self-signed/expired certificates. Crawlers routinely need this.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaces the NestJS mana-notify service with a Go implementation.
Features: 4 notification channels (email/SMTP, Expo push, Matrix,
webhook), goroutine worker pool with retry/backoff (replaces BullMQ),
Go template engine (replaces Handlebars), PostgreSQL with auto-migrations
(5 tables), user preferences with quiet hours, idempotency via
externalId, batch sending, scheduled delivery, JWT + service key auth.
22 API endpoints, 1:1 compatible. Binary: 21 MB.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Port 3060 was already taken by api-gateway. Updated mana-credits to 3061.
Changes:
- docker-compose.macmini.yml: Add mana-credits service with health check,
traefik labels for credits.mana.how, depends on postgres
- docker-compose.macmini.yml: Add MANA_CREDITS_URL to mana-auth env
- Update all port references from 3060 to 3061 (config, Dockerfile, CLAUDE.md)
- Update better-auth.service.ts fallback URLs to 3061
- Update .env.development MANA_CREDITS_URL
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
Update consumers to call the new standalone mana-credits service instead
of the credit endpoints embedded in mana-core-auth.
Changes:
- CreditClientService: Add getCreditsUrl() reading MANA_CREDITS_URL
(falls back to MANA_CORE_AUTH_URL for backward compatibility).
All credit calls now use /api/v1/internal/* endpoints.
- BetterAuthService: Replace direct DB inserts for credit balance and
guild pool init with HTTP calls to mana-credits internal API.
Replace local gift redemption with HTTP call.
- .env.development: Add MANA_CREDITS_URL=http://localhost:3060
- CLAUDE.md: Add mana-credits to services list
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>