Skip to main content

LOCAL_DEV_SETUP — bff-tenant-booking-service

Sibling: DEPLOYMENT_TOPOLOGY · TESTING_STRATEGY · DATA_MODEL

1. Prerequisites

ToolVersionNotes
Node.js20.x LTSengines.node = "20.x"
pnpm9.xWorkspace package manager
Docker DesktoplatestRequired for Postgres + Redis + Pub/Sub emulator
Docker Composev2Bundled
Google Cloud SDKlatestFor impersonating SAs against staging
mkcertlatestLocal TLS for cookie Secure flag
gh CLIlatestPR 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

CommandPurpose
pnpm --filter @ghasi/service-bff-tenant-booking devRun with hot reload
pnpm --filter @ghasi/service-bff-tenant-booking test:unitVitest unit tests
pnpm --filter @ghasi/service-bff-tenant-booking test:integrationVitest + Testcontainers
pnpm --filter @ghasi/service-bff-tenant-booking test:contractPact consumer + provider
pnpm --filter @ghasi/service-bff-tenant-booking test:e2e:localPlaywright against local stack
pnpm --filter @ghasi/service-bff-tenant-booking lintESLint + import-boundary rules
pnpm --filter @ghasi/service-bff-tenant-booking typechecktsc --noEmit
pnpm --filter @ghasi/service-bff-tenant-booking migrateDrizzle migrations
pnpm --filter @ghasi/service-bff-tenant-booking migrate:make <name>New migration
pnpm --filter @ghasi/service-bff-tenant-booking seedSeed dev tenants + sample drafts
pnpm --filter @ghasi/service-bff-tenant-booking openapiRegenerate 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:handoff prints a token bound to local HMAC key.

Pub/Sub emulator topics auto-created on first publish.

8. Useful local URLs

URLPurpose
https://kabul-grand-hotel.local.melmastoon.test:8082/api/health/readyReadiness
https://kabul-grand-hotel.local.melmastoon.test:8082/api/bff/tenant-booking/v1/kabul-grand-hotel/bootstrapBootstrap
http://localhost:16686Jaeger trace explorer
http://localhost:8090/__adminWireMock admin
http://localhost:8097/__adminPayment-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

SymptomLikely causeFix
MELMASTOON.BFF.TENANT.SLUG_UNKNOWN on localtenant-stub not seededpnpm seed or restart compose
MELMASTOON.BFF.TENANT.HANDOFF_SIGNATURE_INVALIDlocal HMAC key rotatedpnpm seed:handoff to mint a fresh one
MELMASTOON.PAYMENT.GATEWAY_TIMEOUT repeatedlypayment-stub configured to return timeoutHit http://localhost:8097/__admin/mappings and reset
Cookie not set on curlSecure flag rejected on plain HTTPUse https URL with mkcert cert
WireMock fixture missing for upstream callNew endpoint not stubbedAdd fixture in services/bff-tenant-booking-service/test/fixtures/wiremock/<service>/; restart
Pact verification fails locallyStale broker pactpnpm test:contract -- --pull-pacts