Skip to content

feat: ApiKey builder adoption, new samples, and role enums#41

Merged
Theauxm merged 4 commits into
mainfrom
feat/api-auth-hardening
Apr 15, 2026
Merged

feat: ApiKey builder adoption, new samples, and role enums#41
Theauxm merged 4 commits into
mainfrom
feat/api-auth-hardening

Conversation

@Theauxm
Copy link
Copy Markdown
Member

@Theauxm Theauxm commented Apr 15, 2026

Summary

  • Every sample (GameServer, ChatService, ApiAudit, JobHunt) migrated to the new AddTraxApiKeyAuth(keys => ...) builder. No more plaintext switch expressions — keys are salted and hashed under the hood and compared in constant time.
  • Per-sample role enums (GameRole, ChatRole, AuditRole) plus nameof(Role.X) at every registration site. Role strings live in one place and stay consistent with [TraxAuthorize] / RequireRole calls.
  • New ApiAudit sample: minimal GraphQL host showing the audit pipeline with a console sink.
  • New JobHunt sample: GraphQL hub + Next.js client demonstrating per-train authorization, principal-backed ownership, and multi-user flows.
  • Drops per-sample ApiKeyAuthHandler copies in favor of the unified Trax.Api.Auth.ApiKey package.
  • ChatService migrated to SQLite and to the shared resolver package.

Depends on

Test plan

  • dotnet build zero warnings
  • dotnet csharpier check . clean
  • JobHunt E2E green (blocked on Trax.Mediator validator fix noted in Clean up TestRunner and add lifecycle hook examples #28)
  • GameServer E2E green (same dependency)
  • ChatService / ApiAudit boot locally and authenticate sample requests

- Adopt the new AddTraxApiKeyAuth(keys => ...) builder surface across
  GameServer, ChatService, and JobHunt samples. Plaintext switch
  expressions are gone; keys are salted and hashed under the hood.
- Introduce per-sample role enums (GameRole, ChatRole, AuditRole) and
  use nameof(Role.X) at registration sites so role strings stay in one
  place and stay consistent with [TraxAuthorize] / RequireRole calls.
- New ApiAudit sample: minimal GraphQL host demonstrating the audit
  pipeline with a console sink (bounded channel, batch writer, principal
  attribution).
- New JobHunt sample: complete GraphQL hub + Next.js client showing
  per-train authorization, principal-backed ownership, and multi-user
  flows. Drops the per-sample ApiKeyAuthHandler copies in favor of the
  unified Trax.Api.Auth.ApiKey package.
- ChatService: migrate to the shared resolver package and clean up
  redundant auth scaffolding.
Theauxm added 3 commits April 15, 2026 11:39
Samples were reaching for the Func<TraxPrincipal> overload just to set
a capitalized display name distinct from the id. Display names are a
demo-only nicety, so drop them: id doubles as display name (lowercase).
TraxPrincipal is now absent from every sample Program.cs, matching the
API design goal of hiding framework types behind the builder surface.
- GameServer.Api: bump MaxExecutionDepth to 6 so model-query chains
  (dispatch → mutation → output → nested type → field → scalar) clear
  the Trax default of 4.
- GameServer.Scheduler: add AllowMissingAuthorizationService() on the
  mediator builder. Scheduler is trusted infrastructure and runs
  [TraxAuthorize]-gated trains that were already authorized at the
  original API submission point.
- GraphQLWebSocketClient (both E2E projects): accept an optional
  apiKey argument and include it in the connection_init payload.
  Subscription auth travels in the payload because browsers cannot
  attach custom headers to a WebSocket upgrade.
- SubscriptionTests (both): pass PlayerKey / AliceKey explicitly so
  the new TraxApiKeySocketInterceptor accepts the connection.
The sample's dispatch → mutation → output → nested type → field → scalar
query chain exceeds the Trax default of 4. Matches the GameServer
sample's treatment of the same default.
@Theauxm Theauxm merged commit 431dc83 into main Apr 15, 2026
1 check passed
@Theauxm Theauxm deleted the feat/api-auth-hardening branch April 15, 2026 19:29
@traxsharp
Copy link
Copy Markdown

traxsharp Bot commented May 6, 2026

This PR is included in version 1.21.0

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