- Add user metrics to mana-core-auth MetricsService:
- auth_users_total: Total registered users
- auth_users_verified: Email-verified users
- auth_users_created_today/this_week/this_month
- Create Grafana user-statistics dashboard with:
- User overview stats (total, verified, verification rate, new today)
- Registration period breakdown (today/week/month)
- User growth trends over time
- Enhance telegram-stats-bot /users command:
- Add yesterday comparison with trends
- Add week-over-week comparison
- Add mini bar chart for last 7 days registration
- Include user stats in daily Telegram report
- Add metrics module to calendar, chat, clock, contacts backends
- Add metrics module to mana-core-auth service
- Expose /metrics endpoint for Prometheus scraping
- Track HTTP requests, response times, and custom business metrics
Co-Authored-By: Claude <noreply@anthropic.com>
Adds a NestJS service that delivers Umami analytics via Telegram:
- Telegram commands: /start, /stats, /today, /week, /realtime, /users
- Scheduled reports: Daily at 9:00, Weekly on Monday at 9:00
- Umami API integration with token management
- User statistics from auth database
- Docker + CI/CD pipeline integration
Bot: @stats_mana_bot
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add rememberMe field to sessions schema
- Mock non-existent service imports in tests
- Add missing docker-entrypoint.sh for clock-backend
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Merge till-dev branch containing:
- Planta plant care tracking application
- Clock backend with alarms, timers, world clocks
- Zitare backend with favorites and lists
- Various app improvements and fixes
- Auth system updates
- Infrastructure improvements
Note: Some type-check issues may need resolution after merge.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Import SecurityEventsService and Referral services
- Provide mocks for all BetterAuthService dependencies
- Fixes 'Cannot resolve dependencies' error in test initialization
- E2E tests still need real database (works in CI with postgres containers)
Implements sliding window expiration for refresh tokens to allow active
users to stay signed in indefinitely while maintaining security through
inactivity timeouts.
Changes:
- Extend refresh token expiration from NOW on each refresh (not from login)
- Preserve rememberMe flag across token rotations
- Active users: stay signed in forever (7/30 day sliding window)
- Inactive users: signed out after 7 days (regular) or 30 days (rememberMe)
This matches industry standards (Gmail, Slack, GitHub) where active users
remain authenticated while inactive users are automatically signed out.
- Add safe-db-push.mjs script for safer database migrations
- Update docker-entrypoint.sh with db:push fallback when migrations fail
- Add validate-migrations.mjs script for CI migration validation
- Update CI workflow to use migration validation
- Update drizzle.config.ts with improved configuration
Add centralized error logging endpoint to mana-core-auth:
- Error logs database schema with app_id, error message, stack traces
- POST /error-logs endpoint for single errors
- POST /error-logs/batch endpoint for batch submissions
- Error logs service with automatic cleanup of old entries
- DTOs with validation for error log submissions
The DO block approach in migration 0001 may not work correctly with
Drizzle's migration parser. This new migration 0002 uses PostgreSQL's
native ALTER TABLE ADD COLUMN IF NOT EXISTS syntax which is simpler
and more reliable.
Each column addition is a separate statement for maximum compatibility.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The sessions table on staging was missing newer columns like remember_me,
refresh_token, device_id, etc. because the initial migration uses
CREATE TABLE IF NOT EXISTS which skips if the table already exists.
This migration adds all potentially missing columns to the sessions table
using IF NOT EXISTS checks for each column.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The migration was failing on staging because the auth schema already
existed from previous db:push operations. This fix makes all DDL
statements idempotent:
- CREATE SCHEMA IF NOT EXISTS for all schemas
- DO $$ BEGIN ... EXCEPTION WHEN duplicate_object ... END $$ for ENUMs
- CREATE TABLE IF NOT EXISTS for all tables
- CREATE INDEX IF NOT EXISTS for all indexes
- DO $$ BEGIN ... EXCEPTION WHEN duplicate_object ... END $$ for constraints
This ensures migrations can run safely against databases that already
have the schema partially or fully created.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The shared-nestjs-cors package was exporting raw TypeScript files, which caused
runtime errors in production Docker containers:
SyntaxError: Unexpected token 'export'
Changes:
- Add build script to compile TypeScript to JavaScript
- Update package.json to export compiled dist files instead of src
- Add build step to all backend Dockerfiles that use this package
- Package now builds to CommonJS in dist/ folder
Fixes staging deployment failures for mana-core-auth and other backends.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add includeAllManaApps option to enable all ManaCore apps to communicate
with each other without manually listing each app's domains.
**Changes:**
- Added MANACORE_STAGING_ORIGINS, MANACORE_PRODUCTION_ORIGINS, and
MANACORE_ALL_APP_ORIGINS constants
- Added includeAllManaApps flag to CorsConfigOptions interface
- Updated createCorsConfig() and createCorsConfigWithCallback() to support
the new flag
- Updated mana-core-auth to use includeAllManaApps: true (auth needs to be
accessible by all apps)
- Updated documentation with usage examples and decision matrix
**Benefits:**
- One-line configuration enables cross-app communication
- Automatically stays in sync as new apps are added
- No need to manually update CORS_ORIGINS for each app
- Works in both staging and production environments
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add required name field (min 2 chars) to all registration forms to fix
Better Auth validation error. Updates backend DTO, shared-auth service,
shared-auth-ui RegisterPage component, i18n translations, and all app
auth stores and register pages.
Add comprehensive tests for role field security:
- Default role assignment verification
- input:false security (prevents role escalation)
- JWT payload role validation
- Role consistency across sessions
- Minimal JWT claims (no sensitive data)
Test infrastructure improvements:
- Add jose mock for ESM compatibility
- Update better-auth mock response format
- Configure Jest e2e to use mocks
- Fix `requestPasswordReset` method name (was incorrectly `forgetPassword`)
- Add proper TypeScript types for password reset, session, and JWT methods
- Consolidate API accessor from `orgApi` to `api` for all Better Auth calls
- Remove unnecessary `as any` casts by extending BetterAuthAPI interface
- Clean up unused imports
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove unused themes API from auth service:
- Delete themes.schema.ts database schema
- Delete themes.controller.ts, themes.service.ts, themes.module.ts
- Remove ThemesModule from app.module.ts imports
- Remove themes schema export from db/schema/index.ts
Custom themes are no longer supported - the built-in theme variants
provide sufficient customization options.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement per-device settings sync via mana-core-auth. Settings are now
stored both locally (localStorage) and in the cloud, with each device
(desktop, mobile, tablet) maintaining its own configuration.
Changes:
- Add deviceSettings JSONB column to user_settings table
- Add device API endpoints (GET/PATCH/DELETE /settings/device/:id/:app)
- Extend user-settings-store with device ID generation and detection
- Integrate calendar settings with cloud sync per device
- Remove todos from calendar header row (sidebar + grid only)
- Add hours dropdown to CalendarHeader for time range configuration
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Priority keywords now show their actual UI colors:
- Dringend (urgent): red #ef4444
- Wichtig (high): orange #f97316
- Normal (medium): yellow #eab308
- Später (low): green #22c55e
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
## Runtime Environment Fix
- Updated all web app hooks.server.ts to use $env/dynamic/private
- This allows Docker containers to inject env vars at runtime
- Updated docker-compose.staging.yml with HTTPS staging domains
- Fixes Mixed Content errors when accessing staging via domains
## New Features
- Added email service to mana-core-auth for sending emails
- Added storage module to chat backend
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Better Auth generates non-UUID user IDs (32-char base62 format like
'otUe1YrfENPdHnrF3g1vSBfpkQfambCZ'). Changed all `uuid('user_id')` to
`text('user_id')` in Drizzle schemas for consistency with auth system.
Affected packages/apps:
- apps/calendar, clock, picture, zitare
- games/figgos, voxelava
- packages/manadeck-database, news-database, uload-database
- services/mana-core-auth (feedback schema)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add referral code input to RegisterPage with live validation
- Create ReferralWidget for dashboard with stats, code sharing, and tier display
- Extend authService.signUp to accept optional referralCode parameter
- Add validateReferralCode function to authStore
- Create referrals.ts API service for frontend
- Add 'referral' widget type to dashboard configuration
- Fix drizzle.config.ts to include 'referrals' schema filter
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add console.log statements to JwtAuthGuard to diagnose
401 errors on /api/v1/settings endpoint.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add password reset functionality to mana-core-auth using Better Auth
- Add forgot-password and reset-password endpoints with DTOs
- Update shared-auth package with resetPassword method and endpoint
- Update manacore-web auth store with resetPassword method
- Refactor reset-password pages to use mana-core-auth instead of Supabase
- Remove Supabase dependencies from manacore-web package.json
- Remove Supabase server code (hooks.server.ts, supabase.ts, API routes)
- Update Dockerfile to remove shared-supabase dependency
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Auth fixes:
- Update fetchInterceptor skip patterns for ManaCore auth endpoints
- Fix URL matching to compare full origins instead of partial matches
- Update token manager state after successful login
- Remove Supabase session dependency from layouts
- Use authStore for auth state in route layouts
Dashboard fixes:
- Add network error detection in base-client to prevent infinite retries
- Update all 9 dashboard widgets to not retry on service unavailable
- Add /api/v1 prefix to all backend service URLs (chat, calendar, contacts, todo, zitare, picture, manadeck)
Commands:
- Add dev:manacore:backends to start all 9 dashboard backends
- Add dev:manacore:full to start web + all backends together
- Update COMMANDS.md with new commands and backend port table
Auth service:
- Fix TypeScript error: crossApp → cross_app in referrals schema
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update helmet middleware to allow cross-origin resource policy and
opener policy for proper CORS functionality with frontend apps.
Also add debug logging for configured CORS origins.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The JWT guards were using RS256 algorithm with jsonwebtoken library,
but Better Auth generates EdDSA tokens. This caused all authenticated
requests to fail with "Invalid token".
Changes:
- Replace jsonwebtoken with jose library
- Use JWKS endpoint for key fetching instead of static publicKey
- Support EdDSA algorithm used by Better Auth
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed remaining NestJS dependency injection issues by converting type-only imports to regular imports for all injectable services used in controllers and service dependencies.
Changes:
- feedback.service.ts: Fixed AiService import (was causing "argument Function at index [1]" error)
- auth.controller.ts: Fixed BetterAuthService import
- feedback.controller.ts: Fixed FeedbackService import
- credits.controller.ts: Fixed CreditsService import
- settings.controller.ts: Fixed SettingsService import
Root cause: Type-only imports (`import { type X }`) are erased at compile time, causing NestJS to fail dependency injection at runtime. All injectable classes must use regular imports.
Verified locally: All modules initialize successfully without DI errors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Found and fixed type-only ConfigService imports in 6 service files that were causing "Nest can't resolve dependencies" errors:
- better-auth.service.ts (BetterAuthService)
- ai.service.ts (AiService)
- settings.service.ts
- feedback.service.ts
- credits.service.ts
- jwt-auth.guard.ts
- optional-auth.guard.ts
Type-only imports are erased at compile time, preventing NestJS from injecting the ConfigService class at runtime.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The `type` keyword on ConfigService import was causing NestJS to fail resolving the dependency at runtime, as type-only imports are erased during compilation. Changed to regular import to fix DI.
Error was: "Nest can't resolve dependencies of the AiService (?)"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixes NestJS dependency injection error where AiService couldn't
resolve ConfigService dependency.
Error:
> Nest can't resolve dependencies of the AiService (?).
> Please make sure that the argument Function at index [0] is available
Root cause: AiModule was missing ConfigModule in its imports array,
but AiService constructor requires ConfigService to read ai.geminiApiKey.
This was preventing mana-core-auth from starting in staging deployment.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>