Conversation
Serves a Blazor dashboard at the emulator's root URL showing whether it is running correctly, backed by two health checks also exposed at /health. Blazor rather than a separate JS framework so the UI ships inside the same assembly — no second build step and nothing extra for `dotnet tool install` to pull down. The page is written from scratch rather than from the Blazor template, which would have brought bootstrap and a sample stylesheet along for what is a handful of cards. The checks cover what actually goes wrong in the environment rather than in the emulator: whether the indexes directory can be written to (a read-only Docker volume, a tool launched from a directory without permission), and whether every index definition on disk still parses after being hand-edited. Both previously surfaced as a 500 from whichever request happened to touch them. Writability is probed with a real write, since no file attribute distinguishes a read-only bind mount from a full disk. Two accommodations were needed to put a UI at "/". OData's route components are registered at the root prefix, which puts its service document on "/" and made the dashboard's page an ambiguous match; the service document gives way, as Azure AI Search does not serve one and the SDK never requests it. MapRazorComponents also requires UseAntiforgery, which is added ahead of the API routes — it ignores requests carrying no token, so SDK writes are unaffected, and an integration test pins that. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CodeQL has failed on every run since the upgrade to Aspire 13.5.3, on main as well as on branches, and for two stacked reasons. The visible one was ASPIRE009: autobuild builds AzureSearchEmulator.Aspire.DemoAppHost, whose AppHost SDK resolves an Aspire CLI bundle during build and errors out when it cannot find one, after which autobuild gives up with "Could not auto-detect a suitable build method". Building the solution explicitly gets past that, but only far enough to reach the real blocker: the repository has CodeQL default setup enabled, covering csharp and actions since 2026-08-10, and GitHub refuses SARIF from an advanced configuration while it is on — "CodeQL analyses from advanced configurations cannot be processed when the default setup is enabled". The two are mutually exclusive, so the checked-in workflow could not have succeeded regardless of how it built. Default setup already scans this repository, so the workflow file is redundant and is removed rather than repaired. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #90 (first sub-issue of #68).
Adds a web UI at the emulator's root URL showing basic health status, plus the health-check infrastructure behind it.
What's here
The dashboard — served at
/, showing overall status, version, environment, uptime, the indexes directory, and each check's result. It refreshes itself every 15 seconds over the Blazor circuit and has a manual refresh button.Blazor, per the issue, so there's no separate JS framework to build or keep in sync — the whole UI lives in the same assembly. It's written from scratch rather than from the Blazor template: the template brings bootstrap, a sample stylesheet and the default error UI along for what is a handful of cards. The stylesheet is ~340 lines of hand-written CSS with tokens for light and dark, following the developer's OS theme.
Two health checks, surfaced on the dashboard and at
/health:index-storage— can the indexes directory actually be written to? This is the one worth having. A read-only Docker volume, or adotnet toollaunched from a directory the user can't write to, currently surfaces as a 500 from whichever indexing request happens to run. Writability is probed with a real write, because no file attribute distinguishes a read-only bind mount from a full disk from a POSIX mode bit.index-definitions— does every definition on disk still deserialize? These are JSON files users are told about and mount as a volume, so hand-editing one is expected. A malformed file currently takes out an unrelated listing request. ReportsDegradedrather thanUnhealthy, since every index that does parse is still being served./healthis kept separate from/servicestats, which Aspire already probes — that route imitates Azure's API surface and answers 200 as long as the process is up.Two accommodations for owning
/Both are the kind of change that works locally and breaks the API surface elsewhere, so the integration tests assert the API side in the same file.
AddRouteComponents("", model)putsMetadataController.GetServiceDocumenton/, which made the dashboard's@page "/"an ambiguous match — the request failed withAmbiguousMatchExceptionrather than either endpoint winning. The service document is the one to drop: Azure AI Search doesn't serve one (its root 404s) and the Azure SDK never requests it./$metadatais a separate action on the same controller and is unaffected — there's a test for that.UseAntiforgeryis now in the pipeline, required byMapRazorComponents. It ignores requests that carry no token, so unauthenticated SDK writes are unaffected —ApiWrites_AreNotBlockedByAntiforgerydrives a real index create/read/delete through the SDK to pin it.Testing
/healthanswers,$metadatasurvives, and SDK writes aren't blocked.Verified by hand against a running instance as well — root,
/health,/servicestats,/indexes,/$metadata, index create, document index, and delete all behave as before.README gains a "Web UI" section covering the dashboard,
/health, and the service-document note.🤖 Generated with Claude Code