feat: consent-ledger echo + re-consent click-through (tos-v1 phase 2)#2456
feat: consent-ledger echo + re-consent click-through (tos-v1 phase 2)#2456jjramirezn wants to merge 4 commits into
Conversation
The backend's new consent_records ledger stores what the user was actually shown, so every acceptance surface now echoes the displayed document versions instead of letting the server assume: signup sends terms+privacy via the x-accepted-legal header (the ZeroDev SDK owns the register/verify body), card apply sends the exact regional doc set from CardTermsScreen, and versions+hashes are generated from the src/content legal frontmatter at build time — no hardcoded versions anywhere. Adds the ToS §17 re-consent flow: a blocking click-through modal when a published document version moves past the user's last provably-accepted one. Fails open — a dead consent endpoint never locks the app.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughAdds generated legal-document versions and consent APIs, sends consent records during signup and card applications, and introduces a session-scoped re-consent modal with analytics and acceptance handling. ChangesConsent ledger flow
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant ReConsentModal
participant consentApi
participant PostHog
User->>ReConsentModal: Authenticate
ReConsentModal->>consentApi: getStatus()
consentApi-->>ReConsentModal: Consent status
ReConsentModal->>PostHog: Record MODAL_SHOWN
User->>ReConsentModal: Accept documents
ReConsentModal->>consentApi: accept(documents)
consentApi-->>ReConsentModal: Acceptance recorded
ReConsentModal->>PostHog: Record MODAL_DISMISSED
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Code-analysis diffPainscore total: 6233.95 → 6251.67 (+17.72) 🆕 New findings (45)
…and 25 more. ✅ Resolved (41)
…and 21 more. 📈 Painscore deltas (top movers)
|
🧪 UI test report — ✅ all greenSuites
📊 Coverage (unit)
⏱ 10 slowest test cases
|
The single-line entries exceeded printWidth 120, so every predev run left a prettier-dirty tree; one field per line keeps the generated file byte-stable under formatting.
|
@coderabbitai review |
✅ Action performedReview finished.
|
A logout followed by login as a different account in the same SPA session skipped the second user's consent-status check.
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai full review |
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@package.json`:
- Around line 15-16: Update the package scripts for dev:clean, dev:fallback, and
analyze so each supported entrypoint runs scripts/generate-legal-versions.mjs
before its existing command, ensuring legal version and hash constants are
regenerated regardless of how development or analysis is started.
In `@src/components/Global/ReConsentModal/index.tsx`:
- Around line 35-48: Update the ReConsentModal effect around lastCheckedUserId,
outdatedDocs, and checked to reset consent UI state whenever the authenticated
userId changes, ensuring prior users’ modal and checkbox state is not reused.
Reset checked after a successful consent submission, and add cancellation or a
userId/token guard to the consentApi.getStatus response before calling
setOutdatedDocs so late responses cannot update state for another user.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: b279ef57-4a5c-4541-a76e-09baf3eaf5e7
⛔ Files ignored due to path filters (1)
src/constants/legal-versions.generated.tsis excluded by!**/*.generated.*
📒 Files selected for processing (9)
package.jsonscripts/generate-legal-versions.mjssrc/app/(mobile-ui)/card/page.tsxsrc/app/(mobile-ui)/layout.tsxsrc/components/Global/ReConsentModal/index.tsxsrc/constants/analytics.consts.tssrc/hooks/useZeroDev.tssrc/services/consent.tssrc/services/rain.ts
Every dev/build entrypoint now regenerates the legal-version constants (dev:clean, dev:fallback, analyze bypassed the predev hook and could ship stale version/hash echoes). ReConsentModal state is fully isolated per account: switching users clears the doc list, checkbox, and error, a slow status response for the previous account is discarded, and the checkbox resets after a successful acceptance.
Summary
Client half of the consent ledger (peanut-api #1209, tos-v1 phase 2): every acceptance surface now echoes the exact legal-document revisions it displayed, and the ToS §17 re-consent click-through ships.
scripts/generate-legal-versions.mjs(predev + prebuild, output committed) derivesslug → { version, hash }from thesrc/contentlegal frontmatter (last_updated+ sha256 of eachen.md). No hardcoded versions; bumping the content submodule refreshes the constants on next build./passkeys/register/verifybody, souseZeroDev.handleRegistersends displayed terms+privacy versions via thex-accepted-legalheader (passkeyServerHeaders).rainApi.applyForCardgainsacceptedDocuments; the card page sends the exact set CardTermsScreen showed (US: card-terms-us + card-esign + card-privacy; international: card-terms-international + card-esign).ReConsentModal(mobile-ui layout) checksGET /users/consent/statusonce per session; when a published version passed the user's last provably-accepted one, a blocking checkbox click-through lists the updated docs and records acceptance viaPOST /users/consent/accept.src/services/consent.ts(no server actions).Risks / breaking changes
QA
pnpm dev→ predev regeneratessrc/constants/legal-versions.generated.ts(7 docs).terms+privacy@2026-07-15with the generated hashes.surface='card-apply'.surface='re-consent'rows; modal never returns.🤖 Generated with Claude Code
Design notes / accepted trade-offs
CardTermsScreen'sLINKS, absolute URLs for native, andReConsentModal'sDOC_LABELS, relative for DocsLink). Unifying them into one legal-links const is a small follow-up.Summary by CodeRabbit