Files
SlipItIn/openwiki/operations/runbook.md
Tim Krampitz de852aada7
Some checks failed
Build / build (pull_request) Has been cancelled
Update OpenWiki documentation and claims
Reference AGENTS.md in CLAUDE.md and record verification claims for
the architecture overview and operations runbook.

Signed-off-by: Tim Krampitz <Tim.Krampitz@live.com>
2026-09-07 17:53:25 +02:00

9.7 KiB

type, title, description, tags, openwiki, verified
type title description tags openwiki verified
Runbook Operations, Environment Setup & Testing Guidance Operational guide for local development setup, .NET Aspire startup, EF Core PostgreSQL migrations, JWT configuration, and testing verification scenarios.
operations
runbook
aspire
postgresql
migrations
testing
xunit
signalr
roles change_kinds source_paths symbols validation_commands
operations
testing
lifecycle
public-api
SlipItIn.AppHost/AppHost.cs
SlipItIn.Server/Program.cs
SlipItIn/MauiProgram.cs
SlipItIn.Server.Tests/TestDbHelper.cs
AppHost
Program
MauiProgram
TestDbHelper
dotnet build SlipItIn.slnx
dotnet test SlipItIn.Server.Tests
by at
openwiki/0.5.0 2026-09-07T15:04:46.288Z

Operations, Environment Setup & Testing Guidance

This runbook provides actionable instructions for local development setup, starting services via .NET Aspire, executing Entity Framework Core migrations, configuring environment keys, running client/server applications, and executing targeted test scenarios.

This guide configures environment parameters for the backend and client architecture, manages database migrations for entities in the domain model, verifies real-time event flows defined in the workflow guide, and references source entrypoints cataloged in the source map.


1. Local Development Environment Setup

Prerequisites

  • .NET 10 SDK (Installed and verified via dotnet --version).
  • Docker Desktop or Podman (Required by .NET Aspire to run the PostgreSQL container).
  • Workloads: .NET Aspire workload and .NET MAUI workload (dotnet workload install aspire maui).

Starting the Distributed Application with Aspire

Run the Aspire orchestrator project:

dotnet run --project SlipItIn.AppHost/SlipItIn.AppHost.csproj

What happens during launch:

  1. Aspire launches a PostgreSQL container (pgsql/postgresdb).
  2. Aspire builds and starts SlipItIn.Server.
  3. Program.cs automatically executes EF Core migrations (db.Database.Migrate()), creating database tables if they do not exist.
  4. DbSeeder.SeedAsync(db) populates initial users and phrases when the database is empty.
  5. Aspire Dashboard opens in your web browser, displaying live metrics, OpenTelemetry traces, and structured logs for all services.

2. Configuration & Secrets Management

Configuration settings are loaded from appsettings.json, appsettings.Development.json, and environment variables.

Key Configuration Keys (SlipItIn.Server)

Key Default Value Description
Jwt:Key (none in production; dev fallback: DevOnlyKey-NotForProduction-ChangeMe-0123456789abcdef) Secret signing key for JWT tokens (Must be >= 32 characters / >= 256 bits). In non-development environments, a missing or short key causes a startup exception.
Jwt:Issuer SlipItInServer Token issuer claim.
Jwt:Audience SlipItInClient Token audience claim.
Jwt:ExpirationMinutes 1440 (24 hours) JWT token lifespan.
ConnectionStrings:postgresdb Configured via Aspire PostgreSQL connection string injected by the Aspire orchestrator.

Production Configuration Security

In production deployment, override Jwt:Key using environment variables or user secrets (dotnet user-secrets):

dotnet user-secrets set "Jwt:Key" "YOUR_HIGH_ENTROPY_PRODUCTION_SECRET_KEY_HERE" --project SlipItIn.Server

3. Entity Framework Core Migrations

When altering models in SlipItIn.Shared/Models/ or SlipItInDbContext.cs:

Adding a New Migration

Run the EF Core CLI from the repository root:

dotnet ef migrations add <MigrationName> --project SlipItIn.Server --startup-project SlipItIn.Server

Applying Migrations Manually

While Program.cs applies migrations at startup (db.Database.Migrate()), migrations can also be manually applied via command line:

dotnet ef database update --project SlipItIn.Server --startup-project SlipItIn.Server

4. Test Project Structure

The SlipItIn.Server.Tests project contains all server-side automated tests. It targets net10.0 and uses xUnit as the test framework, Moq for mocking dependencies, and EF Core InMemory (Microsoft.EntityFrameworkCore.InMemory) for isolated database contexts.

Test Infrastructure

TestDbHelper.cs — Static helper class that creates isolated test databases and seeds test data:

  • CreateFactory() — Returns an IDbContextFactory<SlipItInDbContext> backed by an EF Core InMemory database with a unique name per test, ensuring complete test isolation.
  • SeedUser(db, username, email, isActive) — Inserts a minimal User entity and returns it.
  • SeedPhrases(db, count) — Inserts a set of Phrase entities (with an auto-created creator user) for card-dealing tests.
  • SeedGame(db, host, status) — Creates a Game with a host Player attached, returning both for test assertions.

Test Files

File Class Under Test What It Covers
GameServiceTests.cs GameService Business logic: game creation, joining, starting, player ready, card dealing, slip submission, challenge creation/resolution, game state queries with round time computation.
GameHubTests.cs GameHub SignalR hub behavior: lobby creation/join, player ready, game start, slip submission, challenge submission/resolution, authorization enforcement. Uses Moq to mock IGameService, IHubCallerClients, IGroupManager, and ISingleClientProxy. InMemory DB is used only for the hub's own player-access validation.
AuthControllerTests.cs AuthController Registration (token generation, input validation, case-insensitive duplicate detection), login (credential verification, missing-field handling), and the /auth/me claims endpoint.
DbSeederTests.cs DbSeeder Seed idempotency: verifies SeedAsync creates users and phrases when the database is empty, but does nothing when data already exists, and is safe to call repeatedly.

Running Tests

dotnet test SlipItIn.Server.Tests/SlipItIn.Server.Tests.csproj

For CI-matching behavior (Release configuration):

dotnet test SlipItIn.Server.Tests/SlipItIn.Server.Tests.csproj --configuration Release

5. Testing Guidance & Verification Scenarios

When developing or extending SlipItIn features, verify the core architecture through these targeted test scenarios:

1. JWT Authentication & Claims Tests

  • Test Objective: Verify GameHub rejects unauthenticated WebSocket connections or missing token query parameters.
  • Verification: Connect to /hubs/game without ?access_token=... or with an expired token. Confirm SignalR connection is terminated with 401 Unauthorized.

2. Player Access Authorization Tests

  • Test Objective: Verify Player A cannot manipulate Player B's cards or state.
  • Verification: Authenticate as User A and attempt to call GameHub.SubmitSlip(gameId, playerBId, cardId). Verify that ValidatePlayerAccessAsync throws UnauthorizedAccessException and returns an error response.

3. Client MVVM Decoupled Messaging Tests

  • Test Objective: Confirm GameStateService translates SignalR events into WeakReferenceMessenger messages without memory leak risk.
  • Verification: Trigger a GameStateUpdated event on SignalRService. Confirm that LobbyViewModel and GameBoardViewModel receive GameStateChangedMessage and update their observable collections cleanly.

4. Offline Action Queueing & Resync Verification

  • Test Objective: Verify actions taken while disconnected are stored locally and replayed upon reconnection.
  • Verification:
    1. Disconnect network or stop SignalRService.
    2. Invoke GameBoardViewModel.SubmitSlipAsync(card). Confirm QueuedGameAction is written to Preferences.
    3. Re-establish connection. Confirm GameStateService.ResyncAsync() calls RequestGameStateAsync() and replays the queued action via SendQueuedActionAsync().

5. Dual-Layer Local Storage Verification

  • Test Objective: Confirm sensitive tokens are isolated in SecureStorage while non-sensitive state stays in Preferences.
  • Verification: Inspect local device storage after login. Verify auth_token is stored via platform SecureStorage and game_state / queued_actions are saved in Preferences.

6. Concurrency & Race Condition Tests

  • Test Objective: Confirm IDbContextFactory handles simultaneous WebSocket calls without thread collision.
  • Verification: Simulate 5 parallel calls to GameHub.ChallengeSlip() or SubmitSlip() across multiple clients. Verify that all calls complete cleanly without InvalidOperationException from DbContext.

6. Guidance for Future Agents & Developers

  • When to Consult: Refer to this runbook for local environment setup, Aspire startup commands, EF Core migration commands, and test verification procedures.
  • Invariants:
    • Always run migrations using SlipItIn.Server as both project and startup-project.
    • Test offline queue flushing before submitting client-side real-time changes.
  • CI Build Commands (from .github/workflows/build.yml):
    • Server stack: dotnet build SlipItIn.Shared/SlipItIn.Shared.csproj --no-restore --configuration Release (and similarly for ServiceDefaults, Server, Server.Tests, AppHost).
    • MAUI client: dotnet build SlipItIn/SlipItIn.csproj --no-restore --configuration Debug.
    • Server tests: dotnet test SlipItIn.Server.Tests/SlipItIn.Server.Tests.csproj --no-restore --configuration Release.
  • Minimal Validation Command:
    dotnet build SlipItIn.slnx
    dotnet test SlipItIn.Server.Tests