@skillsmith/core 2.1.1 → 2.1.2

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.
Files changed (194) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/src/analysis/types.d.ts +2 -0
  3. package/dist/src/analysis/types.d.ts.map +1 -1
  4. package/dist/src/analysis/types.js +13 -1
  5. package/dist/src/analysis/types.js.map +1 -1
  6. package/dist/src/analytics/schema.d.ts +1 -1
  7. package/dist/src/analytics/schema.d.ts.map +1 -1
  8. package/dist/src/analytics/schema.js +68 -0
  9. package/dist/src/analytics/schema.js.map +1 -1
  10. package/dist/src/api/client.d.ts +25 -21
  11. package/dist/src/api/client.d.ts.map +1 -1
  12. package/dist/src/api/client.js +13 -8
  13. package/dist/src/api/client.js.map +1 -1
  14. package/dist/src/billing/BillingService.d.ts +139 -0
  15. package/dist/src/billing/BillingService.d.ts.map +1 -0
  16. package/dist/src/billing/BillingService.js +393 -0
  17. package/dist/src/billing/BillingService.js.map +1 -0
  18. package/dist/src/billing/GDPRComplianceService.d.ts +176 -0
  19. package/dist/src/billing/GDPRComplianceService.d.ts.map +1 -0
  20. package/dist/src/billing/GDPRComplianceService.js +361 -0
  21. package/dist/src/billing/GDPRComplianceService.js.map +1 -0
  22. package/dist/src/billing/StripeClient.d.ts +177 -0
  23. package/dist/src/billing/StripeClient.d.ts.map +1 -0
  24. package/dist/src/billing/StripeClient.js +462 -0
  25. package/dist/src/billing/StripeClient.js.map +1 -0
  26. package/dist/src/billing/StripeReconciliationJob.d.ts +95 -0
  27. package/dist/src/billing/StripeReconciliationJob.d.ts.map +1 -0
  28. package/dist/src/billing/StripeReconciliationJob.js +405 -0
  29. package/dist/src/billing/StripeReconciliationJob.js.map +1 -0
  30. package/dist/src/billing/StripeWebhookHandler.d.ts +92 -0
  31. package/dist/src/billing/StripeWebhookHandler.d.ts.map +1 -0
  32. package/dist/src/billing/StripeWebhookHandler.js +409 -0
  33. package/dist/src/billing/StripeWebhookHandler.js.map +1 -0
  34. package/dist/src/billing/index.d.ts +18 -0
  35. package/dist/src/billing/index.d.ts.map +1 -0
  36. package/dist/src/billing/index.js +19 -0
  37. package/dist/src/billing/index.js.map +1 -0
  38. package/dist/src/billing/types.d.ts +266 -0
  39. package/dist/src/billing/types.d.ts.map +1 -0
  40. package/dist/src/billing/types.js +23 -0
  41. package/dist/src/billing/types.js.map +1 -0
  42. package/dist/src/embeddings/hnsw-store.d.ts +568 -0
  43. package/dist/src/embeddings/hnsw-store.d.ts.map +1 -0
  44. package/dist/src/embeddings/hnsw-store.js +805 -0
  45. package/dist/src/embeddings/hnsw-store.js.map +1 -0
  46. package/dist/src/embeddings/index.d.ts +2 -0
  47. package/dist/src/embeddings/index.d.ts.map +1 -1
  48. package/dist/src/embeddings/index.js +2 -0
  49. package/dist/src/embeddings/index.js.map +1 -1
  50. package/dist/src/index.d.ts +1 -0
  51. package/dist/src/index.d.ts.map +1 -1
  52. package/dist/src/index.js +2 -0
  53. package/dist/src/index.js.map +1 -1
  54. package/dist/src/learning/PatternStore.d.ts +457 -0
  55. package/dist/src/learning/PatternStore.d.ts.map +1 -0
  56. package/dist/src/learning/PatternStore.js +893 -0
  57. package/dist/src/learning/PatternStore.js.map +1 -0
  58. package/dist/src/learning/ReasoningBankIntegration.d.ts +403 -0
  59. package/dist/src/learning/ReasoningBankIntegration.d.ts.map +1 -0
  60. package/dist/src/learning/ReasoningBankIntegration.js +627 -0
  61. package/dist/src/learning/ReasoningBankIntegration.js.map +1 -0
  62. package/dist/src/learning/index.d.ts +15 -0
  63. package/dist/src/learning/index.d.ts.map +1 -0
  64. package/dist/src/learning/index.js +15 -0
  65. package/dist/src/learning/index.js.map +1 -0
  66. package/dist/src/routing/SONARouter.d.ts +154 -0
  67. package/dist/src/routing/SONARouter.d.ts.map +1 -0
  68. package/dist/src/routing/SONARouter.js +679 -0
  69. package/dist/src/routing/SONARouter.js.map +1 -0
  70. package/dist/src/routing/index.d.ts +9 -0
  71. package/dist/src/routing/index.d.ts.map +1 -0
  72. package/dist/src/routing/index.js +10 -0
  73. package/dist/src/routing/index.js.map +1 -0
  74. package/dist/src/routing/types.d.ts +331 -0
  75. package/dist/src/routing/types.d.ts.map +1 -0
  76. package/dist/src/routing/types.js +203 -0
  77. package/dist/src/routing/types.js.map +1 -0
  78. package/dist/src/scripts/__tests__/scan-imported-skills.test.js +5 -0
  79. package/dist/src/scripts/__tests__/scan-imported-skills.test.js.map +1 -1
  80. package/dist/src/security/SkillSandbox.d.ts +156 -0
  81. package/dist/src/security/SkillSandbox.d.ts.map +1 -0
  82. package/dist/src/security/SkillSandbox.js +303 -0
  83. package/dist/src/security/SkillSandbox.js.map +1 -0
  84. package/dist/src/security/index.d.ts +3 -1
  85. package/dist/src/security/index.d.ts.map +1 -1
  86. package/dist/src/security/index.js +5 -1
  87. package/dist/src/security/index.js.map +1 -1
  88. package/dist/src/security/rate-limiter/presets.d.ts +12 -0
  89. package/dist/src/security/rate-limiter/presets.d.ts.map +1 -1
  90. package/dist/src/security/rate-limiter/presets.js +12 -0
  91. package/dist/src/security/rate-limiter/presets.js.map +1 -1
  92. package/dist/src/security/sanitization.d.ts +85 -0
  93. package/dist/src/security/sanitization.d.ts.map +1 -1
  94. package/dist/src/security/sanitization.js +133 -0
  95. package/dist/src/security/sanitization.js.map +1 -1
  96. package/dist/src/security/scanner/SecurityScanner.d.ts +22 -1
  97. package/dist/src/security/scanner/SecurityScanner.d.ts.map +1 -1
  98. package/dist/src/security/scanner/SecurityScanner.js +190 -35
  99. package/dist/src/security/scanner/SecurityScanner.js.map +1 -1
  100. package/dist/src/security/scanner/patterns.d.ts +13 -0
  101. package/dist/src/security/scanner/patterns.d.ts.map +1 -1
  102. package/dist/src/security/scanner/patterns.js +51 -0
  103. package/dist/src/security/scanner/patterns.js.map +1 -1
  104. package/dist/src/security/scanner/types.d.ts +13 -1
  105. package/dist/src/security/scanner/types.d.ts.map +1 -1
  106. package/dist/src/security/scanner/weights.d.ts.map +1 -1
  107. package/dist/src/security/scanner/weights.js +1 -0
  108. package/dist/src/security/scanner/weights.js.map +1 -1
  109. package/dist/src/session/SessionManager.d.ts +7 -0
  110. package/dist/src/session/SessionManager.d.ts.map +1 -1
  111. package/dist/src/session/SessionManager.js +117 -10
  112. package/dist/src/session/SessionManager.js.map +1 -1
  113. package/dist/src/sync/SyncEngine.d.ts.map +1 -1
  114. package/dist/src/sync/SyncEngine.js +9 -1
  115. package/dist/src/sync/SyncEngine.js.map +1 -1
  116. package/dist/src/testing/MultiLLMProvider.d.ts +374 -0
  117. package/dist/src/testing/MultiLLMProvider.d.ts.map +1 -0
  118. package/dist/src/testing/MultiLLMProvider.js +720 -0
  119. package/dist/src/testing/MultiLLMProvider.js.map +1 -0
  120. package/dist/src/testing/index.d.ts +8 -0
  121. package/dist/src/testing/index.d.ts.map +1 -0
  122. package/dist/src/testing/index.js +9 -0
  123. package/dist/src/testing/index.js.map +1 -0
  124. package/dist/tests/SecurityScanner.test.js +337 -1
  125. package/dist/tests/SecurityScanner.test.js.map +1 -1
  126. package/dist/tests/billing/BillingService.test.d.ts +7 -0
  127. package/dist/tests/billing/BillingService.test.d.ts.map +1 -0
  128. package/dist/tests/billing/BillingService.test.js +168 -0
  129. package/dist/tests/billing/BillingService.test.js.map +1 -0
  130. package/dist/tests/billing/GDPRCompliance.test.d.ts +7 -0
  131. package/dist/tests/billing/GDPRCompliance.test.d.ts.map +1 -0
  132. package/dist/tests/billing/GDPRCompliance.test.js +195 -0
  133. package/dist/tests/billing/GDPRCompliance.test.js.map +1 -0
  134. package/dist/tests/billing/StripeReconciliation.test.d.ts +7 -0
  135. package/dist/tests/billing/StripeReconciliation.test.d.ts.map +1 -0
  136. package/dist/tests/billing/StripeReconciliation.test.js +266 -0
  137. package/dist/tests/billing/StripeReconciliation.test.js.map +1 -0
  138. package/dist/tests/billing/stripe-validators.test.d.ts +7 -0
  139. package/dist/tests/billing/stripe-validators.test.d.ts.map +1 -0
  140. package/dist/tests/billing/stripe-validators.test.js +107 -0
  141. package/dist/tests/billing/stripe-validators.test.js.map +1 -0
  142. package/dist/tests/embeddings/hnsw-store.test.d.ts +7 -0
  143. package/dist/tests/embeddings/hnsw-store.test.d.ts.map +1 -0
  144. package/dist/tests/embeddings/hnsw-store.test.js +295 -0
  145. package/dist/tests/embeddings/hnsw-store.test.js.map +1 -0
  146. package/dist/tests/integration/neural/e2e-learning.test.d.ts +17 -0
  147. package/dist/tests/integration/neural/e2e-learning.test.d.ts.map +1 -0
  148. package/dist/tests/integration/neural/e2e-learning.test.js +238 -0
  149. package/dist/tests/integration/neural/e2e-learning.test.js.map +1 -0
  150. package/dist/tests/integration/neural/helpers.d.ts +132 -0
  151. package/dist/tests/integration/neural/helpers.d.ts.map +1 -0
  152. package/dist/tests/integration/neural/helpers.js +287 -0
  153. package/dist/tests/integration/neural/helpers.js.map +1 -0
  154. package/dist/tests/integration/neural/personalization.test.d.ts +21 -0
  155. package/dist/tests/integration/neural/personalization.test.d.ts.map +1 -0
  156. package/dist/tests/integration/neural/personalization.test.js +304 -0
  157. package/dist/tests/integration/neural/personalization.test.js.map +1 -0
  158. package/dist/tests/integration/neural/preference-learner.test.d.ts +23 -0
  159. package/dist/tests/integration/neural/preference-learner.test.d.ts.map +1 -0
  160. package/dist/tests/integration/neural/preference-learner.test.js +289 -0
  161. package/dist/tests/integration/neural/preference-learner.test.js.map +1 -0
  162. package/dist/tests/integration/neural/privacy.test.d.ts +19 -0
  163. package/dist/tests/integration/neural/privacy.test.d.ts.map +1 -0
  164. package/dist/tests/integration/neural/privacy.test.js +249 -0
  165. package/dist/tests/integration/neural/privacy.test.js.map +1 -0
  166. package/dist/tests/integration/neural/setup.d.ts +175 -0
  167. package/dist/tests/integration/neural/setup.d.ts.map +1 -0
  168. package/dist/tests/integration/neural/setup.js +487 -0
  169. package/dist/tests/integration/neural/setup.js.map +1 -0
  170. package/dist/tests/integration/neural/signal-collection.test.d.ts +21 -0
  171. package/dist/tests/integration/neural/signal-collection.test.d.ts.map +1 -0
  172. package/dist/tests/integration/neural/signal-collection.test.js +232 -0
  173. package/dist/tests/integration/neural/signal-collection.test.js.map +1 -0
  174. package/dist/tests/learning/PatternStore.test.d.ts +8 -0
  175. package/dist/tests/learning/PatternStore.test.d.ts.map +1 -0
  176. package/dist/tests/learning/PatternStore.test.js +589 -0
  177. package/dist/tests/learning/PatternStore.test.js.map +1 -0
  178. package/dist/tests/learning/ReasoningBankIntegration.test.d.ts +8 -0
  179. package/dist/tests/learning/ReasoningBankIntegration.test.d.ts.map +1 -0
  180. package/dist/tests/learning/ReasoningBankIntegration.test.js +269 -0
  181. package/dist/tests/learning/ReasoningBankIntegration.test.js.map +1 -0
  182. package/dist/tests/routing/SONARouter.test.d.ts +8 -0
  183. package/dist/tests/routing/SONARouter.test.d.ts.map +1 -0
  184. package/dist/tests/routing/SONARouter.test.js +400 -0
  185. package/dist/tests/routing/SONARouter.test.js.map +1 -0
  186. package/dist/tests/security/SkillSandbox.test.d.ts +8 -0
  187. package/dist/tests/security/SkillSandbox.test.d.ts.map +1 -0
  188. package/dist/tests/security/SkillSandbox.test.js +321 -0
  189. package/dist/tests/security/SkillSandbox.test.js.map +1 -0
  190. package/dist/tests/testing/MultiLLMProvider.test.d.ts +14 -0
  191. package/dist/tests/testing/MultiLLMProvider.test.d.ts.map +1 -0
  192. package/dist/tests/testing/MultiLLMProvider.test.js +438 -0
  193. package/dist/tests/testing/MultiLLMProvider.test.js.map +1 -0
  194. package/package.json +16 -3
@@ -0,0 +1,462 @@
1
+ /**
2
+ * SMI-1062: Stripe Client Wrapper
3
+ *
4
+ * Provides a type-safe wrapper around the Stripe SDK with:
5
+ * - Customer management
6
+ * - Subscription management
7
+ * - Checkout session creation
8
+ * - Customer portal sessions
9
+ * - Invoice retrieval
10
+ * - Webhook signature verification
11
+ */
12
+ import Stripe from 'stripe';
13
+ import { createLogger } from '../utils/logger.js';
14
+ import { BillingError } from './types.js';
15
+ const logger = createLogger('StripeClient');
16
+ // ============================================================================
17
+ // StripeClient Class
18
+ // ============================================================================
19
+ /**
20
+ * Stripe API client wrapper
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const client = new StripeClient({
25
+ * secretKey: process.env.STRIPE_SECRET_KEY!,
26
+ * webhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,
27
+ * prices: {
28
+ * individual: { monthly: 'price_xxx', annual: 'price_yyy' },
29
+ * team: { monthly: 'price_xxx', annual: 'price_yyy' },
30
+ * enterprise: { monthly: 'price_xxx', annual: 'price_yyy' },
31
+ * },
32
+ * });
33
+ *
34
+ * const session = await client.createCheckoutSession({
35
+ * tier: 'team',
36
+ * billingPeriod: 'monthly',
37
+ * seatCount: 5,
38
+ * successUrl: 'https://app.example.com/success',
39
+ * cancelUrl: 'https://app.example.com/cancel',
40
+ * });
41
+ * ```
42
+ */
43
+ export class StripeClient {
44
+ stripe;
45
+ webhookSecret;
46
+ prices;
47
+ appUrl;
48
+ constructor(config) {
49
+ this.stripe = new Stripe(config.secretKey, {
50
+ apiVersion: '2023-10-16',
51
+ typescript: true,
52
+ });
53
+ this.webhookSecret = config.webhookSecret;
54
+ this.prices = config.prices;
55
+ this.appUrl = config.appUrl ?? 'https://skillsmith.app';
56
+ logger.info('Stripe client initialized');
57
+ }
58
+ // ==========================================================================
59
+ // Customer Management
60
+ // ==========================================================================
61
+ /**
62
+ * Create a new Stripe customer
63
+ */
64
+ async createCustomer(params) {
65
+ try {
66
+ const customer = await this.stripe.customers.create({
67
+ email: params.email,
68
+ name: params.name,
69
+ metadata: {
70
+ ...params.metadata,
71
+ source: 'skillsmith',
72
+ },
73
+ });
74
+ logger.info('Customer created', { customerId: customer.id });
75
+ return customer.id;
76
+ }
77
+ catch (error) {
78
+ const errorMsg = error instanceof Error ? error.message : String(error);
79
+ logger.error('Failed to create customer', undefined, {
80
+ errorDetails: errorMsg,
81
+ email: params.email,
82
+ });
83
+ throw new BillingError('Failed to create customer', 'STRIPE_API_ERROR', {
84
+ originalError: errorMsg,
85
+ });
86
+ }
87
+ }
88
+ /**
89
+ * Get a Stripe customer by ID
90
+ */
91
+ async getCustomer(customerId) {
92
+ try {
93
+ const customer = await this.stripe.customers.retrieve(customerId);
94
+ if (customer.deleted) {
95
+ return null;
96
+ }
97
+ return customer;
98
+ }
99
+ catch (error) {
100
+ if (error instanceof Stripe.errors.StripeError && error.code === 'resource_missing') {
101
+ return null;
102
+ }
103
+ throw error;
104
+ }
105
+ }
106
+ /**
107
+ * Update a Stripe customer
108
+ */
109
+ async updateCustomer(customerId, params) {
110
+ return this.stripe.customers.update(customerId, params);
111
+ }
112
+ // ==========================================================================
113
+ // Checkout Session
114
+ // ==========================================================================
115
+ /**
116
+ * Create a Stripe Checkout session for subscription
117
+ */
118
+ async createCheckoutSession(request) {
119
+ const priceId = this.getPriceId(request.tier, request.billingPeriod);
120
+ if (!priceId) {
121
+ throw new BillingError(`No price configured for tier: ${request.tier}`, 'INVALID_TIER', {
122
+ tier: request.tier,
123
+ billingPeriod: request.billingPeriod,
124
+ });
125
+ }
126
+ const lineItems = [
127
+ {
128
+ price: priceId,
129
+ quantity: request.seatCount ?? 1,
130
+ },
131
+ ];
132
+ const sessionParams = {
133
+ mode: 'subscription',
134
+ line_items: lineItems,
135
+ success_url: request.successUrl,
136
+ cancel_url: request.cancelUrl,
137
+ metadata: {
138
+ tier: request.tier,
139
+ billingPeriod: request.billingPeriod,
140
+ seatCount: String(request.seatCount ?? 1),
141
+ ...request.metadata,
142
+ },
143
+ subscription_data: {
144
+ metadata: {
145
+ tier: request.tier,
146
+ seatCount: String(request.seatCount ?? 1),
147
+ },
148
+ },
149
+ };
150
+ // Attach to existing customer or create new
151
+ if (request.customerId) {
152
+ sessionParams.customer = request.customerId;
153
+ }
154
+ else if (request.email) {
155
+ sessionParams.customer_email = request.email;
156
+ }
157
+ // Allow seat quantity changes for team/enterprise
158
+ if (request.tier === 'team' || request.tier === 'enterprise') {
159
+ sessionParams.line_items[0].adjustable_quantity = {
160
+ enabled: true,
161
+ minimum: 1,
162
+ maximum: 1000,
163
+ };
164
+ }
165
+ try {
166
+ const session = await this.stripe.checkout.sessions.create(sessionParams);
167
+ logger.info('Checkout session created', {
168
+ sessionId: session.id,
169
+ tier: request.tier,
170
+ seatCount: request.seatCount,
171
+ });
172
+ return {
173
+ sessionId: session.id,
174
+ url: session.url,
175
+ };
176
+ }
177
+ catch (error) {
178
+ const errorMsg = error instanceof Error ? error.message : String(error);
179
+ logger.error('Failed to create checkout session', undefined, { errorDetails: errorMsg });
180
+ throw new BillingError('Failed to create checkout session', 'STRIPE_API_ERROR', {
181
+ originalError: errorMsg,
182
+ });
183
+ }
184
+ }
185
+ /**
186
+ * Retrieve a checkout session
187
+ */
188
+ async getCheckoutSession(sessionId) {
189
+ return this.stripe.checkout.sessions.retrieve(sessionId, {
190
+ expand: ['subscription', 'customer'],
191
+ });
192
+ }
193
+ // ==========================================================================
194
+ // Subscription Management
195
+ // ==========================================================================
196
+ /**
197
+ * Get a subscription by ID
198
+ */
199
+ async getSubscription(subscriptionId) {
200
+ try {
201
+ return await this.stripe.subscriptions.retrieve(subscriptionId);
202
+ }
203
+ catch (error) {
204
+ if (error instanceof Stripe.errors.StripeError && error.code === 'resource_missing') {
205
+ return null;
206
+ }
207
+ throw error;
208
+ }
209
+ }
210
+ /**
211
+ * List subscriptions for a customer
212
+ */
213
+ async listSubscriptions(customerId) {
214
+ const subscriptions = await this.stripe.subscriptions.list({
215
+ customer: customerId,
216
+ status: 'all',
217
+ expand: ['data.default_payment_method'],
218
+ });
219
+ return subscriptions.data;
220
+ }
221
+ /**
222
+ * Update a subscription (tier change or seat count)
223
+ */
224
+ async updateSubscription(subscriptionId, params) {
225
+ const subscription = await this.getSubscription(subscriptionId);
226
+ if (!subscription) {
227
+ throw new BillingError('Subscription not found', 'SUBSCRIPTION_NOT_FOUND');
228
+ }
229
+ const updateParams = {
230
+ proration_behavior: params.prorate !== false ? 'create_prorations' : 'none',
231
+ };
232
+ // Update price if tier or billing period changed
233
+ if (params.tier && params.billingPeriod) {
234
+ const newPriceId = this.getPriceId(params.tier, params.billingPeriod);
235
+ if (newPriceId) {
236
+ updateParams.items = [
237
+ {
238
+ id: subscription.items.data[0].id,
239
+ price: newPriceId,
240
+ quantity: params.seatCount ?? subscription.items.data[0].quantity,
241
+ },
242
+ ];
243
+ updateParams.metadata = {
244
+ ...subscription.metadata,
245
+ tier: params.tier,
246
+ seatCount: String(params.seatCount ?? subscription.items.data[0].quantity),
247
+ };
248
+ }
249
+ }
250
+ else if (params.seatCount !== undefined) {
251
+ // Just update seat count
252
+ updateParams.items = [
253
+ {
254
+ id: subscription.items.data[0].id,
255
+ quantity: params.seatCount,
256
+ },
257
+ ];
258
+ updateParams.metadata = {
259
+ ...subscription.metadata,
260
+ seatCount: String(params.seatCount),
261
+ };
262
+ }
263
+ try {
264
+ const updated = await this.stripe.subscriptions.update(subscriptionId, updateParams);
265
+ logger.info('Subscription updated', { subscriptionId, params });
266
+ return updated;
267
+ }
268
+ catch (error) {
269
+ const errorMsg = error instanceof Error ? error.message : String(error);
270
+ logger.error('Failed to update subscription', undefined, {
271
+ errorDetails: errorMsg,
272
+ subscriptionId,
273
+ });
274
+ throw new BillingError('Failed to update subscription', 'STRIPE_API_ERROR', {
275
+ originalError: errorMsg,
276
+ });
277
+ }
278
+ }
279
+ /**
280
+ * Cancel a subscription
281
+ */
282
+ async cancelSubscription(subscriptionId, options) {
283
+ try {
284
+ if (options?.immediately) {
285
+ return await this.stripe.subscriptions.cancel(subscriptionId, {
286
+ cancellation_details: {
287
+ comment: options.feedback,
288
+ },
289
+ });
290
+ }
291
+ else {
292
+ // Cancel at period end
293
+ return await this.stripe.subscriptions.update(subscriptionId, {
294
+ cancel_at_period_end: true,
295
+ cancellation_details: {
296
+ comment: options?.feedback,
297
+ },
298
+ });
299
+ }
300
+ }
301
+ catch (error) {
302
+ const errorMsg = error instanceof Error ? error.message : String(error);
303
+ logger.error('Failed to cancel subscription', undefined, {
304
+ errorDetails: errorMsg,
305
+ subscriptionId,
306
+ });
307
+ throw new BillingError('Failed to cancel subscription', 'STRIPE_API_ERROR', {
308
+ originalError: errorMsg,
309
+ });
310
+ }
311
+ }
312
+ /**
313
+ * Reactivate a canceled subscription (before period end)
314
+ */
315
+ async reactivateSubscription(subscriptionId) {
316
+ return this.stripe.subscriptions.update(subscriptionId, {
317
+ cancel_at_period_end: false,
318
+ });
319
+ }
320
+ // ==========================================================================
321
+ // Customer Portal
322
+ // ==========================================================================
323
+ /**
324
+ * Create a Stripe Customer Portal session
325
+ */
326
+ async createPortalSession(request) {
327
+ try {
328
+ // Need to get Stripe customer ID from our customer ID
329
+ // This assumes customerId is the Stripe customer ID
330
+ const session = await this.stripe.billingPortal.sessions.create({
331
+ customer: request.customerId,
332
+ return_url: request.returnUrl,
333
+ });
334
+ logger.info('Portal session created', { customerId: request.customerId });
335
+ return {
336
+ url: session.url,
337
+ };
338
+ }
339
+ catch (error) {
340
+ const errorMsg = error instanceof Error ? error.message : String(error);
341
+ logger.error('Failed to create portal session', undefined, {
342
+ errorDetails: errorMsg,
343
+ customerId: request.customerId,
344
+ });
345
+ throw new BillingError('Failed to create portal session', 'STRIPE_API_ERROR', {
346
+ originalError: errorMsg,
347
+ });
348
+ }
349
+ }
350
+ // ==========================================================================
351
+ // Invoice Management
352
+ // ==========================================================================
353
+ /**
354
+ * List invoices for a customer
355
+ */
356
+ async listInvoices(customerId, options) {
357
+ const invoices = await this.stripe.invoices.list({
358
+ customer: customerId,
359
+ limit: options?.limit ?? 10,
360
+ starting_after: options?.startingAfter,
361
+ });
362
+ return {
363
+ invoices: invoices.data,
364
+ hasMore: invoices.has_more,
365
+ };
366
+ }
367
+ /**
368
+ * Get a specific invoice
369
+ */
370
+ async getInvoice(invoiceId) {
371
+ try {
372
+ return await this.stripe.invoices.retrieve(invoiceId);
373
+ }
374
+ catch (error) {
375
+ if (error instanceof Stripe.errors.StripeError && error.code === 'resource_missing') {
376
+ return null;
377
+ }
378
+ throw error;
379
+ }
380
+ }
381
+ /**
382
+ * Get upcoming invoice (preview of next charge)
383
+ */
384
+ async getUpcomingInvoice(customerId) {
385
+ try {
386
+ return await this.stripe.invoices.retrieveUpcoming({
387
+ customer: customerId,
388
+ });
389
+ }
390
+ catch (error) {
391
+ if (error instanceof Stripe.errors.StripeError && error.code === 'invoice_upcoming_none') {
392
+ return null;
393
+ }
394
+ throw error;
395
+ }
396
+ }
397
+ // ==========================================================================
398
+ // Webhook Handling
399
+ // ==========================================================================
400
+ /**
401
+ * Verify and parse a webhook event
402
+ */
403
+ verifyWebhookSignature(payload, signature) {
404
+ try {
405
+ return this.stripe.webhooks.constructEvent(payload, signature, this.webhookSecret);
406
+ }
407
+ catch (error) {
408
+ logger.warn('Webhook signature verification failed', {
409
+ error: error instanceof Error ? error.message : String(error),
410
+ });
411
+ throw new BillingError('Invalid webhook signature', 'WEBHOOK_SIGNATURE_INVALID');
412
+ }
413
+ }
414
+ // ==========================================================================
415
+ // Helper Methods
416
+ // ==========================================================================
417
+ /**
418
+ * Get the price ID for a tier and billing period
419
+ */
420
+ getPriceId(tier, billingPeriod) {
421
+ if (tier === 'community') {
422
+ return null; // Community tier is free, no Stripe price
423
+ }
424
+ const tierPrices = this.prices[tier];
425
+ if (!tierPrices) {
426
+ return null;
427
+ }
428
+ return tierPrices[billingPeriod];
429
+ }
430
+ /**
431
+ * Map Stripe subscription status to our status
432
+ */
433
+ static mapSubscriptionStatus(stripeStatus) {
434
+ switch (stripeStatus) {
435
+ case 'active':
436
+ return 'active';
437
+ case 'past_due':
438
+ return 'past_due';
439
+ case 'canceled':
440
+ return 'canceled';
441
+ case 'trialing':
442
+ return 'trialing';
443
+ case 'paused':
444
+ return 'paused';
445
+ case 'incomplete':
446
+ return 'incomplete';
447
+ case 'incomplete_expired':
448
+ return 'incomplete_expired';
449
+ case 'unpaid':
450
+ return 'unpaid';
451
+ default:
452
+ return 'active';
453
+ }
454
+ }
455
+ /**
456
+ * Get the underlying Stripe instance (for advanced operations)
457
+ */
458
+ getStripeInstance() {
459
+ return this.stripe;
460
+ }
461
+ }
462
+ //# sourceMappingURL=StripeClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StripeClient.js","sourceRoot":"","sources":["../../../src/billing/StripeClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * SMI-1069: Stripe Reconciliation Job
3
+ *
4
+ * Periodically reconciles local subscription and invoice data with Stripe.
5
+ * Identifies and reports discrepancies to ensure data consistency.
6
+ *
7
+ * Features:
8
+ * - Subscription status sync
9
+ * - Invoice status verification
10
+ * - Missing data detection
11
+ * - Automatic correction (optional)
12
+ * - Detailed reporting
13
+ */
14
+ import type { Database as BetterSqliteDatabase } from 'better-sqlite3';
15
+ import type { StripeClient } from './StripeClient.js';
16
+ export interface StripeReconciliationJobConfig {
17
+ /**
18
+ * StripeClient for API calls
19
+ */
20
+ stripeClient: StripeClient;
21
+ /**
22
+ * Database connection
23
+ */
24
+ db: BetterSqliteDatabase;
25
+ /**
26
+ * Whether to automatically fix discrepancies
27
+ * @default false
28
+ */
29
+ autoFix?: boolean;
30
+ /**
31
+ * Maximum subscriptions to process per run
32
+ * @default 100
33
+ */
34
+ batchSize?: number;
35
+ }
36
+ export type DiscrepancyType = 'status_mismatch' | 'missing_local' | 'missing_stripe' | 'tier_mismatch' | 'seat_count_mismatch' | 'period_mismatch' | 'invoice_status_mismatch' | 'invoice_amount_mismatch';
37
+ export interface Discrepancy {
38
+ type: DiscrepancyType;
39
+ entityType: 'subscription' | 'invoice';
40
+ entityId: string;
41
+ stripeId: string;
42
+ localValue: string | number | null;
43
+ stripeValue: string | number | null;
44
+ description: string;
45
+ fixed: boolean;
46
+ }
47
+ export interface ReconciliationResult {
48
+ success: boolean;
49
+ startedAt: string;
50
+ completedAt: string;
51
+ durationMs: number;
52
+ stats: {
53
+ subscriptionsChecked: number;
54
+ invoicesChecked: number;
55
+ discrepanciesFound: number;
56
+ discrepanciesFixed: number;
57
+ };
58
+ discrepancies: Discrepancy[];
59
+ errors: string[];
60
+ }
61
+ /**
62
+ * Stripe Reconciliation Job
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * const job = new StripeReconciliationJob({
67
+ * stripeClient,
68
+ * db,
69
+ * autoFix: true,
70
+ * });
71
+ *
72
+ * // Run reconciliation
73
+ * const result = await job.run();
74
+ * console.log(`Found ${result.discrepancies.length} discrepancies`);
75
+ * ```
76
+ */
77
+ export declare class StripeReconciliationJob {
78
+ private readonly stripe;
79
+ private readonly db;
80
+ private readonly autoFix;
81
+ private readonly batchSize;
82
+ constructor(config: StripeReconciliationJobConfig);
83
+ /**
84
+ * Run the reconciliation job
85
+ */
86
+ run(): Promise<ReconciliationResult>;
87
+ private getLocalSubscriptions;
88
+ private reconcileSubscription;
89
+ private getLocalInvoices;
90
+ private reconcileInvoice;
91
+ private fixDiscrepancy;
92
+ private fixSubscriptionDiscrepancy;
93
+ private fixInvoiceDiscrepancy;
94
+ }
95
+ //# sourceMappingURL=StripeReconciliationJob.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StripeReconciliationJob.d.ts","sourceRoot":"","sources":["../../../src/billing/StripeReconciliationJob.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,QAAQ,IAAI,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAGtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AASrD,MAAM,WAAW,6BAA6B;IAC5C;;OAEG;IACH,YAAY,EAAE,YAAY,CAAA;IAE1B;;OAEG;IACH,EAAE,EAAE,oBAAoB,CAAA;IAExB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAMD,MAAM,MAAM,eAAe,GACvB,iBAAiB,GACjB,eAAe,GACf,gBAAgB,GAChB,eAAe,GACf,qBAAqB,GACrB,iBAAiB,GACjB,yBAAyB,GACzB,yBAAyB,CAAA;AAE7B,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,eAAe,CAAA;IACrB,UAAU,EAAE,cAAc,GAAG,SAAS,CAAA;IACtC,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAClC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IACnC,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE;QACL,oBAAoB,EAAE,MAAM,CAAA;QAC5B,eAAe,EAAE,MAAM,CAAA;QACvB,kBAAkB,EAAE,MAAM,CAAA;QAC1B,kBAAkB,EAAE,MAAM,CAAA;KAC3B,CAAA;IACD,aAAa,EAAE,WAAW,EAAE,CAAA;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB;AAMD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,uBAAuB;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAsB;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;gBAEtB,MAAM,EAAE,6BAA6B;IAgBjD;;OAEG;IACG,GAAG,IAAI,OAAO,CAAC,oBAAoB,CAAC;IAuF1C,OAAO,CAAC,qBAAqB;YAoBf,qBAAqB;IA0EnC,OAAO,CAAC,gBAAgB;YAgBV,gBAAgB;IAyD9B,OAAO,CAAC,cAAc;IAmBtB,OAAO,CAAC,0BAA0B;IA+ClC,OAAO,CAAC,qBAAqB;CA0B9B"}