Files
stack/apps/api
Jason Woltje 737eb40d18
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
feat(#352): Encrypt existing plaintext Account tokens
Implements transparent encryption/decryption of OAuth tokens via Prisma middleware with progressive migration strategy.

Core Implementation:
- Prisma middleware transparently encrypts tokens on write, decrypts on read
- Auto-detects ciphertext format: aes:iv:authTag:encrypted, vault:v1:..., or plaintext
- Uses existing CryptoService (AES-256-GCM) for encryption
- Progressive encryption: tokens encrypted as they're accessed/refreshed
- Zero-downtime migration (schema change only, no bulk data migration)

Security Features:
- Startup key validation prevents silent data loss if ENCRYPTION_KEY changes
- Secure error logging (no stack traces that could leak sensitive data)
- Graceful handling of corrupted encrypted data
- Idempotent encryption prevents double-encryption
- Future-proofed for OpenBao Transit encryption (Phase 2)

Token Fields Encrypted:
- accessToken (OAuth access tokens)
- refreshToken (OAuth refresh tokens)
- idToken (OpenID Connect ID tokens)

Backward Compatibility:
- Existing plaintext tokens readable (encryptionVersion = NULL)
- Progressive encryption on next write
- BetterAuth integration transparent (middleware layer)

Test Coverage:
- 20 comprehensive unit tests (89.06% coverage)
- Encryption/decryption scenarios
- Null/undefined handling
- Corrupted data handling
- Legacy plaintext compatibility
- Future vault format support
- All CRUD operations (create, update, updateMany, upsert)

Files Created:
- apps/api/src/prisma/account-encryption.middleware.ts
- apps/api/src/prisma/account-encryption.middleware.spec.ts
- apps/api/prisma/migrations/20260207_encrypt_account_tokens/migration.sql

Files Modified:
- apps/api/src/prisma/prisma.service.ts (register middleware)
- apps/api/src/prisma/prisma.module.ts (add CryptoService)
- apps/api/src/federation/crypto.service.ts (add key validation)
- apps/api/prisma/schema.prisma (add encryptionVersion)
- .env.example (document ENCRYPTION_KEY)

Fixes #352

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 13:16:43 -06:00
..

Mosaic Stack API

The Mosaic Stack API is a NestJS-based backend service providing REST endpoints and WebSocket support for the Mosaic productivity platform.

Overview

The API serves as the central backend for:

  • Task Management - Create, update, track tasks with filtering and sorting
  • Event Management - Calendar events and scheduling
  • Project Management - Organize work into projects
  • Knowledge Base - Wiki-style documentation with markdown support and wiki-linking
  • Ideas - Quick capture and organization of ideas
  • Domains - Categorize work across different domains
  • Personalities - AI personality configurations for the Ollama integration
  • Widgets & Layouts - Dashboard customization
  • Activity Logging - Track all user actions
  • WebSocket Events - Real-time updates for tasks, events, and projects

Available Modules

Module Base Path Description
Tasks /api/tasks CRUD operations for tasks with filtering
Events /api/events Calendar events and scheduling
Projects /api/projects Project management
Knowledge /api/knowledge/entries Wiki entries with markdown support
Knowledge Tags /api/knowledge/tags Tag management for knowledge entries
Ideas /api/ideas Quick capture and idea management
Domains /api/domains Domain categorization
Personalities /api/personalities AI personality configurations
Widgets /api/widgets Dashboard widget data
Layouts /api/layouts Dashboard layout configuration
Ollama /api/ollama LLM integration (generate, chat, embed)
Users /api/users/me/preferences User preferences

Health Check

  • GET / - API health check
  • GET /health - Detailed health status including database connectivity

Authentication

The API uses BetterAuth for authentication with the following features:

Authentication Flow

  1. Email/Password - Users can sign up and log in with email and password
  2. Session Tokens - BetterAuth generates session tokens with configurable expiration

Guards

The API uses a layered guard system:

Guard Purpose Applies To
AuthGuard Verifies user authentication via Bearer token Most protected endpoints
WorkspaceGuard Validates workspace membership and sets Row-Level Security (RLS) context Workspace-scoped resources
PermissionGuard Enforces role-based access control Admin operations

Workspace Roles

  • OWNER - Full control over workspace
  • ADMIN - Administrative functions (can delete content, manage members)
  • MEMBER - Standard access (create/edit content)
  • GUEST - Read-only access

Permission Levels

Used with @RequirePermission() decorator:

Permission.WORKSPACE_OWNER; // Requires OWNER role
Permission.WORKSPACE_ADMIN; // Requires ADMIN or OWNER
Permission.WORKSPACE_MEMBER; // Requires MEMBER, ADMIN, or OWNER
Permission.WORKSPACE_ANY; // Any authenticated member including GUEST

Providing Workspace Context

Workspace ID can be provided via:

  1. Header: X-Workspace-Id: <workspace-id> (highest priority)
  2. URL Parameter: :workspaceId
  3. Request Body: workspaceId field

Example: Protected Controller

@Controller("tasks")
@UseGuards(AuthGuard, WorkspaceGuard, PermissionGuard)
export class TasksController {
  @Post()
  @RequirePermission(Permission.WORKSPACE_MEMBER)
  async create(@Body() dto: CreateTaskDto, @Workspace() workspaceId: string) {
    // workspaceId is verified and RLS context is set
  }
}

Environment Variables

Variable Description Default
PORT API server port 3001
DATABASE_URL PostgreSQL connection string Required
NODE_ENV Environment (development, production) -
NEXT_PUBLIC_APP_URL Frontend application URL (for CORS) http://localhost:3000
WEB_URL WebSocket CORS origin http://localhost:3000

Running Locally

Prerequisites

  • Node.js 18+
  • PostgreSQL database
  • pnpm workspace (part of Mosaic Stack monorepo)

Setup

  1. Install dependencies:

    pnpm install
    
  2. Set up environment variables:

    cp .env.example .env  # If available
    # Edit .env with your DATABASE_URL
    
  3. Generate Prisma client:

    pnpm prisma:generate
    
  4. Run database migrations:

    pnpm prisma:migrate
    
  5. Seed the database (optional):

    pnpm prisma:seed
    

Development

pnpm dev

The API will start on http://localhost:3001

Production Build

pnpm build
pnpm start:prod

Database Management

# Open Prisma Studio
pnpm prisma:studio

# Reset database (dev only)
pnpm prisma:reset

# Run migrations in production
pnpm prisma:migrate:prod

API Documentation

The API does not currently include Swagger/OpenAPI documentation. Instead:

  • Controller files contain detailed JSDoc comments describing each endpoint
  • DTO classes define request/response schemas with class-validator decorators
  • Refer to the controller source files in src/ for endpoint details

Example: Reading an Endpoint

// src/tasks/tasks.controller.ts

/**
 * POST /api/tasks
 * Create a new task
 * Requires: MEMBER role or higher
 */
@Post()
@RequirePermission(Permission.WORKSPACE_MEMBER)
async create(@Body() createTaskDto: CreateTaskDto, @Workspace() workspaceId: string) {
  return this.tasksService.create(workspaceId, user.id, createTaskDto);
}

WebSocket Support

The API provides real-time updates via WebSocket. Clients receive notifications for:

  • task:created - New task created
  • task:updated - Task modified
  • task:deleted - Task removed
  • event:created - New event created
  • event:updated - Event modified
  • event:deleted - Event removed
  • project:updated - Project modified

Clients join workspace-specific rooms for scoped updates.

Testing

# Run unit tests
pnpm test

# Run tests with coverage
pnpm test:coverage

# Run e2e tests
pnpm test:e2e

# Watch mode
pnpm test:watch

Project Structure

src/
├── activity/          # Activity logging
├── auth/              # Authentication (BetterAuth config, guards)
├── common/            # Shared decorators and guards
├── database/          # Database module
├── domains/           # Domain management
├── events/            # Event management
├── filters/           # Global exception filters
├── ideas/             # Idea capture and management
├── knowledge/         # Knowledge base (entries, tags, markdown)
├── layouts/           # Dashboard layouts
├── lib/               # Utility functions
├── ollama/            # LLM integration
├── personalities/     # AI personality configurations
├── prisma/            # Prisma service
├── projects/          # Project management
├── tasks/             # Task management
├── users/             # User preferences
├── widgets/           # Dashboard widgets
├── websocket/         # WebSocket gateway
├── app.controller.ts  # Root controller (health check)
├── app.module.ts      # Root module
└── main.ts            # Application bootstrap