Skip to main content

api-gateway (Kong) — Domain Model

Status: populated Owner: TBD (Platform / SRE) Last updated: 2026-04-17 Companion: SERVICE_OVERVIEW · ADR-0001 · Service Template

1. Note on terminology

Kong is infrastructure, not a DDD bounded context. This document does not describe a business domain; it describes the Kong configuration model — the concepts Kong exposes and how Ghasi-SMS-Gateway maps to them. Where the service template says "aggregates / entities / value objects," read "Kong configuration objects under our naming and ownership rules."

Authoritative business domain models live in upstream services (sms-orchestrator, auth-service, billing-service, etc.).

2. Kong configuration concepts

Kong conceptDefinitionGhasi mapping
ServiceA named upstream (host + port + protocol + optional path)One per platform microservice (svc-sms-orchestrator, svc-auth, ...)
RouteA match rule (hosts, paths, methods) pointing to a ServiceOne per API path prefix — see API_CONTRACTS
PluginReusable middleware enabled at global / service / route / consumer scopeAuth, rate-limit, correlation-id, opentelemetry, http-log, prometheus
ConsumerAn identity Kong recognisesOne consumer per Ghasi account_id (when pre-provisioned)
CredentialAuth secret attached to a Consumerkey-auth (hashed API key), jwt credential (issuer + key)
UpstreamLoad-balanced target group for a ServiceKubernetes Service DNS per microservice
TargetBackend instance in an UpstreamResolved via Kube DNS; no manual targets in DB-less mode
Vault referenceSecret indirection, e.g. {vault://env/JWT_SECRET}Used for signing keys, Redis password, OTel endpoint

3. Ghasi naming conventions

ObjectName patternExample
Servicesvc-<service-name>svc-sms-orchestrator, svc-auth-service
Routert-<service-short>-<version>-<purpose>rt-sms-v1-send, rt-auth-v1-login
Consumercsm-<account_id>csm-acct_01HW9X...
Plugin instanceplg-<plugin-name>-<scope>plg-rate-limit-global, plg-jwt-default
Tagsenv:<env>, `tier:<customerinternal>, owner:`

All names are stable and referenced from the decK YAML under ops/kong/ in the application monorepo.

4. Plugin catalog (Ghasi usage)

PluginScopePurposeDetail
jwtRoute (most)Validate Bearer JWTs against auth-service JWKSSECURITY_MODEL §3
key-authRoute (SMS send, webhook test)Validate X-Api-Key headerSECURITY_MODEL §4
rate-limiting-advancedGlobal + route overridesPer-key / per-account / per-operator limits, Redis-backedAPPLICATION_LOGIC §4
request-size-limitingRouteReject oversized payloadsAPI_CONTRACTS §6
ip-restrictionRoute (admin, partner)Allow/deny listsSECURITY_MODEL §5
correlation-idGlobalInject/propagate X-Request-IdAPPLICATION_LOGIC §3
opentelemetryGlobalExport spans to OTel collectorOBSERVABILITY §5
http-logGlobalPush access logs to LokiOBSERVABILITY §3
prometheusGlobalExpose /metrics for scrapeOBSERVABILITY §2
request-transformerRoute (selected)Strip dangerous headers, inject X-Gateway-Source: kongSECURITY_MODEL §6
bot-detectionGlobalBlock obvious bot UAsSECURITY_MODEL §7
Custom: ghasi-api-key-lookup (optional)Route (SMS send, webhook)Resolve API key → account_id + scopes via cached call to auth-serviceAPPLICATION_LOGIC §5

The custom plugin is the only Ghasi-authored element. Its code lives in the application monorepo at ops/kong/plugins/ghasi-api-key-lookup/; this folder documents only its contract and behaviour.

5. Consumer model

A Kong Consumer represents an authenticated principal at the edge. Ghasi maps one Consumer per platform account (not per end-user):

  • username = csm-<account_id>
  • Tags: account_id:<id>, tier:<free|starter|pro|enterprise>, env:<staging|prod>
  • Credentials: one or more key-auth entries (rotate-in-place by issuing a second credential before revoking the first); jwt credentials with JWKS pulled from auth-service.

Consumers are provisioned by auth-service (the system of record for accounts and API keys). Sync mechanism:

  • Preferred for static consumers (partners, internal): decK YAML generated by auth-service at release time.
  • Runtime for customer API keys: the custom ghasi-api-key-lookup plugin avoids per-consumer rows — resolves the key at request time against a cached auth-service endpoint (TTL 60s).

6. Invariants

  • Every Route must point at an upstream Service; no Route references an external host directly.
  • Every public Route must enable at least one auth plugin (jwt or key-auth); CI lint rejects a Route without auth unless explicitly tagged public:true.
  • Every Route must have env:<...> and owner:<team> tags.
  • Plugin execution phase order is fixed: auth → rate-limit → request-transformer → correlation-id → opentelemetry → upstream → http-log (Kong's built-in phases; we do not rely on ordering beyond that).
  • Credentials are never stored in plaintext in YAML — use vault references.
  • No body logging. SMS message content never appears in Kong logs.

7. What this folder does not own

  • User / account / API-key domain model → services/auth-service/DOMAIN_MODEL.md.
  • SMS message / idempotency model → services/sms-orchestrator/DOMAIN_MODEL.md.
  • Billing, webhook, DLR models → their service folders.

8. Open questions

  • Per-customer Kong Consumer rows, or rely entirely on the custom ghasi-api-key-lookup plugin? Trade-off: per-consumer rate limit keys vs operational simplicity.
  • Single shared JWT realm (ghasi-platform) vs per-tenant realms.