Skip to main content

regulator-portal-service — Local Dev Setup

Version: 1.0 Status: Draft Owner: Regulator-facing + DevEx Last Updated: 2026-04-21 References: SERVICE_OVERVIEW.md, DEPLOYMENT_TOPOLOGY.md, TESTING_STRATEGY.md


1. Prerequisites

ToolVersion
Node.js20 LTS
pnpm9.x
Docker Engine24+
openssl3.x (for test PKI)
psql16
nats CLI0.1.5+
curl with --cert flag support

2. Docker Compose

infra/docker/docker-compose.regulator-portal.yml:

version: '3.9'
services:
postgres-reg:
image: postgres:16-alpine
environment:
POSTGRES_DB: regulator
POSTGRES_USER: regulator
POSTGRES_PASSWORD: regulator
ports: ["5448:5432"]
volumes:
- reg_pg_data:/var/lib/postgresql/data
- ./regulator-portal/seed/schema.sql:/docker-entrypoint-initdb.d/001-schema.sql:ro
- ./regulator-portal/seed/seed.sql:/docker-entrypoint-initdb.d/002-seed.sql:ro

redis-reg:
image: redis:7-alpine
ports: ["6398:6379"]

nats:
image: nats:2.10-alpine
command: -js -m 8222
ports: ["4226:4222"]

softhsm:
image: ghasi/softhsm-dev:2.6
volumes:
- reg_hsm_data:/var/lib/softhsm
- ./regulator-portal/hsm:/hsm-init:ro

mock-splunk-hec:
image: ghasi/mock-splunk-hec:dev
ports: ["8088:8088"]

mock-qradar:
image: ghasi/mock-qradar:dev
ports: ["514:514/tcp", "6514:6514/tcp"]

mock-logstash:
image: ghasi/mock-logstash:dev
ports: ["5044:5044"]

mock-atra-sftp:
image: atmoz/sftp:latest
command: atra:atra:1001::upload
ports: ["2223:22"]
volumes:
- reg_atra_sftp:/home/atra

mock-national-pki-ca:
image: ghasi/mock-ca:dev
ports: ["8089:8089"]
volumes:
- ./regulator-portal/test-pki:/test-pki:ro

minio-reg:
image: minio/minio:latest
environment:
MINIO_ROOT_USER: regminio
MINIO_ROOT_PASSWORD: regminio
command: server /data --console-address ":9001"
ports: ["9300:9000", "9301:9001"]
volumes: [reg_minio_data:/data]

mock-compliance:
image: ghasi/mock-compliance-engine:dev
ports: ["50055:50055"]

mock-cdr-mediation:
image: ghasi/mock-cdr-mediation:dev
ports: ["50075:50075"]

mock-consent-ledger:
image: ghasi/mock-consent-ledger:dev
ports: ["50076:50076"]

mock-sender-id:
image: ghasi/mock-sender-id-registry:dev
ports: ["50078:50078"]

regulator-portal-api:
image: ghasi/regulator-portal-service:dev
depends_on:
- postgres-reg
- redis-reg
- nats
- softhsm
- mock-atra-sftp
- mock-national-pki-ca
- minio-reg
- mock-compliance
- mock-cdr-mediation
ports: ["3082:3082"]
environment:
NODE_ENV: development
LOG_LEVEL: debug
DATABASE_URL: postgres://regulator:regulator@postgres-reg:5432/regulator
REDIS_URL: redis://redis-reg:6379/0
NATS_URL: nats://nats:4222
S3_ENDPOINT: http://minio-reg:9000
S3_ACCESS_KEY: regminio
S3_SECRET_KEY: regminio
HSM_PKCS11_LIB: /softhsm/libsofthsm2.so
HSM_TOKEN_LABEL: reg-dev
ATRA_SFTP_HOST: mock-atra-sftp
ATRA_SFTP_USER: atra
ATRA_SFTP_PASSWORD: atra
NATIONAL_PKI_CRL_URL: http://mock-national-pki-ca:8089/crl
COMPLIANCE_GRPC: mock-compliance:50055
CDR_GRPC: mock-cdr-mediation:50075
CONSENT_GRPC: mock-consent-ledger:50076
SENDER_ID_GRPC: mock-sender-id:50078
LI_SLA_ACK_HOURS: "1"

regulator-portal-siem:
image: ghasi/regulator-portal-service:dev
depends_on: [nats, mock-splunk-hec, mock-qradar, mock-logstash]
environment:
NODE_ENV: development
NATS_URL: nats://nats:4222
SIEM_DEST_SPLUNK_URL: http://mock-splunk-hec:8088/services/collector
SIEM_DEST_QRADAR_HOST: mock-qradar
SIEM_DEST_LOGSTASH_URL: http://mock-logstash:5044
command: ["node", "dist/apps/siem-forwarder/main.js"]
volumes:
- reg_siem_wal:/var/lib/siem-wal

regulator-portal-web:
image: ghasi/regulator-portal-web:dev
depends_on: [regulator-portal-api]
ports: ["3081:3081"]
environment:
NODE_ENV: development
API_URL: http://regulator-portal-api:3082

volumes:
reg_pg_data:
reg_hsm_data:
reg_atra_sftp:
reg_minio_data:
reg_siem_wal:

Start:

docker compose -f infra/docker/docker-compose.regulator-portal.yml up -d
docker compose exec softhsm /hsm-init/init.sh

# Generate test PKI if not already
cd infra/docker/regulator-portal/test-pki && ./generate-test-pki.sh

3. Test PKI

infra/docker/regulator-portal/test-pki/:

FilePurpose
national-pki-root-ca.pemRoot CA for regulator
regulator-user-atra.{crt,key}Test ATRA user cert
regulator-user-atra-revoked.{crt,key}Revoked test cert
auditor-user-ca.{crt,key}Auditor CA (separate from national-PKI)
auditor-user-test.{crt,key}Test auditor cert (time-boxed)
crl.pemTest CRL containing revoked certs

Callers use their cert via curl:

curl --cert regulator-user-atra.crt --key regulator-user-atra.key \
https://localhost:3081/login

4. Common Commands

4.1 Test login

curl --cert regulator-user-atra.crt --key regulator-user-atra.key \
https://localhost:3082/v1/regulator/me

4.2 Submit a test LI request

curl --cert regulator-user-atra.crt --key regulator-user-atra.key \
-X POST https://localhost:3082/v1/regulator/li/requests \
-d '{"targetMsisdn":"+93701234567","dateRange":{"from":"2026-04-01","to":"2026-04-20"},"scope":"IRI","legalRef":"WAR-2026-001","signedWarrantHash":"sha256:..."}'

4.3 Advance LI state (dual-control)

# Initiator (legal team)
curl --cert ghasi-legal-test.crt --key ghasi-legal-test.key \
-X POST https://localhost:3082/v1/regulator/li/requests/li_abc/transition \
-d '{"to":"ACK"}'

# Approver (security, within 60 s)
curl --cert ghasi-security-test.crt --key ghasi-security-test.key \
-X POST https://localhost:3082/v1/regulator/li/requests/li_abc/approve \
-d '{}'

4.4 Generate a report

curl --cert regulator-user-atra.crt --key regulator-user-atra.key \
-X POST https://localhost:3082/v1/regulator/reports \
-d '{"type":"DAILY_CDR_STATUS","date":"2026-04-20"}'

Polling for completion:

curl --cert regulator-user-atra.crt --key regulator-user-atra.key \
https://localhost:3082/v1/regulator/reports/{reportId}

4.5 Ingest a complaint

curl --cert regulator-user-atra.crt --key regulator-user-atra.key \
-X POST https://localhost:3082/v1/regulator/complaints \
-d '{"citizenMsisdn":"+93701234568","complaintType":"UNSOLICITED_MARKETING","summary":"Receiving SMS I did not opt in to","receivedAt":"2026-04-21T10:00:00Z","regulatorRef":"COMP-2026-042"}'

4.6 Publish a test event for SIEM forwarder

nats pub auth.events.user.login '{"userId":"u_123","ts":"2026-04-21T10:00:00Z","ip":"192.0.2.1"}'

Then inspect mock-splunk + mock-qradar + mock-logstash for the relayed event.

4.7 Auditor flow

# Grant time-boxed auditor access (admin)
curl --cert ghasi-admin-test.crt --key ghasi-admin-test.key \
-X POST https://localhost:3082/v1/admin/regulator/auditor-access \
-d '{"auditorCertSubject":"CN=test-auditor","framework":"ISO27001","expiresAt":"2026-05-21T00:00:00Z"}'

# Auditor uses their cert
curl --cert auditor-user-test.crt --key auditor-user-test.key \
https://localhost:3082/v1/auditor/evidence?framework=ISO27001

4.8 Run tests

pnpm --filter @ghasi/regulator-portal-service test
pnpm --filter @ghasi/regulator-portal-service test:integration
pnpm --filter @ghasi/regulator-portal-service test:contract
pnpm --filter @ghasi/regulator-portal-service test:e2e:local

4.9 Reset

docker compose -f infra/docker/docker-compose.regulator-portal.yml down -v
docker compose -f infra/docker/docker-compose.regulator-portal.yml up -d
docker compose exec softhsm /hsm-init/init.sh

5. Environment Variables

Covered in Docker Compose above. Dev-only flags:

VariablePurpose
DEV_DISABLE_OCSP_STAPLESkip OCSP staple requirement (dev only)
DEV_ACCEPT_SELF_SIGNEDFor local dev; prod rejects
SIEM_WAL_PATH/var/lib/siem-wal

6. Troubleshooting

SymptomCauseFix
Login returns 401 despite valid certCA trust chain not loadedRegenerate test PKI + restart
Login returns CRL_REVOKED unexpectedlyCRL cache stalecurl http://mock-national-pki-ca:8089/refresh-crl
SIEM forwarder shows no eventsSubject mismatch or subscriber not healthynats stream info; check forwarder logs
LI delivery hangsMock SFTP not runningdocker compose ps; restart
Report generation fails with UPSTREAM_UNAVAILABLEMock upstream not runningCheck individual mocks
HSM sign failssofthsm not initialised/hsm-init/init.sh