Stella Router ASP.NET WebService Integration Guide

This guide explains how to integrate any ASP.NET Core WebService with the Stella Router for automatic endpoint discovery and dispatch.

Prerequisites

Add a project reference to StellaOps.Router.AspNet:

<ProjectReference Include="../../__Libraries/StellaOps.Router.AspNet/StellaOps.Router.AspNet.csproj" />

Integration Steps

1. Add Router Options to Service Options

In your service’s options class (e.g., MyServiceOptions.cs), add:

using StellaOps.Router.AspNet;

public class MyServiceOptions
{
    // ... existing options ...

    /// <summary>
    /// Stella Router integration configuration (disabled by default).
    /// </summary>
    public StellaRouterOptionsBase? Router { get; set; }
}

2. Register Services in Program.cs

Add the using directive:

using StellaOps.Router.AspNet;

After service registration (e.g., after AddControllers()), add:

// Stella Router integration
builder.Services.TryAddStellaRouter(
    serviceName: "my-service-name",
    version: typeof(Program).Assembly.GetName().Version?.ToString() ?? "1.0.0",
    routerOptions: options.Router);

Optional: generic microservice transport registration

For services that should auto-register transport clients from configuration, use:

builder.Services.AddRouterMicroservice(
    builder.Configuration,
    serviceName: "my-service-name",
    version: typeof(Program).Assembly.GetName().Version?.ToString() ?? "1.0.0",
    routerOptionsSection: "MyService:Router");

AddRouterMicroservice(...) keeps TryAddStellaRouter(...) behavior and registers transport clients through RouterTransportPluginLoader based on configured gateway transport types (InMemory, Tcp, Certificate/tls, Udp, RabbitMq, Messaging).
The StellaOps.Router.AspNet library does not hard-reference transport assemblies; transports are activated from plugin DLLs and environment/config values.

For Valkey messaging mode, configure:

myservice:
  router:
    enabled: true
    region: "local"
    transportPlugins:
      directory: "plugins/router/transports"
      searchPattern: "StellaOps.Router.Transport.*.dll"
    gateways:
      - host: "router.stella-ops.local"
        port: 9100
        transportType: "Messaging"
    messaging:
      transport: "valkey"
      pluginDirectory: "plugins/messaging"
      searchPattern: "StellaOps.Messaging.Transport.*.dll"
      requestQueueTemplate: "router:requests:{service}"
      responseQueueName: "router:responses"
      consumerGroup: "myservice"
      requestTimeout: "30s"
      leaseDuration: "5m"
      batchSize: 10
      heartbeatInterval: "10s"
      valkey:
        connectionString: "cache.stella-ops.local:6379"

2.2 Gateway trust mode and identity envelope verification

Service-side Router bridge can enforce gateway-issued identity semantics:

myservice:
  router:
    authorizationTrustMode: "GatewayEnforced" # ServiceEnforced | Hybrid | GatewayEnforced
    identityEnvelopeSigningKey: "${ROUTER_IDENTITY_SIGNING_KEY}"
    identityEnvelopeClockSkewSeconds: 30

2.2a Your RequireAuthorization(...) is NOT a backstop on the router path

The trust mode above decides how the principal is populated. It does not make your host enforce its policies for router-dispatched requests: AspNetRouterRequestDispatcher invokes the endpoint delegate directly and your UseAuthorization() middleware never runs. The gateway enforces the claim requirements your host published, and it publishes only what DefaultAuthorizationClaimMapper can read off your policy’s requirement objects. A policy built with RequireAssertion(...) publishes nothing — the gateway then authenticates the caller and lets any token through (SPRINT_20260904_003 ROA-1, measured live 2026-09-04).

Do this:

2.3 Timeout precedence

Gateway dispatch timeout is now resolved with explicit precedence:

  1. Endpoint timeout (including endpoint override/service default published by service).
  2. Route default timeout (optional per gateway route via defaultTimeout).
  3. Gateway routing default timeout (Gateway:Routing:DefaultTimeout).
  4. Global gateway cap (Gateway:Routing:GlobalTimeoutCap).

Route-level timeout example:

gateway:
  routing:
    defaultTimeout: "30s"
    globalTimeoutCap: "120s"
  routes:
    - type: Microservice
      path: "/api/v1/timeline"
      translatesTo: "http://timeline.stella-ops.local/api/v1/timeline"
      defaultTimeout: "15s"

When gateway route prefixes overlap with UI routes (for example /policy), browser navigations must still resolve to the SPA shell.
Gateway RouteDispatchMiddleware now serves the configured static SPA fallback route for browser document requests on both ReverseProxy and Microservice route types. API prefixes (/api, /v1) are explicitly excluded from this fallback and continue to dispatch to backend services.

3. Enable Middleware

After UseAuthorization(), add:

app.TryUseStellaRouter(resolvedOptions.Router);

4. Refresh Endpoint Cache

After all endpoints are mapped (before app.RunAsync()), add:

app.TryRefreshStellaRouterEndpoints(resolvedOptions.Router);

Configuration Example (YAML)

myservice:
  router:
    enabled: true
    region: "us-east-1"
    defaultTimeoutSeconds: 30
    heartbeatIntervalSeconds: 10
    gateways:
      - host: "router.stellaops.local"
        port: 9100
        transportType: "Tcp"
        useTls: true
        certificatePath: "/etc/certs/router.pem"

WebServices Integration Status

Hosts whose Program.cs calls AddRouterMicroservice(..., serviceName: ...) (verified at commit 942a18727c, less the cartographer, doctor and policy-gateway hosts that PCD-73 withdrew on 2026-09-27, with git grep -n -A4 "AddRouterMicroservice(" -- 'src/*Program.cs' ':!src/__Obsoleted'). Whether a host is deployed is decided by the compose files and the release bundle, not by this list.

Router serviceNameHost project directory
advisoryaisrc/AdvisoryAI/StellaOps.AdvisoryAI.WebService
authoritysrc/Authority/StellaOps.Authority/StellaOps.Authority
evidencesrc/Evidence/StellaOps.Evidence.WebService
exportcentersrc/OfflineKit/StellaOps.OfflineKit.WebService
findingssrc/Findings/StellaOps.Findings.WebService
gatewaysrc/Router/StellaOps.Gateway.WebService
graphsrc/Graph/StellaOps.Graph.Api
integrationssrc/Integrations/StellaOps.Integrations.WebService
jobenginesrc/JobEngine/StellaOps.JobEngine.WebService
notifysrc/Notify/StellaOps.Notify.WebService
platformsrc/Platform/StellaOps.Platform.WebService
policy-enginesrc/Policy/StellaOps.Policy.Engine
registry-tokensrc/Registry/StellaOps.Registry.TokenService
release-orchestratorsrc/ReleaseOrchestrator/__Apps/StellaOps.ReleaseOrchestrator.WebApi
replaysrc/Replay/StellaOps.Replay.WebService
sbomservicesrc/SbomService/StellaOps.SbomService
scannersrc/Scanner/StellaOps.Scanner.WebService
signalssrc/Signals/StellaOps.Signals
signersrc/Attestor/StellaOps.Signer/StellaOps.Signer.WebService
smremotesrc/SmRemote/StellaOps.SmRemote.Service
testersrc/Tester/StellaOps.Tester.WebService
timelinesrc/Timeline/StellaOps.Timeline.WebService
unknownssrc/Unknowns/StellaOps.Unknowns.WebService
vulnerabilities-websrc/Vulnerabilities/StellaOps.Vulnerabilities.WebService
workflowsrc/Workflow/StellaOps.Workflow.WebService

Files Created

The Router.AspNet library includes the following files: