Skip to content

fix(submit): adopt legacy rows for first device submit - #609

Merged
junhoyeo merged 2 commits into
junhoyeo:mainfrom
IvGolovach:codex/submit-legacy-device-cutover
May 27, 2026
Merged

fix(submit): adopt legacy rows for first device submit#609
junhoyeo merged 2 commits into
junhoyeo:mainfrom
IvGolovach:codex/submit-legacy-device-cutover

Conversation

@IvGolovach

@IvGolovach IvGolovach commented May 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

Why

#517 fixed the normal modern case where multiple computers submit with stable device IDs, but migrated historical rows still live in the legacy-default device bucket. On current main, the first modern device-aware submit only looks for rows attached to the new device ID, so it can insert a new same-date row while the legacy row remains counted. That can double-count the same historical usage during the upgrade path and leave #248 reproducible for users with pre-device data.

Diff scope

  • packages/frontend/src/app/api/submit/route.ts: before writing incoming daily rows, the submit transaction now adopts a user's legacy daily rows into the first real device bucket when no modern device rows exist yet for that submission.
  • packages/frontend/__tests__/api/submitAuth.test.ts: adds a regression test that fails on current main because the route inserts a duplicate daily row instead of adopting the legacy row.
  • packages/frontend/__tests__/api/usersProfile.test.ts: adds read-path coverage proving same-date rows from multiple submitted devices render as one profile contribution with summed totals.

Branch integrity

  • Base branch: main
  • Validated base SHA: 64e278cdc4f55544576f3b42010644cd8ba6aa9d
  • Head SHA: 49a01dd44d89dc88ce55cd209f33569e53b1f10a
  • Ahead/behind: 0 behind / 1 ahead
  • Merge base: 64e278cdc4f55544576f3b42010644cd8ba6aa9d

Commit integrity

  • Introduced commit: 49a01dd44d89dc88ce55cd209f33569e53b1f10a fix(submit): adopt legacy rows for first device submit
  • The PR contains one logical data-integrity fix plus targeted regression tests.

Diff hygiene

  • git diff --name-status origin/main...HEAD: PASS, only the submit route and two targeted frontend test files changed.
  • git diff --check origin/main...HEAD: PASS, no output.
  • git diff --cached --check: PASS, no output before commit.

Validation mode and proof

  • Validation mode: Mode 3 - submit data-integrity change. The diff changes how legacy daily_breakdown rows are attributed during the device-aware submit transition, so targeted submit/profile/leaderboard coverage is required.
  • bun x vitest run __tests__/api/submitAuth.test.ts: PASS, 7 tests.
  • bun x vitest run __tests__/api/submitAuth.test.ts __tests__/api/usersProfile.test.ts: PASS, 13 tests.
  • bun x vitest run __tests__/api/submitAuth.test.ts __tests__/api/usersProfile.test.ts __tests__/lib/getLeaderboard.test.ts __tests__/lib/getGroupLeaderboard.test.ts: PASS, 22 tests.
  • bun x vitest run __tests__/lib/getLeaderboardAllTime.test.ts: PASS, 4 tests.
  • bun run lint -- src/app/api/submit/route.ts __tests__/api/submitAuth.test.ts __tests__/api/usersProfile.test.ts: PASS.
  • bash scripts/check-version-coherence.sh: PASS, Version coherence OK: 2.1.3.
  • Full frontend suite and Rust suite: not run locally because they are not required for this selected validation mode; the local proof targets the changed submit write path, profile read path, and public leaderboard aggregation.

Ledger and version proof

  • Ledger: not applicable - not required for selected validation mode/change family.
  • Version: PASS via bash scripts/check-version-coherence.sh.

Migration notes

  • Not applicable - no DB migration changed.
  • The fix uses the existing submitted_devices table and existing daily_breakdown.submitted_device_id uniqueness model.

Runtime safety

  • The adoption runs inside the existing /api/submit transaction after the user submission row is selected with FOR UPDATE.
  • Legacy rows are adopted only when the target modern device has no rows yet and the submission has no existing modern device rows, avoiding arbitrary reassignment for mixed/ambiguous accounts.
  • No new background jobs, blocking locks outside the existing transaction, unbounded queues, or schema invariants are introduced.
  • No invariant regression introduced.

CI context confirmation

  • Pending - remote CI has not run because this PR has not been opened yet.
  • CI context names unchanged.

Rollback plan

  • Rollback: revert this PR.
  • DB downgrade: not applicable.
  • Data repair: not applicable.
  • Operational caveats: none known.

Known residual risks

  • Existing accounts that already have both legacy rows and modern device rows are intentionally not auto-reassigned because the original device attribution is ambiguous.
  • Remote CI remains pending until the PR is opened.

Summary by cubic

Fixes #248 by adopting legacy daily_breakdown rows into the first modern submitted device on the first device-aware submit, preventing duplicate same-date rows and double-counted totals. Keeps #517 behavior: modern devices still have separate daily buckets and totals are recalculated from all rows.

  • Bug Fixes
    • In packages/frontend/src/app/api/submit/route.ts, inside the /api/submit transaction, when no modern-device rows exist for the submission and the incoming device is modern, reassign that submission’s legacy rows to the device; otherwise keep legacy rows separate.
    • Adds regression tests in packages/frontend/__tests__/api/submitAuth.test.ts and packages/frontend/__tests__/api/usersProfile.test.ts covering adoption (no duplicate insert), preserving legacy rows when another modern device already submitted, and profile aggregation into a single per-date contribution with summed totals.

Written for commit 1c8a217. Summary will update on new commits. Review in cubic

Validation
* Validation tier: Tier 3 - submit data-integrity change; the diff changes how legacy daily_breakdown rows are attributed during the device-aware submit transition.
* git diff --check: PASS
* git diff --cached --check: PASS
* bun x vitest run __tests__/api/submitAuth.test.ts: PASS (7 tests)
* bun x vitest run __tests__/api/submitAuth.test.ts __tests__/api/usersProfile.test.ts: PASS (13 tests)
* bun x vitest run __tests__/api/submitAuth.test.ts __tests__/api/usersProfile.test.ts __tests__/lib/getLeaderboard.test.ts __tests__/lib/getGroupLeaderboard.test.ts: PASS (22 tests)
* bun x vitest run __tests__/lib/getLeaderboardAllTime.test.ts: PASS (4 tests)
* bun run lint -- src/app/api/submit/route.ts __tests__/api/submitAuth.test.ts __tests__/api/usersProfile.test.ts: PASS
* bash scripts/check-version-coherence.sh: PASS (Version coherence OK: 2.1.3)
* Ledger: not applicable - not required for selected validation tier/change family.
* Version: PASS, bash scripts/check-version-coherence.sh
* Not run: full frontend suite and Rust suite - not required for selected validation tier; targeted submit/profile/leaderboard coverage exercises the changed write path and public totals.

Rollback
* git revert HEAD
@vercel

vercel Bot commented May 26, 2026

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated (UTC)
tokscale Ready Ready Preview, Comment May 27, 2026 7:15am

Request Review

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 3 files

Re-trigger cubic

Add a regression test for the device-aware submit cutover path where legacy daily rows remain separate after another modern device has already submitted.

Constraint: Preserve legacy daily rows when modern-device attribution is ambiguous

Confidence: medium

Scope-risk: narrow

Not-tested: DB-backed legacy adoption with real Postgres rows
@junhoyeo
junhoyeo merged commit b969525 into junhoyeo:main May 27, 2026
5 checks passed
junhoyeo pushed a commit to IvGolovach/tokscale that referenced this pull request May 27, 2026
The regression guard replaces the old client-breakdown merge helper on existing-day submits, so the legacy cutover route tests need to assert the guarded merge path and the provenance now attached to inserted day breakdowns.

Constraint: junhoyeo#609 legacy-device adoption is already on main and shares submitAuth route coverage with this PR
Rejected: Skip the legacy cutover tests on this branch | would hide the integration contract between the guard and legacy adoption
Confidence: high
Scope-risk: narrow
Tested: bun --cwd packages/frontend vitest run __tests__/api/submit.test.ts __tests__/api/submitAuth.test.ts
Tested: bun run --cwd packages/frontend test
Tested: bun --cwd packages/frontend eslint __tests__/api/submitAuth.test.ts src/app/api/submit/route.ts src/lib/db/helpers.ts src/lib/db/schema.ts src/lib/validation/submission.ts
@junhoyeo

Copy link
Copy Markdown
Owner

@IvGolovach this has been merged to v3.0.0: https://github.com/junhoyeo/tokscale/releases/tag/v3.0.0 thanks for the contribution!

leecoder pushed a commit to leecoder/tokscale that referenced this pull request May 29, 2026
* fix(submit): adopt legacy rows for first device submit

Validation
* Validation tier: Tier 3 - submit data-integrity change; the diff changes how legacy daily_breakdown rows are attributed during the device-aware submit transition.
* git diff --check: PASS
* git diff --cached --check: PASS
* bun x vitest run __tests__/api/submitAuth.test.ts: PASS (7 tests)
* bun x vitest run __tests__/api/submitAuth.test.ts __tests__/api/usersProfile.test.ts: PASS (13 tests)
* bun x vitest run __tests__/api/submitAuth.test.ts __tests__/api/usersProfile.test.ts __tests__/lib/getLeaderboard.test.ts __tests__/lib/getGroupLeaderboard.test.ts: PASS (22 tests)
* bun x vitest run __tests__/lib/getLeaderboardAllTime.test.ts: PASS (4 tests)
* bun run lint -- src/app/api/submit/route.ts __tests__/api/submitAuth.test.ts __tests__/api/usersProfile.test.ts: PASS
* bash scripts/check-version-coherence.sh: PASS (Version coherence OK: 2.1.3)
* Ledger: not applicable - not required for selected validation tier/change family.
* Version: PASS, bash scripts/check-version-coherence.sh
* Not run: full frontend suite and Rust suite - not required for selected validation tier; targeted submit/profile/leaderboard coverage exercises the changed write path and public totals.

Rollback
* git revert HEAD

* test(submit): cover legacy rows after modern device submit

Add a regression test for the device-aware submit cutover path where legacy daily rows remain separate after another modern device has already submitted.

Constraint: Preserve legacy daily rows when modern-device attribution is ambiguous

Confidence: medium

Scope-risk: narrow

Not-tested: DB-backed legacy adoption with real Postgres rows

---------

Co-authored-by: Junho Yeo <i@junho.io>
junhoyeo added a commit to blpeng2/tokscale that referenced this pull request Jun 9, 2026
Resolution policy: take main wholesale for everything superseded by the
relational device model that landed via junhoyeo#517/junhoyeo#593/junhoyeo#609 — device.rs,
main.rs, schema.ts, helpers.ts, submit route + tests, and the whole TUI
(app.rs, tui/mod.rs, footer.rs). Keep only the PR's remote-stats half
(tui/remote.rs, /api/me/stats route, meStats tests) to be rebuilt on
top of main in follow-up commits. Drop the next-server.d.ts shim that
the PR added as a workaround for the PR-era Next version.

Refs junhoyeo#699
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.

Submits from different computers seem to overwrite eachother

2 participants