docs: Restructure documentation with Bookstack-compatible hierarchy
- Organized docs into numbered shelf/book/chapter/page structure - Created comprehensive README.md with project overview - Added Getting Started book (quick start, installation, configuration) - Added Development book (workflow, testing, type sharing) - Added Architecture book (design principles, PDA-friendly patterns) - Added API Reference book (conventions, authentication) - Moved TYPE-SHARING.md to proper location - Updated all cross-references in main README - Created docs/README.md as master index - Removed old QA automation reports - Removed deprecated SETUP.md (content split into new structure) Documentation structure follows Bookstack best practices: - Numbered books: 1-getting-started, 2-development, 3-architecture, 4-api - Numbered chapters and pages for ordering - Clear hierarchy and navigation - Cross-referenced throughout Complete documentation available at: docs/README.md Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
77
docs/1-getting-started/1-quick-start/1-overview.md
Normal file
77
docs/1-getting-started/1-quick-start/1-overview.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# Quick Start
|
||||
|
||||
Get Mosaic Stack running in 5 minutes with Docker.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker 24+ and Docker Compose 2.20+
|
||||
- Git 2.x
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# Clone repository
|
||||
git clone https://git.mosaicstack.dev/mosaic/stack mosaic-stack
|
||||
cd mosaic-stack
|
||||
|
||||
# Copy environment file
|
||||
cp .env.example .env
|
||||
|
||||
# Start all services
|
||||
docker compose up -d
|
||||
|
||||
# Run migrations
|
||||
docker compose exec api pnpm prisma migrate deploy
|
||||
|
||||
# Seed development data (optional)
|
||||
docker compose exec api pnpm prisma:seed
|
||||
```
|
||||
|
||||
## Verify Installation
|
||||
|
||||
```bash
|
||||
# Check API health
|
||||
curl http://localhost:3001/health
|
||||
|
||||
# Expected response:
|
||||
# {"status":"ok","timestamp":"...","uptime":...}
|
||||
|
||||
# View logs
|
||||
docker compose logs -f api
|
||||
```
|
||||
|
||||
## What's Running?
|
||||
|
||||
| Service | Port | Purpose |
|
||||
|---------|------|---------|
|
||||
| API | 3001 | NestJS backend |
|
||||
| PostgreSQL | 5432 | Database |
|
||||
| Valkey | 6379 | Cache (Redis-compatible) |
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Configure Authentication** — See [Configuration → Authentik](../3-configuration/2-authentik.md)
|
||||
2. **Explore the API** — Check [API Reference](../../4-api/README.md)
|
||||
3. **Start Developing** — Read [Development → Workflow](../../2-development/1-workflow/1-branching.md)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Port already in use:**
|
||||
```bash
|
||||
# Stop existing services
|
||||
docker compose down
|
||||
|
||||
# Check what's using the port
|
||||
lsof -i :3001
|
||||
```
|
||||
|
||||
**Database connection failed:**
|
||||
```bash
|
||||
# Check PostgreSQL is running
|
||||
docker compose ps postgres
|
||||
|
||||
# View PostgreSQL logs
|
||||
docker compose logs postgres
|
||||
```
|
||||
|
||||
For detailed installation options, see [Installation → Local Setup](../2-installation/2-local-setup.md).
|
||||
172
docs/1-getting-started/2-installation/1-prerequisites.md
Normal file
172
docs/1-getting-started/2-installation/1-prerequisites.md
Normal file
@@ -0,0 +1,172 @@
|
||||
# Prerequisites
|
||||
|
||||
Required and optional software for Mosaic Stack development.
|
||||
|
||||
## Required
|
||||
|
||||
### Node.js 20+
|
||||
|
||||
```bash
|
||||
# Install using nvm (recommended)
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
|
||||
nvm install 20
|
||||
nvm use 20
|
||||
|
||||
# Verify installation
|
||||
node --version # Should be v20.x.x
|
||||
```
|
||||
|
||||
### pnpm 9+
|
||||
|
||||
```bash
|
||||
# Install globally
|
||||
npm install -g pnpm@9
|
||||
|
||||
# Verify installation
|
||||
pnpm --version # Should be 9.x.x
|
||||
```
|
||||
|
||||
### PostgreSQL 17+
|
||||
|
||||
**Option 1: Native Installation (Linux)**
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt update
|
||||
sudo apt install postgresql-17 postgresql-contrib postgresql-17-pgvector
|
||||
|
||||
# Start PostgreSQL
|
||||
sudo systemctl start postgresql
|
||||
sudo systemctl enable postgresql
|
||||
|
||||
# Verify installation
|
||||
sudo -u postgres psql --version
|
||||
```
|
||||
|
||||
**Option 2: macOS (Homebrew)**
|
||||
|
||||
```bash
|
||||
brew install postgresql@17
|
||||
brew services start postgresql@17
|
||||
```
|
||||
|
||||
**Option 3: Docker (Recommended for Development)**
|
||||
|
||||
```bash
|
||||
# PostgreSQL will be started via docker compose
|
||||
# No native installation required
|
||||
```
|
||||
|
||||
### Git 2+
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt install git
|
||||
|
||||
# macOS
|
||||
brew install git
|
||||
|
||||
# Verify installation
|
||||
git --version
|
||||
```
|
||||
|
||||
## Optional
|
||||
|
||||
### Docker & Docker Compose
|
||||
|
||||
Required for containerized deployment and recommended for development.
|
||||
|
||||
**Linux:**
|
||||
|
||||
```bash
|
||||
# Install Docker
|
||||
curl -fsSL https://get.docker.com -o get-docker.sh
|
||||
sudo sh get-docker.sh
|
||||
|
||||
# Add user to docker group
|
||||
sudo usermod -aG docker $USER
|
||||
newgrp docker
|
||||
|
||||
# Install Docker Compose
|
||||
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
||||
sudo chmod +x /usr/local/bin/docker-compose
|
||||
|
||||
# Verify installation
|
||||
docker --version
|
||||
docker compose version
|
||||
```
|
||||
|
||||
**macOS:**
|
||||
|
||||
```bash
|
||||
# Install Docker Desktop
|
||||
# Download from: https://www.docker.com/products/docker-desktop
|
||||
|
||||
# Verify installation
|
||||
docker --version
|
||||
docker compose version
|
||||
```
|
||||
|
||||
### Authentik
|
||||
|
||||
Required for OIDC authentication in production.
|
||||
|
||||
**Docker Installation:**
|
||||
|
||||
```bash
|
||||
# Download Authentik compose file
|
||||
curl -o authentik-compose.yml https://goauthentik.io/docker-compose.yml
|
||||
|
||||
# Start Authentik
|
||||
docker compose -f authentik-compose.yml up -d
|
||||
|
||||
# Access at http://localhost:9000
|
||||
```
|
||||
|
||||
**Or use an existing Authentik instance**
|
||||
|
||||
See [Configuration → Authentik](../3-configuration/2-authentik.md) for setup instructions.
|
||||
|
||||
### Ollama
|
||||
|
||||
Required for AI features (optional for core functionality).
|
||||
|
||||
**Linux:**
|
||||
|
||||
```bash
|
||||
curl -fsSL https://ollama.com/install.sh | sh
|
||||
|
||||
# Pull a model
|
||||
ollama pull llama2
|
||||
```
|
||||
|
||||
**macOS:**
|
||||
|
||||
```bash
|
||||
brew install ollama
|
||||
|
||||
# Pull a model
|
||||
ollama pull llama2
|
||||
```
|
||||
|
||||
**Or use remote Ollama instance**
|
||||
|
||||
Configure `OLLAMA_MODE=remote` and `OLLAMA_ENDPOINT` in `.env`.
|
||||
|
||||
## Verification
|
||||
|
||||
Check all required tools are installed:
|
||||
|
||||
```bash
|
||||
node --version # v20.x.x or higher
|
||||
pnpm --version # 9.x.x or higher
|
||||
git --version # 2.x.x or higher
|
||||
docker --version # 24.x.x or higher (if using Docker)
|
||||
psql --version # 17.x.x or higher (if using native PostgreSQL)
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
Proceed to:
|
||||
- [Local Setup](2-local-setup.md) for native development
|
||||
- [Docker Setup](3-docker-setup.md) for containerized deployment
|
||||
259
docs/1-getting-started/2-installation/2-local-setup.md
Normal file
259
docs/1-getting-started/2-installation/2-local-setup.md
Normal file
@@ -0,0 +1,259 @@
|
||||
# Local Setup
|
||||
|
||||
Native installation for active development with hot reload and debugging.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Complete [Prerequisites](1-prerequisites.md) first.
|
||||
|
||||
## Step 1: Clone Repository
|
||||
|
||||
```bash
|
||||
git clone https://git.mosaicstack.dev/mosaic/stack mosaic-stack
|
||||
cd mosaic-stack
|
||||
```
|
||||
|
||||
## Step 2: Install Dependencies
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
This installs dependencies for:
|
||||
- Root workspace
|
||||
- `apps/api` (NestJS backend)
|
||||
- `apps/web` (Next.js frontend - when implemented)
|
||||
- `packages/shared` (Shared types and utilities)
|
||||
|
||||
## Step 3: Configure Environment
|
||||
|
||||
```bash
|
||||
# Copy environment template
|
||||
cp .env.example .env
|
||||
|
||||
# Edit configuration
|
||||
nano .env # or use your preferred editor
|
||||
```
|
||||
|
||||
**Minimum required configuration:**
|
||||
|
||||
```bash
|
||||
# Database
|
||||
DATABASE_URL=postgresql://mosaic:mosaic@localhost:5432/mosaic
|
||||
|
||||
# JWT Session
|
||||
JWT_SECRET=$(openssl rand -base64 32)
|
||||
JWT_EXPIRATION=24h
|
||||
|
||||
# Application
|
||||
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
||||
```
|
||||
|
||||
See [Configuration → Environment](../3-configuration/1-environment.md) for complete reference.
|
||||
|
||||
## Step 4: Setup PostgreSQL Database
|
||||
|
||||
### Create Database and User
|
||||
|
||||
```bash
|
||||
sudo -u postgres psql <<EOF
|
||||
CREATE USER mosaic WITH PASSWORD 'mosaic';
|
||||
CREATE DATABASE mosaic OWNER mosaic;
|
||||
\c mosaic
|
||||
CREATE EXTENSION IF NOT EXISTS vector;
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
GRANT ALL PRIVILEGES ON DATABASE mosaic TO mosaic;
|
||||
EOF
|
||||
```
|
||||
|
||||
### Or Use Docker PostgreSQL
|
||||
|
||||
```bash
|
||||
# Start only PostgreSQL
|
||||
docker compose up -d postgres
|
||||
|
||||
# Wait for it to be ready
|
||||
sleep 5
|
||||
```
|
||||
|
||||
## Step 5: Run Database Migrations
|
||||
|
||||
```bash
|
||||
# Generate Prisma client
|
||||
pnpm prisma:generate
|
||||
|
||||
# Run migrations
|
||||
cd apps/api
|
||||
pnpm prisma migrate deploy
|
||||
|
||||
# Seed development data (optional)
|
||||
pnpm prisma:seed
|
||||
|
||||
# Return to project root
|
||||
cd ../..
|
||||
```
|
||||
|
||||
## Step 6: Start Development Servers
|
||||
|
||||
```bash
|
||||
# Start all services
|
||||
pnpm dev
|
||||
|
||||
# This starts:
|
||||
# - API on http://localhost:3001
|
||||
# - Web on http://localhost:3000 (when implemented)
|
||||
```
|
||||
|
||||
**Or start individually:**
|
||||
|
||||
```bash
|
||||
# API only
|
||||
pnpm dev:api
|
||||
|
||||
# Web only (when implemented)
|
||||
pnpm dev:web
|
||||
```
|
||||
|
||||
## Step 7: Verify Installation
|
||||
|
||||
### Check API Health
|
||||
|
||||
```bash
|
||||
curl http://localhost:3001/health
|
||||
```
|
||||
|
||||
**Expected response:**
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"timestamp": "2026-01-28T...",
|
||||
"uptime": 1234
|
||||
}
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
pnpm test
|
||||
```
|
||||
|
||||
**Expected output:**
|
||||
```
|
||||
Test Files 5 passed (5)
|
||||
Tests 26 passed (26)
|
||||
```
|
||||
|
||||
### Open Prisma Studio
|
||||
|
||||
```bash
|
||||
cd apps/api
|
||||
pnpm prisma:studio
|
||||
|
||||
# Opens at http://localhost:5555
|
||||
```
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### File Watching
|
||||
|
||||
The development servers automatically reload when you make changes:
|
||||
|
||||
```bash
|
||||
# API watches src/**/*.ts
|
||||
pnpm dev:api
|
||||
|
||||
# Changes trigger automatic restart
|
||||
```
|
||||
|
||||
### Running Specific Tests
|
||||
|
||||
```bash
|
||||
# All tests
|
||||
pnpm test
|
||||
|
||||
# Watch mode (re-runs on file changes)
|
||||
pnpm test:watch
|
||||
|
||||
# Specific test file
|
||||
pnpm test apps/api/src/auth/auth.service.spec.ts
|
||||
|
||||
# Coverage report
|
||||
pnpm test:coverage
|
||||
```
|
||||
|
||||
### Database Management
|
||||
|
||||
```bash
|
||||
cd apps/api
|
||||
|
||||
# Open Prisma Studio GUI
|
||||
pnpm prisma:studio
|
||||
|
||||
# Create migration after schema changes
|
||||
pnpm prisma migrate dev --name your_migration_name
|
||||
|
||||
# Reset database (WARNING: deletes data)
|
||||
pnpm prisma migrate reset
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Port Already in Use
|
||||
|
||||
```bash
|
||||
# Find process using port
|
||||
lsof -i :3001
|
||||
|
||||
# Kill process
|
||||
kill -9 <PID>
|
||||
|
||||
# Or use different port
|
||||
PORT=3002 pnpm dev:api
|
||||
```
|
||||
|
||||
### PostgreSQL Connection Failed
|
||||
|
||||
```bash
|
||||
# Check if PostgreSQL is running
|
||||
sudo systemctl status postgresql
|
||||
|
||||
# Test connection
|
||||
psql -U mosaic -d mosaic -h localhost -W
|
||||
# Password: mosaic
|
||||
|
||||
# Check DATABASE_URL in .env
|
||||
cat .env | grep DATABASE_URL
|
||||
```
|
||||
|
||||
### Prisma Client Not Generated
|
||||
|
||||
```bash
|
||||
cd apps/api
|
||||
pnpm prisma:generate
|
||||
|
||||
# If still failing, clean and reinstall
|
||||
rm -rf node_modules
|
||||
cd ../..
|
||||
pnpm install
|
||||
pnpm prisma:generate
|
||||
```
|
||||
|
||||
### Build Errors
|
||||
|
||||
```bash
|
||||
# Clean build cache
|
||||
rm -rf apps/*/dist packages/*/dist
|
||||
|
||||
# Rebuild
|
||||
pnpm build
|
||||
|
||||
# Type check
|
||||
pnpm typecheck
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Configure Authentication** — [Authentik Setup](../3-configuration/2-authentik.md)
|
||||
2. **Learn the Workflow** — [Development → Workflow](../../2-development/1-workflow/1-branching.md)
|
||||
3. **Explore the Database** — [Development → Database](../../2-development/2-database/1-schema.md)
|
||||
4. **Review API Docs** — [API → Conventions](../../4-api/1-conventions/1-endpoints.md)
|
||||
361
docs/1-getting-started/2-installation/3-docker-setup.md
Normal file
361
docs/1-getting-started/2-installation/3-docker-setup.md
Normal file
@@ -0,0 +1,361 @@
|
||||
# Docker Setup
|
||||
|
||||
Containerized deployment for production or quick testing.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker 24+ and Docker Compose 2.20+
|
||||
- Git 2.x
|
||||
|
||||
See [Prerequisites](1-prerequisites.md) for installation instructions.
|
||||
|
||||
## Step 1: Clone Repository
|
||||
|
||||
```bash
|
||||
git clone https://git.mosaicstack.dev/mosaic/stack mosaic-stack
|
||||
cd mosaic-stack
|
||||
```
|
||||
|
||||
## Step 2: Configure Environment
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
nano .env # Configure as needed
|
||||
```
|
||||
|
||||
**Key variables for Docker deployment:**
|
||||
|
||||
```bash
|
||||
# Database (Docker internal networking)
|
||||
DATABASE_URL=postgresql://mosaic:mosaic@postgres:5432/mosaic
|
||||
|
||||
# Redis (Docker internal networking)
|
||||
REDIS_URL=redis://valkey:6379
|
||||
|
||||
# Application URLs
|
||||
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
||||
|
||||
# JWT
|
||||
JWT_SECRET=$(openssl rand -base64 32)
|
||||
JWT_EXPIRATION=24h
|
||||
```
|
||||
|
||||
## Step 3: Start Services
|
||||
|
||||
```bash
|
||||
# Start entire stack
|
||||
docker compose up -d
|
||||
|
||||
# View startup logs
|
||||
docker compose logs -f
|
||||
|
||||
# Check service status
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
**Services started:**
|
||||
|
||||
| Service | Container | Port | Purpose |
|
||||
|---------|-----------|------|---------|
|
||||
| API | mosaic-api | 3001 | NestJS backend |
|
||||
| Web | mosaic-web | 3000 | Next.js frontend |
|
||||
| PostgreSQL | mosaic-postgres | 5432 | Database |
|
||||
| Valkey | mosaic-valkey | 6379 | Cache |
|
||||
|
||||
## Step 4: Run Database Migrations
|
||||
|
||||
```bash
|
||||
# Enter API container
|
||||
docker compose exec api sh
|
||||
|
||||
# Run migrations
|
||||
pnpm prisma migrate deploy
|
||||
|
||||
# Seed development data (optional)
|
||||
pnpm prisma:seed
|
||||
|
||||
# Exit container
|
||||
exit
|
||||
```
|
||||
|
||||
## Step 5: Verify Deployment
|
||||
|
||||
### Check API Health
|
||||
|
||||
```bash
|
||||
curl http://localhost:3001/health
|
||||
```
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
# All services
|
||||
docker compose logs -f
|
||||
|
||||
# Specific service
|
||||
docker compose logs -f api
|
||||
|
||||
# Last 100 lines
|
||||
docker compose logs --tail=100 api
|
||||
```
|
||||
|
||||
### Access Containers
|
||||
|
||||
```bash
|
||||
# API container shell
|
||||
docker compose exec api sh
|
||||
|
||||
# PostgreSQL client
|
||||
docker compose exec postgres psql -U mosaic -d mosaic
|
||||
|
||||
# Redis CLI
|
||||
docker compose exec valkey redis-cli
|
||||
```
|
||||
|
||||
## Management Commands
|
||||
|
||||
### Start/Stop Services
|
||||
|
||||
```bash
|
||||
# Start all
|
||||
docker compose up -d
|
||||
|
||||
# Stop all
|
||||
docker compose stop
|
||||
|
||||
# Stop and remove containers
|
||||
docker compose down
|
||||
|
||||
# Stop and remove containers + volumes (WARNING: deletes data)
|
||||
docker compose down -v
|
||||
```
|
||||
|
||||
### Restart Services
|
||||
|
||||
```bash
|
||||
# Restart all
|
||||
docker compose restart
|
||||
|
||||
# Restart specific service
|
||||
docker compose restart api
|
||||
```
|
||||
|
||||
### View Service Status
|
||||
|
||||
```bash
|
||||
# List running containers
|
||||
docker compose ps
|
||||
|
||||
# View resource usage
|
||||
docker stats
|
||||
|
||||
# View logs
|
||||
docker compose logs -f [service_name]
|
||||
```
|
||||
|
||||
### Rebuild After Code Changes
|
||||
|
||||
```bash
|
||||
# Rebuild and restart
|
||||
docker compose up -d --build
|
||||
|
||||
# Rebuild specific service
|
||||
docker compose build api
|
||||
docker compose up -d api
|
||||
```
|
||||
|
||||
## Production Deployment
|
||||
|
||||
### Environment Configuration
|
||||
|
||||
Create a production `.env` file:
|
||||
|
||||
```bash
|
||||
# Production database
|
||||
DATABASE_URL=postgresql://user:pass@prod-db-host:5432/mosaic
|
||||
|
||||
# Production Redis
|
||||
REDIS_URL=redis://prod-redis-host:6379
|
||||
|
||||
# Production URLs
|
||||
NEXT_PUBLIC_APP_URL=https://mosaic.example.com
|
||||
|
||||
# Secure JWT secret
|
||||
JWT_SECRET=$(openssl rand -base64 64)
|
||||
JWT_EXPIRATION=24h
|
||||
|
||||
# Authentik OIDC
|
||||
OIDC_ISSUER=https://auth.example.com/application/o/mosaic/
|
||||
OIDC_CLIENT_ID=prod-client-id
|
||||
OIDC_CLIENT_SECRET=prod-client-secret
|
||||
OIDC_REDIRECT_URI=https://mosaic.example.com/auth/callback
|
||||
```
|
||||
|
||||
### Compose Override for Production
|
||||
|
||||
Create `docker-compose.prod.yml`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
api:
|
||||
restart: always
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
deploy:
|
||||
replicas: 2
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1.0'
|
||||
memory: 1G
|
||||
|
||||
web:
|
||||
restart: always
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
deploy:
|
||||
replicas: 2
|
||||
resources:
|
||||
limits:
|
||||
cpus: '0.5'
|
||||
memory: 512M
|
||||
```
|
||||
|
||||
**Deploy:**
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Containers Won't Start
|
||||
|
||||
```bash
|
||||
# Check logs for errors
|
||||
docker compose logs api
|
||||
docker compose logs postgres
|
||||
|
||||
# Check container status
|
||||
docker compose ps
|
||||
|
||||
# Restart specific service
|
||||
docker compose restart api
|
||||
```
|
||||
|
||||
### Database Connection Failed
|
||||
|
||||
```bash
|
||||
# Check PostgreSQL is running
|
||||
docker compose ps postgres
|
||||
|
||||
# Check PostgreSQL logs
|
||||
docker compose logs postgres
|
||||
|
||||
# Test connection from API container
|
||||
docker compose exec api sh
|
||||
nc -zv postgres 5432
|
||||
```
|
||||
|
||||
### Port Already in Use
|
||||
|
||||
```bash
|
||||
# Find what's using the port
|
||||
lsof -i :3001
|
||||
|
||||
# Kill the process or change port in docker-compose.yml
|
||||
```
|
||||
|
||||
### Out of Disk Space
|
||||
|
||||
```bash
|
||||
# Remove unused containers/images
|
||||
docker system prune -a
|
||||
|
||||
# Remove unused volumes (WARNING: may delete data)
|
||||
docker volume prune
|
||||
```
|
||||
|
||||
### Permission Errors
|
||||
|
||||
```bash
|
||||
# Add user to docker group
|
||||
sudo usermod -aG docker $USER
|
||||
|
||||
# Log out and back in, or
|
||||
newgrp docker
|
||||
```
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Resource Usage
|
||||
|
||||
```bash
|
||||
# Live resource stats
|
||||
docker stats
|
||||
|
||||
# Container logs
|
||||
docker compose logs -f --tail=100
|
||||
```
|
||||
|
||||
### Health Checks
|
||||
|
||||
```bash
|
||||
# API health endpoint
|
||||
curl http://localhost:3001/health
|
||||
|
||||
# PostgreSQL connection
|
||||
docker compose exec postgres pg_isready -U mosaic
|
||||
|
||||
# Redis ping
|
||||
docker compose exec valkey redis-cli ping
|
||||
```
|
||||
|
||||
## Updating
|
||||
|
||||
### Pull Latest Changes
|
||||
|
||||
```bash
|
||||
git pull origin develop
|
||||
|
||||
# Rebuild and restart
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
### Update Docker Images
|
||||
|
||||
```bash
|
||||
# Pull latest base images
|
||||
docker compose pull
|
||||
|
||||
# Rebuild
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
## Backup and Restore
|
||||
|
||||
### Database Backup
|
||||
|
||||
```bash
|
||||
# Backup database
|
||||
docker compose exec postgres pg_dump -U mosaic -d mosaic > backup-$(date +%Y%m%d).sql
|
||||
|
||||
# Restore database
|
||||
cat backup-20260128.sql | docker compose exec -T postgres psql -U mosaic -d mosaic
|
||||
```
|
||||
|
||||
### Volume Backup
|
||||
|
||||
```bash
|
||||
# Backup PostgreSQL volume
|
||||
docker run --rm \
|
||||
-v mosaic-stack_postgres-data:/data \
|
||||
-v $(pwd):/backup \
|
||||
alpine tar czf /backup/postgres-backup.tar.gz /data
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Configure Authentication** — [Authentik Setup](../3-configuration/2-authentik.md)
|
||||
2. **Monitor Logs** — Set up log aggregation for production
|
||||
3. **Set up Backups** — Automate database backups
|
||||
4. **Configure SSL** — Add reverse proxy (Traefik/Nginx) for HTTPS
|
||||
305
docs/1-getting-started/3-configuration/1-environment.md
Normal file
305
docs/1-getting-started/3-configuration/1-environment.md
Normal file
@@ -0,0 +1,305 @@
|
||||
# Environment Configuration
|
||||
|
||||
Complete reference for all environment variables in Mosaic Stack.
|
||||
|
||||
## Configuration File
|
||||
|
||||
All environment variables are defined in `.env` at the project root.
|
||||
|
||||
```bash
|
||||
# Copy template
|
||||
cp .env.example .env
|
||||
|
||||
# Edit configuration
|
||||
nano .env
|
||||
```
|
||||
|
||||
## Core Settings
|
||||
|
||||
### Database
|
||||
|
||||
```bash
|
||||
# PostgreSQL connection string
|
||||
DATABASE_URL=postgresql://user:password@host:port/database
|
||||
|
||||
# Examples:
|
||||
# Local: postgresql://mosaic:mosaic@localhost:5432/mosaic
|
||||
# Docker: postgresql://mosaic:mosaic@postgres:5432/mosaic
|
||||
# Production: postgresql://user:pass@prod-host:5432/mosaic
|
||||
```
|
||||
|
||||
**Format:** `postgresql://[user[:password]@][host][:port][/database][?options]`
|
||||
|
||||
### Application URLs
|
||||
|
||||
```bash
|
||||
# Frontend URL (used for CORS and redirects)
|
||||
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
||||
|
||||
# API URL (if different from default)
|
||||
API_URL=http://localhost:3001
|
||||
```
|
||||
|
||||
### Node Environment
|
||||
|
||||
```bash
|
||||
# Development, production, or test
|
||||
NODE_ENV=development
|
||||
|
||||
# API port (default: 3001)
|
||||
PORT=3001
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
### JWT Session Management
|
||||
|
||||
```bash
|
||||
# Secret key for signing JWT tokens (REQUIRED)
|
||||
# Generate with: openssl rand -base64 32
|
||||
JWT_SECRET=your-secret-key-here
|
||||
|
||||
# Token expiration time
|
||||
JWT_EXPIRATION=24h
|
||||
|
||||
# Accepted formats: 60 (seconds), 60s, 5m, 2h, 7d
|
||||
```
|
||||
|
||||
**⚠️ Security Warning:** Never commit `JWT_SECRET` to version control. Use a strong, randomly generated secret in production.
|
||||
|
||||
### Authentik OIDC (Optional)
|
||||
|
||||
```bash
|
||||
# Authentik instance URL with application path
|
||||
OIDC_ISSUER=https://auth.example.com/application/o/mosaic-stack/
|
||||
|
||||
# OAuth2 client credentials
|
||||
OIDC_CLIENT_ID=your-client-id
|
||||
OIDC_CLIENT_SECRET=your-client-secret
|
||||
|
||||
# Callback URL (must match Authentik configuration)
|
||||
OIDC_REDIRECT_URI=http://localhost:3001/auth/callback
|
||||
```
|
||||
|
||||
See [Authentik Setup](2-authentik.md) for complete OIDC configuration.
|
||||
|
||||
## Cache and Storage
|
||||
|
||||
### Redis/Valkey
|
||||
|
||||
```bash
|
||||
# Redis connection string
|
||||
REDIS_URL=redis://localhost:6379
|
||||
|
||||
# With password
|
||||
REDIS_URL=redis://:password@localhost:6379
|
||||
|
||||
# Docker
|
||||
REDIS_URL=redis://valkey:6379
|
||||
```
|
||||
|
||||
### File Storage (Future)
|
||||
|
||||
```bash
|
||||
# Local file storage path
|
||||
FILE_STORAGE_PATH=./storage/uploads
|
||||
|
||||
# S3-compatible storage
|
||||
S3_ENDPOINT=https://s3.amazonaws.com
|
||||
S3_BUCKET=mosaic-uploads
|
||||
S3_ACCESS_KEY=your-access-key
|
||||
S3_SECRET_KEY=your-secret-key
|
||||
```
|
||||
|
||||
## AI Features (Optional)
|
||||
|
||||
### Ollama
|
||||
|
||||
```bash
|
||||
# Local or remote Ollama instance
|
||||
OLLAMA_MODE=local # or 'remote'
|
||||
|
||||
# Ollama API endpoint
|
||||
OLLAMA_ENDPOINT=http://localhost:11434
|
||||
|
||||
# Default model for text generation
|
||||
OLLAMA_MODEL=llama2
|
||||
|
||||
# Default model for embeddings
|
||||
OLLAMA_EMBEDDING_MODEL=nomic-embed-text
|
||||
```
|
||||
|
||||
## Logging and Monitoring
|
||||
|
||||
### Log Level
|
||||
|
||||
```bash
|
||||
# Log verbosity: error, warn, info, debug, verbose
|
||||
LOG_LEVEL=info
|
||||
|
||||
# Production recommended: warn
|
||||
# Development recommended: debug
|
||||
```
|
||||
|
||||
### Sentry (Optional)
|
||||
|
||||
```bash
|
||||
# Sentry DSN for error tracking
|
||||
SENTRY_DSN=https://your-sentry-dsn@sentry.io/project-id
|
||||
|
||||
# Environment name
|
||||
SENTRY_ENVIRONMENT=production
|
||||
|
||||
# Release version
|
||||
SENTRY_RELEASE=v0.0.1
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
# Test database (separate from development)
|
||||
TEST_DATABASE_URL=postgresql://mosaic:mosaic@localhost:5432/mosaic_test
|
||||
|
||||
# Disable external services during testing
|
||||
SKIP_EXTERNAL_SERVICES=true
|
||||
```
|
||||
|
||||
## Development Tools
|
||||
|
||||
### Prisma
|
||||
|
||||
```bash
|
||||
# Prisma Studio port (default: 5555)
|
||||
PRISMA_STUDIO_PORT=5555
|
||||
|
||||
# Enable query logging
|
||||
PRISMA_LOG_QUERIES=true
|
||||
```
|
||||
|
||||
### Hot Reload
|
||||
|
||||
```bash
|
||||
# Disable hot reload (if causing issues)
|
||||
NO_WATCH=true
|
||||
|
||||
# Polling interval for file watching (ms)
|
||||
WATCH_POLL_INTERVAL=1000
|
||||
```
|
||||
|
||||
## Complete Example
|
||||
|
||||
**.env.example:**
|
||||
|
||||
```bash
|
||||
# ======================
|
||||
# Core Settings
|
||||
# ======================
|
||||
NODE_ENV=development
|
||||
PORT=3001
|
||||
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
||||
|
||||
# ======================
|
||||
# Database
|
||||
# ======================
|
||||
DATABASE_URL=postgresql://mosaic:mosaic@localhost:5432/mosaic
|
||||
TEST_DATABASE_URL=postgresql://mosaic:mosaic@localhost:5432/mosaic_test
|
||||
|
||||
# ======================
|
||||
# Authentication
|
||||
# ======================
|
||||
JWT_SECRET=change-this-to-a-random-secret-in-production
|
||||
JWT_EXPIRATION=24h
|
||||
|
||||
# Authentik OIDC (Optional)
|
||||
OIDC_ISSUER=https://auth.example.com/application/o/mosaic-stack/
|
||||
OIDC_CLIENT_ID=your-client-id
|
||||
OIDC_CLIENT_SECRET=your-client-secret
|
||||
OIDC_REDIRECT_URI=http://localhost:3001/auth/callback
|
||||
|
||||
# ======================
|
||||
# Cache
|
||||
# ======================
|
||||
REDIS_URL=redis://localhost:6379
|
||||
|
||||
# ======================
|
||||
# AI Features (Optional)
|
||||
# ======================
|
||||
OLLAMA_MODE=local
|
||||
OLLAMA_ENDPOINT=http://localhost:11434
|
||||
OLLAMA_MODEL=llama2
|
||||
OLLAMA_EMBEDDING_MODEL=nomic-embed-text
|
||||
|
||||
# ======================
|
||||
# Logging
|
||||
# ======================
|
||||
LOG_LEVEL=info
|
||||
|
||||
# ======================
|
||||
# Development
|
||||
# ======================
|
||||
PRISMA_STUDIO_PORT=5555
|
||||
PRISMA_LOG_QUERIES=false
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
Environment variables are validated at application startup. Missing required variables will cause the application to fail with a clear error message.
|
||||
|
||||
**Required variables:**
|
||||
- `DATABASE_URL`
|
||||
- `JWT_SECRET`
|
||||
- `NEXT_PUBLIC_APP_URL`
|
||||
|
||||
**Optional variables:**
|
||||
- All OIDC settings (if using Authentik)
|
||||
- All Ollama settings (if using AI features)
|
||||
- Logging and monitoring settings
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
1. **Never commit secrets** to version control
|
||||
2. **Use strong JWT secrets** (min 32 characters, randomly generated)
|
||||
3. **Rotate secrets regularly** in production
|
||||
4. **Use different secrets per environment** (dev, staging, prod)
|
||||
5. **Restrict database user permissions** in production
|
||||
6. **Enable SSL for database connections** in production
|
||||
7. **Use environment-specific .env files** (`.env.local`, `.env.production`)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Application Won't Start
|
||||
|
||||
```bash
|
||||
# Check for syntax errors in .env
|
||||
cat .env
|
||||
|
||||
# Ensure no quotes around values (unless they contain spaces)
|
||||
# ✅ Good: JWT_SECRET=abc123
|
||||
# ❌ Bad: JWT_SECRET="abc123"
|
||||
```
|
||||
|
||||
### Database Connection Failed
|
||||
|
||||
```bash
|
||||
# Test connection string
|
||||
psql "postgresql://mosaic:mosaic@localhost:5432/mosaic"
|
||||
|
||||
# Check if PostgreSQL is running
|
||||
sudo systemctl status postgresql
|
||||
```
|
||||
|
||||
### OIDC Authentication Fails
|
||||
|
||||
```bash
|
||||
# Verify OIDC_ISSUER ends with /
|
||||
# ✅ Good: https://auth.example.com/application/o/mosaic-stack/
|
||||
# ❌ Bad: https://auth.example.com/application/o/mosaic-stack
|
||||
|
||||
# Check OIDC_REDIRECT_URI matches Authentik configuration exactly
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- **Configure Authentik** — [Authentik Setup](2-authentik.md)
|
||||
- **Review Database Schema** — [Development → Database](../../2-development/2-database/1-schema.md)
|
||||
- **Start Development** — [Development → Workflow](../../2-development/1-workflow/1-branching.md)
|
||||
324
docs/1-getting-started/3-configuration/2-authentik.md
Normal file
324
docs/1-getting-started/3-configuration/2-authentik.md
Normal file
@@ -0,0 +1,324 @@
|
||||
# Authentik OIDC Setup
|
||||
|
||||
Complete guide to configuring Authentik OIDC authentication for Mosaic Stack.
|
||||
|
||||
## Overview
|
||||
|
||||
Mosaic Stack uses **BetterAuth** with **OpenID Connect (OIDC)** for authentication. Authentik serves as the identity provider for SSO capabilities.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Authentik instance (self-hosted or cloud)
|
||||
- Admin access to Authentik
|
||||
- Mosaic Stack installed and running
|
||||
|
||||
## Step 1: Install Authentik (Optional)
|
||||
|
||||
If you don't have an existing Authentik instance:
|
||||
|
||||
### Docker Compose Method
|
||||
|
||||
```bash
|
||||
# Create Authentik directory
|
||||
mkdir ~/authentik && cd ~/authentik
|
||||
|
||||
# Download compose file
|
||||
curl -o docker-compose.yml https://goauthentik.io/docker-compose.yml
|
||||
|
||||
# Generate secret key
|
||||
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60)" >> .env
|
||||
|
||||
# Start Authentik
|
||||
docker compose up -d
|
||||
|
||||
# Wait for startup (~30 seconds)
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
**Access Authentik:**
|
||||
- URL: http://localhost:9000/if/flow/initial-setup/
|
||||
- Create admin account during initial setup
|
||||
|
||||
### Alternative: Use Hosted Authentik
|
||||
|
||||
Sign up at [goauthentik.io](https://goauthentik.io) for managed Authentik.
|
||||
|
||||
## Step 2: Create OAuth2 Provider
|
||||
|
||||
1. **Log in to Authentik** as admin
|
||||
|
||||
2. **Navigate to Applications** → **Providers**
|
||||
|
||||
3. **Click "Create"** and select **OAuth2/OpenID Provider**
|
||||
|
||||
4. **Configure Provider:**
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Name** | Mosaic Stack |
|
||||
| **Authorization flow** | default-provider-authorization-implicit-consent |
|
||||
| **Client type** | Confidential |
|
||||
| **Client ID** | (auto-generated, save this) |
|
||||
| **Client Secret** | (auto-generated, save this) |
|
||||
| **Redirect URIs** | `http://localhost:3001/auth/callback` |
|
||||
| **Scopes** | `openid`, `email`, `profile` |
|
||||
| **Subject mode** | Based on User's UUID |
|
||||
| **Include claims in id_token** | ✅ Enabled |
|
||||
|
||||
5. **Click "Create"**
|
||||
|
||||
6. **Save** the Client ID and Client Secret for Step 4
|
||||
|
||||
## Step 3: Create Application
|
||||
|
||||
1. **Navigate to Applications** → **Applications**
|
||||
|
||||
2. **Click "Create"**
|
||||
|
||||
3. **Configure Application:**
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Name** | Mosaic Stack |
|
||||
| **Slug** | mosaic-stack |
|
||||
| **Provider** | Select "Mosaic Stack" (created in Step 2) |
|
||||
| **Launch URL** | `http://localhost:3000` |
|
||||
|
||||
4. **Click "Create"**
|
||||
|
||||
## Step 4: Configure Mosaic Stack
|
||||
|
||||
Update your `.env` file:
|
||||
|
||||
```bash
|
||||
# Authentik OIDC Configuration
|
||||
OIDC_ISSUER=http://localhost:9000/application/o/mosaic-stack/
|
||||
OIDC_CLIENT_ID=<your-client-id-from-step-2>
|
||||
OIDC_CLIENT_SECRET=<your-client-secret-from-step-2>
|
||||
OIDC_REDIRECT_URI=http://localhost:3001/auth/callback
|
||||
```
|
||||
|
||||
**Important Notes:**
|
||||
- `OIDC_ISSUER` must end with a trailing slash `/`
|
||||
- Replace `<your-client-id>` and `<your-client-secret>` with actual values from Step 2
|
||||
- `OIDC_REDIRECT_URI` must exactly match what you configured in Authentik
|
||||
|
||||
### Production Configuration
|
||||
|
||||
For production deployments:
|
||||
|
||||
```bash
|
||||
OIDC_ISSUER=https://auth.example.com/application/o/mosaic-stack/
|
||||
OIDC_CLIENT_ID=prod-client-id
|
||||
OIDC_CLIENT_SECRET=prod-client-secret
|
||||
OIDC_REDIRECT_URI=https://mosaic.example.com/auth/callback
|
||||
```
|
||||
|
||||
Update Authentik redirect URIs to match your production URL.
|
||||
|
||||
## Step 5: Restart Mosaic Stack
|
||||
|
||||
```bash
|
||||
# Local development
|
||||
pnpm dev:api
|
||||
|
||||
# Docker
|
||||
docker compose restart api
|
||||
```
|
||||
|
||||
## Step 6: Test Authentication
|
||||
|
||||
### Method 1: Web UI (when implemented)
|
||||
|
||||
1. Navigate to `http://localhost:3000`
|
||||
2. Click "Sign In"
|
||||
3. You'll be redirected to Authentik
|
||||
4. Log in with your Authentik credentials
|
||||
5. Authorize the application
|
||||
6. You'll be redirected back to Mosaic Stack
|
||||
|
||||
### Method 2: API Endpoint
|
||||
|
||||
```bash
|
||||
# Initiate OIDC flow
|
||||
curl http://localhost:3001/auth/callback/authentik
|
||||
|
||||
# This will return a redirect URL to Authentik
|
||||
```
|
||||
|
||||
### Method 3: Direct Email/Password (Development)
|
||||
|
||||
```bash
|
||||
# Create user via API (development only)
|
||||
curl -X POST http://localhost:3001/auth/sign-up \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"email": "test@example.com",
|
||||
"password": "SecurePass123!",
|
||||
"name": "Test User"
|
||||
}'
|
||||
|
||||
# Sign in
|
||||
curl -X POST http://localhost:3001/auth/sign-in \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"email": "test@example.com",
|
||||
"password": "SecurePass123!"
|
||||
}'
|
||||
|
||||
# Response includes session token
|
||||
{
|
||||
"user": {
|
||||
"id": "...",
|
||||
"email": "test@example.com",
|
||||
"name": "Test User"
|
||||
},
|
||||
"session": {
|
||||
"token": "eyJhbGc...",
|
||||
"expiresAt": "..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Custom Scopes
|
||||
|
||||
To request additional user information:
|
||||
|
||||
1. In Authentik, navigate to **Customization** → **Property Mappings**
|
||||
2. Create custom **Scope Mapping**
|
||||
3. Add scope to provider configuration
|
||||
4. Update Mosaic Stack to request the scope
|
||||
|
||||
### Multi-Factor Authentication (MFA)
|
||||
|
||||
Enable MFA in Authentik:
|
||||
|
||||
1. **Navigate to Flows & Stages** → **Flows**
|
||||
2. Edit **default-authentication-flow**
|
||||
3. Add **Multi-Factor Authentication** stage
|
||||
4. Configure MFA methods (TOTP, WebAuthn, etc.)
|
||||
|
||||
Users will be prompted for MFA during login.
|
||||
|
||||
### Custom Login Page
|
||||
|
||||
Customize Authentik's login page:
|
||||
|
||||
1. **Navigate to Customization** → **Brands**
|
||||
2. Edit default brand
|
||||
3. Customize logo, title, and theme
|
||||
4. Save changes
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Error: "Invalid redirect URI"
|
||||
|
||||
**Cause:** Redirect URI in `.env` doesn't match Authentik configuration
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
# Ensure exact match (including http vs https)
|
||||
# In Authentik: http://localhost:3001/auth/callback
|
||||
# In .env: OIDC_REDIRECT_URI=http://localhost:3001/auth/callback
|
||||
```
|
||||
|
||||
### Error: "Invalid client credentials"
|
||||
|
||||
**Cause:** Incorrect client ID or secret
|
||||
|
||||
**Fix:**
|
||||
1. Double-check Client ID and Secret in Authentik provider
|
||||
2. Copy values exactly (no extra spaces)
|
||||
3. Update `.env` with correct values
|
||||
4. Restart API
|
||||
|
||||
### Error: "OIDC discovery failed"
|
||||
|
||||
**Cause:** `OIDC_ISSUER` incorrect or Authentik not accessible
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
# Ensure OIDC_ISSUER ends with /
|
||||
# Test discovery endpoint
|
||||
curl http://localhost:9000/application/o/mosaic-stack/.well-known/openid-configuration
|
||||
|
||||
# Should return JSON with OIDC configuration
|
||||
```
|
||||
|
||||
### Users Can't Access Application
|
||||
|
||||
**Cause:** User doesn't have permission in Authentik
|
||||
|
||||
**Fix:**
|
||||
1. In Authentik, go to **Directory** → **Users**
|
||||
2. Select user
|
||||
3. Click **Assigned to applications**
|
||||
4. Add "Mosaic Stack" application
|
||||
|
||||
Or enable **Superuser privileges** for the user (development only).
|
||||
|
||||
### Session Expires Too Quickly
|
||||
|
||||
**Cause:** JWT expiration set too low
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
# In .env, increase expiration
|
||||
JWT_EXPIRATION=7d # 7 days instead of 24h
|
||||
|
||||
# Restart API
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Production Checklist
|
||||
|
||||
- [ ] Use HTTPS for all URLs
|
||||
- [ ] Configure CORS properly
|
||||
- [ ] Use strong client secret (rotate regularly)
|
||||
- [ ] Enable MFA for admin accounts
|
||||
- [ ] Review Authentik audit logs regularly
|
||||
- [ ] Limit redirect URIs to exact matches
|
||||
- [ ] Use environment-specific client credentials
|
||||
- [ ] Enable rate limiting on auth endpoints
|
||||
|
||||
### Recommended Authentik Settings
|
||||
|
||||
```yaml
|
||||
# In Authentik provider configuration:
|
||||
- Access token validity: 30 minutes
|
||||
- Refresh token validity: 30 days
|
||||
- Include claims in ID token: Enabled
|
||||
- Subject mode: Based on User's UUID
|
||||
- Signing algorithm: RS256
|
||||
```
|
||||
|
||||
## User Management
|
||||
|
||||
### Create User in Authentik
|
||||
|
||||
1. **Navigate to Directory** → **Users**
|
||||
2. **Click "Create"**
|
||||
3. Fill in user details:
|
||||
- Username
|
||||
- Email (required for OIDC)
|
||||
- Name
|
||||
4. **Click "Create"**
|
||||
5. User can now log in to Mosaic Stack
|
||||
|
||||
### Assign Users to Application
|
||||
|
||||
1. Go to **Applications** → **Applications**
|
||||
2. Select "Mosaic Stack"
|
||||
3. Click **Policy / Group / User Bindings**
|
||||
4. **Click "Bind existing policy"**
|
||||
5. Select users or groups
|
||||
6. **Click "Create"**
|
||||
|
||||
## Next Steps
|
||||
|
||||
- **Review Authentication Flow** — [Architecture → Authentication](../../3-architecture/2-authentication/1-betterauth.md)
|
||||
- **Start Development** — [Development → Workflow](../../2-development/1-workflow/1-branching.md)
|
||||
- **Explore API** — [API → Authentication](../../4-api/2-authentication/1-endpoints.md)
|
||||
23
docs/1-getting-started/README.md
Normal file
23
docs/1-getting-started/README.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Getting Started
|
||||
|
||||
Complete guide to getting Mosaic Stack installed and configured.
|
||||
|
||||
## Chapters
|
||||
|
||||
1. **Quick Start** — Get up and running in 5 minutes
|
||||
2. **Installation** — Detailed installation instructions for different environments
|
||||
3. **Configuration** — Environment setup and authentication configuration
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, ensure you have:
|
||||
- Node.js 20+ and pnpm 9+
|
||||
- PostgreSQL 17+ (or Docker)
|
||||
- Basic familiarity with TypeScript and NestJS
|
||||
|
||||
## Next Steps
|
||||
|
||||
After completing this book, proceed to:
|
||||
- **Development** — Learn the development workflow
|
||||
- **Architecture** — Understand the system design
|
||||
- **API** — Explore the API documentation
|
||||
276
docs/2-development/1-workflow/1-branching.md
Normal file
276
docs/2-development/1-workflow/1-branching.md
Normal file
@@ -0,0 +1,276 @@
|
||||
# Branching Strategy
|
||||
|
||||
Git workflow and branching conventions for Mosaic Stack.
|
||||
|
||||
## Branch Types
|
||||
|
||||
### Main Branches
|
||||
|
||||
**`main`** — Production-ready code only
|
||||
- Never commit directly
|
||||
- Only merge from `develop` via release
|
||||
- Tagged with version numbers
|
||||
|
||||
**`develop`** — Active development (default branch)
|
||||
- All features merge here first
|
||||
- Must always build and pass tests
|
||||
- Protected branch
|
||||
|
||||
### Supporting Branches
|
||||
|
||||
**`feature/*`** — New features
|
||||
```bash
|
||||
# From: develop
|
||||
# Merge to: develop
|
||||
# Naming: feature/issue-number-description
|
||||
|
||||
git checkout develop
|
||||
git pull --rebase
|
||||
git checkout -b feature/6-frontend-auth
|
||||
```
|
||||
|
||||
**`fix/*`** — Bug fixes
|
||||
```bash
|
||||
# From: develop (or main for hotfixes)
|
||||
# Merge to: develop (or both main and develop)
|
||||
# Naming: fix/issue-number-description
|
||||
|
||||
git checkout develop
|
||||
git checkout -b fix/12-session-timeout
|
||||
```
|
||||
|
||||
**`refactor/*`** — Code improvements
|
||||
```bash
|
||||
# From: develop
|
||||
# Merge to: develop
|
||||
# Naming: refactor/area-description
|
||||
|
||||
git checkout -b refactor/auth-service-cleanup
|
||||
```
|
||||
|
||||
**`docs/*`** — Documentation updates
|
||||
```bash
|
||||
# From: develop
|
||||
# Merge to: develop
|
||||
# Naming: docs/topic
|
||||
|
||||
git checkout -b docs/api-reference
|
||||
```
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Start New Work
|
||||
|
||||
```bash
|
||||
# Always start from latest develop
|
||||
git checkout develop
|
||||
git pull --rebase
|
||||
|
||||
# Create feature branch
|
||||
git checkout -b feature/7-task-management
|
||||
|
||||
# Optional: Use git worktree for parallel work
|
||||
git worktree add ../mosaic-stack_worktrees/7-task-management -b feature/7-task-management
|
||||
```
|
||||
|
||||
### 2. Make Changes
|
||||
|
||||
```bash
|
||||
# Make changes, write tests first (TDD)
|
||||
# Build and test after each change
|
||||
pnpm test
|
||||
pnpm build
|
||||
|
||||
# Commit frequently with conventional format
|
||||
git add .
|
||||
git commit -m "feat(#7): Add task creation endpoint"
|
||||
```
|
||||
|
||||
### 3. Stay Updated
|
||||
|
||||
```bash
|
||||
# Regularly sync with develop
|
||||
git checkout develop
|
||||
git pull --rebase
|
||||
git checkout feature/7-task-management
|
||||
git rebase develop
|
||||
|
||||
# Resolve conflicts if any
|
||||
```
|
||||
|
||||
### 4. Push Changes
|
||||
|
||||
```bash
|
||||
# Push feature branch
|
||||
git push -u origin feature/7-task-management
|
||||
```
|
||||
|
||||
### 5. Create Pull Request
|
||||
|
||||
```bash
|
||||
# Use git.mosaicstack.dev web UI or
|
||||
pr-create.sh -t "Implement task management" \
|
||||
-b "Adds full CRUD for tasks with tests" \
|
||||
-i 7
|
||||
|
||||
# Or with gh CLI
|
||||
gh pr create --title "feat(#7): Implement task management" \
|
||||
--body "Full task management implementation..." \
|
||||
--base develop \
|
||||
--head feature/7-task-management
|
||||
```
|
||||
|
||||
### 6. Code Review
|
||||
|
||||
- All PRs require review before merge
|
||||
- Address review comments
|
||||
- Keep commits clean (squash if messy)
|
||||
|
||||
### 7. Merge
|
||||
|
||||
```bash
|
||||
# After approval, squash and merge
|
||||
pr-merge.sh -n 7 -m squash -d
|
||||
|
||||
# Or via web UI: "Squash and Merge"
|
||||
```
|
||||
|
||||
## Commit Message Format
|
||||
|
||||
```
|
||||
<type>(#issue): Brief description
|
||||
|
||||
Detailed explanation if needed.
|
||||
|
||||
Fixes #123
|
||||
```
|
||||
|
||||
### Types
|
||||
|
||||
- `feat` — New feature
|
||||
- `fix` — Bug fix
|
||||
- `docs` — Documentation
|
||||
- `test` — Test additions/changes
|
||||
- `refactor` — Code restructuring
|
||||
- `chore` — Maintenance tasks
|
||||
- `perf` — Performance improvements
|
||||
|
||||
### Examples
|
||||
|
||||
```bash
|
||||
feat(#7): Add task creation endpoint
|
||||
|
||||
Implements POST /api/tasks with validation and tests.
|
||||
Includes database migration for task table.
|
||||
|
||||
Fixes #7
|
||||
|
||||
---
|
||||
|
||||
fix(#12): Resolve session timeout issue
|
||||
|
||||
Sessions were expiring prematurely due to incorrect JWT config.
|
||||
Updated JWT_EXPIRATION to use proper time format.
|
||||
|
||||
Fixes #12
|
||||
|
||||
---
|
||||
|
||||
docs(#15): Add API authentication guide
|
||||
|
||||
Complete guide for auth endpoints with examples.
|
||||
|
||||
Refs #15
|
||||
```
|
||||
|
||||
## Protected Branch Rules
|
||||
|
||||
### `main` Branch
|
||||
|
||||
- No direct commits
|
||||
- Require PR approval
|
||||
- Require passing tests
|
||||
- Require up-to-date branch
|
||||
|
||||
### `develop` Branch
|
||||
|
||||
- No direct commits (use PRs)
|
||||
- Require passing tests
|
||||
- Auto-delete head branches after merge
|
||||
|
||||
## Git Worktrees
|
||||
|
||||
For working on multiple issues simultaneously:
|
||||
|
||||
```bash
|
||||
# Structure: {project_name}_worktrees/{issue-name}/
|
||||
mkdir ~/src/mosaic-stack_worktrees
|
||||
|
||||
# Create worktree for issue #7
|
||||
cd ~/src/mosaic-stack
|
||||
git worktree add ../mosaic-stack_worktrees/7-task-management -b feature/7-task-management
|
||||
|
||||
# Work in worktree
|
||||
cd ../mosaic-stack_worktrees/7-task-management
|
||||
# Make changes, commit, push
|
||||
|
||||
# List worktrees
|
||||
git worktree list
|
||||
|
||||
# Remove after merge
|
||||
git worktree remove ../mosaic-stack_worktrees/7-task-management
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Always start from `develop`**
|
||||
2. **Keep branches short-lived** (max 1-2 weeks)
|
||||
3. **Write tests first** (TDD approach)
|
||||
4. **Commit frequently** with clear messages
|
||||
5. **Rebase, don't merge** when syncing with develop
|
||||
6. **Squash commits** before merging PR
|
||||
7. **Delete branches** after merging
|
||||
8. **Reference issues** in all commits
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Conflicts During Rebase
|
||||
|
||||
```bash
|
||||
# Start rebase
|
||||
git rebase develop
|
||||
|
||||
# Conflicts occur
|
||||
# Edit conflicting files
|
||||
|
||||
# Mark as resolved
|
||||
git add <conflicted-files>
|
||||
git rebase --continue
|
||||
|
||||
# Or abort and try later
|
||||
git rebase --abort
|
||||
```
|
||||
|
||||
### Accidentally Committed to `develop`
|
||||
|
||||
```bash
|
||||
# Undo last commit (keep changes)
|
||||
git reset --soft HEAD~1
|
||||
|
||||
# Create proper feature branch
|
||||
git checkout -b feature/my-changes
|
||||
|
||||
# Commit again
|
||||
git commit -m "feat: My changes"
|
||||
|
||||
# Force-push develop back to origin (if already pushed)
|
||||
git checkout develop
|
||||
git reset --hard origin/develop
|
||||
git push --force
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- **Testing Requirements** — [Testing](2-testing.md)
|
||||
- **Commit Guidelines** — [Committing](3-committing.md)
|
||||
- **Database Migrations** — [Database](../2-database/2-migrations.md)
|
||||
336
docs/2-development/1-workflow/2-testing.md
Normal file
336
docs/2-development/1-workflow/2-testing.md
Normal file
@@ -0,0 +1,336 @@
|
||||
# Testing Requirements
|
||||
|
||||
Test-driven development standards and practices for Mosaic Stack.
|
||||
|
||||
## Testing Philosophy
|
||||
|
||||
- **Test-Driven Development (TDD)** — Write tests before implementation
|
||||
- **Minimum 85% coverage** for all new code
|
||||
- **All tests must pass** before PR approval
|
||||
- **No untested code** in production
|
||||
|
||||
## Test Types
|
||||
|
||||
### Unit Tests
|
||||
|
||||
Test individual functions and methods in isolation.
|
||||
|
||||
**Location:** `*.spec.ts` next to source file
|
||||
|
||||
**Example:**
|
||||
```typescript
|
||||
// apps/api/src/auth/auth.service.spec.ts
|
||||
describe('AuthService', () => {
|
||||
it('should create a session for valid user', async () => {
|
||||
const result = await authService.createSession(mockUser);
|
||||
expect(result.session.token).toBeDefined();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Integration Tests
|
||||
|
||||
Test interactions between components.
|
||||
|
||||
**Location:** `*.integration.spec.ts` in module directory
|
||||
|
||||
**Example:**
|
||||
```typescript
|
||||
// apps/api/src/auth/auth.integration.spec.ts
|
||||
describe('Auth Integration', () => {
|
||||
it('should complete full login flow', async () => {
|
||||
const login = await request(app.getHttpServer())
|
||||
.post('/auth/sign-in')
|
||||
.send({ email, password });
|
||||
expect(login.status).toBe(200);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### E2E Tests
|
||||
|
||||
Test complete user flows across the entire stack.
|
||||
|
||||
**Location:** `apps/web/tests/e2e/` (when implemented)
|
||||
|
||||
**Framework:** Playwright
|
||||
|
||||
## Running Tests
|
||||
|
||||
```bash
|
||||
# All tests
|
||||
pnpm test
|
||||
|
||||
# Watch mode (re-run on changes)
|
||||
pnpm test:watch
|
||||
|
||||
# Coverage report
|
||||
pnpm test:coverage
|
||||
|
||||
# Specific file
|
||||
pnpm test apps/api/src/auth/auth.service.spec.ts
|
||||
|
||||
# API tests only
|
||||
pnpm test:api
|
||||
|
||||
# E2E tests (when implemented)
|
||||
pnpm test:e2e
|
||||
```
|
||||
|
||||
## Writing Tests
|
||||
|
||||
### Structure
|
||||
|
||||
```typescript
|
||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
||||
|
||||
describe('ComponentName', () => {
|
||||
beforeEach(() => {
|
||||
// Setup
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// Cleanup
|
||||
});
|
||||
|
||||
describe('methodName', () => {
|
||||
it('should handle normal case', () => {
|
||||
// Arrange
|
||||
const input = 'test';
|
||||
|
||||
// Act
|
||||
const result = component.method(input);
|
||||
|
||||
// Assert
|
||||
expect(result).toBe('expected');
|
||||
});
|
||||
|
||||
it('should handle error case', () => {
|
||||
expect(() => component.method(null)).toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Mocking
|
||||
|
||||
```typescript
|
||||
// Mock service dependency
|
||||
const mockPrismaService = {
|
||||
user: {
|
||||
findUnique: vi.fn(),
|
||||
create: vi.fn(),
|
||||
},
|
||||
};
|
||||
|
||||
// Mock module
|
||||
vi.mock('./some-module', () => ({
|
||||
someFunction: vi.fn(() => 'mocked'),
|
||||
}));
|
||||
```
|
||||
|
||||
### Testing Async Code
|
||||
|
||||
```typescript
|
||||
it('should complete async operation', async () => {
|
||||
const result = await asyncFunction();
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
|
||||
// Or with resolves/rejects
|
||||
it('should resolve with data', async () => {
|
||||
await expect(asyncFunction()).resolves.toBe('data');
|
||||
});
|
||||
|
||||
it('should reject with error', async () => {
|
||||
await expect(failingFunction()).rejects.toThrow('Error');
|
||||
});
|
||||
```
|
||||
|
||||
## Coverage Requirements
|
||||
|
||||
### Minimum Coverage
|
||||
|
||||
- **Statements:** 85%
|
||||
- **Branches:** 80%
|
||||
- **Functions:** 85%
|
||||
- **Lines:** 85%
|
||||
|
||||
### View Coverage Report
|
||||
|
||||
```bash
|
||||
pnpm test:coverage
|
||||
|
||||
# Opens HTML report
|
||||
open coverage/index.html
|
||||
```
|
||||
|
||||
### Exemptions
|
||||
|
||||
Some code types may have lower coverage requirements:
|
||||
- **DTOs/Interfaces:** No coverage required (type checking sufficient)
|
||||
- **Constants:** No coverage required
|
||||
- **Database migrations:** Manual verification acceptable
|
||||
|
||||
Always document exemptions in PR description.
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Test Behavior, Not Implementation
|
||||
|
||||
**❌ Bad:**
|
||||
```typescript
|
||||
it('should call getUserById', () => {
|
||||
service.login(email, password);
|
||||
expect(mockService.getUserById).toHaveBeenCalled();
|
||||
});
|
||||
```
|
||||
|
||||
**✅ Good:**
|
||||
```typescript
|
||||
it('should return session for valid credentials', async () => {
|
||||
const result = await service.login(email, password);
|
||||
expect(result.session.token).toBeDefined();
|
||||
expect(result.user.email).toBe(email);
|
||||
});
|
||||
```
|
||||
|
||||
### 2. Use Descriptive Test Names
|
||||
|
||||
**❌ Bad:**
|
||||
```typescript
|
||||
it('works', () => { ... });
|
||||
it('test 1', () => { ... });
|
||||
```
|
||||
|
||||
**✅ Good:**
|
||||
```typescript
|
||||
it('should return 401 for invalid credentials', () => { ... });
|
||||
it('should create session with 24h expiration', () => { ... });
|
||||
```
|
||||
|
||||
### 3. Arrange-Act-Assert Pattern
|
||||
|
||||
```typescript
|
||||
it('should calculate total correctly', () => {
|
||||
// Arrange - Set up test data
|
||||
const items = [{ price: 10 }, { price: 20 }];
|
||||
|
||||
// Act - Execute the code being tested
|
||||
const total = calculateTotal(items);
|
||||
|
||||
// Assert - Verify the result
|
||||
expect(total).toBe(30);
|
||||
});
|
||||
```
|
||||
|
||||
### 4. Test Edge Cases
|
||||
|
||||
```typescript
|
||||
describe('validateEmail', () => {
|
||||
it('should accept valid email', () => {
|
||||
expect(validateEmail('user@example.com')).toBe(true);
|
||||
});
|
||||
|
||||
it('should reject empty string', () => {
|
||||
expect(validateEmail('')).toBe(false);
|
||||
});
|
||||
|
||||
it('should reject null', () => {
|
||||
expect(validateEmail(null)).toBe(false);
|
||||
});
|
||||
|
||||
it('should reject invalid format', () => {
|
||||
expect(validateEmail('notanemail')).toBe(false);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 5. Keep Tests Independent
|
||||
|
||||
```typescript
|
||||
// ❌ Bad - Tests depend on order
|
||||
let userId;
|
||||
it('should create user', () => {
|
||||
userId = createUser();
|
||||
});
|
||||
it('should get user', () => {
|
||||
getUser(userId); // Fails if previous test fails
|
||||
});
|
||||
|
||||
// ✅ Good - Each test is independent
|
||||
it('should create user', () => {
|
||||
const userId = createUser();
|
||||
expect(userId).toBeDefined();
|
||||
});
|
||||
it('should get user', () => {
|
||||
const userId = createUser(); // Create fresh data
|
||||
const user = getUser(userId);
|
||||
expect(user).toBeDefined();
|
||||
});
|
||||
```
|
||||
|
||||
## CI/CD Integration
|
||||
|
||||
Tests run automatically on:
|
||||
- Every push to feature branch
|
||||
- Every pull request
|
||||
- Before merge to `develop`
|
||||
|
||||
**Pipeline must pass** before merging.
|
||||
|
||||
## Debugging Tests
|
||||
|
||||
### Run Single Test
|
||||
|
||||
```typescript
|
||||
it.only('should test specific case', () => {
|
||||
// Only this test runs
|
||||
});
|
||||
```
|
||||
|
||||
### Skip Test
|
||||
|
||||
```typescript
|
||||
it.skip('should test something', () => {
|
||||
// This test is skipped
|
||||
});
|
||||
```
|
||||
|
||||
### Verbose Output
|
||||
|
||||
```bash
|
||||
pnpm test --reporter=verbose
|
||||
```
|
||||
|
||||
### Debug in VS Code
|
||||
|
||||
Add to `.vscode/launch.json`:
|
||||
```json
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Vitest",
|
||||
"runtimeExecutable": "pnpm",
|
||||
"runtimeArgs": ["test", "--no-coverage"],
|
||||
"console": "integratedTerminal"
|
||||
}
|
||||
```
|
||||
|
||||
## Test Database
|
||||
|
||||
Use separate test database:
|
||||
|
||||
```bash
|
||||
# .env.test
|
||||
TEST_DATABASE_URL=postgresql://mosaic:mosaic@localhost:5432/mosaic_test
|
||||
|
||||
# Reset test DB before each run
|
||||
pnpm test:db:reset
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- **Review Commit Guidelines** — [Committing](3-committing.md)
|
||||
- **Learn Database Testing** — [Database](../2-database/3-prisma.md)
|
||||
- **Check Code Style** — [Google TypeScript Style Guide](https://google.github.io/styleguide/tsguide.html)
|
||||
25
docs/2-development/README.md
Normal file
25
docs/2-development/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Development
|
||||
|
||||
Developer guide for contributing to Mosaic Stack.
|
||||
|
||||
## Chapters
|
||||
|
||||
1. **Workflow** — Git workflow, branching strategy, and testing requirements
|
||||
2. **Database** — Schema design, migrations, and Prisma usage
|
||||
3. **Type Sharing** — Type sharing strategy across the monorepo
|
||||
|
||||
## Development Standards
|
||||
|
||||
- **Test Coverage:** Minimum 85% for new code
|
||||
- **TDD Approach:** Write tests before implementation
|
||||
- **Code Style:** Follow Google Style Guides
|
||||
- **Type Safety:** Everything must be properly typed
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Complete the **Getting Started** book before diving into development.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Read **Architecture** to understand the system design
|
||||
- Review **API** for endpoint conventions
|
||||
361
docs/3-architecture/3-design-principles/1-pda-friendly.md
Normal file
361
docs/3-architecture/3-design-principles/1-pda-friendly.md
Normal file
@@ -0,0 +1,361 @@
|
||||
# PDA-Friendly Design Principles
|
||||
|
||||
Mosaic Stack is designed to be calm, supportive, and stress-free. These principles are **non-negotiable**.
|
||||
|
||||
## Core Philosophy
|
||||
|
||||
> "A personal assistant should reduce stress, not create it."
|
||||
|
||||
We design for **pathological demand avoidance (PDA)** patterns, creating interfaces that:
|
||||
- Never pressure or demand
|
||||
- Provide gentle suggestions instead of commands
|
||||
- Use calm, neutral language
|
||||
- Avoid aggressive visual design
|
||||
|
||||
## Language Guidelines
|
||||
|
||||
### Never Use Demanding Language
|
||||
|
||||
| ❌ NEVER | ✅ ALWAYS |
|
||||
|----------|-----------|
|
||||
| OVERDUE | Target passed |
|
||||
| URGENT | Approaching target |
|
||||
| MUST DO | Scheduled for |
|
||||
| CRITICAL | High priority |
|
||||
| YOU NEED TO | Consider / Option to |
|
||||
| REQUIRED | Recommended |
|
||||
| DUE | Target date |
|
||||
| DEADLINE | Scheduled completion |
|
||||
|
||||
### Examples
|
||||
|
||||
**❌ Bad:**
|
||||
```
|
||||
URGENT: You have 3 overdue tasks!
|
||||
You MUST complete these today!
|
||||
```
|
||||
|
||||
**✅ Good:**
|
||||
```
|
||||
3 tasks have passed their target dates
|
||||
Would you like to reschedule or review them?
|
||||
```
|
||||
|
||||
**❌ Bad:**
|
||||
```
|
||||
CRITICAL ERROR: Database connection failed
|
||||
IMMEDIATE ACTION REQUIRED
|
||||
```
|
||||
|
||||
**✅ Good:**
|
||||
```
|
||||
Unable to connect to database
|
||||
Check configuration or contact support
|
||||
```
|
||||
|
||||
## Visual Design Principles
|
||||
|
||||
### 1. 10-Second Scannability
|
||||
|
||||
Users should understand key information in 10 seconds or less.
|
||||
|
||||
**Implementation:**
|
||||
- Most important info at top
|
||||
- Clear visual hierarchy
|
||||
- Minimal text per screen
|
||||
- Progressive disclosure (details on click)
|
||||
|
||||
**Example Dashboard:**
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ Today │
|
||||
│ ───── │
|
||||
│ 🟢 Morning review — 9:00 AM │
|
||||
│ 🔵 Team sync — 2:00 PM │
|
||||
│ │
|
||||
│ This Week │
|
||||
│ ───────── │
|
||||
│ 🔵 Project planning (3 days) │
|
||||
│ ⏸️ Research phase (on hold) │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2. Visual Chunking
|
||||
|
||||
Group related information with clear boundaries.
|
||||
|
||||
**Use:**
|
||||
- Whitespace between sections
|
||||
- Subtle borders or backgrounds
|
||||
- Clear section headers
|
||||
- Consistent spacing
|
||||
|
||||
**Don't:**
|
||||
- Jam everything together
|
||||
- Use wall-of-text layouts
|
||||
- Mix unrelated information
|
||||
- Create visual noise
|
||||
|
||||
### 3. Single-Line Items
|
||||
|
||||
Each list item should fit on one line for scanning.
|
||||
|
||||
**❌ Bad:**
|
||||
```
|
||||
Task: Complete the quarterly report including all financial data, team metrics, and project summaries. This is due next Friday and requires review from management before submission.
|
||||
```
|
||||
|
||||
**✅ Good:**
|
||||
```
|
||||
Complete quarterly report — Target: Friday
|
||||
```
|
||||
*(Details available on click)*
|
||||
|
||||
### 4. Calm Colors
|
||||
|
||||
No aggressive colors for status indicators.
|
||||
|
||||
**Status Colors:**
|
||||
- 🟢 **On track / Active** — Soft green (#10b981)
|
||||
- 🔵 **Upcoming / Scheduled** — Soft blue (#3b82f6)
|
||||
- ⏸️ **Paused / On hold** — Soft yellow (#f59e0b)
|
||||
- 💤 **Dormant / Inactive** — Soft gray (#6b7280)
|
||||
- ⚪ **Not started** — Light gray (#d1d5db)
|
||||
|
||||
**Never use:**
|
||||
- ❌ Aggressive red for "overdue"
|
||||
- ❌ Flashing or blinking elements
|
||||
- ❌ All-caps text for emphasis
|
||||
|
||||
### 5. Progressive Disclosure
|
||||
|
||||
Show summary first, details on demand.
|
||||
|
||||
**Example:**
|
||||
```
|
||||
[Card View - Default]
|
||||
─────────────────────────
|
||||
Project Alpha
|
||||
12 tasks · 3 approaching targets
|
||||
🟢 Active
|
||||
─────────────────────────
|
||||
[Click to expand]
|
||||
|
||||
[Expanded View - On Click]
|
||||
─────────────────────────
|
||||
Project Alpha
|
||||
Description: ...
|
||||
Created: Jan 15, 2026
|
||||
Owner: Jane Doe
|
||||
|
||||
Tasks (12):
|
||||
- Setup environment ✓
|
||||
- Design mockups ✓
|
||||
- Implement API (target passed 2 days)
|
||||
[Show all tasks]
|
||||
─────────────────────────
|
||||
```
|
||||
|
||||
## Implementation Guidelines
|
||||
|
||||
### Date Display
|
||||
|
||||
**Relative dates for recent items:**
|
||||
```
|
||||
Just now
|
||||
5 minutes ago
|
||||
2 hours ago
|
||||
Yesterday at 3:00 PM
|
||||
Monday at 10:00 AM
|
||||
Jan 15 at 9:00 AM
|
||||
```
|
||||
|
||||
**Never:**
|
||||
```
|
||||
2026-01-28T14:30:00.000Z ❌ (ISO format in UI)
|
||||
```
|
||||
|
||||
### Task Status Indicators
|
||||
|
||||
```typescript
|
||||
// Don't say "overdue"
|
||||
const getTaskStatus = (task: Task) => {
|
||||
if (isPastTarget(task)) {
|
||||
return {
|
||||
label: 'Target passed',
|
||||
icon: '⏸️',
|
||||
color: 'yellow',
|
||||
};
|
||||
}
|
||||
// ...
|
||||
};
|
||||
```
|
||||
|
||||
### Notifications
|
||||
|
||||
**❌ Aggressive:**
|
||||
```
|
||||
⚠️ ATTENTION: 5 OVERDUE TASKS
|
||||
You must complete these immediately!
|
||||
```
|
||||
|
||||
**✅ Calm:**
|
||||
```
|
||||
💭 5 tasks have passed their targets
|
||||
Would you like to review or reschedule?
|
||||
```
|
||||
|
||||
### Empty States
|
||||
|
||||
**❌ Negative:**
|
||||
```
|
||||
No tasks found!
|
||||
You haven't created any tasks yet.
|
||||
```
|
||||
|
||||
**✅ Positive:**
|
||||
```
|
||||
All caught up! 🎉
|
||||
Ready to add your first task?
|
||||
```
|
||||
|
||||
## UI Component Examples
|
||||
|
||||
### Task Card
|
||||
|
||||
```jsx
|
||||
<TaskCard>
|
||||
<TaskTitle>Review project proposal</TaskTitle>
|
||||
<TaskMeta>
|
||||
<Status icon="🟢">Active</Status>
|
||||
<Target>Target: Tomorrow at 2 PM</Target>
|
||||
</TaskMeta>
|
||||
<TaskActions>
|
||||
<Button variant="ghost">Reschedule</Button>
|
||||
<Button variant="ghost">Complete</Button>
|
||||
</TaskActions>
|
||||
</TaskCard>
|
||||
```
|
||||
|
||||
### Notification Toast
|
||||
|
||||
```jsx
|
||||
<Toast variant="info">
|
||||
<ToastIcon>💭</ToastIcon>
|
||||
<ToastContent>
|
||||
<ToastTitle>Approaching target</ToastTitle>
|
||||
<ToastMessage>
|
||||
"Team sync" is scheduled in 30 minutes
|
||||
</ToastMessage>
|
||||
</ToastContent>
|
||||
<ToastAction>
|
||||
<Button>View</Button>
|
||||
<Button>Dismiss</Button>
|
||||
</ToastAction>
|
||||
</Toast>
|
||||
```
|
||||
|
||||
## Testing for PDA-Friendliness
|
||||
|
||||
### Checklist
|
||||
|
||||
- [ ] No words like "overdue", "urgent", "must", "required"
|
||||
- [ ] Status indicators use calm colors (no aggressive red)
|
||||
- [ ] All-caps text removed (except acronyms)
|
||||
- [ ] Key info visible within 10 seconds
|
||||
- [ ] List items fit on single line
|
||||
- [ ] Details hidden behind "show more" or click
|
||||
- [ ] Notifications are gentle suggestions, not demands
|
||||
- [ ] Empty states are positive, not negative
|
||||
|
||||
### Review Process
|
||||
|
||||
Every UI change must be reviewed for PDA-friendliness:
|
||||
|
||||
1. **Self-review** using checklist
|
||||
2. **Peer review** for language and tone
|
||||
3. **User testing** with PDA individuals (if possible)
|
||||
|
||||
## Copy Guidelines
|
||||
|
||||
### Microcopy
|
||||
|
||||
**Buttons:**
|
||||
- "View details" not "Click here"
|
||||
- "Reschedule" not "Change deadline"
|
||||
- "Complete" not "Mark as done"
|
||||
|
||||
**Headers:**
|
||||
- "Approaching targets" not "Overdue items"
|
||||
- "High priority" not "Critical tasks"
|
||||
- "On hold" not "Blocked"
|
||||
|
||||
**Instructions:**
|
||||
- "Consider adding a note" not "You must add a note"
|
||||
- "Optional: Set a reminder" not "Set a reminder"
|
||||
|
||||
### Error Messages
|
||||
|
||||
**❌ Blaming:**
|
||||
```
|
||||
Error: You entered an invalid email address
|
||||
```
|
||||
|
||||
**✅ Helpful:**
|
||||
```
|
||||
Email format not recognized
|
||||
Try: user@example.com
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
PDA-friendly design overlaps with accessibility:
|
||||
|
||||
- High contrast (but not aggressive colors)
|
||||
- Clear focus indicators
|
||||
- Descriptive labels
|
||||
- Keyboard navigation
|
||||
- Screen reader friendly
|
||||
|
||||
See [WCAG 2.1 Level AA](https://www.w3.org/WAI/WCAG21/quickref/) for complete accessibility guidelines.
|
||||
|
||||
## Resources
|
||||
|
||||
- Original inspiration: `jarvis-brain/docs/DESIGN-PRINCIPLES.md`
|
||||
- Color palette: [Tailwind CSS Colors](https://tailwindcss.com/docs/customizing-colors)
|
||||
- Icon set: Unicode emojis (universal support)
|
||||
|
||||
## Examples from Codebase
|
||||
|
||||
### Good Example: Task List
|
||||
|
||||
```tsx
|
||||
// apps/web/components/TaskList.tsx
|
||||
<div className="space-y-2">
|
||||
<h2 className="text-lg font-medium text-gray-900">
|
||||
Today
|
||||
</h2>
|
||||
{tasks.map(task => (
|
||||
<TaskCard key={task.id}>
|
||||
<div className="flex items-center gap-2">
|
||||
<StatusBadge status={task.status} />
|
||||
<span className="text-gray-900">{task.title}</span>
|
||||
</div>
|
||||
{task.targetDate && isPastTarget(task) && (
|
||||
<span className="text-sm text-yellow-600">
|
||||
Target passed {formatRelative(task.targetDate)}
|
||||
</span>
|
||||
)}
|
||||
</TaskCard>
|
||||
))}
|
||||
</div>
|
||||
```
|
||||
|
||||
## Enforcement
|
||||
|
||||
- **Code reviews** check for PDA violations
|
||||
- **Linting rules** catch forbidden words
|
||||
- **Design review** before major UI changes
|
||||
- **User feedback** incorporated regularly
|
||||
|
||||
**This is non-negotiable.** If in doubt, make it calmer.
|
||||
29
docs/3-architecture/README.md
Normal file
29
docs/3-architecture/README.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Architecture
|
||||
|
||||
Technical architecture and design principles for Mosaic Stack.
|
||||
|
||||
## Chapters
|
||||
|
||||
1. **Overview** — System design and component architecture
|
||||
2. **Authentication** — BetterAuth integration and OIDC flow
|
||||
3. **Design Principles** — PDA-friendly patterns and UX guidelines
|
||||
|
||||
## Architecture Principles
|
||||
|
||||
- **Type Safety First:** Shared types prevent frontend/backend drift
|
||||
- **Multi-Tenant Ready:** Row-level security with workspace isolation
|
||||
- **PDA-Friendly:** Calm, stress-free language and visual design
|
||||
- **Modular:** Plugin architecture for extensibility
|
||||
|
||||
## Technology Decisions
|
||||
|
||||
Key architectural choices and their rationale:
|
||||
- **BetterAuth** over Passport.js for modern authentication
|
||||
- **Prisma ORM** for type-safe database access
|
||||
- **Monorepo** with pnpm workspaces for code sharing
|
||||
- **PostgreSQL + pgvector** for AI-ready data storage
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Review **API** for implementation details
|
||||
- Check **Development** for workflow standards
|
||||
319
docs/4-api/1-conventions/1-endpoints.md
Normal file
319
docs/4-api/1-conventions/1-endpoints.md
Normal file
@@ -0,0 +1,319 @@
|
||||
# API Endpoint Conventions
|
||||
|
||||
Standard patterns for all Mosaic Stack API endpoints.
|
||||
|
||||
## Base URL
|
||||
|
||||
- **Development:** `http://localhost:3001`
|
||||
- **Production:** `https://api.example.com`
|
||||
|
||||
## Standard REST Endpoints
|
||||
|
||||
```
|
||||
GET /api/{resource} # List resources (with pagination)
|
||||
GET /api/{resource}/:id # Get single resource
|
||||
POST /api/{resource} # Create new resource
|
||||
PATCH /api/{resource}/:id # Update resource (partial)
|
||||
PUT /api/{resource}/:id # Replace resource (full)
|
||||
DELETE /api/{resource}/:id # Delete resource
|
||||
```
|
||||
|
||||
## Response Format
|
||||
|
||||
### Success Response
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"id": "uuid",
|
||||
"name": "Example",
|
||||
"createdAt": "2026-01-28T12:00:00.000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### List Response (with pagination)
|
||||
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{ "id": "1", "name": "Item 1" },
|
||||
{ "id": "2", "name": "Item 2" }
|
||||
],
|
||||
"meta": {
|
||||
"total": 50,
|
||||
"page": 1,
|
||||
"limit": 10,
|
||||
"totalPages": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Error Response
|
||||
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"code": "VALIDATION_ERROR",
|
||||
"message": "Invalid input data",
|
||||
"details": {
|
||||
"email": "Invalid email format"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## HTTP Status Codes
|
||||
|
||||
| Code | Meaning | Usage |
|
||||
|------|---------|-------|
|
||||
| 200 | OK | Successful GET, PATCH, PUT |
|
||||
| 201 | Created | Successful POST |
|
||||
| 204 | No Content | Successful DELETE |
|
||||
| 400 | Bad Request | Invalid input |
|
||||
| 401 | Unauthorized | Missing/invalid auth token |
|
||||
| 403 | Forbidden | Valid token, insufficient permissions |
|
||||
| 404 | Not Found | Resource doesn't exist |
|
||||
| 409 | Conflict | Resource already exists |
|
||||
| 422 | Unprocessable Entity | Validation failed |
|
||||
| 500 | Internal Server Error | Server error |
|
||||
|
||||
## Pagination
|
||||
|
||||
All list endpoints support pagination via query parameters:
|
||||
|
||||
```
|
||||
GET /api/tasks?page=1&limit=20
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `page` — Page number (default: 1)
|
||||
- `limit` — Items per page (default: 10, max: 100)
|
||||
|
||||
**Response includes:**
|
||||
```json
|
||||
{
|
||||
"data": [...],
|
||||
"meta": {
|
||||
"total": 150,
|
||||
"page": 1,
|
||||
"limit": 20,
|
||||
"totalPages": 8
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Filtering
|
||||
|
||||
Use query parameters for filtering:
|
||||
|
||||
```
|
||||
GET /api/tasks?status=active&priority=high
|
||||
GET /api/events?start_date=2026-01-01&end_date=2026-01-31
|
||||
```
|
||||
|
||||
**Supported operators:**
|
||||
- `=` — Equals
|
||||
- `_gt` — Greater than (e.g., `created_at_gt=2026-01-01`)
|
||||
- `_lt` — Less than
|
||||
- `_gte` — Greater than or equal
|
||||
- `_lte` — Less than or equal
|
||||
- `_in` — In array (e.g., `status_in=active,pending`)
|
||||
|
||||
## Sorting
|
||||
|
||||
Use `sort` parameter:
|
||||
|
||||
```
|
||||
GET /api/tasks?sort=created_at # Ascending
|
||||
GET /api/tasks?sort=-created_at # Descending (minus prefix)
|
||||
GET /api/tasks?sort=-priority,created_at # Multiple fields
|
||||
```
|
||||
|
||||
## Field Selection
|
||||
|
||||
Request specific fields to reduce payload size:
|
||||
|
||||
```
|
||||
GET /api/tasks?fields=id,title,status
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{ "id": "1", "title": "Task 1", "status": "active" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Relationships
|
||||
|
||||
Include related resources:
|
||||
|
||||
```
|
||||
GET /api/tasks?include=assignee,project
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"id": "1",
|
||||
"title": "Task 1",
|
||||
"assignee": {
|
||||
"id": "user-1",
|
||||
"name": "John Doe"
|
||||
},
|
||||
"project": {
|
||||
"id": "proj-1",
|
||||
"name": "Project Alpha"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
All authenticated endpoints require Bearer token:
|
||||
|
||||
```http
|
||||
Authorization: Bearer {session_token}
|
||||
```
|
||||
|
||||
See [Authentication Endpoints](../2-authentication/1-endpoints.md) for details.
|
||||
|
||||
## Request Headers
|
||||
|
||||
**Required:**
|
||||
```http
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**Optional:**
|
||||
```http
|
||||
Authorization: Bearer {token}
|
||||
X-Workspace-ID: {workspace-uuid} # For multi-tenant requests
|
||||
```
|
||||
|
||||
## Validation Errors
|
||||
|
||||
Validation errors return 422 with detailed field errors:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"code": "VALIDATION_ERROR",
|
||||
"message": "Input validation failed",
|
||||
"details": {
|
||||
"email": "Invalid email format",
|
||||
"password": "Must be at least 8 characters"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
API endpoints are rate-limited:
|
||||
|
||||
- **Anonymous:** 60 requests/hour
|
||||
- **Authenticated:** 1000 requests/hour
|
||||
|
||||
**Rate limit headers:**
|
||||
```http
|
||||
X-RateLimit-Limit: 1000
|
||||
X-RateLimit-Remaining: 950
|
||||
X-RateLimit-Reset: 1643723400
|
||||
```
|
||||
|
||||
When exceeded, returns 429 Too Many Requests.
|
||||
|
||||
## CORS
|
||||
|
||||
CORS is configured for frontend origin:
|
||||
|
||||
```javascript
|
||||
// Allowed origins
|
||||
const origins = [
|
||||
process.env.NEXT_PUBLIC_APP_URL,
|
||||
'http://localhost:3000',
|
||||
'http://localhost:3001'
|
||||
];
|
||||
```
|
||||
|
||||
## Versioning
|
||||
|
||||
Currently v1 (implicit). Future versions will use URL versioning:
|
||||
|
||||
```
|
||||
/api/v2/tasks
|
||||
```
|
||||
|
||||
## Health Check
|
||||
|
||||
```
|
||||
GET /health
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"timestamp": "2026-01-28T12:00:00.000Z",
|
||||
"uptime": 123456
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Create Task
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3001/api/tasks \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer {token}" \
|
||||
-d '{
|
||||
"title": "Complete API documentation",
|
||||
"description": "Write comprehensive API docs",
|
||||
"priority": "high",
|
||||
"targetDate": "2026-01-30"
|
||||
}'
|
||||
```
|
||||
|
||||
**Response (201):**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"id": "task-uuid",
|
||||
"title": "Complete API documentation",
|
||||
"status": "pending",
|
||||
"priority": "high",
|
||||
"createdAt": "2026-01-28T12:00:00.000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### List Tasks with Filters
|
||||
|
||||
```bash
|
||||
curl "http://localhost:3001/api/tasks?status=active&sort=-created_at&limit=5" \
|
||||
-H "Authorization: Bearer {token}"
|
||||
```
|
||||
|
||||
### Update Task
|
||||
|
||||
```bash
|
||||
curl -X PATCH http://localhost:3001/api/tasks/task-uuid \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer {token}" \
|
||||
-d '{
|
||||
"status": "completed"
|
||||
}'
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- **Authentication** — [Authentication Endpoints](../2-authentication/1-endpoints.md)
|
||||
- **Type Definitions** — [API Types](../2-authentication/2-types.md)
|
||||
- **Implementation** — [Development Workflow](../../2-development/1-workflow/1-branching.md)
|
||||
393
docs/4-api/2-authentication/1-endpoints.md
Normal file
393
docs/4-api/2-authentication/1-endpoints.md
Normal file
@@ -0,0 +1,393 @@
|
||||
# Authentication Endpoints
|
||||
|
||||
Complete reference for authentication API endpoints powered by BetterAuth.
|
||||
|
||||
## Base URL
|
||||
|
||||
```
|
||||
http://localhost:3001/auth
|
||||
```
|
||||
|
||||
All authentication endpoints are prefixed with `/auth`.
|
||||
|
||||
## Endpoints
|
||||
|
||||
### Sign Up
|
||||
|
||||
Create a new user account with email and password.
|
||||
|
||||
```http
|
||||
POST /auth/sign-up
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"email": "user@example.com",
|
||||
"password": "SecurePass123!",
|
||||
"name": "John Doe"
|
||||
}
|
||||
```
|
||||
|
||||
**Response (201):**
|
||||
```json
|
||||
{
|
||||
"user": {
|
||||
"id": "user-uuid",
|
||||
"email": "user@example.com",
|
||||
"name": "John Doe",
|
||||
"emailVerified": false
|
||||
},
|
||||
"session": {
|
||||
"id": "session-uuid",
|
||||
"token": "eyJhbGciOiJIUzI1NiIs...",
|
||||
"expiresAt": "2026-01-29T12:00:00.000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `409 Conflict` — Email already exists
|
||||
- `422 Validation Error` — Invalid input
|
||||
|
||||
---
|
||||
|
||||
### Sign In
|
||||
|
||||
Authenticate with email and password.
|
||||
|
||||
```http
|
||||
POST /auth/sign-in
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"email": "user@example.com",
|
||||
"password": "SecurePass123!"
|
||||
}
|
||||
```
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"user": {
|
||||
"id": "user-uuid",
|
||||
"email": "user@example.com",
|
||||
"name": "John Doe"
|
||||
},
|
||||
"session": {
|
||||
"id": "session-uuid",
|
||||
"token": "eyJhbGciOiJIUzI1NiIs...",
|
||||
"expiresAt": "2026-01-29T12:00:00.000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized` — Invalid credentials
|
||||
|
||||
---
|
||||
|
||||
### Sign Out
|
||||
|
||||
Invalidate current session.
|
||||
|
||||
```http
|
||||
POST /auth/sign-out
|
||||
```
|
||||
|
||||
**Headers:**
|
||||
```http
|
||||
Authorization: Bearer {session_token}
|
||||
```
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Get Session
|
||||
|
||||
Retrieve current session information.
|
||||
|
||||
```http
|
||||
GET /auth/session
|
||||
```
|
||||
|
||||
**Headers:**
|
||||
```http
|
||||
Authorization: Bearer {session_token}
|
||||
```
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"user": {
|
||||
"id": "user-uuid",
|
||||
"email": "user@example.com",
|
||||
"name": "John Doe"
|
||||
},
|
||||
"session": {
|
||||
"id": "session-uuid",
|
||||
"expiresAt": "2026-01-29T12:00:00.000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized` — Invalid or expired session
|
||||
|
||||
---
|
||||
|
||||
### Get Profile
|
||||
|
||||
Get authenticated user's profile (custom endpoint).
|
||||
|
||||
```http
|
||||
GET /auth/profile
|
||||
```
|
||||
|
||||
**Headers:**
|
||||
```http
|
||||
Authorization: Bearer {session_token}
|
||||
```
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"id": "user-uuid",
|
||||
"email": "user@example.com",
|
||||
"name": "John Doe",
|
||||
"emailVerified": false
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized` — Not authenticated
|
||||
|
||||
---
|
||||
|
||||
### OIDC Callback
|
||||
|
||||
OAuth callback handler for Authentik (and other OIDC providers).
|
||||
|
||||
```http
|
||||
GET /auth/callback/authentik
|
||||
```
|
||||
|
||||
**Query Parameters:**
|
||||
- `code` — Authorization code from provider
|
||||
- `state` — CSRF protection token
|
||||
|
||||
This endpoint is called by the OIDC provider after successful authentication.
|
||||
|
||||
**Response:**
|
||||
- Redirects to frontend with session token
|
||||
|
||||
---
|
||||
|
||||
## Authentication Flow
|
||||
|
||||
### Email/Password Flow
|
||||
|
||||
```
|
||||
1. User submits credentials → POST /auth/sign-in
|
||||
2. Server validates credentials
|
||||
3. Server creates session
|
||||
4. Server returns session token
|
||||
5. Client stores token
|
||||
6. Client includes token in subsequent requests
|
||||
```
|
||||
|
||||
### OIDC Flow
|
||||
|
||||
```
|
||||
1. User clicks "Sign in with Authentik"
|
||||
2. Frontend redirects to Authentik
|
||||
3. User authenticates with Authentik
|
||||
4. Authentik redirects to /auth/callback/authentik
|
||||
5. Server exchanges code for tokens
|
||||
6. Server creates/updates user
|
||||
7. Server creates session
|
||||
8. Server redirects to frontend with session token
|
||||
```
|
||||
|
||||
## Using Session Tokens
|
||||
|
||||
Include the session token in the `Authorization` header for all authenticated requests:
|
||||
|
||||
```http
|
||||
GET /api/tasks
|
||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
|
||||
```
|
||||
|
||||
### Token Storage
|
||||
|
||||
**Frontend (Browser):**
|
||||
- Store in `httpOnly` cookie (most secure)
|
||||
- Or `localStorage` (less secure, XSS vulnerable)
|
||||
|
||||
**Mobile/Desktop:**
|
||||
- Secure storage (Keychain on iOS, KeyStore on Android)
|
||||
|
||||
### Token Expiration
|
||||
|
||||
Tokens expire after 24 hours (configurable via `JWT_EXPIRATION`).
|
||||
|
||||
**Check expiration:**
|
||||
```typescript
|
||||
import { AuthSession } from '@mosaic/shared';
|
||||
|
||||
const isExpired = (session: AuthSession) => {
|
||||
return new Date(session.session.expiresAt) < new Date();
|
||||
};
|
||||
```
|
||||
|
||||
**Refresh flow** (future implementation):
|
||||
```http
|
||||
POST /auth/refresh
|
||||
```
|
||||
|
||||
## Error Responses
|
||||
|
||||
### 401 Unauthorized
|
||||
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"code": "UNAUTHORIZED",
|
||||
"message": "Invalid or expired session token"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 422 Validation Error
|
||||
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"code": "VALIDATION_ERROR",
|
||||
"message": "Input validation failed",
|
||||
"details": {
|
||||
"email": "Invalid email format",
|
||||
"password": "Must be at least 8 characters"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Sign Up
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3001/auth/sign-up \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"email": "jane@example.com",
|
||||
"password": "SecurePass123!",
|
||||
"name": "Jane Doe"
|
||||
}'
|
||||
```
|
||||
|
||||
### Sign In
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3001/auth/sign-in \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"email": "jane@example.com",
|
||||
"password": "SecurePass123!"
|
||||
}'
|
||||
```
|
||||
|
||||
**Save the token from response:**
|
||||
```bash
|
||||
TOKEN=$(curl -X POST http://localhost:3001/auth/sign-in \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"email":"jane@example.com","password":"SecurePass123!"}' \
|
||||
| jq -r '.session.token')
|
||||
```
|
||||
|
||||
### Get Profile
|
||||
|
||||
```bash
|
||||
curl http://localhost:3001/auth/profile \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
### Sign Out
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3001/auth/sign-out \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Password Requirements
|
||||
|
||||
- Minimum 8 characters
|
||||
- At least one uppercase letter
|
||||
- At least one lowercase letter
|
||||
- At least one number
|
||||
|
||||
Configure in `apps/api/src/auth/auth.config.ts`.
|
||||
|
||||
### Rate Limiting
|
||||
|
||||
- Sign-up: 5 requests per hour per IP
|
||||
- Sign-in: 10 requests per hour per IP (prevents brute force)
|
||||
|
||||
### CSRF Protection
|
||||
|
||||
OIDC flow includes `state` parameter for CSRF protection.
|
||||
|
||||
### Token Security
|
||||
|
||||
- Tokens are signed with `JWT_SECRET`
|
||||
- Use strong secret (min 32 characters)
|
||||
- Rotate secret regularly in production
|
||||
- Never expose tokens in logs
|
||||
|
||||
## TypeScript Types
|
||||
|
||||
All authentication types are available from `@mosaic/shared`:
|
||||
|
||||
```typescript
|
||||
import type {
|
||||
AuthUser,
|
||||
AuthSession,
|
||||
LoginRequest,
|
||||
LoginResponse,
|
||||
} from '@mosaic/shared';
|
||||
|
||||
// Use in frontend
|
||||
const login = async (req: LoginRequest): Promise<AuthSession> => {
|
||||
const res = await fetch('/auth/sign-in', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(req),
|
||||
});
|
||||
return res.json();
|
||||
};
|
||||
|
||||
// Use in backend
|
||||
@Post('sign-in')
|
||||
async signIn(@Body() request: LoginRequest): Promise<LoginResponse> {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
See [API Types](2-types.md) for complete type definitions.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- **Configure OIDC** — [Configuration → Authentik](../../1-getting-started/3-configuration/2-authentik.md)
|
||||
- **Review Types** — [Authentication Types](2-types.md)
|
||||
- **Understand Architecture** — [Architecture → Authentication](../../3-architecture/2-authentication/1-betterauth.md)
|
||||
32
docs/4-api/README.md
Normal file
32
docs/4-api/README.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# API Reference
|
||||
|
||||
Complete API documentation for Mosaic Stack backend.
|
||||
|
||||
## Chapters
|
||||
|
||||
1. **Conventions** — API design patterns, endpoints, and response formats
|
||||
2. **Authentication** — Auth endpoints and type definitions
|
||||
|
||||
## API Standards
|
||||
|
||||
- **REST Conventions:** Standard HTTP methods and status codes
|
||||
- **Type Safety:** All requests/responses typed via `@mosaic/shared`
|
||||
- **Error Handling:** Consistent error response format
|
||||
- **Authentication:** Bearer token via Authorization header
|
||||
|
||||
## Base URL
|
||||
|
||||
- **Development:** `http://localhost:3001`
|
||||
- **Production:** Configure via `NEXT_PUBLIC_APP_URL`
|
||||
|
||||
## Authentication
|
||||
|
||||
All authenticated endpoints require:
|
||||
```http
|
||||
Authorization: Bearer {session_token}
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Review **Architecture** for design context
|
||||
- Check **Development** for contributing guidelines
|
||||
176
docs/README.md
Normal file
176
docs/README.md
Normal file
@@ -0,0 +1,176 @@
|
||||
# Mosaic Stack Documentation
|
||||
|
||||
Complete documentation for Mosaic Stack, organized in Bookstack-compatible shelf/book/chapter/page structure.
|
||||
|
||||
## 📚 Books
|
||||
|
||||
### 1. Getting Started
|
||||
|
||||
Essential guides to get Mosaic Stack installed and configured.
|
||||
|
||||
- **[Quick Start](1-getting-started/1-quick-start/1-overview.md)** — Get up and running in 5 minutes
|
||||
- **[Installation](1-getting-started/2-installation/)**
|
||||
- [Prerequisites](1-getting-started/2-installation/1-prerequisites.md)
|
||||
- [Local Setup](1-getting-started/2-installation/2-local-setup.md)
|
||||
- [Docker Setup](1-getting-started/2-installation/3-docker-setup.md)
|
||||
- **[Configuration](1-getting-started/3-configuration/)**
|
||||
- [Environment Variables](1-getting-started/3-configuration/1-environment.md)
|
||||
- [Authentik OIDC](1-getting-started/3-configuration/2-authentik.md)
|
||||
|
||||
### 2. Development
|
||||
|
||||
Developer guides for contributing to Mosaic Stack.
|
||||
|
||||
- **[Workflow](2-development/1-workflow/)**
|
||||
- [Branching Strategy](2-development/1-workflow/1-branching.md)
|
||||
- [Testing Requirements](2-development/1-workflow/2-testing.md)
|
||||
- **[Database](2-development/2-database/)**
|
||||
- Schema, migrations, and Prisma guides *(to be added)*
|
||||
- **[Type Sharing](2-development/3-type-sharing/)**
|
||||
- [Type Sharing Strategy](2-development/3-type-sharing/1-strategy.md)
|
||||
|
||||
### 3. Architecture
|
||||
|
||||
Technical architecture and design decisions.
|
||||
|
||||
- **[Overview](3-architecture/1-overview/)** — System design *(to be added)*
|
||||
- **[Authentication](3-architecture/2-authentication/)** — BetterAuth and OIDC *(to be added)*
|
||||
- **[Design Principles](3-architecture/3-design-principles/)**
|
||||
- [PDA-Friendly Patterns](3-architecture/3-design-principles/1-pda-friendly.md)
|
||||
|
||||
### 4. API Reference
|
||||
|
||||
Complete API endpoint documentation.
|
||||
|
||||
- **[Conventions](4-api/1-conventions/)**
|
||||
- [Endpoint Conventions](4-api/1-conventions/1-endpoints.md)
|
||||
- **[Authentication](4-api/2-authentication/)**
|
||||
- [Authentication Endpoints](4-api/2-authentication/1-endpoints.md)
|
||||
|
||||
## 📝 Scratchpads
|
||||
|
||||
Development notes and implementation details for specific issues:
|
||||
|
||||
- [Issue #1: Project Scaffold](scratchpads/1-project-scaffold.md)
|
||||
- [Issue #2: PostgreSQL Schema](scratchpads/2-postgresql-pgvector-schema.md)
|
||||
- [Issue #3: Prisma ORM Setup](scratchpads/3-prisma-orm-setup.md)
|
||||
- [Issue #4: Authentik OIDC Integration](scratchpads/4-authentik-oidc-final-status.md)
|
||||
|
||||
## 🔍 Quick Links
|
||||
|
||||
### For New Users
|
||||
1. [Quick Start](1-getting-started/1-quick-start/1-overview.md)
|
||||
2. [Local Setup](1-getting-started/2-installation/2-local-setup.md)
|
||||
3. [Environment Configuration](1-getting-started/3-configuration/1-environment.md)
|
||||
|
||||
### For Developers
|
||||
1. [Branching Strategy](2-development/1-workflow/1-branching.md)
|
||||
2. [Testing Requirements](2-development/1-workflow/2-testing.md)
|
||||
3. [Type Sharing](2-development/3-type-sharing/1-strategy.md)
|
||||
|
||||
### For Architects
|
||||
1. [PDA-Friendly Design](3-architecture/3-design-principles/1-pda-friendly.md)
|
||||
2. [Authentication Flow](3-architecture/2-authentication/) *(to be added)*
|
||||
3. [System Overview](3-architecture/1-overview/) *(to be added)*
|
||||
|
||||
### For API Consumers
|
||||
1. [API Conventions](4-api/1-conventions/1-endpoints.md)
|
||||
2. [Authentication Endpoints](4-api/2-authentication/1-endpoints.md)
|
||||
|
||||
## 📋 Documentation Standards
|
||||
|
||||
### File Organization
|
||||
|
||||
```
|
||||
docs/
|
||||
├── {N}-{book-name}/ # Book (numbered)
|
||||
│ ├── README.md # Book overview
|
||||
│ ├── {N}-{chapter-name}/ # Chapter (numbered)
|
||||
│ │ ├── {N}-{page-name}.md # Page (numbered)
|
||||
│ │ └── ...
|
||||
│ └── ...
|
||||
└── scratchpads/ # Development notes (unnumbered)
|
||||
```
|
||||
|
||||
### Numbering Convention
|
||||
|
||||
- **Books:** `1-getting-started`, `2-development`, `3-architecture`, `4-api`
|
||||
- **Chapters:** `1-quick-start`, `2-installation`, `3-configuration`
|
||||
- **Pages:** `1-overview.md`, `2-local-setup.md`, `3-docker-setup.md`
|
||||
|
||||
Numbers maintain order in file systems and Bookstack.
|
||||
|
||||
### Writing Style
|
||||
|
||||
- **Concise** — No unnecessary verbosity
|
||||
- **Action-oriented** — Use imperative mood ("Run the command", not "You should run")
|
||||
- **Example-heavy** — Show, don't just tell
|
||||
- **Code blocks** — Always include working examples
|
||||
- **Links** — Cross-reference related topics
|
||||
- **PDA-friendly** — Follow [design principles](3-architecture/3-design-principles/1-pda-friendly.md)
|
||||
|
||||
### Code Examples
|
||||
|
||||
Always include:
|
||||
- Language identifier for syntax highlighting
|
||||
- Complete, runnable examples
|
||||
- Expected output when relevant
|
||||
- Error cases and troubleshooting
|
||||
|
||||
## 🛠️ Contributing to Docs
|
||||
|
||||
### Adding New Pages
|
||||
|
||||
1. Identify the appropriate book/chapter
|
||||
2. Create numbered markdown file
|
||||
3. Add to chapter's parent README
|
||||
4. Link from related pages
|
||||
5. Test all links and code examples
|
||||
|
||||
### Updating Existing Pages
|
||||
|
||||
1. Keep formatting consistent
|
||||
2. Update last-modified date
|
||||
3. Test all examples
|
||||
4. Check cross-references
|
||||
|
||||
### Creating New Books
|
||||
|
||||
1. Number sequentially (`5-{new-book}`)
|
||||
2. Create `README.md` overview
|
||||
3. Add chapter directories
|
||||
4. Update this index
|
||||
|
||||
## 📊 Documentation Status
|
||||
|
||||
| Book | Completion |
|
||||
|------|------------|
|
||||
| Getting Started | 🟢 Complete |
|
||||
| Development | 🟡 Partial |
|
||||
| Architecture | 🟡 Partial |
|
||||
| API Reference | 🟡 Partial |
|
||||
|
||||
**Legend:**
|
||||
- 🟢 Complete
|
||||
- 🟡 Partial
|
||||
- 🔵 Planned
|
||||
- ⚪ Not started
|
||||
|
||||
## 🔗 External Resources
|
||||
|
||||
- **Project Repository:** https://git.mosaicstack.dev/mosaic/stack
|
||||
- **Issue Tracker:** https://git.mosaicstack.dev/mosaic/stack/issues
|
||||
- **Google Style Guides:** https://github.com/google/styleguide
|
||||
- **BetterAuth Docs:** https://www.better-auth.com
|
||||
- **Prisma Docs:** https://www.prisma.io/docs
|
||||
- **NestJS Docs:** https://docs.nestjs.com
|
||||
|
||||
## 📧 Support
|
||||
|
||||
- **Issues:** [Create an issue](https://git.mosaicstack.dev/mosaic/stack/issues/new)
|
||||
- **Discussions:** [Project discussions](https://git.mosaicstack.dev/mosaic/stack/discussions)
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2026-01-28
|
||||
**Version:** 0.0.1 (Pre-MVP)
|
||||
Reference in New Issue
Block a user