Skip to content

release: 0.14.4 [skip review] - #358

Merged
andrewck24 merged 28 commits into
mainfrom
dev
Jul 25, 2026
Merged

release: 0.14.4 [skip review]#358
andrewck24 merged 28 commits into
mainfrom
dev

Conversation

@andrewck24

Copy link
Copy Markdown
Owner

Merge dev into main for the 0.14.4 patch release. After merge, the changesets workflow opens release: update versions (bumps to 0.14.4, updates CHANGELOG), then tags + creates the GitHub Release and syncs back to dev.

User-facing (from the changeset)

Fixed — Record

  • Rally submission failing with a server error when the team roster includes a guest player
  • Crash when recording the first rally of a set
  • Save lineup edits made in single-set settings, with a save confirmation

Fixed — UI

  • Spacing between the fixed header and the court on the game recording screen

Security — Record

  • Reject submitted set lineups that reference players not on the team roster

Internal (not in changelog)

  • Real-DB integration test harness (Jest + mongodb-memory-server, DI auth double); integration tests now run locally pre-PR, not in CI
  • Enable noUncheckedIndexedAccess with a stock-tsc strict gate + fix all indexed-access sites (compile-time guard for the crash class fixed above)
  • Recording-component comment cleanup

Included PRs: #350, #351, #352, #353, #354, #355, #356, #357.


摘要(zh-tw)

0.14.4 patch release(dev → main)。使用者可見:game 記錄 bug 修復(roster 含 guest player 導致 rally 送出 500、首球 crash、單局 lineup 未儲存+無提示)、header↔court 間隙、set lineup roster 驗證(安全,回 400)。內部:real-DB integration 測試 harness(改為本地 pre-PR,不進 CI)、啟用 noUncheckedIndexedAccess、註解精簡。合併後 changesets workflow 會自動開 version PR 升到 0.14.4 並發 release、sync 回 dev。

andrewck24 and others added 28 commits July 24, 2026 04:55
chore: sync v0.14.3 release back to dev [skip review]
…rash

Submitting a rally could white-screen the whole Game tree: at entryIndex 0
the recording Preview freezes and demotes the draft to `previousEntry`, which
resolves to `entries[-1]` (undefined). <Entry> then dereferenced `entry.type`
and threw. The same undefined can arise after an optimistic-mutate rollback.

Guard at the shared choke point so every caller (Preview, summary-drawer rows)
is protected: <Entry> renders null for a nullish/type-less entry, and
useEntryDraftPreview reports `inProgress: false` when the resolved entry would
be undefined so nothing renders instead of a broken card.

Refs ATE-91.
…d honest types

The white-screen crash came from `entries[entryIndex - 1]` resolving to
`entries[-1] === undefined` at the first entry, then flowing through
`PreviewCard`'s freeze into `<Entry>`. Replace the negative-index access with an
explicit `entryIndex > 0` guard so `previousEntry` is honestly `EntryView |
undefined`, and make the optional-in-practice props (`entry`, `previousEntry`)
optional in their types instead of leaning on comments. Freezing the first
entry now falls back to the entry itself (`previousEntry ?? entry`) rather than
surfacing undefined.

Adds a regression test for the real end-to-end freeze path (empty entries +
complete draft + submit) that white-screened before, and drops the stale
undefined-entry cast now that the prop is typed optional.
…ined-guard

fix(game): guard Entry against undefined entry to prevent recording crash
The recording Entry/Preview components carried multi-line comments that restated the code or narrated design docs. Trim to terse why-only notes and let honest types (optional props) document the contract.
chore(game): trim over-commented recording code [skip review]
The backend Jest project stubs mongoose/mongodb with `jest.fn()`, so the
route -> controller -> usecase -> repository -> DB persistence seam had zero
coverage — mapping bugs between the write and read layers could not surface in
tests. `docs/testing-strategy.md` also claimed `jest.setup.backend.ts` used
`mongodb-memory-server`, which was neither installed nor true.

Add a third Jest project, `integration`, that runs `*.itest.ts` against a real
in-memory MongoDB (one server per worker file for isolation), resolves the real
DI container, and swaps only the auth services for DI doubles. Tests drive real
route handlers with a real `NextRequest` so route-layer request mapping is
exercised end to end.

Next's server modules capture `globalThis.AsyncLocalStorage` at import time and
fall back to a stub that throws on use; expose it on the real global (and forward
it to forked workers via an `--import` preload) so imported route handlers work.

Correct the testing-strategy doc to match reality and document the new tier with
a layered request-stack diagram annotating what is real, mocked, or doubled per
layer.
create-set called player.id.toString() on every roster player, but guest players carry a null id, so it threw before the set was saved. The set was never persisted, and later rally submission 404'd SET_NOT_FOUND. Guard on player.id and cover the flow with a real-DB integration test.
PUT /sets forwarded only options, silently dropping the submitted lineup, so lineup edits never persisted and the UI gave no feedback. Thread lineup through the route and use case, add a success toast, and replace the deprecated findByIdAndUpdate new option with returnDocument.
…-harness-and-game-persistence-fixes

fix(game): integration harness + persist new sets and lineup edits
tsgo (TS7 native-preview, used by pnpm typecheck) does not enforce noUncheckedIndexedAccess, so add typecheck:strict running stock tsc and make verify use it. This commit turns the flag on; the indexed-access fixes follow.
Guard or narrow indexed access across game/team feature slices, optimistic
helpers, query helpers, and hooks now that array/record element access yields
T | undefined. Widen getPreviousRally/getPreviousScores/getServingStatus
params to accept undefined (already handled at runtime), guard reducer lineup
lookups, and assert only where an index is provably in bounds. Type-only
corrections; no runtime behavior change.
…os and routes

Enable noUncheckedIndexedAccess-safe access across components, use cases,
mongo repositories, API routes and their tests (excluding src/lib/features).
Indexed access now yields T | undefined; each site is handled truthfully via
guards/early-returns, optional chaining, sensible defaults, or provably
in-bounds non-null assertions — no runtime behavior change.
…rigin/andrewck24/ate-94-batch-b' and 'origin/andrewck24/ate-94-batch-c' into andrewck24/ate-94-no-unchecked-indexed-access
… fallbacks [skip review]

Address non-blocking review notes on #353: add a regression test for the create-substitution 'player not in lineup' NotFoundError branch, default substituteCount to 0 like liberoCount, and comment the intentional stats-absent skip.
…d-indexed-access

build(ts): enable noUncheckedIndexedAccess and fix all indexed-access sites
The fixed header sat flush against the court (gap-1 only applied between court and panel), and the court/panel were full-bleed on mobile so the court's primary frame ran to the screen edge. Add px-1 to inset them and +0.25rem top padding for the header gap; applied to both the live layout and its mirrored skeleton.
The px-1 inset narrowed court/panel against the full-width fixed header and drawer-peek, misaligning their edges. Drop it and keep only the +0.25rem header-court gap.
fix(game): add gap between the fixed header and the court
Set create/update wrote the client-supplied lineup straight onto the set
with no check that its player ids reference the team roster, letting a
buggy or malicious client persist an arbitrary or malformed lineup.

Add a shared entity-level validateLineupPlayers guard (mirroring the
existing validatePlayerStatus pattern) that rejects any non-null player
id in starting/liberos/substitutes or their nested sub not present on
the roster, and call it from both use cases. Null references (empty
slots, unassigned subs) and null-id guest roster entries are handled so
valid lineups are unaffected.
Make `pnpm test` (and thus `pnpm verify`/CI) run only the backend and
frontend Jest projects. The integration project boots a real
mongodb-memory-server binary, which is slow and network-dependent; run
it locally before opening a PR via `pnpm test:integration`.

Update testing-strategy.md to state the integration tier is a local
pre-PR gate rather than part of CI.
…-local-only

ci(test): exclude integration project from CI test runs
The lineup arrives unvalidated from the request body; a missing/non-array shape spread into a raw TypeError (HTTP 500) instead of the intended 400. Guard the shape in validateLineupPlayers, and validate before mutating the set in update-set.
…er-validation

fix(game): validate lineup player ids against team roster
chore: add changeset for 0.14.4 [skip review]
@vercel

vercel Bot commented Jul 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
volleybro Ready Ready Preview, Comment Jul 25, 2026 8:13pm

@andrewck24
andrewck24 merged commit 808426f into main Jul 25, 2026
8 checks passed
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