Skip to content

API Gateway

Purpose

Unified API Gateway providing dynamic gRPC service discovery, JSON-to-Protobuf invocation, REST API generation from proto annotations, distributed state management, and pub/sub event streaming for all backend Virtufin services.

Requirements

Requirement: Dynamic Service Discovery

The gateway SHALL discover available backend gRPC services and their methods via gRPC reflection, without requiring pre-compiled proto stubs for each backend.

Scenario: List known services

  • WHEN a client calls ListServices
  • THEN the gateway SHALL return all services defined in its configuration

Scenario: List methods for a service

  • WHEN a client calls ListMethods for a configured service
  • THEN the gateway SHALL return all gRPC methods discovered via reflection from that backend

Scenario: Schema introspection

  • WHEN a client requests a method's input/output schema
  • THEN the gateway SHALL return the full Protobuf message descriptor including field names, types, and oneof groups

Scenario: Reflection cache invalidation

  • WHEN a backend service is redeployed with new methods
  • THEN the gateway SHALL support invalidating its reflection cache for that service

Requirement: Dynamic gRPC Invocation

The gateway SHALL invoke gRPC methods on backend services without pre-compiled client stubs, using the method name and JSON payload provided at runtime.

Scenario: JSON-to-Protobuf invocation

  • WHEN a client sends a JSON payload with a service name and method name
  • THEN the gateway SHALL dynamically marshal the JSON into the method's Protobuf input type, invoke the backend, and return the Protobuf output as JSON

Scenario: Raw bytes invocation

  • WHEN a client sends a raw Protobuf-encoded byte payload
  • THEN the gateway SHALL forward it directly to the backend method and return the raw response bytes

Requirement: REST API from Proto Annotations

The gateway SHALL expose REST/HTTP endpoints equivalent to each gRPC method that has google.api.http annotations. gRPC-Web SHALL be enabled on all endpoints.

Scenario: GET endpoint

  • WHEN a gRPC method defines a google.api.http.get annotation
  • THEN the gateway SHALL serve that endpoint as an HTTP GET on the annotated path

Scenario: POST endpoint

  • WHEN a gRPC method defines a google.api.http.post annotation with a body field
  • THEN the gateway SHALL serve that endpoint as an HTTP POST, mapping the JSON body to the Protobuf field

Scenario: gRPC-Web browser access

  • WHEN a browser client connects via gRPC-Web
  • THEN the gateway SHALL upgrade the request and forward it as native gRPC to the backend

Requirement: Distributed State Management

The gateway SHALL provide CRUD operations on the Dapr state store with optimistic concurrency control via ETags. State changes SHALL emit events.

Scenario: Save state with ETag

  • WHEN a client saves state with an ETag that matches the stored value
  • THEN the save SHALL succeed and the new ETag SHALL be returned

Scenario: Save state with stale ETag

  • WHEN a client saves state with an ETag that does not match the stored value
  • THEN the save SHALL fail with a concurrency conflict error

Scenario: State change events

  • WHEN state is saved or deleted for a registered key
  • THEN a state change event SHALL be published to Dapr pub/sub on a well-known topic

Scenario: Bulk state retrieval

  • WHEN a client requests all state for a registered service
  • THEN the gateway SHALL return all stored key-value pairs

Requirement: Pub/Sub and Event Streaming

The gateway SHALL support publishing events to Dapr pub/sub topics and subscribing clients to topic events via server-side streaming. Dead subscriptions SHALL be cleaned up.

Scenario: Publish event

  • WHEN a client publishes an event to a topic
  • THEN the gateway SHALL forward it to Dapr pub/sub on that topic

Scenario: Subscribe to events

  • WHEN a client opens a server-side streaming subscription to a topic
  • THEN all events published to that topic SHALL be streamed to the client until the subscription is cancelled

Scenario: Dead subscription cleanup

  • WHEN a subscriber's connection drops without explicit unsubscribe
  • THEN the gateway SHALL detect the dead subscription and remove it within one minute

Requirement: Service Configuration

The gateway SHALL load per-service configuration from a JSON or YAML file, specifying each backend's gRPC host/port, Dapr app ID, pubsub component, state store, and optional cron jobs.

Scenario: Configuration hot-reload

  • WHEN the services configuration file is updated
  • THEN the gateway SHOULD reload the configuration without restarting

Requirement: API Documentation

The gateway SHALL expose an OpenAPI/Swagger specification describing all REST endpoints.

Scenario: Swagger UI

  • WHEN a developer navigates to /swagger
  • THEN the interactive API documentation SHALL be served