Skip to main content

Config Service — Local Dev Setup

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template


1. Prerequisites

ToolVersion
Node.js22 LTS
pnpm9.x
Docker + Docker Compose24+
PostgreSQL client (psql)16 (for manual queries)

2. docker-compose.yml (config-service dev stack)

version: "3.9"
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: ghasi_config
POSTGRES_USER: ghasi
POSTGRES_PASSWORD: ghasi_dev
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data

redis:
image: redis:7-alpine
ports:
- "6379:6379"
command: redis-server --requirepass redis_dev

nats:
image: nats:2.10-alpine
ports:
- "4222:4222"
- "8222:8222"
command: --jetstream

config-service:
build:
context: .
dockerfile: Dockerfile.dev
environment:
DATABASE_URL: postgres://ghasi:ghasi_dev@postgres:5432/ghasi_config
REDIS_URL: redis://:redis_dev@redis:6379
NATS_URL: nats://nats:4222
PORT: 3015
NODE_ENV: development
IDENTITY_JWT_ISSUER: http://keycloak:8080/realms/ghasi-dev
HIERARCHY_SERVICE_URL: http://facility-service:3010
PLATFORM_ADMIN_SERVICE_URL: http://platform-admin-service:3011
ACCESS_POLICY_SERVICE_URL: http://access-policy:3005
IDENTITY_SERVICE_URL: http://identity-service:3001
ports:
- "3015:3015"
depends_on:
- postgres
- redis
- nats

volumes:
postgres_data:

3. Environment Variables

Copy .env.example to .env:

DATABASE_URL=postgres://ghasi:ghasi_dev@localhost:5432/ghasi_config
REDIS_URL=redis://:redis_dev@localhost:6379
NATS_URL=nats://localhost:4222
PORT=3015
NODE_ENV=development
IDENTITY_JWT_ISSUER=http://localhost:8080/realms/ghasi-dev
HIERARCHY_SERVICE_URL=http://localhost:3010
PLATFORM_ADMIN_SERVICE_URL=http://localhost:3011
ACCESS_POLICY_SERVICE_URL=http://localhost:3005
IDENTITY_SERVICE_URL=http://localhost:3001
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318

All env vars are validated at startup via Zod in src/infrastructure/config/env.ts. Service fails fast if any required var is missing.


4. Common Commands

# Start all dependencies
docker compose up -d postgres redis nats

# Install dependencies
pnpm install

# Run database migrations
pnpm db:migrate

# Seed platform GLOBAL node + system roles
pnpm db:seed

# Start in development mode (hot reload)
pnpm dev

# 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

# Lint + type check
pnpm lint && pnpm typecheck

5. Seed Data

The seed script (scripts/seed-dev.ts) creates:

Seed itemDetails
GLOBAL ConfigNodePlatform root
TENANT ConfigNodeten_afg_moph_001 (Afghanistan MoPH)
MODULE: CLIN-MEDSMedications module
MODULE: CLIN-NOTESClinical notes module
Features: ViewMedications, PrescribeMedication, ManageClinicalNotesStandard feature set
Roles: ClinicalStaff (abstract), NURSE, PHYSICIANStandard role hierarchy
RoleInheritance: NURSE → ClinicalStaff, PHYSICIAN → ClinicalStaff
Design tokens: MoPH branding (brand.primary: #006600, RTL direction)Afghan MoPH theme
UserNodeOverride: nurse1 explicit allow for medication:write at ward_aTest scenario

6. Testing with curl

# Resolve a permission (internal endpoint — no Kong in local dev)
curl "http://localhost:3015/internal/config/resolve?userId=usr_nurse_001&tenantId=ten_afg_moph_001&nodeId=cfgn_sdk_ward_a&moduleKey=CLIN-MEDS&featureKey=ViewMedications&action=medication:read&includeUI=true&includeTokens=true" \
-H "Authorization: Bearer <dev-jwt>"