feat(hosting): the endpoint-contribution hook — modules map HTTP routes (#1655) - #1663
Conversation
…es (#1655) New MeshWeaver.Hosting.AspNetCore: an assembly-level MeshEndpointProviderAttribute a module carries, applied by the host's app.MapMeshModuleEndpoints() alongside its other Map* calls. Deliberately separate from MeshNodeProviderAttribute — layering (the mesh contract never references ASP.NET) and timing (endpoints map after auth). Guardrails per the #1655 design: every contribution maps inside an authenticated-by-default group (per-route AllowAnonymous is the only escape), and duplicate (verb, pattern) registrations refuse the app loudly at ApplicationStarted — a silently shadowed route is the #683 trapdoor class. Pinned: discovery over InstalledModuleAssembly, the auth default + opt-out metadata, and the collision predicate (both parties named; verb-distinct same-pattern legitimate). Docs: Modules.md gains the endpoint hook; UiExtensibility's 'HTTP endpoints' wall is retired (mesh DATA still cannot contribute routes — trusted compiled code only). First consumers queued: Social, the python/node gRPC link, then the compiled optional-service endpoints (speech/log-incidents/og). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds an ASP.NET Core hosting integration point so boot-installed modules can contribute HTTP endpoints via an assembly-level attribute, with host-side mapping and startup-time collision detection. This extends the “module lane” without coupling the mesh contract to ASP.NET surfaces.
Changes:
- Introduces
MeshWeaver.Hosting.AspNetCorewithMeshEndpointProviderAttributeandapp.MapMeshModuleEndpoints()to map module-contributed routes under an authenticated-by-default group. - Adds collision detection over the full endpoint table at startup (duplicate (verb, pattern) pairs) plus an integration test covering discovery/auth defaults and the collision predicate.
- Updates architecture docs to reflect that module code (not mesh data) can now contribute HTTP endpoints.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| test/MeshWeaver.Hosting.Monolith.Test/ModuleEndpointContributionTest.cs | Adds tests for module endpoint discovery, auth-by-default behavior, and collision predicate behavior. |
| src/MeshWeaver.Hosting.AspNetCore/MeshWeaver.Hosting.AspNetCore.csproj | New hosting integration project for ASP.NET Core endpoint contributions. |
| src/MeshWeaver.Hosting.AspNetCore/MeshModuleEndpointExtensions.cs | Implements MapMeshModuleEndpoints() and route-collision detection logic. |
| src/MeshWeaver.Hosting.AspNetCore/MeshEndpointProviderAttribute.cs | Defines the assembly-level attribute modules use to contribute endpoints. |
| src/MeshWeaver.Documentation/Data/Architecture/UiExtensibility.md | Updates extensibility “walls” to reflect the new module endpoint seam. |
| src/MeshWeaver.Documentation/Data/Architecture/Modules.md | Documents the endpoint contribution attribute, auth defaults, and collision behavior. |
| MeshWeaver.slnx | Adds the new hosting project to the solution. |
| memex/Memex.Portal.Shared/MemexConfiguration.cs | Wires app.MapMeshModuleEndpoints() into StartMemexApplication. |
| memex/Memex.Portal.Shared/Memex.Portal.Shared.csproj | References the new MeshWeaver.Hosting.AspNetCore project. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Test Results (shard 2)2 322 tests - 62 2 318 ✅ - 62 7m 16s ⏱️ -28s Results for commit 89f9add. ± Comparison against base commit 20b793b. This pull request removes 187 and adds 125 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
Test Results (shard 1)2 242 tests +64 2 139 ✅ +64 7m 28s ⏱️ +7s Results for commit 89f9add. ± Comparison against base commit 20b793b. This pull request removes 125 and adds 189 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Review addressed: the collision-refusal comment now states the actual intent (log + StopApplication + throw — belt and braces). The |
Implements #1655 (maintainer-approved). New
MeshWeaver.Hosting.AspNetCorewith the assembly-levelMeshEndpointProviderAttribute+app.MapMeshModuleEndpoints()wired intoStartMemexApplicationbeside the otherMap*calls.MeshNodeProviderAttributehook — the mesh contract never references ASP.NET, and endpoints apply at endpoint-mapping time (after auth middleware), not mesh build.RequireAuthorization()group; a route is anonymous only via explicit per-routeAllowAnonymous().ApplicationStartednaming both endpoints (module-vs-module AND module-vs-platform); same pattern on different verbs stays legitimate. ASP.NET alone only surfaces ambiguity at request time.UiContributionmesh data, which still cannot contribute routes.Verification: Hosting.AspNetCore / Portal.Shared / Portal.Monolith clean
-c Release -warnaserror;ModuleEndpointContributionTest2/2 (discovery + auth default + anonymous opt-out; collision predicate with both parties named). First consumers land as separate PRs: Social (#59), the python/node gRPC link (#60), then speech/log-incidents/og.No What's New entry: platform capability, no user-visible change.
🤖 Generated with Claude Code