LOCAL_DEV_SETUP — bff-tenant-booking-service
Sibling: DEPLOYMENT_TOPOLOGY · TESTING_STRATEGY · DATA_MODEL
1. Prerequisites
| Tool | Version | Notes |
|---|---|---|
| Node.js | 20.x LTS | engines.node = "20.x" |
| pnpm | 9.x | Workspace package manager |
| Docker Desktop | latest | Required for Postgres + Redis + Pub/Sub emulator |
| Docker Compose | v2 | Bundled |
| Google Cloud SDK | latest | For impersonating SAs against staging |
mkcert | latest | Local TLS for cookie Secure flag |
gh CLI | latest | PR helpers |
2. One-time setup
gh repo clone ghasitech/ghasi-melmastoon
cd ghasi-melmastoon
pnpm install --frozen-lockfile
mkcert -install
mkcert -cert-file ./certs/local.pem -key-file ./certs/local-key.pem \
'*.local.melmastoon.test' localhost
cp services/bff-tenant-booking-service/.env.example services/bff-tenant-booking-service/.env.local
Edit .env.local:
NODE_ENV=development
PORT=8082
LOG_LEVEL=debug
DATABASE_URL=postgres://bff_tenant:bff_tenant@localhost:5441/bff_tenant
REDIS_CACHE_URL=redis://localhost:6391/0
REDIS_SESSION_URL=redis://localhost:6392/0
PUBSUB_PROJECT_ID=local
PUBSUB_EMULATOR_HOST=localhost:8085
BFF_TENANT_BOOKING_HANDOFF_HMAC_KEY_CURRENT=dev-rotating-key-do-not-ship-001
BFF_TENANT_BOOKING_HANDOFF_HMAC_KEY_PREVIOUS=
BFF_TENANT_BOOKING_PEPPER=dev-pepper-do-not-ship
UPSTREAM_TENANT_BASE_URL=http://localhost:8094
UPSTREAM_THEME_BASE_URL=http://localhost:8093
UPSTREAM_PROPERTY_BASE_URL=http://localhost:8092
UPSTREAM_INVENTORY_BASE_URL=http://localhost:8095
UPSTREAM_PRICING_BASE_URL=http://localhost:8091
UPSTREAM_RESERVATION_BASE_URL=http://localhost:8096
UPSTREAM_PAYMENT_BASE_URL=http://localhost:8097
UPSTREAM_BILLING_BASE_URL=http://localhost:8098
UPSTREAM_LOCK_BASE_URL=http://localhost:8099
UPSTREAM_AI_BASE_URL=http://localhost:8100
UPSTREAM_BFF_CONSUMER_BASE_URL=http://localhost:8081
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
3. Stand up dependencies
docker compose -f services/bff-tenant-booking-service/docker-compose.dev.yml up -d
# Brings up:
# postgres (5441 → 5432) seeded with sample tenant, draft snapshots
# redis-cache (6391 → 6379)
# redis-session (6392 → 6379)
# pubsub-emulator (8085)
# wiremock-* for every upstream
# bff-consumer-stub (8081) for handoff handshake
# payment-stub (8097) — issues fake intents + verify-return outcomes
# otel-collector + jaeger (16686)
4. Run the service
pnpm --filter @ghasi/service-bff-tenant-booking dev
# starts in watch mode on https://kabul-grand-hotel.local.melmastoon.test:8082
Smoke check:
curl -k https://kabul-grand-hotel.local.melmastoon.test:8082/api/health/ready
curl -k -c /tmp/c.jar -b /tmp/c.jar \
-H 'Accept-Language: ps-AF' \
https://kabul-grand-hotel.local.melmastoon.test:8082/api/bff/tenant-booking/v1/kabul-grand-hotel/bootstrap
Trace appears in Jaeger UI at http://localhost:16686.
5. Common commands
| Command | Purpose |
|---|---|
pnpm --filter @ghasi/service-bff-tenant-booking dev | Run with hot reload |
pnpm --filter @ghasi/service-bff-tenant-booking test:unit | Vitest unit tests |
pnpm --filter @ghasi/service-bff-tenant-booking test:integration | Vitest + Testcontainers |
pnpm --filter @ghasi/service-bff-tenant-booking test:contract | Pact consumer + provider |
pnpm --filter @ghasi/service-bff-tenant-booking test:e2e:local | Playwright against local stack |
pnpm --filter @ghasi/service-bff-tenant-booking lint | ESLint + import-boundary rules |
pnpm --filter @ghasi/service-bff-tenant-booking typecheck | tsc --noEmit |
pnpm --filter @ghasi/service-bff-tenant-booking migrate | Drizzle migrations |
pnpm --filter @ghasi/service-bff-tenant-booking migrate:make <name> | New migration |
pnpm --filter @ghasi/service-bff-tenant-booking seed | Seed dev tenants + sample drafts |
pnpm --filter @ghasi/service-bff-tenant-booking openapi | Regenerate OpenAPI |
6. Working against real upstreams (staging)
gcloud auth application-default login
gcloud auth print-identity-token --impersonate-service-account=bff-tenant-sa@melmastoon-stage.iam.gserviceaccount.com
# Override in .env.local:
UPSTREAM_TENANT_BASE_URL=https://tenant.staging.melmastoon.internal
# ... etc
USE_GOOGLE_ID_TOKEN=true
7. Seed data
pnpm seed:
- 5 tenants (
tnt_kabul_grand, etc.) with full theme + flow config. - 60 properties.
- Pre-baked PriceQuote fixtures for the WireMock pricing stub.
- 10 sample BookingDraftSnapshot rows (5 abandoned, 5 converted) for analytics dev.
- 1 valid handoff token in clipboard form:
pnpm seed:handoffprints a token bound to local HMAC key.
Pub/Sub emulator topics auto-created on first publish.
8. Useful local URLs
| URL | Purpose |
|---|---|
https://kabul-grand-hotel.local.melmastoon.test:8082/api/health/ready | Readiness |
https://kabul-grand-hotel.local.melmastoon.test:8082/api/bff/tenant-booking/v1/kabul-grand-hotel/bootstrap | Bootstrap |
http://localhost:16686 | Jaeger trace explorer |
http://localhost:8090/__admin | WireMock admin |
http://localhost:8097/__admin | Payment-stub admin (toggle outcomes) |
9. Resetting state
docker compose -f services/bff-tenant-booking-service/docker-compose.dev.yml down -v
docker compose -f services/bff-tenant-booking-service/docker-compose.dev.yml up -d
pnpm --filter @ghasi/service-bff-tenant-booking migrate
pnpm --filter @ghasi/service-bff-tenant-booking seed
10. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
MELMASTOON.BFF.TENANT.SLUG_UNKNOWN on local | tenant-stub not seeded | pnpm seed or restart compose |
MELMASTOON.BFF.TENANT.HANDOFF_SIGNATURE_INVALID | local HMAC key rotated | pnpm seed:handoff to mint a fresh one |
MELMASTOON.PAYMENT.GATEWAY_TIMEOUT repeatedly | payment-stub configured to return timeout | Hit http://localhost:8097/__admin/mappings and reset |
Cookie not set on curl | Secure flag rejected on plain HTTP | Use https URL with mkcert cert |
| WireMock fixture missing for upstream call | New endpoint not stubbed | Add fixture in services/bff-tenant-booking-service/test/fixtures/wiremock/<service>/; restart |
| Pact verification fails locally | Stale broker pact | pnpm test:contract -- --pull-pacts |