Commit 3703027
authored
feat(kilo-pass): disallow duplicate card fingerprints across Kilo Pass subscriptions (#3309)
* feat(kilo-pass): add card fingerprint gate for Kilo Pass subscriptions
* fix(kilo-pass): remove unused imports and fix formatting in card-fingerprint-gate test
* fix(kilo-pass): break circular dependency by moving findActiveKiloPassByCardFingerprint to card-fingerprint-gate
* fix(kilo-pass): pass dbOrTx to checkDuplicateCardFingerprintGate for transaction-safe audit logs
* fix(kilo-pass): only use dbOrTx for audit log, keep email/fingerprint lookups on db
* fix(kilo-pass): mock email sender in card-fingerprint-gate tests so email_log markers persist
* fix(kilo-pass): simplify email mock to fix TS2698 spread type error
* fix(kilo-pass): move email notification after transaction commit so marker persists
* fix(kilo-pass): use invoice.id instead of gateResult.stripeInvoiceId for blockedGateResult
* fix(kilo-pass): rename blockedGateResult to blockedEmailParams and use invoice.id
* fix(kilo-pass): fix tsgo type error and replace raw SQL NOT IN with notInArray
- Return blockedEmailParams from db.transaction instead of mutating
outer variable, fixing tsgo narrowing the type to 'never' because
it doesn't track mutations across async closures.
- Replace raw sql`NOT IN` with Drizzle's notInArray for type safety.
* fix(kilo-pass): regenerate migration after rebase onto main
* fix(kilo-pass): regenerate migration after rebase onto main
* fix(kilo-pass): clear affiliate sale context when card fingerprint gate blocks subscription
* fix(kilo-pass): regenerate migration to fix corrupted snapshot with merge conflict markers
The 0141_snapshot.json had unresolved merge conflict markers from a
previous rebase. Deleted branch-local migration files and regenerated
a clean migration (0142) using pnpm drizzle generate.
* fix(kilo-pass): regenerate migration after rebase onto main
Rename branch migration from 0142 to 0143 since main added 0142_dashing_blue_marvel.
Restore main's 0142 snapshot and journal, regenerate clean migration.
* fix(kilo-pass): regenerate migration after rebase onto main
* fix(kilo-pass): clean up email dedup marker when user has no email
When user.google_user_email is falsy in maybeSendDuplicateCardCanceledEmail,
the transactional_email_log marker was left in the DB permanently. This
suppressed future email sends even if the user later acquired an email.
Now the marker is deleted before returning, consistent with the error-path
cleanup logic.
* feat(kilo-pass): block user when duplicate card fingerprint gate triggers
When the card fingerprint gate detects a duplicate card across users,
the offending user's account is now blocked (blocked_reason set to
'kilo_pass_duplicate_card') in addition to the existing cancel + refund.
Does not overwrite an existing blocked_reason. Follows the same pattern
as cancel-and-refund.ts.
* style(kilo-pass): fix oxfmt formatting in card-fingerprint-gate.ts
* fix(kilo-pass): move audit log and user blocking from gate to handler to fix FK violation
The checkDuplicateCardFingerprintGate function was passing dbOrTx through
a parameter to appendKiloPassAuditLog, but the FK constraint on
kilo_pass_audit_log.kilo_pass_subscription_id was being violated inside
the transaction. Move the audit log insert and user-blocking update into
the handler where tx is used directly. Also fix the catch block to omit
kiloPassSubscriptionId when the transaction may have rolled back, and
wrap the failure audit log in a try-catch so it doesn't mask the original
error.
* style(kilo-pass): fix oxfmt formatting
* fix(kilo-pass): add migration for duplicate_card_subscription_canceled check constraint1 parent 2e17562 commit 3703027
10 files changed
Lines changed: 26153 additions & 17 deletions
File tree
- apps/web/src
- emails
- lib
- kilo-pass
- packages/db/src
- migrations
- meta
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
54 | 54 | | |
55 | 55 | | |
56 | 56 | | |
| 57 | + | |
57 | 58 | | |
58 | 59 | | |
59 | 60 | | |
| |||
555 | 556 | | |
556 | 557 | | |
557 | 558 | | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
0 commit comments