SAIF.Platform.Aspire.Hosting¶
Aspire AppHost extensions for Forge's local/dev orchestration: custom resources for Keycloak, WireMock, Oracle, and Scalar/Swagger UI wiring, plus the SaifEnvironmentResource abstraction that drives Forge's pipeline generation.
Getting started¶
Add a mocked dependency with the basic WireMock container resource — points a static image at a directory of mapping files:
var builder = DistributedApplication.CreateBuilder(args);
var wiremock = builder.AddWiremock("wiremock", "./wiremock-mappings");
builder.AddProject<Projects.MyApi>("my-api")
.WithReference(wiremock);
AddWiremock bind-mounts path into the container's /home/wiremock and exposes an HTTP endpoint. Pass EnableCors = true (the default) via the options delegate to add --enable-stub-cors.
SaifEnvironmentResource¶
AddSaifEnvironment() is the primary entry point for a Forge AppHost. It registers a non-manifest SaifEnvironmentResource that carries application identity — application name, business domain, owner, tenant (defaults to "corporate") — and pipeline defaults, then wires up Forge's pipeline-generation DAG step automatically (no separate registration call needed):
var builder = DistributedApplication.CreateBuilder(args);
builder.AddSaifEnvironment()
.WithApplicationName("MyApp")
.WithBusinessDomain("it")
.WithOwner("Architecture");
builder.AddApiService<Projects.MyApi>("my-api");
WithPipelineDefaults() overrides the sensible built-in defaults (.NET 10.x, Node 22.x, pipeline-templates@refs/heads/releases/v3) only when a service needs something different — e.g. a custom SecretsVariableGroupName. This API surface is marked [Experimental("SAIFENV001")]. AddSecurity() and AddUpstreamApi(), referenced in its own XML doc example, are also part of this package (Generation/Infrastructure/Security), registering the SecurityResource and UpstreamApiResource used by pipeline generation — no separate package is needed for them.
Keycloak¶
AddKeycloak(name, realm, ...) wraps Aspire.Hosting.Keycloak's container resource with Forge-specific realm generation: it reads business-role-app-role.yml (business role → app role mappings) and an optional project_id from the app's infra/auth/ext/user/ features folder, renders a set of Mustache (Stubble) templates under ./Keycloak/Templates into realm-import JSON, and calls WithRealmImport so Keycloak boots pre-seeded with those users and roles. Admin credentials default to admin/admin on port 8135 and are passed through as Aspire secret parameters. Use the realm-less AddKeycloak(name, ...) overload plus WithGeneratedRealm(realm, ...) directly if you need to configure realm options (template/import paths, whether to prefix role names with the project ID) separately from container options.
WireMock¶
There are three related but distinct WireMock integrations in this package, at different points in their evolution:
Wiremock/(AddWiremock) — the simplest option, shown above: a singlewiremock/wiremockcontainer bind-mounted to a local directory of static mapping files. No cloud integration.WiremockCli/(AddWiremockCli+AddMock) — runs mocks via the WireMock CLI executable rather than a container, supports pulling stub definitions from WireMock Cloud projects, and integrates per-mock with the Aspire dashboard and health checks. SeeWiremockCli/README.mdfor the full usage example (builder.AddWiremockCli("wiremock").AddMock("my-api", 8080, "wiremock-project-id")) — that README's content is accurate and is summarized, not duplicated, here.WiremockRunner/(AddWiremockRunner) — the newest variant, built around thewiremock/wiremock-runnercontainer. It detects CI (CI=trueorTF_BUILD=true) vs. local dev automatically: in CI it readsWMC_API_TOKENdirectly from the environment, while locally it prompts for the token as an Aspire secret parameter. OnBeforeStartEvent, it writes a.manifest.jsonof configured mocks and runs a provision-and-pull PowerShell script that installs@wiremock/cli, provisions any mocks that don't yet have a WireMock Cloud project ID, and pulls stubs for the rest — skipped entirely in test/CI environments where mocks are expected to already be available.
Prefer WiremockCli or WiremockRunner over the plain container resource once you need WireMock Cloud–backed stubs; pick WiremockRunner for the CI-aware token handling if you're setting up a new AppHost.
Oracle¶
WithOracleDatabaseSeed(database, ...) attaches a seeding configuration to a project resource that seeds an Oracle database: it wires a WithReference to the database resource and passes Schema, SchemaPassword (default "password"), and SeedDelayMilliseconds (default 5000, to let the database finish starting) as environment variables for the seeding project to read. It doesn't wait on the database dependency directly yet — there's a TODO in source referencing davidfowl/WaitForDependenciesAspire.
Scalar and Swagger¶
AddScalar(name, path, ...) and AddSwagger(name, path, openApiFileName, ...) both follow the same pattern: bind-mount a directory containing an OpenAPI spec into a documentation-UI container (scalar/api-reference or swaggerapi/swagger-ui, respectively) and expose it over HTTP. Scalar reads its spec via the API_REFERENCE_CONFIG environment variable pointed at the mounted path; Swagger UI reads it via SWAGGER_JSON pointed at path/openApiFileName. Both accept an optional fixed HttpPort in their options delegate; otherwise Aspire assigns one.
Related packages¶
SAIF.Platform— the base service-defaults package most AppHost-referenced projects depend on.SAIF.Platform.Authentication/SAIF.Platform.Authentication.AspNetCore— the security configuration consumed byAddSecurity()in theSaifEnvironmentResourceexample above.