Release 0.2.0-preview.1
Coordinated AppSurface release 0.2.0-preview.1, tagged on 2026-06-28.
Source of truth
This is the release note for AppSurface 0.2.0-preview.1 after 0.1.0-rc.4. It stays provisional until the next tag is cut.
What is taking shape
ForgeTrust.AppSurface.Authnow defines durable external-subject to app-user-id mapping contracts without taking on user-store, ASP.NET Core, OIDC, EF Core, Aspire, or tenant-authority responsibilities.ForgeTrust.AppSurface.Auth.AspNetCorenow includes AppSurface-shaped Minimal API policy helpers:AddAppSurfacePolicy(...)keeps policy definition in ASP.NET Core, whileRequireSurfacePolicy(...)evaluates the named host policy through the existing AppSurface evaluator and returns API-safe ProblemDetails JSON for challenge, forbid, missing-policy, missing-service, and missing-subject outcomes instead of triggering browser redirects.ForgeTrust.AppSurface.Auth.AspNetCore.DevAuthadds a Development-only persona lab with a named fake auth scheme, protected persona cookie, loopback-only and same-origin mutation controls, status JSON, embeddable state marker overlay, and startup guards so package consumers can prove AppSurface auth flows without shipping fake identity.ForgeTrust.AppSurface.Auth.Testingadds a public test-only integration harness with deterministic personas, WebApplicationFactory helpers, per-request persona selection, diagnostics, and AppSurface auth assertion helpers while keeping real ASP.NET Core policy evaluation in the path.- Add
ForgeTrust.AppSurface.Auth.AspNetCore.Oidc, a public preview ASP.NET Core cookie + OIDC convenience package with explicit AppSurface scheme names,SaveTokens=falseby default, passive prompt helpers, safe diagnostics, event chaining, and package chooser/readiness coverage. - Sanitized AppSurface Config audit diffs for comparing captured runtime configuration reports.
- AppSurface Observability package defaults for sending app-side logs, traces, and metrics to Aspire or another OTLP collector.
- LocalSecrets platform-index self-healing so
appsurface secrets listno longer surfaces stale names whose stored values are missing. - The AppSurface CLI now carries the design contract for future authenticated command execution. The design keeps
ForgeTrust.AppSurface.Authpassive, usesappsurface docs publish --archive ./dist/docs --site <site>as the protected command wedge, treats RFC 8628 device flow as one auth method rather than the whole CLI story, and requires secure token-cache boundaries, CI no-prompt behavior,ASCLI1xxdiagnostics, and packed-tool readiness proof before auth commands ship. - LocalSecrets Linux
secret-toolresolution now uses trusted system candidates or an explicit absolute override instead of executing the firstsecret-tooldiscovered onPATH. ForgeTrust.AppSurface.Webnow rejects the literal CORS origin wildcard*outside Development when AppSurface owns the CORS policy, so permissive production APIs must either name explicit browser origins or register host-owned ASP.NET Core CORS.
Included in the next coordinated version
Release and docs surface
- Stable package release automation now has a protected NuGet publish gate for annotated
vX.Y.Ztags, including stable-only package-version validation, trusted-publishing environment checks, fresh smoke-install proof, publish-ledger evidence, and./eng/release publish --base-refsupport so GitHub Release creation can be tied to the intended source branch after NuGet proof is complete. examples/auth-web-razorwire-proofnow gives package adopters a five-minute browser proof forForgeTrust.AppSurface.Auth.AspNetCore: one host-ownedOperatorsOnlypolicy drives both a Minimal API response and a RazorWire-facing rendered state while all fake auth and persona switching stays sample-local.- Added
ExternalSubject,AppUserId,IAppSurfaceUserIdentityResolver,AppSurfaceUserIdentityResolutionContext,AppSurfaceUserIdentityResult, andAppSurfaceUserIdentityStatus, with README guidance for uniqueness, idempotency, cancellation, concurrency, PII-safe diagnostics, and ASP.NET Core adapter integration planning. ForgeTrust.AppSurface.Auth.AspNetCoredocuments the new Minimal API policy helper flow, package chooser metadata, safe ProblemDetails failure shape, and when native ASP.NET CoreRequireAuthorization(...)remains the better choice.ForgeTrust.AppSurface.Auth.AspNetCore.DevAuthdocuments the five-minute local persona flow, persistent in-app marker overlay, marker skinning options, same-origin POST protection, DevAuth versus real host auth/OIDC/test harness boundaries, stableASDEV###diagnostics, and removal guidance before deployment.ForgeTrust.AppSurface.Auth.Testingdocuments the under-five-minute WebApplicationFactory path, scheme modes, persona registry rules, subject mapping defaults and overrides, diagnostics, assertion helpers, and troubleshooting for integration-test consumers.- Document the AppSurface OIDC package boundary, including when to use raw ASP.NET Core OIDC or provider SDKs instead, and add a no-secret local registration proof example.
- AppSurface Config now exposes a sanitized config audit diff surface.
ConfigAuditReportDiffercompares two existingConfigAuditReportsnapshots without re-resolving providers,ConfigAuditDiffTextRendererrenders deterministic same-host or captured-snapshot evidence with redaction uncertainty called out, andConfigAuditDiffCommandRunnergives apps command-framework-agnostic same-host and captured JSON workflows with display-safe problem/cause/fix/docs-link failures. ForgeTrust.AppSurface.Config.LocalSecretshardens the explicit file fallback path. Unix fallback directories are created with0700mode bits when missing, existing loose parent directories fail closed instead of being modified in place, and JSON files are written or repaired with0600mode bits duringset,delete, anddoctor; reads reject symbolic-link paths and non-canonical mode bits before returning a secret value.appsurface secrets doctor --store-filenow treatsready,repaired, anddegradedposture diagnostics as doctor-style success while keepingunsupportedpath shapes terminal. This is Unix mode-bit hardening, not Windows ACL hardening or a universal POSIX ACL proof; OS-backed LocalSecrets stores remain the recommended local-development path.- AppSurface Observability adds
ForgeTrust.AppSurface.Observabilitywith module-first OpenTelemetry logging, tracing, and metrics registration, endpoint-driven OTLP exporter setup, service identity resource metadata, and docs for Aspire and non-Aspire adoption paths. - AppSurface Docs adds a trusted maintainer harvest rebuild loop:
_healthcan render aRebuild docsaction,POST {DocsRootPath}/_harvest/rebuildstarts or queues a full source-backed harvest throughAppSurfaceDocsHarvestCoordinator.RequestRebuildAsync(...), and{DocsRootPath}/_harvestshows the live observatory before returning to the validated docs/search context. - AppSurface Docs health routes now support
AppSurfaceDocs:Harvest:Health:AuthorizationPolicy, an optional host-owned ASP.NET Core policy for{DocsRootPath}/_healthand{DocsRootPath}/_health.json; route exposure, health read authorization, and operator write authorization remain separate configuration concepts, with broader operator-read diagnostics tracked in forge-trust/AppSurface#578. - RazorWire hybrid islands now reject inline
data:module specifiers from bothclient-module/data-rw-moduleandwindow.RazorWireIslandModules, and also reject protocol-relative//...module URLs. Move any prototype inline module such asdata:text/javascript,...into a served module like/js/my-island.jsthat exportsmount(root, props). - RazorWire export now owns HTTP redirect handling for artifact-producing fetches, including crawled routes and conventional
404.htmlstaging. Same-origin redirects remain supported, while redirects outside the configured export origin and base path fail withRWEXPORT008before response content is read or written; routes that intentionally point to a different host or app path should be modeled as external references instead of exporter-managed artifacts. - RazorWire stream authorization can now return
AppSurfaceAuthResultthroughIRazorWireStreamAuthorizer, preserving legacy bool authorizers while mapping challenge, forbid, setup failure, unsafe navigation, and stale session outcomes before SSE starts. - AppSurface CLI export and docs export now configure the shared RazorWire
ExportEngineHTTP client with automatic redirects disabled, soRWEXPORT008redirect-boundary checks run before artifact response bodies are read or written. - RazorWire export now guards generated artifact materialization and AppSurface Docs release archive traversal with
RWEXPORT009. HTML, CSS, binary assets,404.html, docs partials, redirect alias HTML,_redirects, frozen route manifests, and release manifests are validated before parent creation, final writes, archive enumeration, metadata reads, or hashing, so symlinks, junctions, reparse points, and lexical output-root escapes are rejected without following them. - RazorWire form interactions now give server-rendered apps stable local mechanics for conditional form targets and one-dimensional ASP.NET Core model-bound collections. Use raw
data-rw-*attributes or the matching TagHelpers to reveal and disable app-owned fields, add rows from an app-authored__index__template, duplicate editable values without copying identity/delete/concurrency fields, and choose between physical remove or explicit mark-for-removal. - AppSurface LocalSecrets platform-backed stores now validate indexed names against live stored values during
appsurface secrets list. Missing values are pruned from the index when validation and repair succeed, andappsurface secrets delete KEYrepairs a stale indexed name when the value is already gone while preservinglocal-secret-missingfor keys that never existed. Cli/ForgeTrust.AppSurface.Cli/docs/authenticated-command-design.mddocuments the future CLI auth ladder, including browser/loopback PKCE, RFC 8628 device flow, non-interactive CI tokens, command-gate state, token-cache threat modeling, deterministic auth diagnostics, and follow-up issue slices.- AppSurface LocalSecrets now hardens Linux Secret Service command selection. Linux uses
/usr/bin/secret-tool, then/bin/secret-tool, or an explicit trusted absolute path throughAppSurfaceLocalSecretsOptions.LinuxSecretToolPathandappsurface secrets --secret-tool-path. PATH matches are reported only as ignored diagnostic context, invalid overrides fail before command launch, and--secret-tool-pathcannot be combined with--store-file. - AppSurface Web CORS startup validation now fails closed before policy registration when non-development
CorsOptions.AllowedOriginsincludes the exact literal*, while preserving Development all-origin convenience and wildcard subdomain origins such ashttps://*.example.com. - Package verification tests now keep Tailwind packed-consumer smoke restores out of the user-level NuGet package cache and clean up generated RazorWire ToolVerifier package entries after the tool contract proof completes.
AppSurface Flow
- Reduce internal
InMemoryFlowRunner<TContext>routing overhead by using prevalidatedFlowDefinition<TContext>execution metadata while keeping public Flow APIs unchanged. - Reduce synchronous in-memory runner allocations by making
FlowExecutionContext<TContext>an immutable value-type snapshot passed into each node execution. - Expand the Flow benchmark suite with runner-shape, generated-authoring, and outcome-allocation lanes so future performance work can attribute remaining overhead before changing public APIs.
Migration watch
AppSurfaceUser.Idremains a host-owned subject identifier in the existing ASP.NET Core adapter. Consumers that need durable app-owned users should resolve that subject through the new identity resolver contract instead of treating the mapped subject claim as an app user id.- Production AppSurface-managed CORS no longer accepts
AllowedOrigins = ["*"]. Replace the literal wildcard with explicit origins such as["https://app.example.com"]; keep local permissive behavior behindEnableAllOriginsInDevelopment; use wildcard subdomains such as["https://*.example.com"]only when matching subdomains; and register/apply host-owned ASP.NET Core CORS when an API is intentionally public to every browser origin. - Hosts adopting
ForgeTrust.AppSurface.Auth.AspNetCore.Oidcmust still callUseAuthentication()andUseAuthorization()in ASP.NET Core order and must explicitly configure default schemes if they want host-wide defaults. - Record breaking or behavior-changing guidance here before it moves into the tagged release note.
FlowExecutionContext<TContext>is now a readonly record struct instead of a sealed record class. Most node implementations continue to readFlowId,Version,NodeId,State, andResumeEventthe same way, but code that depended on reference identity, nullable context parameters, orcontext is nullchecks should switch to checking the populated members it requires.- RazorWire no longer treats
data:text/javascript,...values inwindow.RazorWireIslandModulesas importable modules. Use a relative, root-relative, same-origin, explicit HTTPS, or bare import-map module specifier instead.