Repository navigation
feat(identity) #216 makes the framework unconsumable downstream: SM0026 (duplicate IUserContracts impl) + SM0028 (internal Admin/OpenIddict services) #236
Description
Summary
As of #216 (feat(identity): pluggable identity providers — Keycloak + OpenIddict), the framework on main can no longer be consumed by a downstream host: the host's source-generator pass fails with 7 errors (1× SM0026 + 6× SM0028). This is build-blocking for any consumer (a fresh sm new app, or a hand-built host).
Discovered while building a downstream reference app (InvoiceManager) against a local source build of main (needed because of #220).
Repro
- Take
main(post-feat(identity): pluggable identity providers — Keycloak + OpenIddict #216) — e.g. build the framework into a local NuGet feed and reference it from a downstream host that pulls inSimpleModule.Users+SimpleModule.OpenIddict. dotnet buildthe host.
Errors
error SM0026: Multiple implementations of 'SimpleModule.Users.Contracts.IUserContracts' found in module 'Users':
SimpleModule.Users.UserService, SimpleModule.Users.Services.ExternalUserService.
Only one implementation per contract interface is allowed.
error SM0028: Implementation 'SimpleModule.OpenIddict.Services.OpenIddictSessionContractsAdapter'
of 'SimpleModule.OpenIddict.Contracts.IOpenIddictSessionContracts' must be public.
error SM0028: Implementation 'SimpleModule.OpenIddict.Services.OpenIddictSessionService' ... must be public.
error SM0028: Implementation 'SimpleModule.Users.RoleAdminService' of 'IRoleAdminContracts' must be public.
error SM0028: Implementation 'SimpleModule.Users.UserAdminService' of 'IUserAdminContracts' must be public.
error SM0028: Implementation 'SimpleModule.Users.Services.ExternalRoleAdminService' of 'IRoleAdminContracts' must be public.
error SM0028: Implementation 'SimpleModule.Users.Services.ExternalUserAdminService' of 'IUserAdminContracts' must be public.
Root causes
- SM0026 (new): feat(identity): pluggable identity providers — Keycloak + OpenIddict #216 adds a second
IUserContractsimplementation (ExternalUserService) alongsideUserService, but the generator enforces exactly one implementation per contract interface. Both are discovered, so discovery fails. There appears to be no way to mark a primary/active implementation or to gate one by the configured identity provider at discovery time. - SM0028 (widened): the new identity / admin / OpenIddict session services ship as
internal, so a downstream host can't reference the generated DI registrations across assemblies. This is the same class of problem as SimpleModule.Users 0.0.37/0.0.38 service impls are internal → downstream host fails to build (SM0028) #220 (which was only aboutUserService), now extended to six more services — including duplicated "External" variants from the pluggable provider.
Impact
Build-blocking. The #220 workaround (patch UserService to public in a local source build) is no longer sufficient on main: SM0026 can't be resolved by visibility alone, and six additional services would each need to be made public.
Note: the Form Request feature added in #215 works correctly once it can be consumed — the only blocker to adopting it from a downstream app is this #216 regression. (We pinned our local feed to #215 to get Form Requests without the #216 breakage.)
Suggested fixes
- SM0026: don't auto-discover
ExternalUserServiceas anIUserContractsimplementation — register it conditionally based on the configured identity provider, or let the generator honor a "primary implementation" marker so exactly one impl is discovered per contract. - SM0028: make the new contract implementations
public(consistent with the fix SimpleModule.Users 0.0.37/0.0.38 service impls are internal → downstream host fails to build (SM0028) #220 needs), or have the generator emit each module's DI registrations within the owning module assembly so cross-assembly visibility isn't required.
Related
- SimpleModule.Users 0.0.37/0.0.38 service impls are internal → downstream host fails to build (SM0028) #220 —
SimpleModule.Usersservice impls areinternal→ SM0028 (the underlying visibility issue, now widened) - feat(identity): pluggable identity providers — Keycloak + OpenIddict #216 — the PR that introduced the regression
- feat(core): add Form Request classes for typed binding + validation per endpoint #215 — Form Requests (the feature we were trying to consume)
Activity
fix: downstream consumability bugs (#236, #220, #222, #223, #224) (#238)