@ssheleg/sheleg-dev 0.11.8 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/package.json +4 -3
- package/plugins/sheleg-dev/.claude-plugin/plugin.json +1 -1
- package/plugins/sheleg-dev/skills/ad-tracking/SKILL.md +24 -8
- package/plugins/sheleg-dev/skills/ad-tracking/references/consent-mode.md +57 -12
- package/plugins/sheleg-dev/skills/crypto-payments/SKILL.md +24 -26
- package/plugins/sheleg-dev/skills/crypto-payments/references/callback-route-hardening.md +52 -0
- package/plugins/sheleg-dev/skills/crypto-payments/references/heleket-provider.md +42 -23
- package/plugins/sheleg-dev/skills/error-tracking/SKILL.md +34 -6
- package/plugins/sheleg-dev/skills/error-tracking/references/scrubbing.md +65 -2
- package/plugins/sheleg-dev/skills/frontend-performance/SKILL.md +51 -23
- package/plugins/sheleg-dev/skills/google-auth/SKILL.md +13 -1
- package/plugins/sheleg-dev/skills/google-auth/references/adc-and-service-accounts.md +13 -3
- package/plugins/sheleg-dev/skills/google-auth/references/oauth2-web-server.md +150 -64
- package/plugins/sheleg-dev/skills/google-auth/references/sign-in-with-google.md +36 -19
- package/plugins/sheleg-dev/skills/google-signin/SKILL.md +55 -23
- package/plugins/sheleg-dev/skills/google-signin/references/full-guide.md +150 -49
- package/plugins/sheleg-dev/skills/stripe-billing/SKILL.md +9 -7
- package/plugins/sheleg-dev/skills/stripe-billing/fixtures/README.md +17 -1
- package/plugins/sheleg-dev/skills/stripe-billing/fixtures/assert-money-invariants.mjs +171 -5
- package/plugins/sheleg-dev/skills/stripe-billing/fixtures/manifest.json +333 -198
- package/plugins/sheleg-dev/skills/stripe-billing/fixtures/reference-handler.mjs +259 -35
- package/plugins/sheleg-dev/skills/stripe-billing/references/subscription-lifecycle.md +149 -28
- package/plugins/sheleg-dev/skills/stripe-billing/references/webhook-events.md +76 -5
|
@@ -1,200 +1,335 @@
|
|
|
1
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
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
2
|
+
"skill": "stripe-billing",
|
|
3
|
+
"assertionPack": "assert-money-invariants.mjs",
|
|
4
|
+
"referenceHandler": "reference-handler.mjs",
|
|
5
|
+
"runbook": "README.md",
|
|
6
|
+
"note": "The single home of the invariant -> fixture -> document mapping. test/validate.py in this repository reads it: every fixture must be claimed by a row, every row's fixtures must exist, and every claiming document must still carry its phrase, name the invariant id, and name a path under fixtures/. A claim whose fixture is gone and a fixture nobody claims are both failures.",
|
|
7
|
+
"invariants": [
|
|
8
|
+
{
|
|
9
|
+
"id": "renewal-grants-exactly-once",
|
|
10
|
+
"isolates": "grant-on-renewal",
|
|
11
|
+
"fixtures": [
|
|
12
|
+
"invoice-paid-subscription-cycle.json"
|
|
13
|
+
],
|
|
14
|
+
"claimedBy": [
|
|
15
|
+
{
|
|
16
|
+
"document": "references/webhook-events.md",
|
|
17
|
+
"phrase": "| `subscription_cycle` | the renewal | **yes** |"
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "proration-invoice-grants-nothing",
|
|
23
|
+
"isolates": "billing-reason",
|
|
24
|
+
"fixtures": [
|
|
25
|
+
"invoice-paid-subscription-cycle.json",
|
|
26
|
+
"invoice-paid-subscription-update-proration.json"
|
|
27
|
+
],
|
|
28
|
+
"claimedBy": [
|
|
29
|
+
{
|
|
30
|
+
"document": "references/webhook-events.md",
|
|
31
|
+
"phrase": "mid-cycle proration (quantity or plan change)"
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"id": "sequential-redelivery-grants-once",
|
|
37
|
+
"isolates": null,
|
|
38
|
+
"fixtures": [
|
|
39
|
+
"invoice-paid-subscription-cycle.json",
|
|
40
|
+
"invoice-paid-subscription-cycle-redelivery.json"
|
|
41
|
+
],
|
|
42
|
+
"claimedBy": [
|
|
43
|
+
{
|
|
44
|
+
"document": "references/webhook-events.md",
|
|
45
|
+
"phrase": "`claimEvent` = `INSERT`; a unique violation is not yet an answer"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"id": "concurrent-redelivery-grants-once",
|
|
51
|
+
"isolates": "claim",
|
|
52
|
+
"fixtures": [
|
|
53
|
+
"invoice-paid-subscription-cycle.json",
|
|
54
|
+
"invoice-paid-subscription-cycle-redelivery.json"
|
|
55
|
+
],
|
|
56
|
+
"claimedBy": [
|
|
57
|
+
{
|
|
58
|
+
"document": "references/webhook-events.md",
|
|
59
|
+
"phrase": "A failure to *claim* (database down) is a 503"
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"id": "crash-after-receipt-is-retryable",
|
|
65
|
+
"isolates": "claim-expiry",
|
|
66
|
+
"fixtures": [
|
|
67
|
+
"invoice-paid-subscription-cycle.json",
|
|
68
|
+
"invoice-paid-subscription-cycle-redelivery.json"
|
|
69
|
+
],
|
|
70
|
+
"claimedBy": [
|
|
71
|
+
{
|
|
72
|
+
"document": "references/webhook-events.md",
|
|
73
|
+
"phrase": "belonged to a worker that died between receipt and completion"
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"id": "in-flight-claim-answers-retry-later",
|
|
79
|
+
"isolates": "claim",
|
|
80
|
+
"fixtures": [
|
|
81
|
+
"invoice-paid-subscription-cycle.json",
|
|
82
|
+
"invoice-paid-subscription-cycle-redelivery.json"
|
|
83
|
+
],
|
|
84
|
+
"claimedBy": [
|
|
85
|
+
{
|
|
86
|
+
"document": "references/webhook-events.md",
|
|
87
|
+
"phrase": "another worker is (or may still be) on it: answer 5xx"
|
|
88
|
+
}
|
|
89
|
+
]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"id": "completion-is-recorded-with-the-grant",
|
|
93
|
+
"isolates": "claim-completion",
|
|
94
|
+
"fixtures": [
|
|
95
|
+
"invoice-paid-subscription-cycle.json"
|
|
96
|
+
],
|
|
97
|
+
"claimedBy": [
|
|
98
|
+
{
|
|
99
|
+
"document": "references/webhook-events.md",
|
|
100
|
+
"phrase": "a row that says completed is one whose business write committed"
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"id": "duplicate-of-completed-never-regrants",
|
|
106
|
+
"isolates": null,
|
|
107
|
+
"fixtures": [
|
|
108
|
+
"invoice-paid-subscription-cycle.json",
|
|
109
|
+
"invoice-paid-subscription-cycle-redelivery.json"
|
|
110
|
+
],
|
|
111
|
+
"claimedBy": [
|
|
112
|
+
{
|
|
113
|
+
"document": "references/webhook-events.md",
|
|
114
|
+
"phrase": "ages a completed row past the expiry and requires the late retry to answer duplicate"
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"id": "transaction-rolls-back-whole",
|
|
120
|
+
"isolates": "atomic-application",
|
|
121
|
+
"fixtures": [
|
|
122
|
+
"invoice-paid-subscription-cycle.json"
|
|
123
|
+
],
|
|
124
|
+
"claimedBy": [
|
|
125
|
+
{
|
|
126
|
+
"document": "references/webhook-events.md",
|
|
127
|
+
"phrase": "commit together, or none of them exist"
|
|
128
|
+
}
|
|
129
|
+
]
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"id": "crash-before-commit-applies-nothing",
|
|
133
|
+
"isolates": null,
|
|
134
|
+
"fixtures": [
|
|
135
|
+
"invoice-paid-subscription-cycle.json",
|
|
136
|
+
"invoice-paid-subscription-cycle-redelivery.json"
|
|
137
|
+
],
|
|
138
|
+
"claimedBy": [
|
|
139
|
+
{
|
|
140
|
+
"document": "references/webhook-events.md",
|
|
141
|
+
"phrase": "the retry runs the whole application again"
|
|
142
|
+
}
|
|
143
|
+
]
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"id": "committed-retry-sends-once",
|
|
147
|
+
"isolates": "outbox-consumer-key",
|
|
148
|
+
"fixtures": [
|
|
149
|
+
"invoice-paid-subscription-cycle.json"
|
|
150
|
+
],
|
|
151
|
+
"claimedBy": [
|
|
152
|
+
{
|
|
153
|
+
"document": "references/webhook-events.md",
|
|
154
|
+
"phrase": "A redelivered outbox row must send nothing twice"
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"id": "sequential-redelivery-grants-once-by-count-alone",
|
|
160
|
+
"isolates": null,
|
|
161
|
+
"fixtures": [
|
|
162
|
+
"invoice-paid-subscription-cycle.json",
|
|
163
|
+
"invoice-paid-subscription-cycle-redelivery.json"
|
|
164
|
+
],
|
|
165
|
+
"claimedBy": [
|
|
166
|
+
{
|
|
167
|
+
"document": "references/testing-and-local-dev.md",
|
|
168
|
+
"phrase": "two mechanisms cover each other"
|
|
169
|
+
}
|
|
170
|
+
]
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"id": "concurrent-entry-points-grant-once",
|
|
174
|
+
"isolates": "grant-key-atomic",
|
|
175
|
+
"fixtures": [
|
|
176
|
+
"invoice-paid-subscription-cycle.json"
|
|
177
|
+
],
|
|
178
|
+
"claimedBy": [
|
|
179
|
+
{
|
|
180
|
+
"document": "references/subscription-lifecycle.md",
|
|
181
|
+
"phrase": "both pass the read and both credit"
|
|
182
|
+
}
|
|
183
|
+
]
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"id": "serialization-conflict-does-not-lose-the-renewal",
|
|
187
|
+
"isolates": "tx-retry-bounded",
|
|
188
|
+
"fixtures": [
|
|
189
|
+
"invoice-paid-subscription-cycle.json"
|
|
190
|
+
],
|
|
191
|
+
"claimedBy": [
|
|
192
|
+
{
|
|
193
|
+
"document": "references/webhook-events.md",
|
|
194
|
+
"phrase": "a conflict may delay a grant, never lose it"
|
|
195
|
+
}
|
|
196
|
+
]
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"id": "exhausted-retries-answer-5xx-and-the-redelivery-lands",
|
|
200
|
+
"isolates": null,
|
|
201
|
+
"fixtures": [
|
|
202
|
+
"invoice-paid-subscription-cycle.json",
|
|
203
|
+
"invoice-paid-subscription-cycle-redelivery.json"
|
|
204
|
+
],
|
|
205
|
+
"claimedBy": [
|
|
206
|
+
{
|
|
207
|
+
"document": "references/webhook-events.md",
|
|
208
|
+
"phrase": "a swallowed conflict answered 200 is a renewal that silently never happened"
|
|
209
|
+
}
|
|
210
|
+
]
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"id": "reconciliation-does-not-regrant",
|
|
214
|
+
"isolates": "grant-marker",
|
|
215
|
+
"fixtures": [
|
|
216
|
+
"invoice-paid-subscription-cycle.json"
|
|
217
|
+
],
|
|
218
|
+
"claimedBy": [
|
|
219
|
+
{
|
|
220
|
+
"document": "references/webhook-events.md",
|
|
221
|
+
"phrase": "Guard the grant with a marker that survives a replay"
|
|
222
|
+
}
|
|
223
|
+
]
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"id": "out-of-order-pair-does-not-rewind-state",
|
|
227
|
+
"isolates": "ordering",
|
|
228
|
+
"fixtures": [
|
|
229
|
+
"invoice-paid-subscription-cycle.json",
|
|
230
|
+
"invoice-paid-subscription-cycle-next-period.json"
|
|
231
|
+
],
|
|
232
|
+
"claimedBy": [
|
|
233
|
+
{
|
|
234
|
+
"document": "references/webhook-events.md",
|
|
235
|
+
"phrase": "**Never derive state from arrival order.**"
|
|
236
|
+
}
|
|
237
|
+
]
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"id": "refund-total-is-cumulative",
|
|
241
|
+
"isolates": "cumulative-refund",
|
|
242
|
+
"fixtures": [
|
|
243
|
+
"charge-refunded-partial.json",
|
|
244
|
+
"charge-refunded-remainder.json"
|
|
245
|
+
],
|
|
246
|
+
"claimedBy": [
|
|
247
|
+
{
|
|
248
|
+
"document": "references/webhook-events.md",
|
|
249
|
+
"phrase": "`amount_refunded` is **cumulative**."
|
|
250
|
+
}
|
|
251
|
+
]
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
"id": "duplicate-refund-claws-back-once",
|
|
255
|
+
"isolates": null,
|
|
256
|
+
"fixtures": [
|
|
257
|
+
"charge-refunded-partial.json"
|
|
258
|
+
],
|
|
259
|
+
"claimedBy": [
|
|
260
|
+
{
|
|
261
|
+
"document": "references/testing-and-local-dev.md",
|
|
262
|
+
"phrase": "two mechanisms cover each other"
|
|
263
|
+
}
|
|
264
|
+
]
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
"id": "unpaid-session-grants-nothing",
|
|
268
|
+
"isolates": "async-gate",
|
|
269
|
+
"fixtures": [
|
|
270
|
+
"checkout-session-completed-async-unpaid.json",
|
|
271
|
+
"checkout-session-async-payment-failed.json"
|
|
272
|
+
],
|
|
273
|
+
"claimedBy": [
|
|
274
|
+
{
|
|
275
|
+
"document": "references/webhook-events.md",
|
|
276
|
+
"phrase": "grant belongs to `async_payment_succeeded`"
|
|
277
|
+
}
|
|
278
|
+
]
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
"id": "paid-session-grants-once",
|
|
282
|
+
"isolates": "grant-on-checkout",
|
|
283
|
+
"fixtures": [
|
|
284
|
+
"checkout-session-completed-paid.json"
|
|
285
|
+
],
|
|
286
|
+
"claimedBy": [
|
|
287
|
+
{
|
|
288
|
+
"document": "references/webhook-events.md",
|
|
289
|
+
"phrase": "Uniqueness key: the subscription id for subscriptions, the payment intent id"
|
|
290
|
+
}
|
|
291
|
+
]
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
"id": "conversion-id-survives-the-session",
|
|
295
|
+
"isolates": "conversion-id-from-metadata",
|
|
296
|
+
"fixtures": [
|
|
297
|
+
"invoice-paid-subscription-cycle.json"
|
|
298
|
+
],
|
|
299
|
+
"claimedBy": [
|
|
300
|
+
{
|
|
301
|
+
"document": "references/testing-and-local-dev.md",
|
|
302
|
+
"phrase": "the id the browser will reuse"
|
|
303
|
+
}
|
|
304
|
+
]
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
"id": "retention-offer-is-consumed-once",
|
|
308
|
+
"isolates": "retention-eligibility",
|
|
309
|
+
"fixtures": [
|
|
310
|
+
"customer-discount-created-retention.json",
|
|
311
|
+
"customer-subscription-updated-discount-consumed.json"
|
|
312
|
+
],
|
|
313
|
+
"claimedBy": [
|
|
314
|
+
{
|
|
315
|
+
"document": "references/cancellation-and-retention.md",
|
|
316
|
+
"phrase": "**The ledger is the source of truth, Stripe is the second opinion.**"
|
|
317
|
+
}
|
|
318
|
+
]
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
"id": "scheduled-cancellation-survives-billing-mode",
|
|
322
|
+
"isolates": "cancellation-timestamp",
|
|
323
|
+
"fixtures": [
|
|
324
|
+
"customer-subscription-updated-cancel-flexible.json",
|
|
325
|
+
"customer-subscription-updated-cancel-classic.json"
|
|
326
|
+
],
|
|
327
|
+
"claimedBy": [
|
|
328
|
+
{
|
|
329
|
+
"document": "references/cancellation-and-retention.md",
|
|
330
|
+
"phrase": "Store the timestamp, not the boolean."
|
|
331
|
+
}
|
|
332
|
+
]
|
|
333
|
+
}
|
|
334
|
+
]
|
|
200
335
|
}
|