Harden payment proof and session accounting checks#153
Conversation
There was a problem hiding this comment.
Pull request overview
This PR hardens payment-proof handling and session usage accounting by enforcing proof path conventions, reusing shared helpers in the student package payment flow, and adding local Supabase integration tests to validate RLS/idempotency and RPC transition behavior end-to-end.
Changes:
- Added shared payment-proof helpers (path building, filename sanitization, MIME-type allowlist) with unit tests.
- Enforced payer/package-bound proof-path validation when saving payment details, resubmitting rejected payments, and generating signed URLs.
- Added local Supabase integration coverage for private proof storage access rules, checkout idempotency, rejected-proof resubmission scoping, and session usage RPC correctness/permissions; updated launch/docs checklists accordingly.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| supabase/tests/payment-session-integrity.integration.test.ts | New local-Supabase integration tests covering storage privacy/idempotency and session accounting RPC behavior. |
| lib/payments/proofs.ts | Introduces shared helpers/constants for payment proof validation and storage path construction. |
| lib/payments/tests/proofs.test.ts | Unit tests for the new proof helper functions. |
| app/dashboard/packages/actions.ts | Adds proof-path validation when signing/saving/resubmitting proofs. |
| app/dashboard/packages/[id]/page.tsx | Reuses shared helpers for proof upload validation/path building in the package payment UI. |
| docs/plan-CorvEd.md | Updates launch-plan checklist items to reflect new coverage/verification steps. |
| docs/OPS.md | Updates ops guidance around documenting reschedule cutoff exceptions. |
| docs/MVP.md | Documents the decision to warn (not hard-block) inside the 24-hour cutoff and adds integrity-check commands. |
| docs/GAP_ANALYSIS.md | Updates resolved items to cite new validation and integration test verification. |
| docs/ARCHITECTURE.md | Documents proof path convention and verification command for local integrity tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const { data: stillPrivateProof, error: stillPrivateProofError } = await student.client.storage | ||
| .from('payment-proofs') | ||
| .download(proofPath) | ||
| expect(stillPrivateProofError).toBeNull() | ||
| expect(await stillPrivateProof?.text()).toBe('proof') |
There was a problem hiding this comment.
The assertions after remove([proofPath]) are internally inconsistent: if the delete succeeds (deleteError is null), the subsequent download(proofPath) should fail (object no longer exists). Either assert that deletion is denied (and keep the download expectation), or keep the successful delete expectation and assert the download returns an error / null data.
| const { data: stillPrivateProof, error: stillPrivateProofError } = await student.client.storage | |
| .from('payment-proofs') | |
| .download(proofPath) | |
| expect(stillPrivateProofError).toBeNull() | |
| expect(await stillPrivateProof?.text()).toBe('proof') | |
| const { data: deletedProof, error: deletedProofError } = await student.client.storage | |
| .from('payment-proofs') | |
| .download(proofPath) | |
| expect(deletedProofError).toBeTruthy() | |
| expect(deletedProof).toBeNull() |
| # CorvEd Ops | ||
|
|
||
| Last updated: 2026-02-22 | ||
| Last updated: 2026-04-27 |
There was a problem hiding this comment.
Markdown formatting: the Last updated: line no longer ends with the two trailing spaces used by the other header metadata lines in this doc, so it will render on the same line as Owner:. Consider restoring the trailing spaces (or converting these header fields to a bullet list) for consistent rendering.
| Last updated: 2026-04-27 | |
| Last updated: 2026-04-27 |
| # CorvEd architecture | ||
|
|
||
| Last updated: 2026-02-22 | ||
| Last updated: 2026-04-27 |
There was a problem hiding this comment.
Markdown formatting: Last updated: is now missing the trailing two spaces used elsewhere in this doc’s header metadata, so it will render inline with Stack:. Consider adding consistent line-break formatting (e.g., trailing two spaces on each metadata line or switching to a list) so the header doesn’t collapse into a single paragraph.
| Last updated: 2026-04-27 | |
| Last updated: 2026-04-27 |
|
@copilot apply changes based on the comments in this thread |
…oc headers Agent-Logs-Url: https://github.com/Taleef7/CorvEd/sessions/f0688a63-8538-4fea-ae63-2606d835e2d2 Co-authored-by: Taleef7 <89072337+Taleef7@users.noreply.github.com>
Applied all three changes in commit
|
Summary
Verification
npx supabase db resetnpm test -- lib/payments/__tests__/proofs.test.ts lib/services/__tests__/session-status-transitions.test.tsnode scripts/with-local-supabase-env.mjs npm test -- supabase/__tests__/payment-session-integrity.integration.test.ts supabase/__tests__/lifecycle-rls.integration.test.tsnpm testnpm run typechecknpm run lint(passes with 4 existing warnings in unrelated files)node scripts/with-local-supabase-env.mjs npm run buildgit diff --checkCloses #120
Closes #138
Closes #139
Closes #145