saga-full — services reference

One shared shape, six services, real per-service differences.

Every Kafka-driven service in this repo follows the same outbox-then-poll shape (see Saga Flow for the pattern itself). The table below is what actually differs per service — port, topics, schema, and the one detail worth knowing about each.

HTTP Controller (2 of 6) Domain Write Outbox Row (same txn) Poller (SKIP LOCKED) Kafka Publish Consumer

Only order-service and api-gateway-service expose an HTTP controller — payment-service and restaurant-service are Kafka-driven only (their web/actuator starters exist purely for health probes), and user-service is gRPC-only with no outbox at all.

Service Port / protocol Publishes Consumes Schema Worth knowing
user-contract n/a — contract only ValidateToken RPC has zero real callers in this repo — see the callout below.
user-service 9090 gRPC only user_service_schema No outbox, no HTTP surface. Login's three failure modes all collapse to one generic UNAUTHENTICATED (login-enumeration fix).
order-service 8081 HTTP order-created-topic restaurant-approved-topic, restaurant-rejected-topic order_service_schema The saga's entry point and sole owner of order lifecycle state. Ships the outbox row's raw JSON as-is — no deserialize/reserialize round trip.
payment-service 8082 health only payment-processed-topic order-created-topic, restaurant-rejected-topic payment_service_schema Two consumer groups on two different topics — one charges, the other (payment-compensation-group) is the saga's real compensating transaction.
restaurant-service 8083 health only restaurant-approved-topic or restaurant-rejected-topic payment-processed-topic restaurant_service_schema The one service whose outbox publisher routes to one of two topics by eventType, not a fixed single topic. InventoryItem uses a natural-key String itemCode, not a UUID.
api-gateway-service 8080 HTTP (WebFlux) — (proxies only) — (gRPC client + HTTP routing, no Kafka) Verifies JWTs locally against the same HMAC secret user-service signs with, not via ValidateToken. Circuit breaker falls back to /fallback/orders.
!

user.proto's ValidateToken RPC is fully implemented and tested but has no real caller anywhere in this repo — the original plan was for api-gateway-service to call it on every guarded request; what got built instead verifies locally (see the gateway row above). Not a bug — local verification is itself a legitimate pattern — but it's tested API surface built against a stated intent that was never wired up. Flagged during the code-review audit, not fixed.