Skip to content

Move to .NET 10, and give the DbContext its own project - #50

Merged
konradcinkusz merged 2 commits into
mainfrom
claude/issues-prs-version-tagging-1e40kv
Aug 15, 2026
Merged

Move to .NET 10, and give the DbContext its own project#50
konradcinkusz merged 2 commits into
mainfrom
claude/issues-prs-version-tagging-1e40kv

Conversation

@konradcinkusz

Copy link
Copy Markdown
Owner

What this changes

The service targets .NET 10 instead of .NET 9 — target frameworks, packages, both container base images and CI's SDK. ApplicationDbContext and the entity types move out of AuthService into a new AuthService.Data project, which is what finally makes migration generation possible. The published GHCR image gains linux/arm64.

Behaviourally the service is identical: no endpoint, response shape, configuration key or default changed.

Why

Closes #38, closes #41, closes #47

.NET 9 left support in May 2026. Every deployment of this service has been running an unpatched runtime since — which is a poor position for the component that issues everyone's tokens. Dependabot has been asking for the two halves of this separately (#38 for the runtime image, #41 for the SDK image); #38's Docker build failed because bumping the runtime image alone strands a net9.0 app on a 10.0 runtime. It only works as one change.

The AuthService.Data extraction is the refactor #17 has been blocked on, and the linux/arm64 platform is the last open item from #26.

Approach and alternatives

The reference cycle (#17). dotnet ef loads a migrations assembly out of the startup project's output directory, so AuthService has to reference AuthService.Migrations.*. Those projects in turn need the ApplicationDbContext type their [DbContext(...)] attributes name — which lived in AuthService. Every attempt to generate a set failed with File '.../AuthService.Migrations.PostgreSQL.dll' not found, and no combination of flags resolved it.

src/AuthService.Data/ holds the entity types, ApplicationDbContext, DesignTimeDbContextFactory and DatabaseProviderExtensions, and depends on nothing else in the repository:

AuthService.Data  ←  AuthService.Migrations.PostgreSQL  ←┐
                  ←  AuthService.Migrations.SqlServer   ←┤
                  ←──────────────────────────────────── AuthService

Namespaces are deliberately unchanged (AuthService.Data, AuthService.Models, AuthService.Extensions), so not one using in the service or the tests was touched. The C# diff is pure file renames; everything else is project files. DbSeeder stayed behind in AuthService — it seeds through IServiceProvider and logs against Program, so it belongs with the application, not the model.

Rejected: renaming namespaces to match the new assembly, which would have turned a rename-only diff into a change to every file in the repository for no benefit.

Swashbuckle stays on 9.0.6. Dependabot's #48 offers 10.2.3, which fails to build: OpenAPI.NET v2 moved everything out of Microsoft.OpenApi.Models and removed OpenApiSecurityScheme.Reference. That is an API migration, not a version bump, and it does not belong in a framework upgrade. 9.0.6 ships lib/net9.0, which resolves cleanly on net10.0.

Cross-compiling rather than QEMU. The Dockerfile pins its build stage to $BUILDPLATFORM and passes -a $TARGETARCH to restore and publish. Emulating a .NET SDK build to produce an arm64 image is an order of magnitude slower than cross-compiling, and slow enough to make the second platform not worth having.

Test tooling. Also carries the bumps from #45 (Microsoft.NET.Test.Sdk 18.9.0, xunit 2.9.3, xunit.runner.visualstudio 3.1.5), which could not merge on its own after #44 landed in the same block of the file.

Security impact

Positive, and it is the main reason for the change: the service moves off a runtime that stopped receiving security patches in May 2026, onto the current LTS.

Nothing else about the security surface moves. Token signing, the JWKS endpoint, hashing and the authentication pipeline are untouched.

Breaking changes

None for consumers of the API.

For anyone building from source: the solution has a fourth project, and the .NET 10 SDK is now required. The Dockerfile copies all four project files, so docker compose up and the published image are unaffected.

Schema changes

None. The model is byte-identical — the files moved, nothing in them changed, so docs/schema/upgrade/ needs no new DDL.

Worth saying explicitly since this PR is about migrations infrastructure: it makes generating a set possible, it does not generate one. Database:SchemaMode still defaults to EnsureCreated.

Checklist

  • dotnet build AuthService.sln passes
  • dotnet test AuthService.sln passes
  • dotnet format --verify-no-changes passes
  • Behaviour changes are covered by a test — no behaviour changed; the existing suite is the regression check for the move
  • Documentation updated (README / docs/) where the change is user-visible

The three build boxes are unticked deliberately: the environment this was written in has no .NET SDK and its egress policy blocks downloading one, so CI on this PR is the first execution of any of them. Please treat a green CI run, not my say-so, as the evidence.


Generated by Claude Code

Three changes that only make sense together.

**.NET 10.** .NET 9 left support in May 2026, so every deployment of this
service has been running an unpatched runtime. Target frameworks, the
Microsoft.* and Npgsql packages, both container base images and CI's SDK all
move to the 10.0 line. Swashbuckle stays on 9.0.6 — its 10.x release is a
Microsoft.OpenApi v2 rewrite and belongs in its own change.

**AuthService.Data.** `dotnet ef` loads a migrations assembly out of the
startup project's output, so AuthService has to reference
AuthService.Migrations.*; those projects need ApplicationDbContext, which lived
in AuthService. That cycle is why no migration set could ever be generated
(#17). The context, the entity types, the design-time factory and the provider
wiring now live in a project that depends on nothing else here, and the graph
is acyclic. Namespaces are unchanged, so not one `using` moved and the diff is
file renames plus project files.

`scripts/generate-migrations.sh` works now. Running it and committing the
result is what remains of #17; CI's migration guard stops being a no-op the
moment that lands.

**Multi-arch images.** The published image gains linux/arm64, the last open
item on #26. The Dockerfile cross-compiles with `-a $TARGETARCH` from a
build-platform SDK rather than building under QEMU, which is what keeps the
second platform cheap.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AqCTaRLXbyujh5WPaEMj7N
.NET 10 deprecates it (ASPDEPR005) in favour of KnownIPNetworks, which holds
System.Net.IPNetwork rather than the HttpOverrides type of the same name. The
upgrade compiled with two new warnings; this clears them.

Not purely mechanical: System.Net.IPNetwork insists its base address is the
network address, so a value like "10.0.0.5/8" now throws where the old type
accepted it. Parsed through TryParse so a malformed Network:KnownNetworks entry
is skipped like every other one here, rather than failing startup.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AqCTaRLXbyujh5WPaEMj7N
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants