Files
gravl/.planning/codebase/INTEGRATIONS.md
T
2026-02-15 21:49:31 +01:00

5.2 KiB

External Integrations

Analysis Date: 2026-02-15

APIs & External Services

None - No external third-party APIs currently integrated.

Data Storage

Databases:

  • PostgreSQL (Primary)
    • Connection via pg client library (8.11.3)
    • Environment variables:
      • DB_HOST - Default: postgres (Docker service name)
      • DB_PORT - Default: 5432
      • DB_USER - Default: postgres
      • DB_PASSWORD - Required secret
      • DB_NAME - Default: gravl
    • ORM/Client: pg (node-postgres) - Direct SQL queries, no ORM
    • Initialization: db/init.sql - Schema and seed data
    • Tables: users, programs, program_days, exercises, program_exercises, workout_logs, user_measurements, user_strength

File Storage:

  • Local filesystem only - No external file storage service
  • Static assets served by Nginx from built frontend dist/ directory

Caching:

  • None detected - No Redis, Memcached, or other caching layer

Authentication & Identity

Auth Provider:

  • Custom JWT-based authentication
    • Implementation: backend/src/index.js (lines 22-29, 35-68)
    • Token generation: jsonwebtoken 9.0.2
    • Password hashing: bcryptjs 2.4.3
    • Secret: JWT_SECRET environment variable (default: gravl-secret-key-change-in-production)
    • Token expiration: 30 days

Auth Flow:

  1. Frontend AuthContext (frontend/src/context/AuthContext.jsx) manages user state
  2. User registers or logs in via /api/auth/register or /api/auth/login
  3. Backend verifies credentials, generates JWT token
  4. Frontend stores token in localStorage as token
  5. Subsequent requests include Authorization: Bearer {token} header
  6. Backend authMiddleware validates token on protected routes
  7. User profile fetched on app load via /api/user/profile

Protected Routes:

  • /api/user/profile - GET/PUT (requires auth)
  • /api/user/measurements - GET/POST (requires auth)
  • /api/user/strength - GET/POST (requires auth)
  • /api/logs - GET/POST (no auth check in code - potential security gap)
  • /api/progression/:programExerciseId - GET (no auth check - potential security gap)

Public Routes:

  • /api/health - Health check endpoint
  • /api/auth/register - User registration
  • /api/auth/login - User login
  • /api/programs - List all programs
  • /api/programs/:id - Get program details
  • /api/days/:dayId/exercises - Get exercises for a day
  • /api/today/:programId - Get workout for day

Frontend-Backend Communication

API Base URL:

  • Hardcoded as /api in frontend/src/context/AuthContext.jsx (line 2)
  • Development: Proxied by Vite to http://localhost:3001
  • Production: Proxied by Nginx to http://gravl-backend:3001

CORS:

  • Enabled on backend via cors middleware 2.8.5
  • app.use(cors()) in backend/src/index.js (line 19)

HTTP Methods:

  • POST /api/auth/register - Register user
  • POST /api/auth/login - Login user
  • GET /api/user/profile - Get user profile
  • PUT /api/user/profile - Update user profile
  • POST /api/user/measurements - Add measurements
  • GET /api/user/measurements - Get measurement history
  • POST /api/user/strength - Add strength record
  • GET /api/user/strength - Get strength history
  • GET /api/programs - List programs
  • GET /api/programs/:id - Get program with days and exercises
  • GET /api/days/:dayId/exercises - Get exercises for day
  • GET/POST /api/logs - Get/create workout logs
  • GET /api/logs/last/:programExerciseId - Get last workout for exercise
  • GET /api/progression/:programExerciseId - Calculate suggested weight

Request/Response Format:

  • Content-Type: application/json
  • Token: Passed in Authorization: Bearer {token} header
  • Response: JSON objects

Monitoring & Observability

Error Tracking:

  • None detected - No Sentry, LogRocket, or similar

Logs:

  • Backend: console.error() for errors (lines 48, 65, 98, 115, 133, 147, 165, 179, 190, 228, 246, 276, 294, 327, 380, 417)
  • Frontend: No error tracking integrated
  • Example: console.error('Register error:', err) in backend/src/index.js (line 48)

Database Logging:

  • None detected - SQL queries not logged

Webhooks & Callbacks

Incoming:

  • None detected

Outgoing:

  • None detected

Environment Configuration

Required env vars for backend:

  • DB_HOST - PostgreSQL hostname
  • DB_PORT - PostgreSQL port
  • DB_USER - Database user
  • DB_PASSWORD - Database password (REQUIRED SECRET)
  • DB_NAME - Database name
  • JWT_SECRET - JWT signing secret (REQUIRED SECRET for production)
  • PORT - Backend port (optional, default 3001)

Secrets location:

  • Docker Compose: docker-compose.yml (lines 8-13) - WARNING: Password visible in file
  • Backend defaults: backend/src/index.js (lines 9, 14-16)
  • Frontend: None (token stored in browser localStorage)

Traefik Integration:

  • Frontend exposed via Traefik reverse proxy
  • Host: gravl.homelab.local
  • HTTP and HTTPS support configured
  • Networks: proxy (external), homelab (internal Docker Compose network)

Service Dependencies

Backend Dependencies:

  • PostgreSQL (required)
  • Traefik proxy (for production routing)

Frontend Dependencies:

  • Backend API at /api (required for all authenticated operations)
  • Can operate in degraded mode if API is unavailable

Integration audit: 2026-02-15