@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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/analysis/types.d.ts +2 -0
- package/dist/src/analysis/types.d.ts.map +1 -1
- package/dist/src/analysis/types.js +13 -1
- package/dist/src/analysis/types.js.map +1 -1
- package/dist/src/analytics/schema.d.ts +1 -1
- package/dist/src/analytics/schema.d.ts.map +1 -1
- package/dist/src/analytics/schema.js +68 -0
- package/dist/src/analytics/schema.js.map +1 -1
- package/dist/src/api/client.d.ts +25 -21
- package/dist/src/api/client.d.ts.map +1 -1
- package/dist/src/api/client.js +13 -8
- package/dist/src/api/client.js.map +1 -1
- package/dist/src/billing/BillingService.d.ts +139 -0
- package/dist/src/billing/BillingService.d.ts.map +1 -0
- package/dist/src/billing/BillingService.js +393 -0
- package/dist/src/billing/BillingService.js.map +1 -0
- package/dist/src/billing/GDPRComplianceService.d.ts +176 -0
- package/dist/src/billing/GDPRComplianceService.d.ts.map +1 -0
- package/dist/src/billing/GDPRComplianceService.js +361 -0
- package/dist/src/billing/GDPRComplianceService.js.map +1 -0
- package/dist/src/billing/StripeClient.d.ts +177 -0
- package/dist/src/billing/StripeClient.d.ts.map +1 -0
- package/dist/src/billing/StripeClient.js +462 -0
- package/dist/src/billing/StripeClient.js.map +1 -0
- package/dist/src/billing/StripeReconciliationJob.d.ts +95 -0
- package/dist/src/billing/StripeReconciliationJob.d.ts.map +1 -0
- package/dist/src/billing/StripeReconciliationJob.js +405 -0
- package/dist/src/billing/StripeReconciliationJob.js.map +1 -0
- package/dist/src/billing/StripeWebhookHandler.d.ts +92 -0
- package/dist/src/billing/StripeWebhookHandler.d.ts.map +1 -0
- package/dist/src/billing/StripeWebhookHandler.js +409 -0
- package/dist/src/billing/StripeWebhookHandler.js.map +1 -0
- package/dist/src/billing/index.d.ts +18 -0
- package/dist/src/billing/index.d.ts.map +1 -0
- package/dist/src/billing/index.js +19 -0
- package/dist/src/billing/index.js.map +1 -0
- package/dist/src/billing/types.d.ts +266 -0
- package/dist/src/billing/types.d.ts.map +1 -0
- package/dist/src/billing/types.js +23 -0
- package/dist/src/billing/types.js.map +1 -0
- package/dist/src/embeddings/hnsw-store.d.ts +568 -0
- package/dist/src/embeddings/hnsw-store.d.ts.map +1 -0
- package/dist/src/embeddings/hnsw-store.js +805 -0
- package/dist/src/embeddings/hnsw-store.js.map +1 -0
- package/dist/src/embeddings/index.d.ts +2 -0
- package/dist/src/embeddings/index.d.ts.map +1 -1
- package/dist/src/embeddings/index.js +2 -0
- package/dist/src/embeddings/index.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/learning/PatternStore.d.ts +457 -0
- package/dist/src/learning/PatternStore.d.ts.map +1 -0
- package/dist/src/learning/PatternStore.js +893 -0
- package/dist/src/learning/PatternStore.js.map +1 -0
- package/dist/src/learning/ReasoningBankIntegration.d.ts +403 -0
- package/dist/src/learning/ReasoningBankIntegration.d.ts.map +1 -0
- package/dist/src/learning/ReasoningBankIntegration.js +627 -0
- package/dist/src/learning/ReasoningBankIntegration.js.map +1 -0
- package/dist/src/learning/index.d.ts +15 -0
- package/dist/src/learning/index.d.ts.map +1 -0
- package/dist/src/learning/index.js +15 -0
- package/dist/src/learning/index.js.map +1 -0
- package/dist/src/routing/SONARouter.d.ts +154 -0
- package/dist/src/routing/SONARouter.d.ts.map +1 -0
- package/dist/src/routing/SONARouter.js +679 -0
- package/dist/src/routing/SONARouter.js.map +1 -0
- package/dist/src/routing/index.d.ts +9 -0
- package/dist/src/routing/index.d.ts.map +1 -0
- package/dist/src/routing/index.js +10 -0
- package/dist/src/routing/index.js.map +1 -0
- package/dist/src/routing/types.d.ts +331 -0
- package/dist/src/routing/types.d.ts.map +1 -0
- package/dist/src/routing/types.js +203 -0
- package/dist/src/routing/types.js.map +1 -0
- package/dist/src/scripts/__tests__/scan-imported-skills.test.js +5 -0
- package/dist/src/scripts/__tests__/scan-imported-skills.test.js.map +1 -1
- package/dist/src/security/SkillSandbox.d.ts +156 -0
- package/dist/src/security/SkillSandbox.d.ts.map +1 -0
- package/dist/src/security/SkillSandbox.js +303 -0
- package/dist/src/security/SkillSandbox.js.map +1 -0
- package/dist/src/security/index.d.ts +3 -1
- package/dist/src/security/index.d.ts.map +1 -1
- package/dist/src/security/index.js +5 -1
- package/dist/src/security/index.js.map +1 -1
- package/dist/src/security/rate-limiter/presets.d.ts +12 -0
- package/dist/src/security/rate-limiter/presets.d.ts.map +1 -1
- package/dist/src/security/rate-limiter/presets.js +12 -0
- package/dist/src/security/rate-limiter/presets.js.map +1 -1
- package/dist/src/security/sanitization.d.ts +85 -0
- package/dist/src/security/sanitization.d.ts.map +1 -1
- package/dist/src/security/sanitization.js +133 -0
- package/dist/src/security/sanitization.js.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.d.ts +22 -1
- package/dist/src/security/scanner/SecurityScanner.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.js +190 -35
- package/dist/src/security/scanner/SecurityScanner.js.map +1 -1
- package/dist/src/security/scanner/patterns.d.ts +13 -0
- package/dist/src/security/scanner/patterns.d.ts.map +1 -1
- package/dist/src/security/scanner/patterns.js +51 -0
- package/dist/src/security/scanner/patterns.js.map +1 -1
- package/dist/src/security/scanner/types.d.ts +13 -1
- package/dist/src/security/scanner/types.d.ts.map +1 -1
- package/dist/src/security/scanner/weights.d.ts.map +1 -1
- package/dist/src/security/scanner/weights.js +1 -0
- package/dist/src/security/scanner/weights.js.map +1 -1
- package/dist/src/session/SessionManager.d.ts +7 -0
- package/dist/src/session/SessionManager.d.ts.map +1 -1
- package/dist/src/session/SessionManager.js +117 -10
- package/dist/src/session/SessionManager.js.map +1 -1
- package/dist/src/sync/SyncEngine.d.ts.map +1 -1
- package/dist/src/sync/SyncEngine.js +9 -1
- package/dist/src/sync/SyncEngine.js.map +1 -1
- package/dist/src/testing/MultiLLMProvider.d.ts +374 -0
- package/dist/src/testing/MultiLLMProvider.d.ts.map +1 -0
- package/dist/src/testing/MultiLLMProvider.js +720 -0
- package/dist/src/testing/MultiLLMProvider.js.map +1 -0
- package/dist/src/testing/index.d.ts +8 -0
- package/dist/src/testing/index.d.ts.map +1 -0
- package/dist/src/testing/index.js +9 -0
- package/dist/src/testing/index.js.map +1 -0
- package/dist/tests/SecurityScanner.test.js +337 -1
- package/dist/tests/SecurityScanner.test.js.map +1 -1
- package/dist/tests/billing/BillingService.test.d.ts +7 -0
- package/dist/tests/billing/BillingService.test.d.ts.map +1 -0
- package/dist/tests/billing/BillingService.test.js +168 -0
- package/dist/tests/billing/BillingService.test.js.map +1 -0
- package/dist/tests/billing/GDPRCompliance.test.d.ts +7 -0
- package/dist/tests/billing/GDPRCompliance.test.d.ts.map +1 -0
- package/dist/tests/billing/GDPRCompliance.test.js +195 -0
- package/dist/tests/billing/GDPRCompliance.test.js.map +1 -0
- package/dist/tests/billing/StripeReconciliation.test.d.ts +7 -0
- package/dist/tests/billing/StripeReconciliation.test.d.ts.map +1 -0
- package/dist/tests/billing/StripeReconciliation.test.js +266 -0
- package/dist/tests/billing/StripeReconciliation.test.js.map +1 -0
- package/dist/tests/billing/stripe-validators.test.d.ts +7 -0
- package/dist/tests/billing/stripe-validators.test.d.ts.map +1 -0
- package/dist/tests/billing/stripe-validators.test.js +107 -0
- package/dist/tests/billing/stripe-validators.test.js.map +1 -0
- package/dist/tests/embeddings/hnsw-store.test.d.ts +7 -0
- package/dist/tests/embeddings/hnsw-store.test.d.ts.map +1 -0
- package/dist/tests/embeddings/hnsw-store.test.js +295 -0
- package/dist/tests/embeddings/hnsw-store.test.js.map +1 -0
- package/dist/tests/integration/neural/e2e-learning.test.d.ts +17 -0
- package/dist/tests/integration/neural/e2e-learning.test.d.ts.map +1 -0
- package/dist/tests/integration/neural/e2e-learning.test.js +238 -0
- package/dist/tests/integration/neural/e2e-learning.test.js.map +1 -0
- package/dist/tests/integration/neural/helpers.d.ts +132 -0
- package/dist/tests/integration/neural/helpers.d.ts.map +1 -0
- package/dist/tests/integration/neural/helpers.js +287 -0
- package/dist/tests/integration/neural/helpers.js.map +1 -0
- package/dist/tests/integration/neural/personalization.test.d.ts +21 -0
- package/dist/tests/integration/neural/personalization.test.d.ts.map +1 -0
- package/dist/tests/integration/neural/personalization.test.js +304 -0
- package/dist/tests/integration/neural/personalization.test.js.map +1 -0
- package/dist/tests/integration/neural/preference-learner.test.d.ts +23 -0
- package/dist/tests/integration/neural/preference-learner.test.d.ts.map +1 -0
- package/dist/tests/integration/neural/preference-learner.test.js +289 -0
- package/dist/tests/integration/neural/preference-learner.test.js.map +1 -0
- package/dist/tests/integration/neural/privacy.test.d.ts +19 -0
- package/dist/tests/integration/neural/privacy.test.d.ts.map +1 -0
- package/dist/tests/integration/neural/privacy.test.js +249 -0
- package/dist/tests/integration/neural/privacy.test.js.map +1 -0
- package/dist/tests/integration/neural/setup.d.ts +175 -0
- package/dist/tests/integration/neural/setup.d.ts.map +1 -0
- package/dist/tests/integration/neural/setup.js +487 -0
- package/dist/tests/integration/neural/setup.js.map +1 -0
- package/dist/tests/integration/neural/signal-collection.test.d.ts +21 -0
- package/dist/tests/integration/neural/signal-collection.test.d.ts.map +1 -0
- package/dist/tests/integration/neural/signal-collection.test.js +232 -0
- package/dist/tests/integration/neural/signal-collection.test.js.map +1 -0
- package/dist/tests/learning/PatternStore.test.d.ts +8 -0
- package/dist/tests/learning/PatternStore.test.d.ts.map +1 -0
- package/dist/tests/learning/PatternStore.test.js +589 -0
- package/dist/tests/learning/PatternStore.test.js.map +1 -0
- package/dist/tests/learning/ReasoningBankIntegration.test.d.ts +8 -0
- package/dist/tests/learning/ReasoningBankIntegration.test.d.ts.map +1 -0
- package/dist/tests/learning/ReasoningBankIntegration.test.js +269 -0
- package/dist/tests/learning/ReasoningBankIntegration.test.js.map +1 -0
- package/dist/tests/routing/SONARouter.test.d.ts +8 -0
- package/dist/tests/routing/SONARouter.test.d.ts.map +1 -0
- package/dist/tests/routing/SONARouter.test.js +400 -0
- package/dist/tests/routing/SONARouter.test.js.map +1 -0
- package/dist/tests/security/SkillSandbox.test.d.ts +8 -0
- package/dist/tests/security/SkillSandbox.test.d.ts.map +1 -0
- package/dist/tests/security/SkillSandbox.test.js +321 -0
- package/dist/tests/security/SkillSandbox.test.js.map +1 -0
- package/dist/tests/testing/MultiLLMProvider.test.d.ts +14 -0
- package/dist/tests/testing/MultiLLMProvider.test.d.ts.map +1 -0
- package/dist/tests/testing/MultiLLMProvider.test.js +438 -0
- package/dist/tests/testing/MultiLLMProvider.test.js.map +1 -0
- package/package.json +16 -3
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-1068: GDPR Compliance Service
|
|
3
|
+
*
|
|
4
|
+
* Provides data subject rights implementation for billing data:
|
|
5
|
+
* - Article 17: Right to Erasure (data deletion)
|
|
6
|
+
* - Article 20: Right to Data Portability (data export)
|
|
7
|
+
*
|
|
8
|
+
* All operations are logged for audit purposes.
|
|
9
|
+
*/
|
|
10
|
+
import { createLogger } from '../utils/logger.js';
|
|
11
|
+
const logger = createLogger('GDPRComplianceService');
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// GDPRComplianceService Class
|
|
14
|
+
// ============================================================================
|
|
15
|
+
/**
|
|
16
|
+
* GDPR Compliance Service for billing data
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const gdpr = new GDPRComplianceService({
|
|
21
|
+
* db,
|
|
22
|
+
* stripeClient,
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* // Export customer data (Article 20)
|
|
26
|
+
* const data = gdpr.exportCustomerData('customer_123');
|
|
27
|
+
*
|
|
28
|
+
* // Delete customer data (Article 17)
|
|
29
|
+
* const result = await gdpr.deleteCustomerData('customer_123');
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export class GDPRComplianceService {
|
|
33
|
+
db;
|
|
34
|
+
stripe;
|
|
35
|
+
constructor(config) {
|
|
36
|
+
this.db = config.db;
|
|
37
|
+
this.stripe = config.stripeClient;
|
|
38
|
+
logger.info('GDPR Compliance service initialized');
|
|
39
|
+
}
|
|
40
|
+
// ==========================================================================
|
|
41
|
+
// Data Export (Article 20: Right to Data Portability)
|
|
42
|
+
// ==========================================================================
|
|
43
|
+
/**
|
|
44
|
+
* Export all billing data for a customer
|
|
45
|
+
*
|
|
46
|
+
* Returns a structured JSON export of all data associated with the customer.
|
|
47
|
+
* This fulfills GDPR Article 20 requirements.
|
|
48
|
+
*
|
|
49
|
+
* @param customerId - The customer ID to export data for
|
|
50
|
+
* @returns Complete data export in JSON format
|
|
51
|
+
*/
|
|
52
|
+
exportCustomerData(customerId) {
|
|
53
|
+
logger.info('Starting customer data export', { customerId });
|
|
54
|
+
const subscriptions = this.exportSubscriptions(customerId);
|
|
55
|
+
const invoices = this.exportInvoices(customerId);
|
|
56
|
+
const licenseKeys = this.exportLicenseKeys(customerId);
|
|
57
|
+
const webhookEvents = this.exportWebhookEvents(customerId);
|
|
58
|
+
const exportData = {
|
|
59
|
+
metadata: {
|
|
60
|
+
exportedAt: new Date().toISOString(),
|
|
61
|
+
customerId,
|
|
62
|
+
format: 'json',
|
|
63
|
+
version: '1.0',
|
|
64
|
+
},
|
|
65
|
+
subscriptions,
|
|
66
|
+
invoices,
|
|
67
|
+
licenseKeys,
|
|
68
|
+
webhookEvents,
|
|
69
|
+
};
|
|
70
|
+
logger.info('Customer data export completed', {
|
|
71
|
+
customerId,
|
|
72
|
+
subscriptionCount: subscriptions.length,
|
|
73
|
+
invoiceCount: invoices.length,
|
|
74
|
+
licenseKeyCount: licenseKeys.length,
|
|
75
|
+
webhookEventCount: webhookEvents.length,
|
|
76
|
+
});
|
|
77
|
+
return exportData;
|
|
78
|
+
}
|
|
79
|
+
exportSubscriptions(customerId) {
|
|
80
|
+
const rows = this.db
|
|
81
|
+
.prepare(`SELECT
|
|
82
|
+
id,
|
|
83
|
+
stripe_subscription_id as stripeSubscriptionId,
|
|
84
|
+
tier,
|
|
85
|
+
status,
|
|
86
|
+
seat_count as seatCount,
|
|
87
|
+
current_period_start as currentPeriodStart,
|
|
88
|
+
current_period_end as currentPeriodEnd,
|
|
89
|
+
canceled_at as canceledAt,
|
|
90
|
+
created_at as createdAt,
|
|
91
|
+
updated_at as updatedAt
|
|
92
|
+
FROM user_subscriptions
|
|
93
|
+
WHERE customer_id = ?`)
|
|
94
|
+
.all(customerId);
|
|
95
|
+
return rows.map((row) => ({
|
|
96
|
+
...row,
|
|
97
|
+
seatCount: row.seatCount ?? 1,
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
exportInvoices(customerId) {
|
|
101
|
+
const rows = this.db
|
|
102
|
+
.prepare(`SELECT
|
|
103
|
+
id,
|
|
104
|
+
stripe_invoice_id as stripeInvoiceId,
|
|
105
|
+
amount_cents as amountCents,
|
|
106
|
+
currency,
|
|
107
|
+
status,
|
|
108
|
+
invoice_number as invoiceNumber,
|
|
109
|
+
paid_at as paidAt,
|
|
110
|
+
period_start as periodStart,
|
|
111
|
+
period_end as periodEnd,
|
|
112
|
+
created_at as createdAt
|
|
113
|
+
FROM invoices
|
|
114
|
+
WHERE customer_id = ?`)
|
|
115
|
+
.all(customerId);
|
|
116
|
+
return rows;
|
|
117
|
+
}
|
|
118
|
+
exportLicenseKeys(customerId) {
|
|
119
|
+
// Get subscription IDs for this customer
|
|
120
|
+
const subscriptionIds = this.db
|
|
121
|
+
.prepare(`SELECT id FROM user_subscriptions WHERE customer_id = ?`)
|
|
122
|
+
.all(customerId);
|
|
123
|
+
if (subscriptionIds.length === 0) {
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
const placeholders = subscriptionIds.map(() => '?').join(',');
|
|
127
|
+
const ids = subscriptionIds.map((s) => s.id);
|
|
128
|
+
const rows = this.db
|
|
129
|
+
.prepare(`SELECT
|
|
130
|
+
id,
|
|
131
|
+
key_expiry as keyExpiry,
|
|
132
|
+
is_active as isActive,
|
|
133
|
+
generated_at as generatedAt,
|
|
134
|
+
revoked_at as revokedAt,
|
|
135
|
+
revocation_reason as revocationReason
|
|
136
|
+
FROM license_keys
|
|
137
|
+
WHERE subscription_id IN (${placeholders})`)
|
|
138
|
+
.all(...ids);
|
|
139
|
+
return rows.map((row) => ({
|
|
140
|
+
id: row.id,
|
|
141
|
+
keyExpiry: row.keyExpiry,
|
|
142
|
+
isActive: row.isActive === 1,
|
|
143
|
+
generatedAt: row.generatedAt,
|
|
144
|
+
revokedAt: row.revokedAt,
|
|
145
|
+
revocationReason: row.revocationReason,
|
|
146
|
+
}));
|
|
147
|
+
}
|
|
148
|
+
exportWebhookEvents(customerId) {
|
|
149
|
+
// Get stripe customer ID for this customer
|
|
150
|
+
const customer = this.db
|
|
151
|
+
.prepare(`SELECT stripe_customer_id FROM user_subscriptions WHERE customer_id = ? LIMIT 1`)
|
|
152
|
+
.get(customerId);
|
|
153
|
+
if (!customer?.stripe_customer_id) {
|
|
154
|
+
return [];
|
|
155
|
+
}
|
|
156
|
+
// Find webhook events that contain this customer ID in the payload
|
|
157
|
+
const rows = this.db
|
|
158
|
+
.prepare(`SELECT
|
|
159
|
+
id,
|
|
160
|
+
stripe_event_id as stripeEventId,
|
|
161
|
+
event_type as eventType,
|
|
162
|
+
processed_at as processedAt,
|
|
163
|
+
success
|
|
164
|
+
FROM stripe_webhook_events
|
|
165
|
+
WHERE payload LIKE ?`)
|
|
166
|
+
.all(`%${customer.stripe_customer_id}%`);
|
|
167
|
+
return rows.map((row) => ({
|
|
168
|
+
id: row.id,
|
|
169
|
+
stripeEventId: row.stripeEventId,
|
|
170
|
+
eventType: row.eventType,
|
|
171
|
+
processedAt: row.processedAt,
|
|
172
|
+
success: row.success === 1,
|
|
173
|
+
}));
|
|
174
|
+
}
|
|
175
|
+
// ==========================================================================
|
|
176
|
+
// Data Deletion (Article 17: Right to Erasure)
|
|
177
|
+
// ==========================================================================
|
|
178
|
+
/**
|
|
179
|
+
* Delete all billing data for a customer
|
|
180
|
+
*
|
|
181
|
+
* Performs cascading deletion of:
|
|
182
|
+
* 1. License keys
|
|
183
|
+
* 2. Invoices
|
|
184
|
+
* 3. Webhook events (those containing customer data)
|
|
185
|
+
* 4. Subscriptions
|
|
186
|
+
* 5. Stripe customer (if stripeClient provided)
|
|
187
|
+
*
|
|
188
|
+
* This fulfills GDPR Article 17 requirements.
|
|
189
|
+
*
|
|
190
|
+
* @param customerId - The customer ID to delete data for
|
|
191
|
+
* @param options - Deletion options
|
|
192
|
+
* @returns Result of the deletion operation
|
|
193
|
+
*/
|
|
194
|
+
async deleteCustomerData(customerId, options) {
|
|
195
|
+
const dryRun = options?.dryRun ?? false;
|
|
196
|
+
const deleteFromStripe = options?.deleteFromStripe ?? true;
|
|
197
|
+
logger.info('Starting customer data deletion', { customerId, dryRun });
|
|
198
|
+
const errors = [];
|
|
199
|
+
const counts = {
|
|
200
|
+
subscriptions: 0,
|
|
201
|
+
invoices: 0,
|
|
202
|
+
licenseKeys: 0,
|
|
203
|
+
webhookEvents: 0,
|
|
204
|
+
};
|
|
205
|
+
// Get Stripe customer ID before deletion
|
|
206
|
+
const stripeCustomerRow = this.db
|
|
207
|
+
.prepare(`SELECT stripe_customer_id FROM user_subscriptions WHERE customer_id = ? LIMIT 1`)
|
|
208
|
+
.get(customerId);
|
|
209
|
+
const stripeCustomerId = stripeCustomerRow?.stripe_customer_id;
|
|
210
|
+
// Perform deletion in a transaction
|
|
211
|
+
if (!dryRun) {
|
|
212
|
+
this.db.exec('BEGIN TRANSACTION');
|
|
213
|
+
}
|
|
214
|
+
try {
|
|
215
|
+
// 1. Delete license keys (depends on subscriptions)
|
|
216
|
+
const subscriptionIds = this.db
|
|
217
|
+
.prepare(`SELECT id FROM user_subscriptions WHERE customer_id = ?`)
|
|
218
|
+
.all(customerId);
|
|
219
|
+
if (subscriptionIds.length > 0) {
|
|
220
|
+
const placeholders = subscriptionIds.map(() => '?').join(',');
|
|
221
|
+
const ids = subscriptionIds.map((s) => s.id);
|
|
222
|
+
if (dryRun) {
|
|
223
|
+
const count = this.db
|
|
224
|
+
.prepare(`SELECT COUNT(*) as count FROM license_keys WHERE subscription_id IN (${placeholders})`)
|
|
225
|
+
.get(...ids);
|
|
226
|
+
counts.licenseKeys = count.count;
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
const result = this.db
|
|
230
|
+
.prepare(`DELETE FROM license_keys WHERE subscription_id IN (${placeholders})`)
|
|
231
|
+
.run(...ids);
|
|
232
|
+
counts.licenseKeys = result.changes;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// 2. Delete invoices
|
|
236
|
+
if (dryRun) {
|
|
237
|
+
const count = this.db
|
|
238
|
+
.prepare(`SELECT COUNT(*) as count FROM invoices WHERE customer_id = ?`)
|
|
239
|
+
.get(customerId);
|
|
240
|
+
counts.invoices = count.count;
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
const result = this.db.prepare(`DELETE FROM invoices WHERE customer_id = ?`).run(customerId);
|
|
244
|
+
counts.invoices = result.changes;
|
|
245
|
+
}
|
|
246
|
+
// 3. Delete related webhook events (containing customer ID in payload)
|
|
247
|
+
if (stripeCustomerId) {
|
|
248
|
+
if (dryRun) {
|
|
249
|
+
const count = this.db
|
|
250
|
+
.prepare(`SELECT COUNT(*) as count FROM stripe_webhook_events WHERE payload LIKE ?`)
|
|
251
|
+
.get(`%${stripeCustomerId}%`);
|
|
252
|
+
counts.webhookEvents = count.count;
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
const result = this.db
|
|
256
|
+
.prepare(`DELETE FROM stripe_webhook_events WHERE payload LIKE ?`)
|
|
257
|
+
.run(`%${stripeCustomerId}%`);
|
|
258
|
+
counts.webhookEvents = result.changes;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
// 4. Delete subscriptions
|
|
262
|
+
if (dryRun) {
|
|
263
|
+
const count = this.db
|
|
264
|
+
.prepare(`SELECT COUNT(*) as count FROM user_subscriptions WHERE customer_id = ?`)
|
|
265
|
+
.get(customerId);
|
|
266
|
+
counts.subscriptions = count.count;
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
const result = this.db
|
|
270
|
+
.prepare(`DELETE FROM user_subscriptions WHERE customer_id = ?`)
|
|
271
|
+
.run(customerId);
|
|
272
|
+
counts.subscriptions = result.changes;
|
|
273
|
+
}
|
|
274
|
+
if (!dryRun) {
|
|
275
|
+
this.db.exec('COMMIT');
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
if (!dryRun) {
|
|
280
|
+
this.db.exec('ROLLBACK');
|
|
281
|
+
}
|
|
282
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
283
|
+
errors.push(`Database deletion failed: ${errorMsg}`);
|
|
284
|
+
logger.error('Customer data deletion failed', undefined, { customerId, error: errorMsg });
|
|
285
|
+
}
|
|
286
|
+
// 5. Delete from Stripe if requested
|
|
287
|
+
let stripeDeleted = false;
|
|
288
|
+
if (deleteFromStripe && stripeCustomerId && this.stripe && !dryRun) {
|
|
289
|
+
try {
|
|
290
|
+
const stripeInstance = this.stripe.getStripeInstance();
|
|
291
|
+
await stripeInstance.customers.del(stripeCustomerId);
|
|
292
|
+
stripeDeleted = true;
|
|
293
|
+
logger.info('Stripe customer deleted', { stripeCustomerId });
|
|
294
|
+
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
297
|
+
errors.push(`Stripe deletion failed: ${errorMsg}`);
|
|
298
|
+
logger.error('Stripe customer deletion failed', undefined, {
|
|
299
|
+
stripeCustomerId,
|
|
300
|
+
error: errorMsg,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const result = {
|
|
305
|
+
success: errors.length === 0,
|
|
306
|
+
customerId,
|
|
307
|
+
deletedAt: new Date().toISOString(),
|
|
308
|
+
counts,
|
|
309
|
+
stripeDeleted,
|
|
310
|
+
errors,
|
|
311
|
+
};
|
|
312
|
+
logger.info('Customer data deletion completed', {
|
|
313
|
+
customerId,
|
|
314
|
+
success: result.success,
|
|
315
|
+
counts,
|
|
316
|
+
dryRun,
|
|
317
|
+
});
|
|
318
|
+
return result;
|
|
319
|
+
}
|
|
320
|
+
// ==========================================================================
|
|
321
|
+
// Utility Methods
|
|
322
|
+
// ==========================================================================
|
|
323
|
+
/**
|
|
324
|
+
* Check if a customer has any billing data
|
|
325
|
+
*/
|
|
326
|
+
hasCustomerData(customerId) {
|
|
327
|
+
const subscription = this.db
|
|
328
|
+
.prepare(`SELECT id FROM user_subscriptions WHERE customer_id = ? LIMIT 1`)
|
|
329
|
+
.get(customerId);
|
|
330
|
+
return !!subscription;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Get a summary of customer data (for consent/overview purposes)
|
|
334
|
+
*/
|
|
335
|
+
getDataSummary(customerId) {
|
|
336
|
+
const subscription = this.db
|
|
337
|
+
.prepare(`SELECT id, stripe_customer_id FROM user_subscriptions WHERE customer_id = ? LIMIT 1`)
|
|
338
|
+
.get(customerId);
|
|
339
|
+
if (!subscription) {
|
|
340
|
+
return {
|
|
341
|
+
hasSubscription: false,
|
|
342
|
+
invoiceCount: 0,
|
|
343
|
+
licenseKeyCount: 0,
|
|
344
|
+
stripeCustomerId: null,
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
const invoiceCount = this.db
|
|
348
|
+
.prepare(`SELECT COUNT(*) as count FROM invoices WHERE customer_id = ?`)
|
|
349
|
+
.get(customerId);
|
|
350
|
+
const licenseKeyCount = this.db
|
|
351
|
+
.prepare(`SELECT COUNT(*) as count FROM license_keys WHERE subscription_id = ?`)
|
|
352
|
+
.get(subscription.id);
|
|
353
|
+
return {
|
|
354
|
+
hasSubscription: true,
|
|
355
|
+
invoiceCount: invoiceCount.count,
|
|
356
|
+
licenseKeyCount: licenseKeyCount.count,
|
|
357
|
+
stripeCustomerId: subscription.stripe_customer_id,
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
//# sourceMappingURL=GDPRComplianceService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GDPRComplianceService.js","sourceRoot":"","sources":["../../../src/billing/GDPRComplianceService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,177 @@
|
|
|
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 type { BillingPeriod, CreateCheckoutSessionRequest, CreateCheckoutSessionResponse, CreatePortalSessionRequest, CreatePortalSessionResponse, LicenseTier, StripeCheckoutSessionId, StripeCustomerId, StripePriceId, StripeSubscriptionId, SubscriptionStatus } from './types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Stripe client configuration
|
|
16
|
+
*/
|
|
17
|
+
export interface StripeClientConfig {
|
|
18
|
+
/**
|
|
19
|
+
* Stripe secret key (sk_test_xxx or sk_live_xxx)
|
|
20
|
+
*/
|
|
21
|
+
secretKey: string;
|
|
22
|
+
/**
|
|
23
|
+
* Stripe webhook signing secret (whsec_xxx)
|
|
24
|
+
*/
|
|
25
|
+
webhookSecret: string;
|
|
26
|
+
/**
|
|
27
|
+
* Price ID mappings for each tier
|
|
28
|
+
*/
|
|
29
|
+
prices: TierPriceConfigs;
|
|
30
|
+
/**
|
|
31
|
+
* Base URL for success/cancel redirects
|
|
32
|
+
*/
|
|
33
|
+
appUrl?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Price configurations for all tiers
|
|
37
|
+
*/
|
|
38
|
+
export interface TierPriceConfigs {
|
|
39
|
+
individual: {
|
|
40
|
+
monthly: StripePriceId;
|
|
41
|
+
annual: StripePriceId;
|
|
42
|
+
};
|
|
43
|
+
team: {
|
|
44
|
+
monthly: StripePriceId;
|
|
45
|
+
annual: StripePriceId;
|
|
46
|
+
};
|
|
47
|
+
enterprise: {
|
|
48
|
+
monthly: StripePriceId;
|
|
49
|
+
annual: StripePriceId;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Stripe API client wrapper
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const client = new StripeClient({
|
|
58
|
+
* secretKey: process.env.STRIPE_SECRET_KEY!,
|
|
59
|
+
* webhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,
|
|
60
|
+
* prices: {
|
|
61
|
+
* individual: { monthly: 'price_xxx', annual: 'price_yyy' },
|
|
62
|
+
* team: { monthly: 'price_xxx', annual: 'price_yyy' },
|
|
63
|
+
* enterprise: { monthly: 'price_xxx', annual: 'price_yyy' },
|
|
64
|
+
* },
|
|
65
|
+
* });
|
|
66
|
+
*
|
|
67
|
+
* const session = await client.createCheckoutSession({
|
|
68
|
+
* tier: 'team',
|
|
69
|
+
* billingPeriod: 'monthly',
|
|
70
|
+
* seatCount: 5,
|
|
71
|
+
* successUrl: 'https://app.example.com/success',
|
|
72
|
+
* cancelUrl: 'https://app.example.com/cancel',
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export declare class StripeClient {
|
|
77
|
+
private readonly stripe;
|
|
78
|
+
private readonly webhookSecret;
|
|
79
|
+
private readonly prices;
|
|
80
|
+
private readonly appUrl;
|
|
81
|
+
constructor(config: StripeClientConfig);
|
|
82
|
+
/**
|
|
83
|
+
* Create a new Stripe customer
|
|
84
|
+
*/
|
|
85
|
+
createCustomer(params: {
|
|
86
|
+
email: string;
|
|
87
|
+
name?: string;
|
|
88
|
+
metadata?: Record<string, string>;
|
|
89
|
+
}): Promise<StripeCustomerId>;
|
|
90
|
+
/**
|
|
91
|
+
* Get a Stripe customer by ID
|
|
92
|
+
*/
|
|
93
|
+
getCustomer(customerId: StripeCustomerId): Promise<Stripe.Customer | null>;
|
|
94
|
+
/**
|
|
95
|
+
* Update a Stripe customer
|
|
96
|
+
*/
|
|
97
|
+
updateCustomer(customerId: StripeCustomerId, params: {
|
|
98
|
+
email?: string;
|
|
99
|
+
name?: string;
|
|
100
|
+
metadata?: Record<string, string>;
|
|
101
|
+
}): Promise<Stripe.Customer>;
|
|
102
|
+
/**
|
|
103
|
+
* Create a Stripe Checkout session for subscription
|
|
104
|
+
*/
|
|
105
|
+
createCheckoutSession(request: CreateCheckoutSessionRequest): Promise<CreateCheckoutSessionResponse>;
|
|
106
|
+
/**
|
|
107
|
+
* Retrieve a checkout session
|
|
108
|
+
*/
|
|
109
|
+
getCheckoutSession(sessionId: StripeCheckoutSessionId): Promise<Stripe.Checkout.Session>;
|
|
110
|
+
/**
|
|
111
|
+
* Get a subscription by ID
|
|
112
|
+
*/
|
|
113
|
+
getSubscription(subscriptionId: StripeSubscriptionId): Promise<Stripe.Subscription | null>;
|
|
114
|
+
/**
|
|
115
|
+
* List subscriptions for a customer
|
|
116
|
+
*/
|
|
117
|
+
listSubscriptions(customerId: StripeCustomerId): Promise<Stripe.Subscription[]>;
|
|
118
|
+
/**
|
|
119
|
+
* Update a subscription (tier change or seat count)
|
|
120
|
+
*/
|
|
121
|
+
updateSubscription(subscriptionId: StripeSubscriptionId, params: {
|
|
122
|
+
tier?: LicenseTier;
|
|
123
|
+
billingPeriod?: BillingPeriod;
|
|
124
|
+
seatCount?: number;
|
|
125
|
+
prorate?: boolean;
|
|
126
|
+
}): Promise<Stripe.Subscription>;
|
|
127
|
+
/**
|
|
128
|
+
* Cancel a subscription
|
|
129
|
+
*/
|
|
130
|
+
cancelSubscription(subscriptionId: StripeSubscriptionId, options?: {
|
|
131
|
+
immediately?: boolean;
|
|
132
|
+
feedback?: string;
|
|
133
|
+
}): Promise<Stripe.Subscription>;
|
|
134
|
+
/**
|
|
135
|
+
* Reactivate a canceled subscription (before period end)
|
|
136
|
+
*/
|
|
137
|
+
reactivateSubscription(subscriptionId: StripeSubscriptionId): Promise<Stripe.Subscription>;
|
|
138
|
+
/**
|
|
139
|
+
* Create a Stripe Customer Portal session
|
|
140
|
+
*/
|
|
141
|
+
createPortalSession(request: CreatePortalSessionRequest): Promise<CreatePortalSessionResponse>;
|
|
142
|
+
/**
|
|
143
|
+
* List invoices for a customer
|
|
144
|
+
*/
|
|
145
|
+
listInvoices(customerId: StripeCustomerId, options?: {
|
|
146
|
+
limit?: number;
|
|
147
|
+
startingAfter?: string;
|
|
148
|
+
}): Promise<{
|
|
149
|
+
invoices: Stripe.Invoice[];
|
|
150
|
+
hasMore: boolean;
|
|
151
|
+
}>;
|
|
152
|
+
/**
|
|
153
|
+
* Get a specific invoice
|
|
154
|
+
*/
|
|
155
|
+
getInvoice(invoiceId: string): Promise<Stripe.Invoice | null>;
|
|
156
|
+
/**
|
|
157
|
+
* Get upcoming invoice (preview of next charge)
|
|
158
|
+
*/
|
|
159
|
+
getUpcomingInvoice(customerId: StripeCustomerId): Promise<Stripe.UpcomingInvoice | null>;
|
|
160
|
+
/**
|
|
161
|
+
* Verify and parse a webhook event
|
|
162
|
+
*/
|
|
163
|
+
verifyWebhookSignature(payload: string, signature: string): Stripe.Event;
|
|
164
|
+
/**
|
|
165
|
+
* Get the price ID for a tier and billing period
|
|
166
|
+
*/
|
|
167
|
+
getPriceId(tier: LicenseTier, billingPeriod: BillingPeriod): StripePriceId | null;
|
|
168
|
+
/**
|
|
169
|
+
* Map Stripe subscription status to our status
|
|
170
|
+
*/
|
|
171
|
+
static mapSubscriptionStatus(stripeStatus: Stripe.Subscription.Status): SubscriptionStatus;
|
|
172
|
+
/**
|
|
173
|
+
* Get the underlying Stripe instance (for advanced operations)
|
|
174
|
+
*/
|
|
175
|
+
getStripeInstance(): Stripe;
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=StripeClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StripeClient.d.ts","sourceRoot":"","sources":["../../../src/billing/StripeClient.ts"],"names":[],"mappings":"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"}
|