Skip to content

fix(purchase): preserve ramp progress across stale plan updates - #464

Merged
cristim merged 4 commits into
mainfrom
fix/230-plan-update-cas
Oct 4, 2026
Merged

cristim merged 4 commits into
mainfrom
fix/230-plan-update-cas

Conversation

@cristim

@cristim cristim commented Oct 1, 2026

Copy link
Copy Markdown
Member

A notification sweep could restore a stale ramp step after an approval completed the next step, stopping further ramp purchases. Plan updates now reject stale snapshots, and notification stamping updates only its own field. A plan-specific trigger makes version timestamps advance even for repeated writes in the same transaction.

Closes #230.

Independent adversarial gpt-6-astra review approved exact commit 5c5e1fea5e3ad24e02c52b8d13bd7d2af3afae35 with no actionable findings, using the owner's authorized local-review alternative. The reviewer reread all 19 changed files and independently reproduced the original failures and targeted mutations.

Connected tests exercise the real notification sweep, PostgreSQL store and migrations, completion, next-execution creation and step-3 continuation. Stale PUT, PATCH and disable requests return sanitized HTTP 409 while distinct fresh edits succeed. Store tests cover notification-token invalidation, missing versus stale rows, rollback, failed commits and database errors. Existing PostgreSQL 16 container fixtures and separately labeled native PostgreSQL 17 checks passed. Independent final-SHA race tests, backend build and normal commit hooks passed; the author also passed the full race suite with synthetic AWS credentials, empty configuration files, metadata disabled and verified closed loopback endpoints.

Negative controls independently restored the old timestamp trigger, removed the version check and restored the full-row notification writer. Each failed its intended assertions; fresh-edit controls continued to pass where applicable.

The initial broad suite used an existing AWS resolver test that could attempt reads with ambient credentials. That run does not establish offline execution; the final isolated rerun passed. Connected issue230 probes mock external email and authentication boundaries and use synthetic database data. No purchase, email delivery or deployment was performed for verification.

The schema and application change belong in one rollout. This fix protects persisted plan progress; it does not promise exactly-once notification delivery. Size exception approved for one coherent concern: production plus migrations 71 additions/50 deletions, tests and mock support 402 additions/37 deletions.

Use a plan-specific monotonic timestamp trigger so optimistic writers
can distinguish updates within one transaction and clock regressions.
Use the persisted update token for plan edits and locked ramp writers.
Return conflicts without replacing completed progress, and stamp sent
notifications without replaying an older plan snapshot.
@cristim cristim added severity/medium Moderate harm urgency/this-sprint Within the current sprint triaged Item has been triaged priority/p1 Next up; this sprint impact/many Affects most users effort/m Days type/bug Defect labels Oct 1, 2026
@coderabbitai

coderabbitai Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

  • Run on-demand review

This review includes 19 billable files and costs up to $4.75.

  • Ask an admin to make reviews automatic

Open in CodeRabbit

Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing.

Or wait 50 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available. Your 83 included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: LeanerCloud/cloud-commitments-platform/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: b961a8b5-e679-42e3-a615-d1742897e72f
📥 Commits

Reviewing files that changed from the base of the PR and between fa8c39e and 95514c1.

📒 Files selected for processing (19)
  • internal/analytics/collector_test.go
  • internal/api/handler_plans.go
  • internal/api/handler_plans_edit_race_integration_test.go
  • internal/config/errors.go
  • internal/config/interfaces.go
  • internal/config/store_postgres.go
  • internal/config/store_postgres_complete_step_test.go
  • internal/config/store_postgres_coverage_test.go
  • internal/config/store_postgres_pgxmock_test.go
  • internal/config/store_postgres_plan_update_integration_test.go
  • internal/config/store_postgres_plan_update_test.go
  • internal/database/postgres/migrations/000102_purchase_plan_update_token.down.sql
  • internal/database/postgres/migrations/000102_purchase_plan_update_token.up.sql
  • internal/database/postgres/migrations/000102_purchase_plan_update_token_test.go
  • internal/mocks/stores.go
  • internal/purchase/notifications.go
  • internal/purchase/notifications_ramp_race_integration_test.go
  • internal/purchase/notifications_test.go
  • internal/server/test_helpers_test.go
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@cristim
cristim merged commit a3484df into main Oct 4, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/m Days impact/many Affects most users priority/p1 Next up; this sprint severity/medium Moderate harm triaged Item has been triaged type/bug Defect urgency/this-sprint Within the current sprint

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(db): the notification sweep's full-row plan update can roll a ramp position back

1 participant