MimironsGoldOMatic

Migration — legacy monolith removed

The legacy single-host monolith layout under src/ is gone. The canonical ASP.NET Core host is MimironsGoldOMatic.Backend.Api (Program.cs under src/MimironsGoldOMatic.Backend/MimironsGoldOMatic.Backend.Api/). Supporting code is in sibling Backend.* projects under src/MimironsGoldOMatic.Backend/ (.Application, .Infrastructure, .Infrastructure.Persistence, .Common, and .Configuration). Docker image: src/MimironsGoldOMatic.Backend/MimironsGoldOMatic.Backend.Api/Dockerfile. CI and local runbooks use dotnetMimironsGoldOMatic.Backend.Api.csproj (see .github/workflows/e2e-test.yml, docs/setup/SETUP-for-developer.md).

Backend (EBS — Extension Backend Service)

Key Functions

API Endpoints

Automated tests (MVP-6)

Tier B integration (summary): SyntheticDesktop (HTTP-only stand-in for WPF Desktop) calls the same REST routes as MimironsGoldOMatic.Desktop: confirm-acceptance, PATCH status InProgressSent. On Sent, EBS posts to Helix; in CI, Twitch:HelixApiBaseUrl points at MockHelixApi (9053), which records POST /helix/chat/messages for assertions. Development-only POST /api/e2e/prepare-pending-payout seeds a Pending payout when Mgm:EnableE2eHarness is true (see docs/e2e/E2E_AUTOMATION_PLAN.md).

Running Tier A E2E locally (manual)

Mirror the workflow on one machine (Linux/macOS/WSL or separate terminals on Windows):

  1. Start PostgreSQL 16 with database mgm, user/password matching your connection string (same shape as CI: Host=localhost;Port=5432;Database=mgm;Username=postgres;Password=postgres).
  2. Terminal A — Backend: ASPNETCORE_ENVIRONMENT=Development ASPNETCORE_URLS=http://127.0.0.1:8080 ConnectionStrings__PostgreSQL=Host=localhost;Port=5432;Database=mgm;Username=postgres;Password=postgres Mgm__ApiKey=ci-desktop-api-key Mgm__DevSkipSubscriberCheck=true Twitch__EventSubSecret=<same secret as mocks> then dotnet run --project src/MimironsGoldOMatic.Backend/MimironsGoldOMatic.Backend.Api/MimironsGoldOMatic.Backend.Api.csproj -c Release (or Debug).
  3. Terminal B — MockEventSubWebhook: ASPNETCORE_URLS=http://127.0.0.1:9051 Backend__BaseUrl=http://127.0.0.1:8080 Twitch__EventSubSecret=<same as Backend> then dotnet run --project src/Mocks/MockEventSubWebhook/MimironsGoldOMatic.Mocks.MockEventSubWebhook.csproj.
  4. Terminal C — MockExtensionJwt: ASPNETCORE_URLS=http://127.0.0.1:9052 Leave Twitch:ExtensionSecret empty only if Backend is in Development (shared dev key); otherwise set the same base64 Twitch:ExtensionSecret on both. dotnet run --project src/Mocks/MockExtensionJwt/MimironsGoldOMatic.Mocks.MockExtensionJwt.csproj.
  5. Send the synthetic EventSub notification: python3 .github/scripts/send_e2e_eventsub.py --url http://127.0.0.1:9051 --secret "<secret>" --user-id e2e-viewer-1 --login e2eviewer1 --text "!twgold Etoehero"
  6. Fetch a token and call the API: curl -s "http://127.0.0.1:9052/token?userId=e2e-viewer-1&displayName=E2EViewer" → use access_token as Authorization: Bearer … on GET http://127.0.0.1:8080/api/pool/me.

Full checklist: docs/e2e/E2E_AUTOMATION_TASKS.md (Tier A Validation Checklist — all items verified; see Tier A Test Results).

Setting up Tier B Environment

Tier B adds MockHelixApi (loopback Helix stub on 9053), SyntheticDesktop (HTTP harness on 9054), and Twitch:HelixApiBaseUrl in HelixChatService / TwitchOptions. Use this sequence for local integration and for docs/e2e/E2E_AUTOMATION_PLAN.md Tier B First Run Guide.

  1. Complete Tier A local steps above (Postgres + Backend + 9051 + 9052 + synthetic enrollment).
  2. Python deps: pip install -r .github/scripts/tier_b_verification/requirements.txt
  3. MockHelixApi: ASPNETCORE_URLS=http://127.0.0.1:9053 dotnet run --project src/Mocks/MockHelixApi/MimironsGoldOMatic.Mocks.MockHelixApi.csproj -c Release Verify: python3 .github/scripts/tier_b_verification/check_mockhelixapi.py
  4. SyntheticDesktop: ASPNETCORE_URLS=http://127.0.0.1:9054 Mgm__ApiKey=ci-desktop-api-key (must match Backend) SyntheticDesktop__BackendBaseUrl=http://127.0.0.1:8080 dotnet run --project src/Mocks/SyntheticDesktop/MimironsGoldOMatic.Mocks.SyntheticDesktop.csproj -c Release Verify: python3 .github/scripts/tier_b_verification/check_syntheticdesktop.py Full sequence (needs Pending payout): python3 .github/scripts/tier_b_verification/check_syntheticdesktop.py --payout-id <GUID>
  5. Backend Helix → mock: set Twitch__HelixApiBaseUrl=http://127.0.0.1:9053, plus non-empty Twitch__BroadcasterAccessToken, Twitch__BroadcasterUserId, Twitch__HelixClientId so HelixChatService does not skip the outbound call. Restart Backend.
  6. Sweep: python3 .github/scripts/tier_b_verification/check_workflow_integration.py (or --skip-tier-b if Tier B processes are stopped).

References: docs/e2e/E2E_AUTOMATION_PLAN.md (Tier B Readiness Verification), Tier B Troubleshooting, docs/e2e/TIER_B_PRELAUNCH_CHECKLIST.md.

Tier B environment variables

Variable Component Purpose
Twitch__HelixApiBaseUrl Backend Points Helix HttpClient at MockHelixApi (e.g. http://127.0.0.1:9053). Requires A1–A2.
Twitch__BroadcasterAccessToken Backend Bearer for Helix; mock accepts any non-empty string unless strict auth is enabled.
Twitch__BroadcasterUserId Backend broadcaster_id / sender_id in JSON body.
Twitch__HelixClientId Backend Client-Id header; align with MockHelix__StrictAuth if used.
MockHelix__StrictAuth MockHelixApi If true, require Authorization: Bearer and Client-Id on POST /helix/chat/messages.
SyntheticDesktop__BackendBaseUrl SyntheticDesktop EBS root (default http://127.0.0.1:8080).
Mgm__ApiKey Backend + SyntheticDesktop Must match for X-MGM-ApiKey.
Mgm__EnableE2eHarness Backend true (Development only) enables POST /api/e2e/prepare-pending-payout for CI Tier B.
ASPNETCORE_URLS All ASP.NET processes 8080 Backend; 9051 / 9052 Tier A mocks; 9053 MockHelixApi; 9054 SyntheticDesktop.

Running Tier B E2E locally (full chain)

After Setting up Tier B Environment, either seed a Pending payout via POST /api/e2e/prepare-pending-payout (Development + Mgm:EnableE2eHarness) as in CI, or via enrollment → roulette tick → POST /api/roulette/verify-candidate with X-MGM-ApiKey.

  1. POST http://127.0.0.1:9054/run-sequence with JSON {"payoutId":"<GUID>","characterName":"Etoehero"} (or use check_syntheticdesktop.py --payout-id / run_e2e_tier_b.py).
  2. When Backend calls Helix on Sent, GET http://127.0.0.1:9053/last-request should show the Russian §11 template message for the winner.
  3. Inspect GET http://127.0.0.1:9054/last-run if any step returns non-2xx.

With Twitch__HelixApiBaseUrl unset, HelixChatService uses the production Twitch host — use MockHelixApi + base URL for local/CI validation.

Debugging mock services

Environment variables (local E2E)

Variable Component Purpose
ASPNETCORE_ENVIRONMENT Backend Development for dev Extension JWT key when secret empty.
ASPNETCORE_URLS All ASP.NET processes Bind addresses (8080, 9051, 9052).
ConnectionStrings__PostgreSQL Backend Marten / PostgreSQL.
Mgm__ApiKey Backend Desktop X-MGM-ApiKey routes (set for parity with Desktop tests).
Mgm__DevSkipSubscriberCheck Backend true so synthetic subscriber payload enrolls without Helix.
Twitch__EventSubSecret Backend + MockEventSubWebhook HMAC verification (empty = skip verification).
Backend__BaseUrl MockEventSubWebhook EBS root URL for forward.
Twitch__ExtensionSecret Backend + MockExtensionJwt Base64 symmetric key; empty + Development uses shared dev fallback string.
Twitch__ExtensionClientId Backend + MockExtensionJwt Optional JWT aud; must match if set.

Additional Libraries

Architecture & Patterns

Event Sourcing