Skip to content

Cross-cutting

Purpose

Shared infrastructure, security, observability, and resilience requirements that apply across all Virtufin services. Every service SHALL conform to these requirements.

Requirements

Requirement: Dapr Service Mesh Integration

Every service SHALL run with a Dapr sidecar providing state management, pub/sub messaging, and service-to-service invocation. Service code SHALL NOT connect directly to infrastructure backends.

Scenario: Sidecar communication

  • WHEN a service needs to read/write persistent state
  • THEN it SHALL use the Dapr state management API via the sidecar (HTTP :3500 or gRPC :50001)

Scenario: Event publishing

  • WHEN a service publishes a domain event
  • THEN it SHALL use the Dapr pub/sub API through the configured pubsub component

Scenario: Service invocation

  • WHEN a service calls another service
  • THEN it SHALL use Dapr service invocation or direct gRPC with mTLS; no unauthenticated calls

Requirement: Observability

Every service SHALL emit OpenTelemetry traces and metrics. Health checks SHALL gate readiness until the service is fully initialized.

Scenario: Distributed tracing

  • WHEN a request is processed across multiple services
  • THEN each span SHALL be exported to the configured OpenTelemetry collector with correlation context

Scenario: Liveness and readiness

  • WHEN a service starts up and before it recovers its persistent state
  • THEN the readiness health check SHALL fail, preventing traffic routing

Scenario: Startup recovery

  • WHEN a service restarts after a crash
  • THEN it SHALL restore its persisted state from the Dapr state store before marking itself healthy

Requirement: Resilience

All Dapr operations and external calls SHALL use retry with exponential backoff and circuit breaking.

Scenario: Transient Dapr failure

  • WHEN a Dapr API call fails with a transient error
  • THEN the operation SHALL be retried up to 3 times with exponential backoff before failing

Scenario: Persistent failure

  • WHEN Dapr API calls consistently fail beyond a threshold
  • THEN the circuit breaker SHALL open, failing fast for subsequent calls until the break duration elapses

Requirement: Security

All service-to-service communication SHALL be encrypted. User-supplied code execution SHALL be sandboxed. URL-based code fetching SHALL prevent SSRF.

Scenario: Service-to-service communication

  • WHEN one service communicates with another
  • THEN Dapr mTLS SHALL encrypt the connection

Scenario: SSRF prevention

  • WHEN fetching code from a user-supplied URL
  • THEN the service SHALL reject URLs targeting private IP ranges (loopback, RFC1918, link-local) unless the host is in an explicit allowlist

Requirement: Native AOT Compilation

Services targeting AOT-capable runtimes SHALL compile to native code. All JSON serialization SHALL use source-generated contexts.

Scenario: Build and deployment

  • WHEN a service is built for production
  • THEN it SHALL compile to a self-contained native binary with trimmed dependencies

Requirement: Configuration

Every service SHALL support configuration via command-line arguments, environment variables, and configuration files. Ports SHALL be configurable. Dapr component names SHALL be configurable.

Scenario: Port override

  • WHEN the HttpPort environment variable or --http-port argument is set
  • THEN the service SHALL listen on that port instead of the default

Scenario: Dapr component override

  • WHEN pubsubName is configured
  • THEN the service SHALL use the named Dapr pubsub component for all pub/sub operations

Requirement: Containerization

Every service SHALL be containerizable as a minimal Docker image based on the chiseled runtime image.

Scenario: Docker build

  • WHEN a service's Dockerfile is built
  • THEN the resulting image SHALL contain only the native AOT binary and its runtime dependencies on a runtime-deps base