Repository navigation
Lift the non-visual portal infrastructure out of MeshWeaver.Blazor - #2285
Merged
rbuergi merged 12 commits intoAug 26, 2026
Merged
Conversation
Removing GUI from core is blocked by a mislabelled layer, not by volume. MeshWeaver.Blazor/Infrastructure holds eight files that are NOT views: ArticleExtensions, CircuitContextAccessor, MeshUserProjection, NonfileRouteConstraint, PortalApplication, PortalErrorSink, UserContextMiddleware, UserIdentityCache. Not one of them imports MeshWeaver.Blazor or Microsoft.AspNetCore.Components — they were already Blazor-free and merely LIVED in the UI project. Meanwhile 12 core files and 12 core test projects import that namespace, so deleting the Blazor project would take core's own middleware and caches with it. They move to MeshWeaver.Hosting.AspNetCore/Portal/, which is where ASP.NET middleware belongs, with namespaces that stop claiming to be Blazor. Because the files were already Blazor-free the move is pure: no code changes, and it costs exactly three project references — ContentCollections (ArticleExtensions), Layout (PortalErrorSink) and Markdown.Export.Contract (PortalApplication). PortalApplication stays in src/ with the middleware that uses it. The first attempt put it in memex/Memex.Portal.Shared and the compiler rejected it: UserContextMiddleware consumes it, and src/ cannot reference memex/. MeshWeaver.Blazor now references MeshWeaver.Hosting.AspNetCore rather than owning this code — UI depends on hosting, never the reverse. Verified with CI's flags (-c Release -warnaserror), all 0/0: Hosting.AspNetCore · Blazor · Blazor.Portal · Hosting.Blazor · Portal.Shared Hosting.Blazor.Test · Hosting.PostgreSql.Test · Hosting.Monolith.Test Memex.Portal.Shared.Test The InternalsVisibleTo hazard was checked rather than hoped: MeshWeaver.Blazor grants IVT to three assemblies and the new home to one, which is how MeshWeaver.OgCard.Test silently lost CS1729 when it moved. Only PortalErrorSink declares anything internal and every consumer compiles. No What's New entry: internal restructuring, no user-visible change.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR relocates non-visual “portal infrastructure” types (middleware, caches, accessors, routing constraint) out of MeshWeaver.Blazor into MeshWeaver.Hosting.AspNetCore/Portal, so core/hosting can depend on them without taking a UI/Blazor assembly dependency.
Changes:
- Moved portal infrastructure types to
MeshWeaver.Hosting.AspNetCore.Portaland updated namespaces/usings acrosssrc/,memex/, and tests. - Updated
MeshWeaver.Hosting.AspNetCoreandMeshWeaver.Blazorproject references to reflect the new ownership direction (UI → hosting). - Updated doc comments and fully-qualified type references where they mentioned the old namespace.
Reviewed changes
Copilot reviewed 51 out of 51 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| test/MeshWeaver.Security.Test/AuthBootstrapIdentityLatchTest.cs | Update using from MeshWeaver.Blazor.Infrastructure to MeshWeaver.Hosting.AspNetCore.Portal. |
| test/MeshWeaver.Hosting.PostgreSql.Test/UserDirectoryCompletenessTests.cs | Update using to the new portal namespace. |
| test/MeshWeaver.Hosting.Monolith.Test/UserDirectoryContentShapeTest.cs | Update using to the new portal namespace. |
| test/MeshWeaver.Hosting.Monolith.Test/NodeTypeDeclarationSelfTypingTest.cs | Update using to the new portal namespace. |
| test/MeshWeaver.Hosting.Blazor.Test/UserIdentityLookupClassifierTest.cs | Update using to the new portal namespace. |
| test/MeshWeaver.Hosting.Blazor.Test/UserContextMiddlewareExclusionTest.cs | Update using to the new portal namespace. |
| test/MeshWeaver.Hosting.Blazor.Test/ResolveHttpCallerTest.cs | Update using to the new portal namespace. |
| test/MeshWeaver.Hosting.Blazor.Test/PortalErrorPopupTest.cs | Update using to the new portal namespace. |
| test/MeshWeaver.Hosting.Blazor.Test/NonfileRouteConstraintTest.cs | Update using to the new portal namespace. |
| test/MeshWeaver.Hosting.Blazor.Test/NavigationServiceTest.cs | Update using to the new portal namespace. |
| test/MeshWeaver.Hosting.Blazor.Test/NavigationProgressTest.cs | Update using to the new portal namespace. |
| test/MeshWeaver.Hosting.Blazor.Test/DegradedCircuitIdentityRecoveryTest.cs | Update using to the new portal namespace. |
| test/MeshWeaver.Hosting.Blazor.Test/CatchAllPageRoutingTest.cs | Update using to the new portal namespace. |
| test/MeshWeaver.Hosting.Blazor.Test/AnonymousCircuitLocaleSeedTest.cs | Update using to the new portal namespace. |
| test/Memex.Portal.Shared.Test/EaConnectRouteTest.cs | Update using to the new portal namespace. |
| src/MeshWeaver.Hosting.Blazor/NavigationService.cs | Update using to the new portal namespace. |
| src/MeshWeaver.Hosting.Blazor/CircuitAccessHandler.cs | Update namespace references in XML docs and type/service references to the new portal namespace. |
| src/MeshWeaver.Hosting.Blazor/BlazorHostingExtensions.cs | Update using to the new portal namespace. |
| src/MeshWeaver.Hosting.AspNetCore/Portal/UserIdentityCache.cs | Change namespace to MeshWeaver.Hosting.AspNetCore.Portal. |
| src/MeshWeaver.Hosting.AspNetCore/Portal/UserContextMiddleware.cs | Change namespace to MeshWeaver.Hosting.AspNetCore.Portal. |
| src/MeshWeaver.Hosting.AspNetCore/Portal/PortalErrorSink.cs | Change namespace to MeshWeaver.Hosting.AspNetCore.Portal. |
| src/MeshWeaver.Hosting.AspNetCore/Portal/PortalApplication.cs | Change namespace to MeshWeaver.Hosting.AspNetCore.Portal. |
| src/MeshWeaver.Hosting.AspNetCore/Portal/NonfileRouteConstraint.cs | Change namespace to MeshWeaver.Hosting.AspNetCore.Portal. |
| src/MeshWeaver.Hosting.AspNetCore/Portal/MeshUserProjection.cs | Change namespace to MeshWeaver.Hosting.AspNetCore.Portal. |
| src/MeshWeaver.Hosting.AspNetCore/Portal/CircuitContextAccessor.cs | Change namespace to MeshWeaver.Hosting.AspNetCore.Portal. |
| src/MeshWeaver.Hosting.AspNetCore/Portal/ArticleExtensions.cs | Change namespace to MeshWeaver.Hosting.AspNetCore.Portal. |
| src/MeshWeaver.Hosting.AspNetCore/MeshWeaver.Hosting.AspNetCore.csproj | Add project references needed by moved portal infrastructure. |
| src/MeshWeaver.Blazor/Services/BlazorAutocompleteService.cs | Update using to the new portal namespace. |
| src/MeshWeaver.Blazor/Pages/ContentPage.razor.cs | Update using to the new portal namespace. |
| src/MeshWeaver.Blazor/Pages/ArticlesCatalogPage.razor | Update @using to the new portal namespace. |
| src/MeshWeaver.Blazor/Pages/ArticlePage.razor | Update @using to the new portal namespace. |
| src/MeshWeaver.Blazor/MeshWeaver.Blazor.csproj | Add reference to MeshWeaver.Hosting.AspNetCore so UI consumes hosting-owned portal infrastructure. |
| src/MeshWeaver.Blazor/BlazorView.razor.cs | Update using to the new portal namespace. |
| src/MeshWeaver.Blazor.Portal/Layout/PortalLayoutBase.razor.cs | Update using to the new portal namespace. |
| src/MeshWeaver.Blazor.Portal/Infrastructure/VUserHelper.cs | Update using to the new portal namespace. |
| src/MeshWeaver.Blazor.Portal/Components/UserProfile.razor.cs | Update using to the new portal namespace. |
| src/MeshWeaver.Blazor.Portal/Components/PortalErrorModal.razor | Update injected PortalErrorSink type to the new namespace. |
| src/MeshWeaver.Blazor.Portal/Chat/ThreadChatView.razor.cs | Update service resolve of PortalErrorSink to the new namespace. |
| memex/Memex.Portal.Shared/Social/GitHubConnectEndpoints.cs | Update using comment/import for PortalApplication to new namespace. |
| memex/Memex.Portal.Shared/Skills/AgentSkillSyncService.cs | Update using to the new portal namespace. |
| memex/Memex.Portal.Shared/Pages/Onboarding.razor | Update @using to the new portal namespace. |
| memex/Memex.Portal.Shared/MemexConfiguration.cs | Update using to the new portal namespace. |
| memex/Memex.Portal.Shared/Layout/MemexMobileMenu.razor | Update @using to the new portal namespace. |
| memex/Memex.Portal.Shared/Email/OutboundEmailSender.cs | Update using to the new portal namespace. |
| memex/Memex.Portal.Shared/Email/InvitationEmailSender.cs | Update using to the new portal namespace. |
| memex/Memex.Portal.Shared/Authentication/VirtualUserMiddleware.cs | Update using to the new portal namespace. |
| memex/Memex.Portal.Shared/Authentication/OnboardingMiddleware.cs | Update using to the new portal namespace. |
| memex/Memex.Portal.Shared/Authentication/OAuthConnectController.cs | Update using comment/import for PortalApplication to new namespace. |
| memex/Memex.Portal.Shared/Authentication/EaGraphAuth.cs | Update using comment/import for PortalApplication to new namespace. |
| memex/Memex.Portal.Shared/Authentication/ApiTokenController.cs | Update using comment/import for PortalApplication to new namespace. |
| memex/Memex.Portal.Shared/Api/MeshApiEndpoints.cs | Update using comment/import for PortalApplication to new namespace. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
MeshWeaver.Blazor.Portal carries the same mislabelling MeshWeaver.Blazor did:
an Authentication/ and Infrastructure/ of plain services, none of which import
any Blazor view type. Core code depends on two of them:
AuthenticationOptions <- Memex.Portal.Shared/Authentication/ExternalAuthController
VUserHelper <- Memex.Portal.Shared/Authentication/VirtualUserMiddleware
AND src/MeshWeaver.Hosting/Persistence/PersistenceExtensions
I first lifted seven, then checked each file's real consumers and put five back.
AuthenticationBuilderExtensions, AuthenticationNavigation{Service,Extensions},
IAuthenticationNavigationService and StylesConfiguration are consumed only by
MemexConfiguration and by views — all of which move out — so lifting them would
have dragged AspNet.Security.OAuth.Apple (and transitively OpenIdConnect and
IdentityModel) into the ASP.NET hosting layer to serve nobody who stays.
That is the discipline this whole refactor turns on: lift what the platform
needs, not what happens to sit in the same folder.
Verified with CI's flags, 0/0: Hosting.AspNetCore, Blazor.Portal, Hosting.
The blanket namespace rewrite was too eager in three places:
VirtualUserMiddleware duplicated a using (CS0105)
Login.razor lost the VIEW namespace when IAuthenticationNavigationService
went back to Blazor.Portal
MemexConfiguration same, for AuthenticationBuilderExtensions and
AddAuthenticationNavigation
All three need BOTH namespaces now: the two services that stayed lifted
(AuthenticationOptions, VUserHelper) and the five that went back to the views.
🚨 Caught only because the build's exit code was checked. An earlier run of the
#2245 ratchet reported "Passed! 2 tests" while the build had exited 1 — the test
ran against a stale DLL and proved nothing. Re-verified properly:
build exit=0 / 0 Error(s), THEN NodeTypeDeclarationSelfTypingTest 2/2 passed.
That ratchet guards a defect measured at 3.2 failures/second on every serving
pod (a NodeType declaration filed under the type it declares, so it matched every
nodeType:User query). It stays in core and still runs; the lift only rewrote its
using.
Contributor
Review caught it: the note claimed 'these two references are the only ones the move adds' while the project adds three. Markdown.Export.Contract went in later, for PortalApplication, and I did not update the sentence above it. A dependency note that undercounts is worse than none — it is exactly what a future audit would trust instead of reading the list.
The over-lift correction put AuthenticationBuilderExtensions back into MeshWeaver.Blazor.Portal.Authentication, but the blanket namespace rewrite had already repointed this consumer at the lifted namespace — so it referenced a type that is no longer there. Caught by CI's clean build, not locally: this project was not in the set I rebuilt after the correction. Swept the other four returned types the same way and this was the only consumer left stale. Verified: Memex.Portal.Shared.Test builds 0 errors under -warnaserror.
Contributor
Contributor
Contributor
Test Results (shard 0)1 206 tests 1 206 ✅ 12m 22s ⏱️ Results for commit 22f92cf. ♻️ This comment has been updated with latest results. |
Contributor
Contributor
Contributor
The gate builds MeshWeaver.Plugins' src against this PR, and twelve of its modules referenced the PLATFORM's MeshWeaver.Blazor through $(MeshWeaverRoot) — so this lift removed Infrastructure/ out from under them and they lost even the transitive types (MeshNodeProviderAttribute, MessageHubConfiguration, MeshWeaver.Layout, MeshWeaver.Messaging). Plugins#688 points them at that repo's OWN copy, which it has carried all along. Empty commit purely to re-run the gate against it. Worth noting the gate did exactly its job: a platform change breaking the plugins repo failed the PLATFORM's PR, before merge, instead of surfacing there hours later. That is the property #2277 just widened from two packages to all 53.
…al-infrastructure-out-of-blazor # Conflicts: # memex/Memex.Portal.Shared/Authentication/EaGraphAuth.cs
rbuergi
deleted the
refactor/lift-nonvisual-infrastructure-out-of-blazor
branch
August 28, 2026 08:56
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.
Unblocks removing GUI from core. The blocker turned out to be a mislabelled layer, not volume.
What was in the way
MeshWeaver.Blazor/Infrastructure/holds eight files that are not views:Not one of them imports
MeshWeaver.BlazororMicrosoft.AspNetCore.Components— they werealready Blazor-free and merely lived in the UI project. Meanwhile 12 core files and 12 core test
projects import that namespace, so deleting the Blazor project would take core's own middleware
and caches with it.
The move
They go to
MeshWeaver.Hosting.AspNetCore/Portal/, where ASP.NET middleware belongs, withnamespaces that stop claiming to be Blazor. Because the files were already Blazor-free the move is
pure — no code changes — and it costs exactly three project references:
ContentCollectionsArticleExtensionsLayoutPortalErrorSinkMarkdown.Export.ContractPortalApplicationPortalApplicationstays insrc/with the middleware that consumes it. My first attempt put it inmemex/Memex.Portal.Sharedand the compiler rejected it:UserContextMiddlewareuses it, andsrc/cannot referencememex/.MeshWeaver.Blazornow referencesMeshWeaver.Hosting.AspNetCorerather than owning this code —UI depends on hosting, never the reverse.
Verification
CI's flags (
-c Release -warnaserror), all 0 warnings / 0 errors:The
InternalsVisibleTohazard was checked rather than hoped:MeshWeaver.Blazorgrants IVT tothree assemblies and the new home to one — which is exactly how
MeshWeaver.OgCard.Testsilentlylost
CS1729when it moved out. OnlyPortalErrorSinkdeclares anythinginternal, and everyconsumer compiles.
No What's New entry: internal restructuring, no user-visible change.