Router
Verified against commit
942a18727c(2026-09-26, DOC-2 of SPRINT_20260926_001). Re-verify by reading the evidence paths listed in the Evidence section of architecture.md.
Service wiring (image, database and role, compose profile, bundle presence) is generated in the service inventory; this dossier does not restate it.
Internal communication fabric for Stella Ops: the single HTTP front door (
router-gateway) and the binary transports that connect it to the platform microservices.
The Stella Ops Router is the HTTP ingress and internal routing layer. The gateway (StellaOps.Gateway.WebService) terminates HTTPS, validates tokens, signs an identity envelope, serves the Angular console, and dispatches API requests to microservices over binary transports with health-aware routing, claims-based authorization and centralized admission control. It owns no database.
Why a dedicated router
- One routing authority: services publish their endpoints in a HELLO frame; the gateway routes to them without a per-service route-table entry.
- Streaming: first-class support for large payloads (SBOMs, scan results, evidence bundles).
- Cancellation: request abortion propagates across service boundaries (
Cancelframes). - Health-aware routing: instance selection uses heartbeat recency and latency.
- Claims-based authorization: unified enforcement at the gateway, with Authority overrides.
- Transport flexibility: Messaging over Valkey in the deployed estate, TLS for certificate-based streams, RabbitMQ; TCP and UDP are development-only.
- Centralized rate limiting: admission control at the gateway (429 + Retry-After).
Architecture Overview
┌─────────────────────────────────┐
│ router-gateway │
HTTP Clients ────────────────────► (StellaOps.Gateway.WebService) │
│ │
│ ┌─────────────────────────────┐│
│ │ Endpoint Resolution ││
│ │ Authorization (Claims) ││
│ │ Routing Decision ││
│ │ Transport Dispatch ││
│ └─────────────────────────────┘│
└──────────────┬──────────────────┘
│ binary frames
┌─────────────────────────┼─────────────────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Microservice A │ │ Microservice B │ │ Microservice C │
│ Messaging/Valkey│ │ Messaging/Valkey│ │ TLS │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Deployment
| Attribute | Value |
|---|---|
| Compose service | router-gateway (release bundle devops/release/bundle/docker-compose.yml; development estate devops/compose/docker-compose.stella-services.yml) |
| Network aliases | router.stella-ops.local, stella-ops.local |
| Container ports | 8080 (HTTP), 443 (HTTPS); bundle host ports STELLA_HTTP_PORT (default 8080) and STELLA_HTTPS_PORT (default 8443) |
| Route configuration | devops/release/bundle/config/router-gateway.json mounted as /app/appsettings.json |
| State | Valkey (Messaging transport); no PostgreSQL |
| Health check | GET /health/ready must return 200 |
Components
| Component | Project | Purpose |
|---|---|---|
| Gateway | StellaOps.Gateway.WebService | HTTP ingress, routing, authorization; the router-gateway deployable |
| Microservice SDK | StellaOps.Microservice | SDK for building microservices |
| Source Generator | StellaOps.Microservice.SourceGen | Compile-time endpoint discovery |
| Common | StellaOps.Router.Common | Shared types, frames, transport abstractions, transport plugin loader |
| Config | StellaOps.Router.Config | Configuration models, YAML binding |
| Gateway library | StellaOps.Router.Gateway | Gateway DI/composition (AddRouterGateway, UseRouterGateway), routing state, route model, microservice-pipeline middleware |
| Local harness | StellaOps.Router.Gateway.LocalInMemoryHarness | AddRouterGatewayLocalInMemoryHarness, in-memory transport for Development/Testing/Local hosts only |
| ASP.NET bridge | StellaOps.Router.AspNet | Maps ASP.NET endpoint registrations as Router endpoints (AddRouterMicroservice) |
| Microservice AspNetCore bridge | StellaOps.Microservice.AspNetCore | Hosts a Router microservice inside an ASP.NET Core app; identity population and trust mode |
| InMemory Transport | StellaOps.Router.Transport.InMemory | Testing transport |
| TCP Transport | StellaOps.Router.Transport.Tcp | Development-only transport (insecure-transport gate) |
| TLS Transport | StellaOps.Router.Transport.Tls | Certificate-based TCP transport (TransportType.Certificate) |
| UDP Transport | StellaOps.Router.Transport.Udp | Development-only small-payload transport |
| RabbitMQ Transport | StellaOps.Router.Transport.RabbitMq | Message queue transport |
| Messaging Transport | StellaOps.Router.Transport.Messaging | Messaging/RPC transport over StellaOps.Messaging (Valkey, Postgres, InMemory backends) |
| Messaging | StellaOps.Messaging, StellaOps.Messaging.Transport.{InMemory,Postgres,Valkey} | Queue abstraction and backends |
| Unified transport plugin adapter | StellaOps.Router.Plugin.Unified | Adapts IRouterTransportPlugin to the unified IPlugin / ITransportCapability interfaces. No host or src/Router/StellaOps.Router.sln entry references it (it is listed only in src/StellaOps.sln). |
Transport selection is driven by the StellaOps.Router.Common.Enums.TransportType enum: InMemory, Udp, Tcp, Certificate (TLS/mTLS), RabbitMq, and Messaging. HTTP is excluded by design (see Invariants).
Gateway-owned endpoints
Beyond proxying microservice routes, the gateway hosts health, metrics, OpenAPI and build-info aggregation, product-security metadata, Doctor checks, plugin diagnostics, routing administration (router:routing:read / router:routing:write) and the operator verify surface (operator.verify.read / operator.verify.admin). The complete table with scopes and sources is in architecture.md, Gateway-owned HTTP endpoints.
Solution Structure
The solution file is src/Router/StellaOps.Router.sln. Libraries live under src/Router/__Libraries/ and tests under src/Router/__Tests/.
src/Router/
├── StellaOps.Router.sln
├── StellaOps.Gateway.WebService/ (HTTP ingress / gateway host)
├── StellaOps.Router.Plugin.Unified/ (unified transport plugin adapter)
├── __Libraries/
│ ├── StellaOps.Router.Common/
│ ├── StellaOps.Router.Config/
│ ├── StellaOps.Router.Gateway/
│ ├── StellaOps.Router.Gateway.LocalInMemoryHarness/
│ ├── StellaOps.Router.AspNet/
│ ├── StellaOps.Router.Transport.InMemory/
│ ├── StellaOps.Router.Transport.Tcp/
│ ├── StellaOps.Router.Transport.Tls/
│ ├── StellaOps.Router.Transport.Udp/
│ ├── StellaOps.Router.Transport.RabbitMq/
│ ├── StellaOps.Router.Transport.Messaging/
│ ├── StellaOps.Microservice/
│ ├── StellaOps.Microservice.AspNetCore/
│ ├── StellaOps.Microservice.SourceGen/
│ ├── StellaOps.Messaging/
│ ├── StellaOps.Messaging.Transport.InMemory/
│ ├── StellaOps.Messaging.Transport.Postgres/
│ └── StellaOps.Messaging.Transport.Valkey/
├── __Tests/
│ └── (test projects)
└── examples/
Key Documents
Module Documentation (this directory)
| Document | Purpose |
|---|---|
| architecture.md | Canonical specification |
| schema-validation.md | JSON Schema validation feature |
| openapi-aggregation.md | OpenAPI document generation |
| migration-guide.md | WebService to Microservice migration |
| rate-limiting.md | Centralized router rate limiting |
| aspnet-endpoint-bridge.md | Using ASP.NET endpoint registration as Router endpoint registration |
| aspnet-request-cancellation.md | Request cancellation through the ASP.NET bridge |
| messaging-valkey-transport.md | Messaging transport over Valkey |
| microservice-transport-guardrails.md | Plugin-only transport guardrails and migration PR checklist |
| authority-gateway-enforcement-runbook.md | Operations runbook for gateway-enforced auth and signed identity envelope trust |
| IDENTITY_ENVELOPE_MIDDLEWARE.md | Signed identity-envelope middleware (HMAC-SHA256) reference |
| webservice-integration-guide.md | Integrating an existing ASP.NET WebService behind the gateway |
| transports/README.md | Transport plugin reference |
| timelineindexer-microservice-pilot.md | Historical: TimelineIndexer Valkey transport pilot (the TimelineIndexer hosts are retired) |
| webservices-valkey-rollout-matrix.md | Historical: all-webservices Valkey migration matrix |
| rollout-acceptance-20260222.md | Historical: dual-mode rollout acceptance package (2026-02-22) |
Implementation Guides (docs/modules/router/guides/)
| Document | Purpose |
|---|---|
| GETTING_STARTED.md | Step-by-step setup guide |
| rate-limiting-config.md | Rate limiting configuration guide |
| rate-limiting-routes.md | Per-route rate-limiting configuration |
Runbooks
- add-router-transport.md - build and deploy a signed transport plugin
- local-runtime-replay.md - replay and verify the local runtime route boundary
Quick Start
Gateway (library composition)
The deployable gateway is StellaOps.Gateway.WebService. A custom host composes the gateway library like this; the in-memory harness is registered only for Development, Testing or Local environments:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRouterGateway(builder.Configuration);
builder.Services.AddRouterGatewayLocalInMemoryHarness(builder.Environment); // local harness only
var app = builder.Build();
app.UseRouterGateway();
await app.RunAsync();
Microservice
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddStellaMicroservice(options =>
{
options.ServiceName = "billing";
options.Version = "1.0.0";
options.Region = "us-east-1";
});
builder.Services.AddInMemoryTransportClient();
await builder.Build().RunAsync();
Endpoint Definition
[StellaEndpoint("POST", "/invoices")]
[ValidateSchema(Summary = "Create invoice")]
public sealed class CreateInvoiceEndpoint : IStellaEndpoint<CreateInvoiceRequest, CreateInvoiceResponse>
{
public Task<CreateInvoiceResponse> HandleAsync(
CreateInvoiceRequest request,
CancellationToken ct)
{
return Task.FromResult(new CreateInvoiceResponse
{
InvoiceId = Guid.NewGuid().ToString()
});
}
}
Invariants
These are non-negotiable design constraints:
- Method + Path is the endpoint identity (see
StellaEndpointAttribute(method, path)) - Strict semver for version matching
- Region from node config: the gateway region comes from
RouterNodeConfig.Region(config sectionGatewayNode, legacyRouter:Node; the gateway host mapsGateway:Nodeonto it); it is never derived from headers or URLs - No HTTP transport between gateway and microservices (HTTP is excluded from the
TransportTypeenum) - Claims, not roles, for endpoint authorization at the gateway: a microservice declares
StellaEndpointAttribute.RequiredClaims(string array), which is published asEndpointDescriptor.RequiringClaims - Opaque body handling (the router does not interpret payloads)
Building
# Build router solution
dotnet build src/Router/StellaOps.Router.sln
# Run tests
dotnet test src/Router/StellaOps.Router.sln
# Run gateway
dotnet run --project src/Router/StellaOps.Gateway.WebService
