# Team Brief — AuthBlocks: Register `ModelView`'s Missing Dependency via `ConfigureAuthServices` **Audience:** an orchestrator (and its implementers) working **only** in the AuthBlocks repository at `C:\Development\AuthBlocks`. You do not need, and should not assume, any knowledge of the products that consume AuthBlocks. Everything you need is in this brief or in that one repo (plus a single new BlazorBlocks package version — see §2, the blocking prerequisite). **Status:** ✅ RESOLVED — shipped in `Cerebellum.BlazorBlocks.Web` 10.3.33 + `Cerebellum.AuthBlocks.Web` 10.3.36 (2026-06-20). ~~scoped request, blocked on a BlazorBlocks publish (see §2). Confirmed at runtime against `Cerebellum.AuthBlocks.Web` 10.3.33 / `Cerebellum.BlazorBlocks.Web` 10.3.32. Author: product-designer (for a downstream consumer team). Date: 2026-06-19.~~ > **Resolution (2026-06-20):** `AddBlazorBlocksWeb()` landed in `Cerebellum.BlazorBlocks.Web` 10.3.33 and `ConfigureAuthServices` calls it in `Cerebellum.AuthBlocks.Web` 10.3.36; DeepDrftManager picked up 10.3.36 and removed its local `EditModalSaveContextHolder` stopgap. > This brief is retained as historical record — no further action required. **This is one half of a two-team, ordered fix. AuthBlocks ships second — see §2 and §9.** --- ## 1. The defect in one sentence `AuthBlocksWeb` ships `Users.razor` and `Registrations.razor`, both of which render BlazorBlocks' `` component — but `ConfigureAuthServices` (the single DI entry point consumers call to light up the AuthBlocks Web surface) does **not** ensure `ModelView`'s required service `Web.Maintenance.Entities.EditModalSaveContextHolder` is registered. So a consumer that wires up AuthBlocks the normal way gets an unhandled `InvalidOperationException` that **terminates the Blazor circuit on navigation** to either page, unless that consumer manually hand-registers an internal BlazorBlocks service in its own `Program.cs`. The fix: have `ConfigureAuthServices` call BlazorBlocks' new `AddBlazorBlocksWeb()` extension (which registers the holder), so AuthBlocks stays self-contained for *its* consumers. --- ## 2. Blocking prerequisite — BlazorBlocks must ship first This fix **cannot land until BlazorBlocks publishes a new `Cerebellum.BlazorBlocks.Web` version that exposes a Web-side registration extension** (working name `AddBlazorBlocksWeb()`). That extension is what actually registers `EditModalSaveContextHolder`; AuthBlocks' job is only to *call* it. - AuthBlocks is currently on `Cerebellum.BlazorBlocks.Web` **10.3.32**, which has **no** such extension. - The BlazorBlocks team is shipping the extension and bumping the package as the first half of this fix. - **Reference the specific new version BlazorBlocks publishes for this fix** — fill in the exact version number once the BlazorBlocks team reports it. Do not proceed against 10.3.32; the method will not exist. If you reach this work before the BlazorBlocks version is available, stop and wait for the published version number. The AuthBlocks change is small once the prerequisite is in hand. --- ## 3. The confirmed failure ### Stack trace (captured from a consuming app on navigation to the Users admin page) ``` System.InvalidOperationException: Cannot provide a value for property 'SaveContextHolder' on type 'Web.Maintenance.Entities.ModelView`5[[AuthBlocksModels.InputModels.UserInputModel, ...], [AuthBlocksModels.Models.UserModel, ...],[AuthBlocksWeb.Components.Pages.UserAdmin.Users.UserEditModal, ...], [AuthBlocksWeb.Components.Pages.UserAdmin.Users.UsersViewModel, ...], [AuthBlocksModels.Converters.UserModelToInputConverter, ...]]'. There is no registered service of type 'Web.Maintenance.Entities.EditModalSaveContextHolder'. at Microsoft.AspNetCore.Components.ComponentFactory...CreatePropertyInjector... ``` `ModelView` declares `SaveContextHolder` as `required` with `[Inject]`, so Blazor's component factory throws during component activation. There is no try/catch around component instantiation in the render path, so the exception propagates and tears down the circuit. The user sees a dead page / "An unhandled error has occurred" and must reload. ### Which AuthBlocks pages trigger it `AuthBlocksWeb` ships two user-admin pages that render ``: - `AuthBlocksWeb/Components/Pages/UserAdmin/Users/Users.razor` - `AuthBlocksWeb/Components/Pages/UserAdmin/Registrations/Registrations.razor` Any consumer that routes to either page hits the defect on first navigation. --- ## 4. Why this is AuthBlocks' gap to close (not the consumer's) `AuthBlocksWeb/Startup.cs` exposes `ConfigureAuthServices(IServiceCollection, string apiBaseUrl)` — the **single DI entry point** consumers call to light up the AuthBlocks Web surface. It already registers all the user-admin viewmodels and clients (`UsersViewModel`, `RegistrationsViewModel`, `PermissionsViewModel`, their clients, auth state, hierarchical authorization, etc.). It does **not** register `EditModalSaveContextHolder` and does **not** call any BlazorBlocks Web extension. So AuthBlocks ships pages that depend on `ModelView` while leaving one of `ModelView`'s required services unregistered. The consumer is silently expected to fill the gap — and that is exactly what happened: **two independent downstream products** each had to hand-register the internal BlazorBlocks service (`AddScoped()`) in their own `Program.cs` to make AuthBlocks' shipped pages work. The whole value of a single `ConfigureAuthServices` entry point is that a consumer calling it (plus the already-required `AddMudServices`) gets a working surface with zero manual registrations. Today they don't. Closing this gap inside `ConfigureAuthServices` restores that promise. Note: `IDialogService` / `ISnackbar` (also injected by `ModelView`) come from MudBlazor's `AddMudServices()`, which every AuthBlocks Web consumer already calls as a documented prerequisite — those are not the gap. The single library-owned gap is `EditModalSaveContextHolder`. --- ## 5. The fix ### 5.1 Bump the BlazorBlocks reference Update the `Cerebellum.BlazorBlocks.Web` package reference (currently 10.3.32) to the new version BlazorBlocks publishes for this fix (see §2 — fill in the exact version). This is what makes `AddBlazorBlocksWeb()` available. ### 5.2 Call the extension from `ConfigureAuthServices` ```csharp // AuthBlocksWeb/Startup.cs, inside ConfigureAuthServices(...) services.AddBlazorBlocksWeb(); // registers EditModalSaveContextHolder for the ModelView-based pages ``` Order does not matter for this scoped service; place it near the other registrations. The `AddBlazorBlocksWeb()` extension registers `EditModalSaveContextHolder` as scoped per circuit (its correct lifetime — the holder is per-circuit mutable state that `ModelView` writes and `EditModelModal` reads). ### 5.3 Why this belongs in `ConfigureAuthServices`, not pushed onto consumers - `ConfigureAuthServices` is AuthBlocks' **single DI entry point**. A consumer calling only `AddMudServices()` + `ConfigureAuthServices(...)` should get a fully working user-admin surface. Folding the BlazorBlocks call into the existing entry point keeps that promise; introducing a second method the consumer must remember to call (or expecting them to call `AddBlazorBlocksWeb()` themselves) just relocates the leaked registration one layer up. - AuthBlocks must **not** register `EditModalSaveContextHolder` directly (reaching into BlazorBlocks' internal `Web.Maintenance.Entities` namespace) — that is the same smell the two consumers exhibited, merely relocated. Compose BlazorBlocks' own `Add*` extension instead; the registration lives with its owner, and AuthBlocks stays self-contained by calling it. This is the standard ASP.NET Core layering: each library exposes an `Add*` for its own services, and a higher-level library's `Add*` calls the lower one's. --- ## 6. Constraints - **Do not register `EditModalSaveContextHolder` directly** in AuthBlocks. Call `AddBlazorBlocksWeb()`; let BlazorBlocks own its type (§5.3). - **Keep `ConfigureAuthServices` the single AuthBlocks entry point.** Do not introduce a second method consumers must remember to call; fold the BlazorBlocks call into the existing one. - **MudBlazor remains a caller-owned prerequisite.** AuthBlocks already relies on consumers calling `AddMudServices()` for all its MudBlazor-based pages; do not absorb it into `ConfigureAuthServices`. - **Versioning:** AuthBlocks Web packs/pushes via its `pack.ps1` / packaging script. `AuthBlocksWeb` is currently `Cerebellum.AuthBlocks.Web` **10.3.33**; bump to the next version after referencing the new BlazorBlocks version and adding the `AddBlazorBlocksWeb()` call. **Record the new version** so consumers can pin. --- ## 7. Acceptance criteria 1. The `Cerebellum.BlazorBlocks.Web` package reference is bumped to the new version BlazorBlocks published for this fix, and `ConfigureAuthServices` calls `AddBlazorBlocksWeb()`. 2. A fresh consumer that calls **only** `AddMudServices()` and `AuthBlocksWeb.Startup.ConfigureAuthServices(...)` — and **registers nothing else by hand** — can navigate to the Users admin page and the Registrations admin page with **no `InvalidOperationException`** and **no circuit teardown**. 3. Working behavior means not just page load: opening the edit dialog on a user, saving a valid change, **succeeds** — i.e. the save bridge actually works end-to-end through AuthBlocks' pages. 4. No AuthBlocks consumer needs to touch `Web.Maintenance.Entities` directly; no manual registrations are required beyond the documented `AddMudServices`. 5. `AuthBlocksWeb` is published as a version bump from 10.3.33, and the new version number is recorded. --- ## 8. Open questions for the implementing team / its sponsor 1. **Exact BlazorBlocks version to reference.** Pending the BlazorBlocks team's publish (§2). Confirm the published version number and the exact extension method name (proposed `AddBlazorBlocksWeb()`) before landing the call. 2. **Placement within `ConfigureAuthServices`.** Anywhere in the method works (scoped service, order- independent). Confirm there is no existing convention in `Startup.cs` for grouping third-party `Add*` calls that this should follow. 3. **Any other AuthBlocks pages built on `ModelView`/`NewModelView`?** This brief identified Users and Registrations. If the team expects to add more maintenance pages, note that calling `AddBlazorBlocksWeb()` once covers them all (it is the single home for the maintenance-component deps). --- ## 9. Suggested reading order in the repo 1. `AuthBlocksWeb/Startup.cs` — `ConfigureAuthServices`, the single entry point; add the `AddBlazorBlocksWeb()` call here. 2. `AuthBlocksWeb/Components/Pages/UserAdmin/Users/Users.razor` — renders ``; triggers the defect on navigation. 3. `AuthBlocksWeb/Components/Pages/UserAdmin/Registrations/Registrations.razor` — the second page that renders ``. 4. The AuthBlocks Web `.csproj` — the `Cerebellum.BlazorBlocks.Web` package reference to bump. 5. The AuthBlocks `pack.ps1` / packaging script — to bump and publish `AuthBlocksWeb` after referencing the new BlazorBlocks version. --- ## 10. Cross-team ordering (important — you ship second) This fix is layered across two repos and **must land in order**: 1. **BlazorBlocks ships first.** It adds `AddBlazorBlocksWeb()`, bumps `Cerebellum.BlazorBlocks.Web` from 10.3.32, packs/pushes, and reports the new version number. 2. **Then AuthBlocks (this team)** bumps its `Cerebellum.BlazorBlocks.Web` reference to that published version, calls `AddBlazorBlocksWeb()` from `ConfigureAuthServices`, bumps `Cerebellum.AuthBlocks.Web` from 10.3.33, and publishes. This team **cannot complete its part until the BlazorBlocks version is published** (§2). Confirm that version number is in hand before starting.