Skip to content

chore(api): fix integration-test Jwt:SecretKey length (>=32 bytes) - #176

Merged
thomasluizon merged 1 commit into
mainfrom
chore/fix-integration-jwt-secret
Jun 4, 2026
Merged

chore(api): fix integration-test Jwt:SecretKey length (>=32 bytes)#176
thomasluizon merged 1 commit into
mainfrom
chore/fix-integration-jwt-secret

Conversation

@thomasluizon

Copy link
Copy Markdown
Owner

What

Set a test-only Jwt:SecretKey (>=32 bytes, ASCII) for the integration-test host via UseSetting in IntegrationTestWebApplicationFactory.

Why

This is a pre-existing failure on main that blocks the entire tests/Orbit.IntegrationTests suite at startup — it is not introduced by any feature branch. Every test threw before reaching any assertion:

System.InvalidOperationException : Jwt:SecretKey must be at least 32 bytes (27 provided).
  at Orbit.Infrastructure.Configuration.JwtSettings.Validate()
  at Orbit.Api.Extensions.ServiceCollectionExtensions.ValidateOrbitSecuritySettings(...)
  at Program.<Main>$(...)

Root cause

WebApplicationFactory<Program> resolves its content root to src/Orbit.Api (per the generated MvcTestingAppManifest.json), so the host loads src/Orbit.Api/appsettings.json, where Jwt:SecretKey is the placeholder "REPLACE-IN-DEVELOPMENT-JSON" — exactly 27 bytes. JwtSettings.Validate() (called at startup) requires >=32 bytes for HMAC-SHA256 and throws.

The test project's own tests/Orbit.IntegrationTests/appsettings.json does contain a valid 50-byte key, but it is never loaded by the factory (content root is the API project, not the test assembly dir), so it was dead config for this path.

Fix

Inject a clearly test-only secret through the web host builder in the factory. This feeds the configuration the host actually reads, independent of content root. The production validator and production secrets are untouched — no weakening of JwtSettings.Validate().

Validation (in worktree)

  • dotnet build — clean (0 errors).
  • dotnet test tests/Orbit.IntegrationTests --filter "FullyQualifiedName~AuthControllerTests":
    • Before: all 4 fail with Jwt:SecretKey must be at least 32 bytes (27 provided).
    • After: zero JWT-secret errors; the suite boots fully past startup and now reaches the EF/Npgsql layer (The ConnectionString property has not been initialized), an unrelated env-specific empty-connection-string in this sandbox shell. On an environment where orbit_test is reachable, the suite boots and connects.

Impact

Unblocks the integration suite for in-flight PRs (#81 / #78 / #79).

🤖 Generated with Claude Code

WebApplicationFactory<Program> loads config from the Orbit.Api content
root, where appsettings.json carries a 27-byte "REPLACE-IN-DEVELOPMENT-JSON"
placeholder for Jwt:SecretKey. JwtSettings.Validate() requires >=32 bytes,
so every integration test threw at startup
("Jwt:SecretKey must be at least 32 bytes (27 provided)").

The test project's own appsettings.json is never loaded by the factory
(content root resolves to src/Orbit.Api), so its valid key was dead config.
Inject a test-only secret via UseSetting in the factory instead. Production
validator is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct minimal fix for a pre-existing startup blocker. UseSetting is the right mechanism — it injects a config value that wins over appsettings files regardless of content root, so the 27-byte placeholder in src/Orbit.Api/appsettings.json is overridden cleanly. The injected key is 47 bytes (ASCII), satisfying the JwtSettings.Validate() ≥32-byte guard. Production validator and production secrets are untouched. No contract changes, no CLAUDE.md violations.

@thomasluizon thomasluizon reopened this Jun 4, 2026
@thomasluizon
thomasluizon merged commit 24690e9 into main Jun 4, 2026
5 checks passed
@thomasluizon
thomasluizon deleted the chore/fix-integration-jwt-secret branch June 4, 2026 23:54
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.

1 participant