# Gateway OpenAPI Implementation This document describes the implementation architecture of OpenAPI document aggregation in the StellaOps Router Gateway. ## Architecture The Gateway generates OpenAPI 3.1.0 documentation by aggregating schemas and endpoint metadata from connected microservices. ### Component Overview ``` ┌─────────────────────────────────────────────────────────────────────┐ │ Gateway │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────┐ ┌────────────────────┐ │ │ │ ConnectionManager │───►│ InMemoryRoutingState│ │ │ │ │ │ │ │ │ │ - OnHelloReceived │ │ - Connections[] │ │ │ │ - OnConnClosed │ │ - Endpoints │ │ │ └──────────────────┘ │ - Schemas │ │ │ │ └─────────┬──────────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌──────────────────┐ ┌────────────────────┐ │ │ │ OpenApiDocument │◄───│ GatewayOpenApi │ │ │ │ Cache │ │ DocumentCache │ │ │ │ │ │ │ │ │ │ - Invalidate() │ │ - TTL expiration │ │ │ └──────────────────┘ │ - ETag generation │ │ │ └─────────┬──────────┘ │ │ │ │ │ ▼ │ │ ┌────────────────────┐ │ │ │ OpenApiDocument │ │ │ │ Generator │ │ │ │ │ │ │ │ - GenerateInfo() │ │ │ │ - GeneratePaths() │ │ │ │ - GenerateTags() │ │ │ │ - GenerateSchemas()│ │ │ └─────────┬──────────┘ │ │ │ │ │ ▼ │ │ ┌────────────────────┐ │ │ │ ClaimSecurity │ │ │ │ Mapper │ │ │ │ │ │ │ │ - SecuritySchemes │ │ │ │ - SecurityRequire │ │ │ └────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────┘ ``` ### Components | Component | File | Responsibility | |-----------|------|----------------| | `IOpenApiDocumentGenerator` | `OpenApi/IOpenApiDocumentGenerator.cs` | Interface for document generation | | `OpenApiDocumentGenerator` | `OpenApi/OpenApiDocumentGenerator.cs` | Builds OpenAPI 3.1.0 JSON | | `IGatewayOpenApiDocumentCache` | `OpenApi/IGatewayOpenApiDocumentCache.cs` | Interface for document caching | | `GatewayOpenApiDocumentCache` | `OpenApi/GatewayOpenApiDocumentCache.cs` | TTL + invalidation caching | | `ClaimSecurityMapper` | `OpenApi/ClaimSecurityMapper.cs` | Maps claims to OAuth2 scopes | | `OpenApiEndpoints` | `OpenApi/OpenApiEndpoints.cs` | HTTP endpoint handlers | | `OpenApiAggregationOptions` | `OpenApi/OpenApiAggregationOptions.cs` | Configuration options | --- ## OpenApiDocumentGenerator Generates the complete OpenAPI 3.1.0 document from routing state. ### Process Flow 1. **Collect connections** from `IGlobalRoutingState` 2. **Generate info** section from `OpenApiAggregationOptions` 3. **Generate paths** by iterating all endpoints across connections 4. **Generate components** including schemas and security schemes 5. **Generate tags** from unique service names ### Schema Handling Schemas are prefixed with service name to avoid naming conflicts: ```csharp var prefixedId = $"{conn.Instance.ServiceName}_{schemaId}"; // billing_CreateInvoiceRequest ``` ### Operation ID Generation Operation IDs follow a consistent pattern: ```csharp var operationId = $"{serviceName}_{path}_{method}"; // billing_invoices_POST ``` --- ## GatewayOpenApiDocumentCache Implements caching with TTL expiration and content-based ETags. ### Cache Behavior | Trigger | Action | |---------|--------| | First request | Generate and cache document | | Subsequent requests (within TTL) | Return cached document | | TTL expired | Regenerate document | | Connection added/removed | Invalidate cache | ### ETag Generation ETags are computed from SHA256 hash of document content: ```csharp var hash = SHA256.HashData(Encoding.UTF8.GetBytes(documentJson)); var etag = $"\"{Convert.ToHexString(hash)[..16]}\""; ``` ### Thread Safety The cache uses locking to ensure thread-safe regeneration: ```csharp lock (_lock) { if (_cachedDocument is null || IsExpired()) { RegenerateDocument(); } } ``` --- ## ClaimSecurityMapper Maps endpoint claim requirements to OpenAPI security schemes. ### Security Scheme Generation Always generates `BearerAuth` scheme. Generates `OAuth2` scheme only when endpoints have claim requirements: ```csharp public static JsonObject GenerateSecuritySchemes( IEnumerable endpoints, string tokenUrl) { var schemes = new JsonObject(); // Always add BearerAuth schemes["BearerAuth"] = new JsonObject { ... }; // Collect scopes from all endpoints var scopes = CollectScopes(endpoints); // Add OAuth2 only if scopes exist if (scopes.Count > 0) { schemes["OAuth2"] = GenerateOAuth2Scheme(tokenUrl, scopes); } return schemes; } ``` ### Per-Operation Security Each endpoint with claims gets a security requirement: ```csharp public static JsonArray GenerateSecurityRequirement(EndpointDescriptor endpoint) { if (endpoint.RequiringClaims.Count == 0) return new JsonArray(); // No security required return new JsonArray { new JsonObject { ["BearerAuth"] = new JsonArray(), ["OAuth2"] = new JsonArray(claims.Select(c => c.Type)) } }; } ``` --- ## Configuration Reference ### OpenApiAggregationOptions | Property | Type | Default | Description | |----------|------|---------|-------------| | `Title` | `string` | `"StellaOps Gateway API"` | API title | | `Description` | `string` | `"Unified API..."` | API description | | `Version` | `string` | `"1.0.0"` | API version | | `ServerUrl` | `string` | `"/"` | Base server URL | | `CacheTtlSeconds` | `int` | `60` | Cache TTL | | `Enabled` | `bool` | `true` | Enable/disable | | `LicenseName` | `string` | `"AGPL-3.0-or-later"` | License name | | `ContactName` | `string?` | `null` | Contact name | | `ContactEmail` | `string?` | `null` | Contact email | | `TokenUrl` | `string` | `"/auth/token"` | OAuth2 token URL | ### YAML Configuration ```yaml OpenApi: Title: "My Gateway API" Description: "Unified API for all microservices" Version: "2.0.0" ServerUrl: "https://api.example.com" CacheTtlSeconds: 60 Enabled: true LicenseName: "AGPL-3.0-or-later" ContactName: "API Team" ContactEmail: "api@example.com" TokenUrl: "/auth/token" ``` --- ## Service Registration Services are registered via dependency injection in `ServiceCollectionExtensions`: ```csharp services.Configure( configuration.GetSection("OpenApi")); services.AddSingleton(); services.AddSingleton(); ``` Endpoints are mapped in `ApplicationBuilderExtensions`: ```csharp app.MapGatewayOpenApiEndpoints(); ``` --- ## Cache Invalidation The `ConnectionManager` invalidates the cache on connection changes: ```csharp private Task HandleHelloReceivedAsync(ConnectionState state, HelloPayload payload) { _routingState.AddConnection(state); _openApiCache?.Invalidate(); // Invalidate on new connection return Task.CompletedTask; } private Task HandleConnectionClosedAsync(string connectionId) { _routingState.RemoveConnection(connectionId); _openApiCache?.Invalidate(); // Invalidate on disconnect return Task.CompletedTask; } ``` --- ## Extension Points ### Custom Routing Plugins The Gateway supports custom routing plugins via `IRoutingPlugin`. While not directly related to OpenAPI, routing decisions can affect which endpoints are exposed. ### Future Enhancements Potential extension points for future development: - **Schema Transformers**: Modify schemas before aggregation - **Tag Customization**: Custom tag generation logic - **Response Examples**: Include example responses from connected services - **Webhooks**: Notify external systems on document changes --- ## Testing Unit tests are located in `src/Gateway/__Tests/StellaOps.Gateway.WebService.Tests/OpenApi/`: | Test File | Coverage | |-----------|----------| | `OpenApiDocumentGeneratorTests.cs` | Document structure, schema merging, tag generation | | `GatewayOpenApiDocumentCacheTests.cs` | TTL expiry, invalidation, ETag consistency | | `ClaimSecurityMapperTests.cs` | Security scheme generation from claims | ### Test Patterns ```csharp [Fact] public void GenerateDocument_WithConnections_GeneratesPaths() { // Arrange var endpoint = new EndpointDescriptor { ... }; var connection = CreateConnection("inventory", "1.0.0", endpoint); _routingState.Setup(x => x.GetAllConnections()).Returns([connection]); // Act var document = _sut.GenerateDocument(); // Assert var doc = JsonDocument.Parse(document); doc.RootElement.GetProperty("paths") .TryGetProperty("/api/items", out _) .Should().BeTrue(); } ``` --- ## See Also - [Schema Validation](../router/schema-validation.md) - JSON Schema validation in microservices - [OpenAPI Aggregation](../router/openapi-aggregation.md) - Configuration and usage guide - [API Overview](../../api/overview.md) - General API conventions