Zum Inhalt

EPPA Developer Setup

EPPA is the LABIS posturography tool for clinical/research workflows. This front contains a Next.js frontend, a FastAPI calculation/auth API, Docker deployment assets, Python tests, and Playwright end-to-end tests.

Work from this directory unless a command says otherwise:

cd fronts/eppa

Do not commit real patient data, clinical payloads, secrets, production tokens, database dumps, Vaultwarden exports, PANs, CVVs, PIN blocks, or track data.

Prerequisites

  • Node.js 20.x. There is no .nvmrc; use Node 20 because the Docker image is node:20-alpine and local dependencies are tested against modern Node.
  • npm 10.x, included with current Node 20 releases.
  • Python 3.11 or newer. Python 3.12 also works for the current API/test stack.
  • Docker Engine with the Compose plugin (docker compose ...).
  • Playwright browsers, installed after npm ci.
  • Optional: PostgreSQL and MinIO via docker compose for auth/clinical-data work. The calculation API and most Playwright coverage do not require real clinical records.

Fresh Checkout Setup

cd fronts/eppa
npm ci
npx playwright install --with-deps chromium

python3 -m venv venv
source venv/bin/activate
pip install -r python/requirements.txt

For local infrastructure used by the auth and clinical-data backend:

docker compose up -d postgres minio
docker compose ps
DATABASE_URL="${DATABASE_URL:?Set DATABASE_URL before running migrations}" \
  PYTHONPATH=python python3 -m alembic -c python/alembic.ini upgrade head

Compose requires Postgres, MinIO, database URL, and JWT secret inputs from the environment. Start from .env.example and keep the populated file outside version control.

Local Development

Run the API and frontend in separate terminals.

Terminal 1, FastAPI on host port 8100:

source venv/bin/activate
API_PORT=8100 \
CORS_ALLOW_ORIGINS=http://localhost:9002 \
PYTHONPATH=python \
python3 python/api.py

Terminal 2, Next.js on host port 9002:

NEXT_PUBLIC_API_URL=http://127.0.0.1:8100 npm run dev

Open:

  • Frontend: http://localhost:9002
  • API health: http://localhost:8100/health
  • API docs: http://localhost:8100/docs
  • MinIO console, when running: http://localhost:9001

./start-api.sh is still available for the legacy default API port 8000, but new local setup should prefer the explicit API_PORT=8100 command above so it matches Docker and Playwright.

Playwright

The default Playwright config starts its own API and production Next.js server:

npx playwright test

Defaults:

  • Frontend: WEB_PORT=9102, so PLAYWRIGHT_BASE_URL defaults to http://localhost:9102.
  • API: API_PORT=8100, so PLAYWRIGHT_API_URL defaults to http://localhost:8100.
  • Python executable: PYTHON=python3.

To test against already-running local servers instead of letting Playwright start them:

PLAYWRIGHT_BASE_URL=http://localhost:9002 \
PLAYWRIGHT_API_URL=http://127.0.0.1:8100 \
npx playwright test

Useful variants:

npm run test:e2e:playwright -- playwright/e2e/login.spec.ts
npm run test:e2e:playwright:ui
npm run test:e2e:playwright:report

Other Verification

npm run typecheck
npm run test:py:coverage
PYTHONPATH=python pytest tests python/tests/auth
PYTHONPATH=python pytest tests/test_integration.py -v
node tests/js/testAnalysis.js
node tests/js/testMissingDataSemantics.js
python3 scripts/validate_matlab_fixtures.py

npm run test also runs Python tests, JavaScript analysis tests, and an Octave MATLAB-equivalence test. Use it only when Octave is installed.

npm run test:py:coverage generates coverage.xml and prints missing Python lines in the terminal. It excludes only tests that depend on real, private, or binary MATLAB validation fixtures (Base completa- CORREGIDA.xlsx and real .mat files), so CI remains reproducible without committing private data. There is currently no enforced minimum coverage threshold.

Environment Variables

Use a local .env file only for backend settings that python/auth/config.py loads, or export values in the shell before starting processes. Do not commit a populated .env.

Variable Example value Used by Notes
NEXT_PUBLIC_API_URL http://127.0.0.1:8100 Next.js build/runtime Public API base URL baked into frontend builds. Use https://eppa.firemandeveloper.com or https://eppa2.firemandeveloper.com for server builds.
API_PORT 8100 FastAPI, Playwright, Docker entrypoint FastAPI listens on this port inside the process. Docker maps container port 8000 to host 8100 for the legacy eppa service.
CORS_ALLOW_ORIGINS http://localhost:9002 FastAPI Comma-separated browser origins allowed to call the API.
PYTHONPATH python Python commands Required when running the API/tests from fronts/eppa.
PYTHON python3 npm scripts, Playwright Override when the interpreter is named differently.
WEB_PORT 9102 Playwright Port for the Playwright-managed Next.js server.
PLAYWRIGHT_BASE_URL http://localhost:9002 Playwright When set, Playwright assumes the frontend server already exists and skips its webServer startup.
PLAYWRIGHT_API_URL http://127.0.0.1:8100 Playwright tests API URL used by tests and health checks.
DATABASE_URL postgresql+psycopg://eppa:<url-encoded-secret>@postgres:5432/eppa FastAPI auth/data backend, Alembic Required by Compose. Keep the populated value outside version control.
JWT_ALGO HS256 FastAPI auth HS256 for local/dev. RS256 is supported with key paths.
JWT_SECRET <generated-secret> FastAPI auth Required in production for stable HS256 tokens (or use JWT_SECRET_FILE). Never commit a real value.
JWT_SECRET_FILE /run/secrets/eppa2_jwt_secret FastAPI auth Path to a file containing the JWT secret (e.g. a Docker mounted secret). JWT_SECRET takes priority when both are set.
EPPA_JWT_SECRET_SOURCE /absolute/path/to/eppa2-jwt-secret Docker Compose Host path to the external secret file mounted as eppa2_jwt_secret.
JWT_PRIVATE_KEY_PATH /etc/eppa/jwt-private.pem FastAPI auth Required only when JWT_ALGO=RS256.
JWT_PUBLIC_KEY_PATH /etc/eppa/jwt-public.pem FastAPI auth Required only when JWT_ALGO=RS256.
JWT_ISSUER eppa-api FastAPI auth Token issuer claim.
ACCESS_TOKEN_TTL_SECONDS 900 FastAPI auth Access-token lifetime.
REFRESH_TOKEN_TTL_SECONDS 1209600 FastAPI auth Refresh-token lifetime.
COOKIE_SECURE false locally, true in production FastAPI auth Set true behind HTTPS.
COOKIE_SAMESITE lax FastAPI auth lax, strict, or none.
COOKIE_DOMAIN .firemandeveloper.com FastAPI auth Optional. Leave unset for localhost.
LOGIN_RATE_LIMIT 10/minute FastAPI auth SlowAPI limit for login.
FORGOT_PASSWORD_RATE_LIMIT 5/hour FastAPI auth SlowAPI limit for forgot-password.
RESET_PASSWORD_RATE_LIMIT 10/hour FastAPI auth SlowAPI limit for reset-password.
PASSWORD_RESET_TTL_SECONDS 3600 FastAPI auth Password reset token lifetime.
PASSWORD_MIN_LENGTH 10 FastAPI auth Minimum practitioner password length.
FRONTEND_BASE_URL http://localhost:9002 FastAPI auth email links Public frontend URL used in reset links.
EPPA_SMTP_HOST smtp.example.test FastAPI email Optional. If unset, password-reset email content is logged by the stub backend.
EPPA_SMTP_PORT 587 FastAPI email SMTP port.
EPPA_SMTP_USER eppa-dev@example.test FastAPI email Optional SMTP username.
EPPA_SMTP_PASSWORD <generated-secret> FastAPI email Optional SMTP password. Never commit real credentials.
EPPA_SMTP_FROM no-reply@labis.uca FastAPI email Sender address for reset emails.
EPPA_ENV dev FastAPI auth dev, test, or prod.
MINIO_ROOT_USER eppa_minio_admin Docker MinIO Dev-only value from Compose.
MINIO_ROOT_PASSWORD <generated-secret> Docker MinIO Required by Compose.
POSTGRES_USER eppa Docker Postgres Dev-only value from Compose.
POSTGRES_PASSWORD <generated-secret> Docker Postgres Required by Compose.
POSTGRES_DB eppa Docker Postgres Dev-only value from Compose.
CYPRESS_apiUrl http://localhost:8000 legacy Cypress script Only needed for npm run test:e2e, which wraps Cypress.

The eppa2 Compose service mounts the file selected by EPPA_JWT_SECRET_SOURCE at JWT_SECRET_FILE=/run/secrets/eppa2_jwt_secret. The Python auth backend reads JWT_SECRET_FILE and loads the file contents as the JWT secret when JWT_SECRET is not set explicitly. EPPA_ENV=prod fails fast if neither an explicit secret nor key paths are configured, or if COOKIE_SECURE is false.

Docker

Build the legacy production image:

docker compose build eppa

Run it locally:

docker compose up -d eppa
docker compose ps
curl -fsS http://127.0.0.1:8100/health

Host port mapping for the legacy eppa service:

  • 127.0.0.1:9002 -> container Next.js port 3000
  • 127.0.0.1:8100 -> container FastAPI port 8000

Build-time API URL example without Compose:

docker build \
  --build-arg NEXT_PUBLIC_API_URL=https://eppa.firemandeveloper.com \
  -t eppa:local .

The container starts both processes through entrypoint.sh: FastAPI first, then next start -H 0.0.0.0 -p 3000.

Production Deployment

Production deployment is Docker + Nginx on the server. Run these commands on the server checkout, not on a developer laptop:

cd /home/luis/personal/github-repos/labis-eppa-software/fronts/eppa
git pull --ff-only

docker compose build eppa
docker compose up -d eppa
docker compose ps

curl -fsS http://127.0.0.1:8100/health
curl -sI http://127.0.0.1:9002/ | head -3

For the parallel v2 deployment:

docker compose up -d postgres minio
docker compose build eppa2
docker compose up -d eppa2
docker compose exec eppa2 sh -c 'cd /app && DATABASE_URL=$DATABASE_URL python3 -m alembic upgrade head'
curl -fsS http://127.0.0.1:8101/health

Nginx serves public HTTPS and proxies to loopback ports. The prepared v2 config lives at deploy/nginx/eppa2.firemandeveloper.com.conf; the full v2 rollout, TLS, smoke-test, and rollback sequence is in deploy/RUNBOOK-eppa2.md.

Basic-auth credentials for the public Nginx preview must be retrieved from Vaultwarden. Do not print those credentials in this README, PRs, issues, logs, or screenshots.

Project Layout

fronts/eppa/
  src/                  Next.js app, UI components, API client
  python/               FastAPI app, calculation engine, auth/data backend
  python/migrations/    Alembic migrations
  playwright/e2e/       Playwright end-to-end tests
  tests/                Python integration and fixture tests
  scripts/              Validation and test helpers
  deploy/               Deployment runbooks and Nginx config
  datos/                Example/research data used by the project
  docs/                 Product, validation, API, and testing docs

Clinical Data Safety

  • Use synthetic or explicitly approved fixture data for local tests.
  • Do not add new real patient images, clinical records, secrets, or production exports to the repository.
  • Keep local databases and MinIO buckets on 127.0.0.1 unless a deployment runbook explicitly says otherwise.
  • Before opening a PR, check git diff --stat and git diff for accidental data or secret additions.