Skip to content

feat(mod): recorderFriendCode w payloadzie v2 (schemaVersion 3.0.0) i w D1 - #383

Merged
quarties merged 3 commits into
mainfrom
feat/recorder-friend-code
Oct 21, 2026
Merged

quarties merged 3 commits into
mainfrom
feat/recorder-friend-code

Conversation

@quarties

Copy link
Copy Markdown
Collaborator

Merge i deploy tylko w oknie przełączenia, razem z hostem moda 1.2.0. Zod ma .strict(): nowy host i stary serwer dają 400, stary host i nowy serwer też dają 400.

Co się zmienia

  • gamesV2.ts: schemaVersion: z.literal('3.0.0') i wymagane recorderFriendCode: z.string().min(1). Brak pola, null albo 2.0.0 daje 400. Endpoint zostaje /api/v2/games.
  • Migracja 0013_game_recorder_friend_code.sql: games.recorderFriendCode (String?) i games.recorderPlayerId (Int?, relacja do players, ON DELETE SET NULL), indeks na recorderPlayerId. Migracja jest napisana ręcznie (ALTER TABLE ADD COLUMN). Powód: prisma migrate diff przebudowuje całą tabelę games. Po migracji diff Prisma jest pusty.
  • createGameV2.ts, reguła recorderPlayerId (recorder.ts):
    1. Gracz z payloadu ma ten sam friend code: jego Player.id.
    2. Inaczej dokładnie jeden gracz w players (bez usuniętych) ma ten friend code: jego id.
    3. Zero albo kilka: NULL. Upload działa dalej.
  • Widoczność: oba pola są tylko w D1. getGameData i odpowiedź POST ich nie pokazują (Player identity: the null case, merges, and what leaks publicly #287).
  • HostClient.tsx: bez zmian. Strona wysyła tekst pliku bez parsowania, więc plik 3.0.0 działa. Kopia z okna przełączenia (host 1.1.3): admin zmienia schemaVersion na 3.0.0 i dodaje recorderFriendCode ręcznie.
  • aggregate.test.ts i fixtures/v2-synthetic.json dostają 3.0.0.

Numer migracji

main ma już 0012_discord_accounts_emperor_polls.sql, więc ten PR używa 0013. Draft PR #346 (0012–0015) robi rebase.

Testy

  • npm run typecheck: OK.
  • npm test: 156 passed. Nowe: gamesV2.test.ts (brak pola, null, puste, 2.0.0), recorder.test.ts (trzy przypadki reguły), getGameData.test.ts (żadne z dwóch pól).
  • npm run db:migrate:apply:local: OK.

Closes #377

🤖 Generated with Claude Code

… in D1

The v2 payload now has schemaVersion 3.0.0 and a required recorderFriendCode: the friend code of the machine that recorded the match. A missing field, null, or a 2.0.0 payload gives 400. The endpoint stays /api/v2/games.

Migration 0013 adds games.recorderFriendCode and games.recorderPlayerId (relation to players, ON DELETE SET NULL). It is hand-written with ALTER TABLE ADD COLUMN, because the Prisma diff rebuilds the games table. createGameV2 takes the id of the payload player with the same friend code, else the one live player with that code, else NULL. The upload never fails on this.

Both columns stay in D1. getGameData and the POST response do not show them. Tests: gamesV2 (missing, null, 2.0.0), recorder.ts (three cases), getGameData. HostClient.tsx sends the file text as it is, so a 3.0.0 file works there with no change.

Refs #377

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@quarties quarties left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Review

Kod jest gotowy do merge. Brak blokerów. Merge tylko w oknie przełączenia, razem z hostem 1.2.0.

Punkt Wynik
gamesV2.ts: z.literal('3.0.0'), recorderFriendCode: z.string().min(1), .strict() OK. Brak pola, null, '' i 2.0.0 dają 400
Migracja 0013 OK. main ma już 0012. Migracje 0001–0013 przechodzą w sqlite3. FK players.id, ON DELETE SET NULL. prisma migrate diff do schema.prisma daje pustą migrację
Reguła recorderPlayerId OK. Krok (a) z dbIdByPlayerId, krok (b) findMany z deletedAt: null i take: 2, inaczej null. Odczyt przed batchem
Widoczność OK. Pola nie są w odpowiedzi POST, w getGameData ani w API graczy i gier
HostClient.tsx OK bez zmian. Strona wysyła plik bez parsowania
Twarde 2.0.0 w ingest OK. Tylko testy odrzucenia i komentarz
CI i konflikty CI przechodzi. Brak konfliktu z main

Drobne uwagi

  1. Brak testu dla zapytania Prisma w createGameV2.ts:272-277. Test sprawdza czystą funkcję z mockiem. Przykład: ktoś usuwa ...withoutDeleted, a testy dalej przechodzą.
  2. Draft #346 ma też 0013_discord_host_permissions.sql. Przy rebase #346 musi zmienić numery na 0014 i wyższe.

Deploy

  • Po merge każdy ręczny deploy prod z main (także dla bota) wysyła serwer 3.0.0. Wtedy stary host dostaje 400 na każdą grę.
  • Migracja jest addytywna i nullable. Można ją bezpiecznie zastosować na prod przed kodem (npm run db:migrate:apply:production).

Review of #383. The D1 lookup for recorderPlayerId moves from createGameV2.ts to findLivePlayerIdsByFriendCode in recorder.ts. A new test makes sure that it filters deletedAt: null and takes at most two rows. If someone removes withoutDeleted, the test fails.

Refs #377

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@quarties

Copy link
Copy Markdown
Collaborator Author

Uwaga 1 z review jest w 34862df: zapytanie przeniesione do findLivePlayerIdsByFriendCode w recorder.ts. Nowy test sprawdza deletedAt: null i take: 2. Uwaga 2 dotyczy draftu #346: przy rebase #346 zmienia numery swoich migracji na 0014 i wyższe.

DramaAferaStats.Client.dll 1.3.0+0370f42 from the client-v1.3.0 tag. The hat files stay the same. Goes live with the deploy of this branch.

Refs #377

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@quarties
quarties merged commit fa282f7 into main Oct 21, 2026
2 checks passed
@quarties
quarties deleted the feat/recorder-friend-code branch October 21, 2026 09:44
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.

recorderFriendCode w payloadzie v2 (schemaVersion 3.0.0) i w D1

1 participant