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
ListMethodsfor 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.getannotation - 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.postannotation 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