Release 0.1.0-rc.2
Coordinated AppSurface release 0.1.0-rc.2, tagged on 2026-06-03.
Source of truth
This release note records the delta from AppSurface 0.1.0-rc.1 to 0.1.0-rc.2. The broader coordinated prerelease story remains in v0.1.0 RC 1; this page only calls out what changed after that candidate.
What changed since RC 1
RC 2 turns the first release candidate into a more publishable package surface. The main changes are new AppSurface Auth and Flow package families, harder AppSurface Docs archive boundaries, safer RazorWire streams and exports, and release/package documentation that now points at the RC 2 note as the current package-facing record.
Included in RC 2
New package surfaces
- AppSurface now has
ForgeTrust.AppSurface.Authas a surface-neutral auth vocabulary package for module authors and host integrations. It defines passive user, session, context, result, login/logout prompt, audit-event, and metadata-key contracts while avoiding runtime authentication, authorization policy evaluation, redirects, audit sinks, and identity-provider integration. - AppSurface Flow is now a first-class package family.
ForgeTrust.AppSurface.Flowprovides stablenet10.0typed process contracts, discriminated outcome records, graph validation, a definition registry, and an in-memory runner. ForgeTrust.AppSurface.Flow.DurableTaskadds a passive Durable Task adapter boundary with runner/client services, resume-event authorization, timeout handling, late-event and retry behavior, and context serialization validation. Semantic Kernel remains out of v1 scope.- The new
examples/flow-approval-localsample demonstrates local typed flow execution before a host opts into durable infrastructure.
Release and package operations
- Public package READMEs and generated package chooser/readiness pages now link to the v0.1.0 RC 2 release note for current release risk, migration guidance, and package readiness.
- Older
v0.1preview release-note routes now redirect to the RC 2 release note, keeping legacy preview links on the current candidate instead of a stale pre-RC page. - Package maintainers now have a generated
packages/readiness.mdevidence dashboard that groups packages by product family, reports package-index readiness evidence, and keeps blocker/notes annotations separate from live NuGet publish status. - The AppSurface CLI now reports package SemVer from
appsurface --version, preserving prerelease labels such as0.1.0-rc.2while omitting leadingvtags and build metadata. Tool smoke validation now installs the package and checks--versionexactly against the package manifest. - Release preparation now leaves
CHANGELOG.mdas a compact ledger, moves detailed release narrative into tagged release notes, and makes generated release PR reports stop at a manual maintainer review gate before merge, tag, or publish. - The release authoring checklist now records the preview-rollup rule: when a tagged or release-candidate note supersedes a preview, remove the preview source file and carry its browser routes as
redirect_aliaseson the canonical note.
AppSurface Docs hardening
- AppSurface Docs exact release trees now carry catalog-pinned archive integrity: export writes
.appsurface-docs-release-manifest.json, prints thereleaseManifestSha256catalog snippet, runtime verifies pinned archives before mounting them, and keeps unpinned public archives unavailable until HTML, JavaScript, CSS, SVG, and search payloads are pinned and verified. - AppSurface Docs version catalogs now mount exact release trees only from
AppSurfaceDocs:Versioning:TrustedReleaseRootPath, which defaults to the catalog directory for colocatedcatalog.jsonplusreleases/layouts. AbsoluteexactTreePathvalues are no longer mountable; set the trusted release root to the old parent directory and make catalog paths relative. - Published AppSurface Docs search indexes now reject unsafe
documents[].pathvalues before a release tree is mounted. Absolute URLs, executable schemes, protocol-relative URLs, traversal, encoded separators, request path bases, custom deployment roots, and docs operational routes make only the affected published version unavailable until rebuilt or rewritten. - AppSurface Docs published release trees now enforce
AppSurfaceDocs:Versioning:MaxRewrittenFileSizeBytesfor request-time rewrites of exported.htmlfiles and rootsearch-index.json. Oversized search payloads are rejected during catalog validation, while oversized request rewrites fail closed with a controlled 404. - Built-in Markdown and C# harvesters now skip file and directory reparse points during direct and aggregated source traversal, and Markdown root
LICENSEplus paired sidecar metadata reads use the same no-reparse boundary. - JavaScript harvesting now applies the same no-reparse boundary to explicit includes, global include roots, recursive traversal, child files, and child directories. Symlinked include roots emit
appsurfacedocs.javascript.reparse_point_skippedwith redacted recovery guidance and block strict JavaScript health when JavaScript participates. - AppSurface Docs configured branding directories now deny SVG by default because SVG is active document content under the docs origin. Operator-owned SVG logos and favicons can still be served by setting
AppSurfaceDocs:Identity:BrandingAssets:AllowSvgAssets=true. - AppSurface Docs parser input budgets now bound Markdown, C#, and JavaScript source reads so extremely large authoring files fail as controlled harvest diagnostics instead of consuming unbounded memory.
- The standalone AppSurface Docs host now owns its docs-specific 404 recovery page, including search links resolved from
DocsUrlBuilder.Routes.Search, while embedded docs consumers remain responsible for their own app-wide browser error UX. - AppSurface Docs JavaScript API pages can now resolve public doclets into reader-facing API families. Explicit
@namespaceand@moduletags remain authoritative, orderedGroupNameRulescan name known source trees, and untagged fallback groups use path-aware identities so same-stem files in different folders do not merge.
RazorWire streams and export
- RazorWire stream builder text APIs now HTML-encode template content by default.
Append,Prepend,Replace, andUpdateare safe text helpers, while newAppendHtml,PrependHtml,ReplaceHtml, andUpdateHtmlmethods preserve trusted server-authored markup without encoding or sanitizing. - RazorWire stream endpoints now enforce single-process public SSE admission guardrails before allocating hub subscriber state. Channel names are validated before authorization, malformed channels return
400, authorization denials return403, and live capacity exhaustion returns429before SSE headers are written. - RazorWire's in-memory stream hub now releases empty live channel tracking after the last subscriber disconnects or publish-time cleanup prunes stale writers. Replay buffers remain separate from live subscriber state and are pruned by retained-channel limits instead of live subscriber disconnects.
- RazorWire stream admission limits are configurable through
RazorWireOptions.Streams.MaxChannelNameLength,MaxLiveChannels,MaxLiveSubscriptions, andMaxLiveSubscriptionsPerChannel. These are per-process limits for live SSE requests, not distributed user, tenant, IP, or cluster quotas. - Static and hybrid export now handle RazorWire-owned anti-forgery forms safely: hybrid exports remove crawler-minted tokens and refresh them lazily from
/_rw/antiforgery/token, while CDN exports fail early withRWEXPORT006guidance instead of publishing stale request tokens. - RazorWire and AppSurface hybrid export now fail missing browser-delivered static assets with
RWEXPORT003instead of returning success for a folder that would keep serving broken CSS, image, script, stylesheet, module preload, icon, font, or asset-shaped preload/prefetch requests. - RazorWire CLI process execution now follows an explicit reliability contract for one-shot commands and launched target apps. Target-app failures that were previously hidden behind startup or readiness timeouts may now surface earlier with captured output and recovery guidance.
- RazorWire now has first-class page navigation for server-rendered brochure and docs pages. Native anchors opt in with
rw-page-nav/rw-page-nav-link/rw-page-nav-toggle/rw-page-nav-panel, while the runtime owns active state, hash navigation, lifecycle-safe rebinding, diagnostics, and optional panel close.
Configuration diagnostics
- Config audit entries can now be explicitly classified with
ConfigAuditEntryOptions.Sensitivity, letting package authors mark domain-specific provider-only or wrapper-discovered keys sensitive without changing key names. - Config audit discovered-key reports now expose
ConfigAuditDiscoveredValueDisplayStateand omit raw scalar values for non-redacted unknown keys or descendants under broad audit registrations. JSON consumers should branch onValueDisplayStateinstead of treatingDisplayValue == nullas complex-only. - Config audit redaction now recognizes additional secret-bearing fragments such as passphrase, DSN, assertion, certificate, cookie, client secret, private key, JWT, bearer, access/refresh tokens, session IDs, and shared access signatures.
- Opted-in configuration audit collection traversal now reports environment-created collection elements when audit provenance can prove the lower-priority element was absent, and reports a separate base-unknown diagnostic when environment variables supplied the final element but provider evidence cannot prove prior presence.
Web and Tailwind polish
- AppSurface preview startup now treats
--portas a loopback-only shortcut that bindshttp://localhost:<port>. Add--all-hostswith--portonly when LAN, container, or other all-interface preview access is intentional. - Tailwind build execution now uses a compiled MSBuild task with stable
ASTW###diagnostics, structured CLI arguments, bounded output capture, cancellation support, and a packed-package smoke test that proves task/dependency loading from a real nupkg consumer. - Tailwind development watch mode now treats a missing standalone CLI as a recoverable local-tooling gap: the app keeps serving existing CSS and logs a warning that points to the runtime package or
TailwindOptions.CliPathoverride. - The new
examples/web-error-pagesproof starts a production-mode AppSurface Web host and verifies the browser/API error-page split with one command, including response-body sentinel checks for the generic500page.
Tests and repository policy
- Test fixture paths now use a shared
ForgeTrust.AppSurface.Testinghelper withTestPathUtils.PathUnder,RelativePath, andFindRepoRoot, replacing duplicated local helpers in high-risk test path construction. - A repository policy test now scans test sources for dynamic
Path.CombineandPath.Joinunder-base fixture paths, reports maintainer-friendly replacement guidance, and keeps intentional platform-path behavior behind reasoned allowlist entries. - Static website export docs now spell out the deployment extras boundary:
--seedsare crawl routes rather than local copy paths, AppSurface's conventional/_appsurface/errors/404output can stage root404.html, deployment-owned files such asCNAMEbelong in explicit post-export copy steps, and exporter-owned Netlify_redirectsshould still come from--redirects netlify.
Dependency maintenance
- The central .NET dependency set now carries
Microsoft.Extensions.Caching.Memory,Microsoft.Extensions.Hosting, andMicrosoft.Extensions.Logging.Console10.0.8, while the ABP benchmark host now uses ABP10.4.0; solution lock files were regenerated so locked restore sees the same graph in CI and local development.
Migration watch
- The stable pre-1.0 contract lives in Pre-1.0 upgrade policy.
- RazorWire stream markup callers should audit
.Append(,.Prepend(,.Replace(,.Update(,new RazorWireStreamResult(, andPublishAsync(..., string). Keep text/status/counter updates on the existing methods, move Razor markup to partial or component helpers when practical, and useAppendHtml/PrependHtml/ReplaceHtml/UpdateHtmlonly for trusted fragments with user values encoded before composition. - RazorWire stream consumers do not need application code changes for the live-channel cleanup update. Public or demo stream endpoints may now see
429 Too Many Requestsunder high live-connection fanout because RazorWire admits only a bounded number of live channels and live SSE requests per process. - Existing RazorWire CLI users do not need command or flag changes for the process-execution migration. The main behavior difference is that target-app failures may now appear earlier with captured output instead of being hidden behind startup or readiness timeouts.
- AppSurface Docs version-catalog maintainers should copy the
releaseManifestSha256value printed by export into each public exact release entry. Existing unpinned public archives are unavailable until the release manifest is pinned and verified. - Operators may see more conservative redaction in config audit reports as the secret-fragment list expands. Treat that as the intended default, and use explicit sensitivity options only to document package-owned keys.
- AppSurface preview users who depended on
--portlistening beyond loopback should add--all-hostsor pass explicit--urls. The wildcard host can expose the preview process beyond the local machine, so keep the default localhost binding for routine docs and web previews. - Tailwind package consumers do not need source changes for the compiled MSBuild task. Maintainers should keep the packed-package smoke path green when changing task dependencies or diagnostics.