Skip to content

Fix on-demand persist reverting profile hash after concurrent generate - #57

Draft
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/critical-bug-investigation-3d03
Draft

cursor[bot] wants to merge 1 commit into
mainfrom
cursor/critical-bug-investigation-3d03

Conversation

@cursor

@cursor cursor Bot commented Aug 24, 2026

Copy link
Copy Markdown

What changed

  • Skip on-demand tool persist when users.profileDataHash no longer matches the hash captured at generation start, so an in-flight Tarot (or other tool) write cannot revert a newer Generate Full Report.
  • Return 409 profile_hash_changed from POST /api/profile/ensure-tool-report instead of storing the stale reading.
  • Link issue/error report (automated critical-bug investigation).

Why this change is safe

  • Root cause identified: persistOnDemandToolReports always wrote users.profileDataHash, the tool report, and generation lock/job docs from the request-start hash, with no live-hash check. Ensure-tool-report can run up to 90s and does not hold the generation lock.
  • Scope is focused (hash fence + 409 + tests). No catalog or billing refactor.
  • Risk areas reviewed: natal persist from Generate Full Report still succeeds because it writes the new hash before persist; matching-hash tool visits still persist.

Bug and impact

  1. User has profile hash H1 and opens a slow on-demand tool (e.g. Tarot).
  2. In another tab they correct birth data and click Generate Full Report (hash H2, natal charts rewritten).
  3. The in-flight persist then merge-writes profileDataHash: H1, an old-birth tool report onto the new natal profile, and marks generation locks/jobs completed.

That reverts the stored hash while birth fields stay H2, so the next Generate is treated as another hash-change regen (possible extra PAYG debit) and mixed-generation reports remain stored.

This is complementary to open PR #53, which clears stale catalog fields at generate time and gates display on hash match. #53 does not stop a persist that finishes after generate.

Verification

  • pnpm exec eslint on touched files (0 errors).
  • pnpm test — 70 suites / 384 tests passed.
  • pnpm run security passed (audit + security lint).
  • Playwright smoke (API persist fence; no UI routing change).

Regression prevention

  • Added tests/unit/onDemandStalePersist.test.ts proving a live H2 hash blocks H1 persist writes.
  • Added ensure-tool-report 409 coverage for skippedStaleHash.
  • Matching-hash persist still writes users.profileDataHash as before.

Release checklist (solo-friendly)

  • CI is green:
    • CI / Lint + Jest
    • CI / Playwright smoke
  • Ready to merge to main.
  • Post-merge sanity check planned: generate profile, open a tool, then regenerate with changed birth data while the tool request is in flight — stored hash should remain the new hash and the old tool report should not be written.
Open in Web View Automation 

In-flight tool generation could finish after Generate Full Report and
write the old profileDataHash plus a stale report onto the new natal
charts. Re-read the live user hash before persist and return 409 when
it no longer matches.

Co-authored-by: Andy Oliver Rozario <andyrozario7@gmail.com>
@vercel

vercel Bot commented Aug 24, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
future-seer Ready Ready Preview Aug 24, 2026 11:11am

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