Document Service — Local Dev Setup
Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template
1. Prerequisites
| Tool | Version |
|---|---|
| Node.js | 22 LTS |
| pnpm | 9.x |
| Docker + Docker Compose | 24+ |
AWS CLI or MinIO CLI (mc) | For object storage inspection |
2. docker-compose.yml (document-service dev stack)
version: "3.9"
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: ghasi_documents
POSTGRES_USER: ghasi
POSTGRES_PASSWORD: ghasi_dev
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
minio:
image: minio/minio:latest
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: ghasi_minio
MINIO_ROOT_PASSWORD: ghasi_minio_dev
ports:
- "9000:9000"
- "9001:9001"
volumes:
- minio_data:/data
clamav:
image: clamav/clamav:latest
ports:
- "3310:3310"
nats:
image: nats:2.10-alpine
ports:
- "4222:4222"
command: --jetstream
document-service:
build:
context: .
dockerfile: Dockerfile.dev
environment:
DATABASE_URL: postgres://ghasi:ghasi_dev@postgres:5432/ghasi_documents
NATS_URL: nats://nats:4222
OBJECT_STORAGE_ENDPOINT: http://minio:9000
OBJECT_STORAGE_ACCESS_KEY: ghasi_minio
OBJECT_STORAGE_SECRET_KEY: ghasi_minio_dev
OBJECT_STORAGE_BUCKET: ghasi-documents-dev
OBJECT_STORAGE_REGION: us-east-1
CLAMAV_HOST: clamav
CLAMAV_PORT: 3310
FHIR_GATEWAY_URL: http://interop-service:3030
CONFIG_SERVICE_URL: http://config-service:3015
PORT: 3020
NODE_ENV: development
IDENTITY_JWT_ISSUER: http://keycloak:8080/realms/ghasi-dev
PRESIGNED_URL_TTL_SECONDS: 900
ports:
- "3020:3020"
depends_on:
- postgres
- minio
- clamav
- nats
volumes:
postgres_data:
minio_data:
3. Environment Variables
Copy .env.example to .env:
DATABASE_URL=postgres://ghasi:ghasi_dev@localhost:5432/ghasi_documents
NATS_URL=nats://localhost:4222
OBJECT_STORAGE_ENDPOINT=http://localhost:9000
OBJECT_STORAGE_ACCESS_KEY=ghasi_minio
OBJECT_STORAGE_SECRET_KEY=ghasi_minio_dev
OBJECT_STORAGE_BUCKET=ghasi-documents-dev
OBJECT_STORAGE_REGION=us-east-1
CLAMAV_HOST=localhost
CLAMAV_PORT=3310
FHIR_GATEWAY_URL=http://localhost:3030
CONFIG_SERVICE_URL=http://localhost:3015
PORT=3020
NODE_ENV=development
IDENTITY_JWT_ISSUER=http://localhost:8080/realms/ghasi-dev
PRESIGNED_URL_TTL_SECONDS=900
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
4. Common Commands
# Start all dependencies
docker compose up -d postgres minio clamav nats
# Create MinIO bucket
mc alias set local http://localhost:9000 ghasi_minio ghasi_minio_dev
mc mb local/ghasi-documents-dev
# Install dependencies
pnpm install
# Run database migrations
pnpm db:migrate
# Seed platform reference templates
pnpm db:seed
# Start in development mode (hot reload)
pnpm dev
# Start render worker separately
pnpm dev:worker
# Run unit tests
pnpm test:unit
# Run integration tests (requires docker compose running)
pnpm test:integration
# Run all tests
pnpm test
# Check coverage
pnpm test:coverage
# Run PDF contract tests (golden hash comparison)
pnpm test:pdf-contracts
5. Seed Data
The seed script (scripts/seed-dev.ts) creates:
| Seed item | Details |
|---|---|
| Platform reference templates | General Test Requisition (platform.dms.general-lab.general-test-requisition) |
| Sample tenant template | "Outpatient Prescription" for ten_afg_moph_001 |
| Published version | Version 1.0.0 of General Test Requisition |
| Sample render job | Completed job for test patient |
6. MinIO Console
Access MinIO admin console at http://localhost:9001 (user: ghasi_minio, password: ghasi_minio_dev) to inspect uploaded objects and quarantine bucket.
7. Testing with curl
# List templates
curl "http://localhost:3020/v1/document-templates?origin=all&status=published" \
-H "Authorization: Bearer <dev-jwt>"
# Generate a document
curl -X POST "http://localhost:3020/v1/documents/generate" \
-H "Authorization: Bearer <dev-jwt>" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"templateVersionId":"tv_seed_001","patientId":"pat_seed_001","locale":"ps-AF"}'