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> |
||
|---|---|---|
| .. | ||
| docs | ||
| postgres/init | ||
| src | ||
| test | ||
| .env.example | ||
| .gitignore | ||
| APPLY_SECURITY_FIXES.md | ||
| auth.ts | ||
| CLAUDE.md | ||
| docker-entrypoint.sh | ||
| Dockerfile | ||
| drizzle.config.ts | ||
| eslint.config.mjs | ||
| IMPLEMENTATION_COMPLETE.md | ||
| jest.config.js | ||
| MIGRATIONS.md | ||
| nest-cli.json | ||
| package.json | ||
| pnpm-lock.yaml | ||
| QUICKSTART.md | ||
| README.md | ||
| SECURITY_FIXES_STATUS.md | ||
| tsconfig.json | ||
Mana Core Auth
Central authentication and credit management system for the Mana Universe ecosystem.
Features
-
JWT-based Authentication (EdDSA/Ed25519 via Better Auth)
- User registration and login
- Refresh token rotation
- Multi-session management
- Device tracking
- Automatic key management via JWKS
-
Credit System
- User balance management
- Transaction ledger with double-entry bookkeeping
- Optimistic locking for concurrency
- Daily free credits
- Signup bonus (150 credits)
- Idempotency for credit operations
-
Security
- Row-Level Security (RLS) on PostgreSQL
- Rate limiting
- CORS protection
- Helmet security headers
- SCRAM-SHA-256 password authentication
-
Infrastructure
- Docker-based deployment
- Traefik reverse proxy with automatic SSL
- PgBouncer connection pooling
- Redis caching
- Prometheus + Grafana monitoring
Quick Start
Development Setup
-
Install dependencies
pnpm install -
Generate JWT keys
cd mana-core-auth ./scripts/generate-keys.sh -
Set up environment variables
cp .env.example .env # Edit .env and add your JWT keys and other configuration -
Start PostgreSQL and Redis (using Docker)
docker-compose up postgres redis -d -
Run migrations
pnpm migration:generate pnpm migration:run -
Start development server
pnpm start:devThe server will be available at
http://localhost:3001/api/v1
Production Deployment (Docker)
-
Set up environment variables
cp .env.example .env # Edit .env with production values -
Generate JWT keys
./mana-core-auth/scripts/generate-keys.sh # Add the generated keys to .env -
Start all services
docker-compose up -d -
Check service health
docker-compose ps docker-compose logs -f mana-core-auth
API Endpoints
Authentication
POST /api/v1/auth/register
- Register a new user
- Body:
{ email, password, name? } - Returns: User object
POST /api/v1/auth/login
- Login with email and password
- Body:
{ email, password, deviceId?, deviceName? } - Returns:
{ user, accessToken, refreshToken, expiresIn, tokenType }
POST /api/v1/auth/refresh
- Refresh access token
- Body:
{ refreshToken } - Returns: New token pair
POST /api/v1/auth/logout
- Logout and revoke session
- Requires: Bearer token
- Returns: Success message
POST /api/v1/auth/validate
- Validate a JWT token
- Body:
{ token } - Returns:
{ valid, payload }
Credits
GET /api/v1/credits/balance
- Get current credit balance
- Requires: Bearer token
- Returns:
{ balance, freeCreditsRemaining, totalEarned, totalSpent }
POST /api/v1/credits/use
- Deduct credits from balance
- Requires: Bearer token
- Body:
{ amount, appId, description, idempotencyKey?, metadata? } - Returns: Transaction details
GET /api/v1/credits/transactions?limit=50&offset=0
- Get transaction history
- Requires: Bearer token
- Returns: Array of transactions
GET /api/v1/credits/purchases
- Get purchase history
- Requires: Bearer token
- Returns: Array of purchases
GET /api/v1/credits/packages
- Get available credit packages
- Requires: Bearer token
- Returns: Array of packages
Database Schema
Auth Schema
auth.users- User accountsauth.sessions- Active sessionsauth.passwords- Hashed passwordsauth.accounts- OAuth provider accountsauth.verification_tokens- Email verification & password resetauth.two_factor_auth- 2FA configurationauth.security_events- Security audit log
Credits Schema
credits.balances- User credit balancescredits.transactions- Transaction ledgercredits.packages- Available credit packagescredits.purchases- Purchase historycredits.usage_stats- Usage analytics
Environment Variables
See .env.example for all available configuration options.
Key variables:
DATABASE_URL- PostgreSQL connection stringJWT_ISSUER- JWT issuer claim (default: manacore)JWT_AUDIENCE- JWT audience claim (default: manacore)REDIS_HOST,REDIS_PORT,REDIS_PASSWORD- Redis configurationSTRIPE_SECRET_KEY,STRIPE_WEBHOOK_SECRET- Stripe integrationCORS_ORIGINS- Allowed origins for CORSCREDITS_SIGNUP_BONUS- Free credits on signup (default: 150)CREDITS_DAILY_FREE- Daily free credits (default: 5)
Note: JWT signing keys are managed automatically by Better Auth using EdDSA (Ed25519). Keys are stored in the
auth.jwksdatabase table - no manual key configuration needed.
Development
Available Scripts
# Start development server with hot-reload
pnpm start:dev
# Build for production
pnpm build
# Start production server
pnpm start:prod
# Run tests
pnpm test
# Generate database migration
pnpm migration:generate
# Run migrations
pnpm migration:run
# Open Drizzle Studio (database GUI)
pnpm db:studio
# Lint and format
pnpm lint
pnpm format
Architecture
Token Flow
- User registers/logs in → Receives
accessToken(15min) +refreshToken(7 days) - Client stores tokens securely (httpOnly cookies on web, SecureStore on mobile)
- Client includes
Authorization: Bearer <accessToken>in requests - When access token expires, client uses refresh token to get new pair
- Refresh tokens are single-use (rotation for security)
Credit System
- Signup Bonus: 150 free credits on registration
- Daily Free Credits: 5 credits added every 24 hours
- Paid Credits: Purchased via Stripe (100 mana = €1)
- Usage Priority: Free credits used first, then paid credits
- Idempotency: Duplicate requests with same key are detected and ignored
- Concurrency: Optimistic locking prevents race conditions
Security Considerations
- JWT Keys: Managed automatically by Better Auth (EdDSA/Ed25519) - keys stored in
auth.jwkstable - Database: Use strong passwords and enable SSL in production
- Redis: Always set a password for Redis
- CORS: Only allow trusted origins
- Rate Limiting: Configured via Traefik and NestJS throttler
- RLS Policies: Enforce data isolation at database level
- HTTPS: Always use SSL/TLS in production (via Traefik)
- Security Headers: OWASP-compliant headers (HSTS, CSP, X-Frame-Options)
- Security Audit Logging: Login events tracked in
auth.security_eventstable
Monitoring
- Prometheus: Available at
http://localhost:9090 - Grafana: Available at
http://localhost:3000 - Logs:
docker-compose logs -f mana-core-auth
License
Private - Mana Universe
Support
For issues and questions, contact the development team.