learning_ai_notes/docker-compose.override.yml
saravanakumardb1 d5e857dbf7 test(e2e): docker compose E2E test + seed scripts + 9-step verification
Implements the full E2E flow against the deployed docker stack and
documents it as a repeatable test playbook.

Surfaced and fixed three real issues while building the E2E:

1. JWT secret mismatch — docker-compose.override.yml backend was using
   a NoteLett-only JWT_SECRET that platform-service did not share, so
   every Authorization: Bearer call returned 'Invalid or expired token'.
   Aligned the override to use platform-service's actual secret
   (dev-ecosystem-secret-do-not-use-in-production).

2. CORS preflight missing PATCH/DELETE — @bytelyst/fastify-core registers
   @fastify/cors with only { origin }, which leaves Access-Control-Allow-
   Methods at the @fastify/cors default of 'GET,HEAD,POST'. Real browser
   PATCH/DELETE preflights would fail. Added an onSend hook in
   backend/src/server.ts that rewrites the header to
   'GET,HEAD,POST,PATCH,PUT,DELETE,OPTIONS' on CORS preflight responses.

3. Product 'notelett' wasn't registered with platform-service — auth
   register/login both error with 'Unknown or disabled product: notelett'.
   The seed script now POSTs to /api/products idempotently.

Deliverables:

- scripts/e2e-docker-seed.sh — idempotent: registers the notelett product
  and creates two test users (admin@notelett.app with role=admin who can
  write, user@notelett.app with role=user who is read-only). Re-runs are
  no-ops once seeded.

- scripts/e2e-docker-test.sh — 9-step E2E that drives the deployed stack
  via HTTP only (no browser): login → CORS preflight for PATCH →
  workspace create → note create → note read → note PATCH (status:
  draft→active) → note list → note delete → workspace delete.

- docs/testing/E2E_DOCKER_TESTING.md — full playbook covering prereqs,
  seed, automated E2E, manual UI smoke, stack architecture diagram,
  troubleshooting (JWT mismatch, unknown product, role rejection,
  CORS, port conflict, data loss), tear-down, CI wiring guidance.

- package.json — pnpm e2e:docker:seed and pnpm e2e:docker:test
  shortcuts.

Verified live on this host's deployed stack:

  $ bash scripts/e2e-docker-seed.sh
  ↷ product 'notelett' already exists
  ↷ admin user already registered + login works
  ✓ user created
  🟢 Seed complete.

  $ bash scripts/e2e-docker-test.sh
  ✓ user=usr_e094e0c2-... role=admin
  ✓ CORS allows PATCH
  ✓ workspace created
  ✓ note created
  ✓ note read matches
  ✓ note patched (status: draft → active)
  ✓ note list returned (1 item)
  ✓ note deleted (HTTP 204)
  ✓ workspace deleted (HTTP 204)
  🟢 All 9 E2E steps passed.

Backend regression suite still green: 380/380.
2026-05-23 01:16:19 -07:00

42 lines
1.5 KiB
YAML

# Local override for `docker compose up` on this host.
#
# Why this exists:
# docker-compose.yml maps the web container to host port 3000, but
# port 3000 on this host is already occupied (Grafana). This file
# remaps web to host port 3050 and backend stays on 4016. The backend
# is configured to point at the sibling platform/extraction/mcp
# services already running on the host network.
#
# Bring up:
# docker compose up -d
# URLs:
# Web: http://localhost:3050
# Backend: http://localhost:4016
# Health: http://localhost:4016/health
# Bring down:
# docker compose down
services:
backend:
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
CORS_ORIGIN: "http://localhost:3050"
PLATFORM_SERVICE_URL: "http://host.docker.internal:4003"
EXTRACTION_SERVICE_URL: "http://host.docker.internal:4005"
MCP_SERVER_URL: "http://host.docker.internal:4007"
DB_PROVIDER: memory
# MUST match the JWT_SECRET used by the sibling platform-service so
# tokens platform issues are accepted by NoteLett backend. The
# platform-service in this dev compose stack uses the value below.
JWT_SECRET: "dev-ecosystem-secret-do-not-use-in-production"
web:
ports: !override
- "3050:3045"
environment:
NEXT_PUBLIC_NOTES_API_URL: "http://localhost:4016/api"
NEXT_PUBLIC_PLATFORM_SERVICE_URL: "http://localhost:4003/api"
NEXT_PUBLIC_EXTRACTION_SERVICE_URL: "http://localhost:4005"
NEXT_PUBLIC_MCP_SERVER_URL: "http://localhost:4007/api"