Commit graph

608 commits

Author SHA1 Message Date
Wuesteon
9e771c9ae2 🔧 chore(auth): improve migration safety and docker setup
- 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
2025-12-19 02:18:31 +01:00
Wuesteon
319ccd1a46 feat(auth): add error logs API and database schema
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
2025-12-19 02:17:55 +01:00
Wuesteon
5e1118b711 feat(error-tracking): add shared error tracking package
Add @manacore/shared-error-tracking package with:
- Frontend error tracker with batching and offline support
- SvelteKit integration with hooks handler
- Expo/React Native integration with global error handler
- NestJS module with exception filter and service
- Shared TypeScript types for error log entries
2025-12-19 02:17:36 +01:00
Wuesteon
f834986a82 🐛 fix(ci): add db:push fallback when migrations fail
If db:migrate fails (e.g., due to migration hash mismatch after
modifying an already-applied migration), fall back to db:push
which syncs the schema directly.

This ensures the database schema is always up-to-date even when
migration tracking gets out of sync.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 23:26:10 +01:00
Wuesteon
ffc41b2b1d 🐛 fix(auth-migrations): use native ADD COLUMN IF NOT EXISTS syntax
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>
2025-12-18 23:25:07 +01:00
Wuesteon
5bb1abb23a 🐛 fix(auth-migrations): add missing session columns migration
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>
2025-12-18 22:28:28 +01:00
Wuesteon
7f3575387c 🐛 fix(auth-migrations): make initial migration idempotent
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>
2025-12-18 22:10:00 +01:00
Wuesteon
4d15d9e764 🔒 security(auth): migrate to EdDSA JWT and add automated monitoring
BREAKING: JWT keys are now auto-managed by Better Auth (EdDSA/Ed25519)
- Remove all JWT_PRIVATE_KEY, JWT_PUBLIC_KEY, JWT_SECRET references
- Keys stored in auth.jwks database table (auto-generated on first run)
- Delete obsolete generate-keys.sh and generate-staging-secrets.sh scripts
- Clean up legacy AUTH_*.md analysis files from root

Security Improvements:
- Add security_events table for audit logging
- Add SecurityEventsService for tracking auth events
- Enhanced security headers (HSTS, CSP, X-Frame-Options)
- Rate limiting configuration

Monitoring Setup:
- Add auth-health-check.sh for automated testing
- Add generate-dashboard.sh for HTML status dashboard
- Tests: health endpoint, JWKS (EdDSA), security headers, response time
- Ready for Hetzner cron deployment

Documentation:
- Update deployment docs with Better Auth notes
- Update environment variable references
- Add security improvements documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 21:42:47 +01:00
Wuesteon
1214c78a3c 🐛 fix(picture-backend): fix TypeScript output path for Docker
Added rootDir: "./src" to tsconfig.json so that main.ts compiles to
dist/main.js instead of dist/src/main.js. This matches the CMD path
in the Dockerfile.

Also added include/exclude and moduleResolution to match other backends.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 19:49:37 +01:00
Wuesteon
70c9196b40 🐛 fix(cors): handle both string and array corsOriginsEnv
The mana-core-auth configuration.ts was already splitting CORS_ORIGINS
into an array, but createCorsConfig expected a string and called .split()
on it, causing "corsOriginsEnv.split is not a function" TypeError.

Now handles both string and array inputs gracefully.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 19:27:57 +01:00
Wuesteon
05ad5f1ed8 🔧 fix(picture-web): switch from adapter-netlify to adapter-node
The Docker build was failing because adapter-netlify outputs to .netlify/
directory but the Dockerfile expected build output in build/ directory.

Switched to adapter-node with explicit `out: 'build'` configuration
which matches the Dockerfile expectations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 19:13:29 +01:00
Wuesteon
71cbca07d5 🐛 fix(picture-web): fix Docker build and auth pages
- Remove unused Google/Apple OAuth imports from login page
- Add missing shared-types package to Dockerfile
- Fix signup page to pass name parameter to signUp
- Add confirmResetPassword method to auth store
- Add reset-password page for completing password reset flow
2025-12-17 18:58:31 +01:00
Wuesteon
dcdc15f154 🚀 ci(picture): add picture app to CI/CD deployment pipeline
- Add picture-backend and picture-web to CI Docker build matrix
- Add picture services to staging deployment workflow
- Add picture-backend to production deployment workflow
- Create Dockerfile and docker-entrypoint.sh for picture-web
- Fix picture-backend Dockerfile port (3003→3006) and health endpoint
- Add picture routes to Caddyfile.staging
- Add REPLICATE_API_TOKEN and MANA_CORE_SERVICE_KEY env vars
2025-12-17 18:47:42 +01:00
Wuesteon
74654e652a 🐛 fix(cors): compile shared-nestjs-cors to JavaScript for production
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>
2025-12-17 18:42:47 +01:00
Wuesteon
47881ae410 feat(husky): add helpful error messages to git hooks
- Add clear error messages when pre-commit checks fail
- Add clear error messages when pre-push builds fail
- Explicitly warn against using --no-verify flag
- Encourage developers to fix issues rather than bypass checks

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-17 18:39:41 +01:00
Wuesteon
1be3d7a3ae 🐛 fix(docker): add missing workspace dependencies to all Dockerfiles
Ensure all backend Dockerfiles copy and build ALL workspace dependencies
they need. This fixes Docker build failures where packages couldn't find
their @manacore/* dependencies.

**Changes:**

**Picture Backend:**
- Added better-auth-types (with build)
- Added mana-core-nestjs-integration (with build)
- Added shared-nestjs-auth (with build)
- Added shared-storage (with build)

**Chat Backend:**
- Added mana-core-nestjs-integration (with build)

**Calendar, Clock, Todo Backends:**
- Added shared-nestjs-cors (already had other deps)

**Mana Core Auth:**
- Restructured for monorepo workspace support
- Added shared-nestjs-cors

**Key Improvements:**
- All packages in alphabetical order
- Build steps for compiled packages
- Source-only packages (shared-nestjs-cors) skip build
- Proper dependency ordering in build steps

This ensures Docker builds work correctly after the CORS package addition.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-17 18:19:29 +01:00
Wuesteon
c5d662bb89 test(cors): add comprehensive unit tests for shared-nestjs-cors
Add 63 unit tests with 100% code coverage for CORS configuration utilities.

**Test Coverage:**
- createCorsConfig() function (24 tests)
  - Default behavior and configuration structure
  - Environment variable parsing (comma-separated, trimming)
  - includeAllManaApps flag functionality
  - Custom development origins
  - Additional origins (mobile apps)
  - Origin deduplication across all sources
  - Combined options integration

- createCorsConfigWithCallback() function (15 tests)
  - Callback mode for mobile app support
  - No origin handling (server-to-server)
  - Valid/invalid origin validation
  - Security: protocol-sensitive matching
  - Callback return value validation

- Origin constants (24 tests)
  - MANACORE_STAGING_ORIGINS validation
  - MANACORE_PRODUCTION_ORIGINS validation
  - MANACORE_ALL_APP_ORIGINS combination
  - URL format validation
  - Duplicate detection
  - Consistency between environments

**Results:**
- 63 tests passing
- 100% code coverage (statements, branches, functions, lines)
- All edge cases covered (empty values, whitespace, duplicates)

**Setup:**
- Added Jest with ts-jest for TypeScript support
- Added test scripts: test, test:watch, test:coverage
- Created jest.config.js with coverage configuration
- Proper TypeScript types for callback functions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-17 18:11:13 +01:00
Wuesteon
3504172e60 feat(cors): add cross-app communication bundle
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>
2025-12-17 18:11:13 +01:00
Wuesteon
4c44764838 1. Brevo email integration (API key, sender settings)
2. URL configuration fix (BASE_URL, FRONTEND_URL)
  3. Password reset URL pointing to frontend instead of API
2025-12-17 18:11:13 +01:00
Wuesteon
8c973e4354 1. Brevo email integration (API key, sender settings)
2. URL configuration fix (BASE_URL, FRONTEND_URL)
  3. Password reset URL pointing to frontend instead of API
2025-12-16 21:12:25 +01:00
Wuesteon
3e3e9f33aa 🩹 fix(voxelava): fix type errors in level types and user profile
- Make userId, createdAt, updatedAt nullable in LevelMetadata to match API
- Disable password change feature (not supported by Mana Core Auth yet)
2025-12-16 20:29:38 +01:00
Wuesteon
d3e11b320a 🐛 fix(auth): require name field in registration forms
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.
2025-12-16 20:28:28 +01:00
Nils Weiser
11324b5e68
Merge pull request #19 from Memo-2023/till-dev
Till dev
2025-12-16 19:27:03 +01:00
Wuesteon
285e142970 Merge branch 'dev' into till-dev 2025-12-16 19:17:07 +01:00
Till-JS
6035994972 feat(calendar): add stats sidebar section and heatmap support in year view
- Add StatsSidebarSection component with event statistics, weekly trend chart, and calendar activity
- Show stats sidebar when heatmap mode is enabled instead of todo section
- Add heatmap level classes (1-5) to YearView with GitHub-style coloring
- Only show StatsOverlay when sidebar is collapsed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 18:39:59 +01:00
Till-JS
ea856214fe feat(calendar): show settings as modal on homepage
- Create SettingsModal component with all settings sections
- Update layout to show settings modal when clicking Settings in PillNav
- Modal appears above the input bar with glassmorphism styling
- Settings changes are saved immediately via settingsStore

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 18:37:11 +01:00
Till-JS
31f187b816 feat(calendar): integrate network view into homepage with heatmap stats
- Add network view as "N" option in view switcher (like contacts app pattern)
- Create view-mode store to switch between calendar/network modes
- Move NetworkView from /network route to embedded component
- Add heatmap mode with StatsOverlay for event density visualization
- Extend network service to create connections by:
  - Shared tags (highest priority, variable strength)
  - Same calendar (strength 50%)
  - Same date (strength 40%)
  - Same location (strength 60%)
- Fix network controller route prefix (was /api/v1/api/v1/network)
- Remove separate /network and /statistics pages

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 18:35:03 +01:00
Till-JS
484efccb45 style(calendar): use neutral colors for TagStrip action buttons
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 18:08:11 +01:00
Till-JS
c7c451e439 feat(calendar): add tag filtering to calendar views
- Add selectedTagIds to settings store with toggle/clear methods
- Update TagStrip to select tags for filtering instead of navigation
- Add filterByTags function to eventFiltering utils
- Apply tag filtering across all calendar views:
  - MultiDayView (timed & all-day events)
  - AgendaView (with empty group removal)
  - MonthView
  - YearView (event counts)
- Add "Filter löschen" button (hidden when no tags selected)
- Rename buttons: "Mehr" → "Alle Tags", "Neu" → "Neuer Tag"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 17:59:28 +01:00
Till-JS
781bc529ba fix(calendar): equal cell heights in month view on smaller screens
Fix flexbox layout for month view grid cells by:
- Adding height: 100% and min-height: 0 to .month-view container
- Using flex: 1 1 0 on week rows for equal distribution
- Adding overflow: hidden on day cells to prevent content overflow

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 17:43:38 +01:00
Wuesteon
ad495b2044 📝 docs: restructure CLAUDE.md and documentation (74% reduction)
Optimize CLAUDE.md based on industry best practices from HN and HumanLayer:

Changes:
- Trim CLAUDE.md from 678 to 176 lines (74% reduction, 5.7KB)
- Add "Critical Gotchas" section for common AI mistakes
- Add verification signature (🏗️ ManaCore Monorepo)
- Create docs/README.md navigation hub with "I want to..." index
- Delete 5 outdated audit files (ENV_AUDIT_*, DEPENDENCY_ALIGNMENT)
- Archive 7 analysis/historical docs to docs/archive/
- Keep authentication docs separate per request (.claude/guidelines/)

Benefits:
- Better AI instruction adherence (within ~150-200 line budget)
- Progressive disclosure via signposting to detailed docs
- Cleaner navigation with topic-based organization
- Reduced maintenance burden (stale docs archived)

Backup: CLAUDE.md.backup preserves original 678-line version
Change log: docs/archive/RESTRUCTURE_2025-12-16.md
2025-12-16 17:37:19 +01:00
Wuesteon
d2c2326ed7 🐛 fix(calendar): use runtime config for cross-app service URLs
Calendar app was using $env/dynamic/public for TODO and Contacts API
URLs, which doesn't work in SPA mode. Updated to use runtime config:

- Add TODO_API_URL and CONTACTS_API_URL to runtime config
- Update docker-entrypoint.sh to include new env vars
- Refactor todos.ts and birthdays.ts to use lazy-loaded clients
- Refactor user-settings.svelte.ts with lazy store initialization
- Add env vars to docker-compose.staging.yml

This fixes staging deployment where cross-app integrations were
calling localhost instead of staging URLs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 05:10:01 +01:00
Wuesteon
7b33f6a761 📝 docs(staging): add troubleshooting for pre-compressed configs and caching
- Document SvelteKit pre-compressed files issue (.br, .gz) causing wrong config
- Add Caddy response caching troubleshooting
- Add Docker disk space cleanup guide
- Update "Adding a New App" with complete docker-entrypoint.sh template
- Include runtime config pattern (runtime.ts, static/config.json)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 05:03:23 +01:00
Wuesteon
bdbe66d2df 🐛 fix(docker): remove pre-compressed config files at runtime
SvelteKit pre-compresses static files (config.json.br, config.json.gz)
during build. When docker-entrypoint.sh regenerates config.json at
runtime, the server still serves the stale compressed versions.

This fix removes the .br and .gz files after generating the fresh
config.json, ensuring browsers receive the correct runtime configuration.

Affected apps: calendar, chat, clock, contacts, manacore

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 04:43:11 +01:00
Wuesteon
c5ffd92bad feat(auth): add Brevo email integration for password reset and org invites 2025-12-16 03:33:15 +01:00
Wuesteon
f37f85eded 🐛 fix(docker): add better-auth-types to backend Dockerfiles
Add missing @manacore/better-auth-types package to backend Docker builds.
The shared-nestjs-auth package depends on this new types package.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 03:14:45 +01:00
Wuesteon
cd19106857 🐛 fix(docker): add better-auth-types to web app Dockerfiles
Add missing @manacore/better-auth-types package to Docker builds.
The shared-auth package now depends on this new types package.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 02:59:51 +01:00
Wuesteon
6e6815a5fa 📝 docs(auth): document Better Auth typing improvements
Add comprehensive documentation for Better Auth improvements:
- Centralized types package usage guide
- Frontend type inference examples
- Zod validation implementation
- Rate limiting configuration
- Integration test documentation
- Migration guide for developers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 02:45:41 +01:00
Wuesteon
a7f274632f test(auth): add role security integration tests
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
2025-12-16 02:44:39 +01:00
Wuesteon
fff2819b59 🔒️ feat(auth): add Zod validation and endpoint rate limiting
Security improvements for Better Auth:
- Add Zod schema for runtime role validation (user/admin/service)
- Add rate limiting to sensitive endpoints:
  - Login: 5 requests/minute
  - Register: 10 requests/hour
  - Password reset: 3 requests/5 minutes
  - B2B register: 5 requests/hour
- Skip rate limiting for /validate and /jwks endpoints
2025-12-16 02:44:21 +01:00
Wuesteon
26ca921158 feat(auth): add centralized @manacore/better-auth-types package
Create new shared package for Better Auth type definitions:
- UserRole, JWTPayload, CurrentUserData types
- Type guards: isValidUserRole, isValidOrganizationRole
- Utility functions: jwtPayloadToCurrentUser
- userAdditionalFields for client type inference

Migrate shared packages to use centralized types:
- @manacore/shared-auth re-exports from new package
- @manacore/shared-nestjs-auth uses new package as dependency
2025-12-16 02:43:55 +01:00
Wuesteon
eeab9b7fea fix(auth): use correct Better Auth API method for password reset
- 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>
2025-12-16 01:49:06 +01:00
Wuesteon
78cd59a77a feat(storage): unified single-bucket architecture with Hetzner S3
- Refactor @manacore/shared-storage to use single `manacore-storage` bucket
- Add generateStorageKey() for path structure: {userId}/{appName}/...
- Update docker-compose.dev.yml for unified MinIO bucket
- Migrate CD workflow to use GitHub Environment Secrets
- Update picture and contacts backends to use unified storage
- Remove per-app bucket configuration (cleaner architecture)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 01:29:11 +01:00
Wuesteon
d268e8e463 docs: add comprehensive session report for runtime config implementation
Complete documentation of today's work including:

## What We Accomplished
- Runtime config for Contacts & Calendar apps
- Fixed 10 bugs (2 critical staging issues)
- Created 3-layer protection system (ESLint + Validation + Docs)
- Successfully deployed to staging

## Problems Encountered & Solutions
1. Type errors (zod dependency, onMount return type)
2. Pre-push build failures (MIDDLEWARE_URL, missing zod)
3. CI/CD frozen lockfile mismatch
4. Docker entrypoint absolute path crash
5. Critical: ERR_CONNECTION_REFUSED (missing await)
6. Critical: Window injection in user-settings

## Protection System Created
- Layer 1: ESLint rules (no-floating-promises, no-misused-promises)
- Layer 2: Validation script (450 LOC, scans 22 apps)
- Layer 3: Documentation (650 lines, implementation guide)

## Future Enhancements Plan
- Phase 1: Add validation to pre-push hook (2-3 hours)
- Phase 2: Create shared runtime config package (1 week)
- Phase 3: Project generator CLI (2 weeks)

## Stats
- Added: ~1,130 lines
- Modified: 28 files
- Created: 19 files
- Commits: 6 commits
- Apps completed: 5 (Clock, Chat, Picture, Contacts, Calendar)

This serves as a reference for future runtime config implementations
and documents the entire debugging and implementation process.
2025-12-16 00:34:06 +01:00
Wuesteon
aab8c73a9c feat: add multi-layered runtime config protection system
Add comprehensive defense system to prevent runtime config bugs across all projects:

## 1. Enhanced ESLint Rules
- Added @typescript-eslint/no-floating-promises (error)
  Catches: fetch(`${getAuthUrl()}/api`) without await
- Added @typescript-eslint/no-misused-promises (error)
  Catches: Promises in conditionals and logical expressions
- Added @typescript-eslint/require-await (warn)
  Ensures async functions actually use await

## 2. Validation Script (scripts/validate-runtime-config.mjs)
Automated checker that scans all web apps for:
-  Required files (runtime.ts, docker-entrypoint.sh, Dockerfile)
-  Window injection patterns (window.__PUBLIC_*)
-  Build-time env usage in stores/api (import.meta.env.PUBLIC_*)
-  Missing await on async config functions
- ⚠️  Docker entrypoint best practices

Usage: pnpm validate:runtime-config

## 3. Comprehensive Documentation (docs/RUNTIME_CONFIG.md)
Complete implementation guide covering:
- Why runtime configuration is needed
- Step-by-step implementation guide
- Common patterns (API clients, auth stores)
- Anti-patterns to avoid
- Migration checklist
- ESLint protection details

## Benefits
- Prevents "[object Promise]" in API URLs (staging bug)
- Catches missing await at lint time
- Validates all apps automatically
- Clear documentation for new projects
- Can run in CI/CD

## Future Work
- Add to pre-push hook (optional)
- Create project generator/template
- Shared runtime config package

This prevents the class of bugs we just fixed in manacore-web where
getAuthUrl() was called without await, causing ERR_CONNECTION_REFUSED
on staging.
2025-12-16 00:28:57 +01:00
Wuesteon
b2a8ffa6d9 fix(manacore-web): await getAuthUrl() and use runtime config in user-settings
Critical fixes for runtime configuration:
- auth.svelte.ts: Added missing await on getAuthUrl() in validateReferralCode()
- user-settings.svelte.ts: Replaced window injection with runtime config loading

This fixes ERR_CONNECTION_REFUSED on staging by ensuring auth URL is properly loaded from config.json before making API calls.
2025-12-16 00:21:23 +01:00
Wuesteon
9b55f10c28 fix(manacore-web): fix Docker entrypoint path for config.json
The entrypoint was trying to write to /app/build/client/config.json with an
absolute path, but since WORKDIR is /app/apps/manacore/apps/web, it should
use relative paths instead.

Changes:
- Use relative path 'build/client/config.json' instead of '/app/build/client/config.json'
- Add 'mkdir -p build/client' to ensure directory exists
- Update cat command to use relative path

This fixes the "nonexistent directory" error causing manacore-web to crash
in staging environment.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-16 00:00:53 +01:00
Wuesteon
5c594a4b23 fix(deps): add missing zod dependency to Calendar and Chat web apps for CI
Fixes CI/CD frozen-lockfile failure. The pnpm-lock.yaml had zod entries for
Calendar and Chat web apps, but their package.json files were missing the
dependency. This mismatch caused CI builds to fail.

Added zod@^3.25.76 to:
- apps/calendar/apps/web/package.json
- apps/chat/apps/web/package.json

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-15 23:41:37 +01:00
Wuesteon
22af71883e fix(runtime-config): add missing zod dependency to Clock and Contacts web apps
Added zod ^3.25.76 to package.json dependencies for:
- @clock/web
- @contacts/web

This fixes build failures in pre-push hook where runtime.ts config validation
required zod but it wasn't listed as a dependency.

Calendar and Chat apps already had zod installed (^4.2.0).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-15 22:44:24 +01:00
Wuesteon
b8d1067414 🐛 fix: use dynamic env for MIDDLEWARE_URL in server middleware
- Replace static private env import with dynamic env
- Add default value for MIDDLEWARE_URL
- Fixes build error where MIDDLEWARE_URL wasn't defined
2025-12-15 22:33:23 +01:00