@agentlensai/server 0.10.0 → 0.11.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.
Files changed (185) hide show
  1. package/dist/cloud/auth/api-key-middleware.d.ts +66 -0
  2. package/dist/cloud/auth/api-key-middleware.d.ts.map +1 -0
  3. package/dist/cloud/auth/api-key-middleware.js +147 -0
  4. package/dist/cloud/auth/api-key-middleware.js.map +1 -0
  5. package/dist/cloud/auth/api-keys.d.ts +90 -0
  6. package/dist/cloud/auth/api-keys.d.ts.map +1 -0
  7. package/dist/cloud/auth/api-keys.js +162 -0
  8. package/dist/cloud/auth/api-keys.js.map +1 -0
  9. package/dist/cloud/auth/audit-log.d.ts +66 -0
  10. package/dist/cloud/auth/audit-log.d.ts.map +1 -0
  11. package/dist/cloud/auth/audit-log.js +92 -0
  12. package/dist/cloud/auth/audit-log.js.map +1 -0
  13. package/dist/cloud/auth/auth-service.d.ts +77 -0
  14. package/dist/cloud/auth/auth-service.d.ts.map +1 -0
  15. package/dist/cloud/auth/auth-service.js +229 -0
  16. package/dist/cloud/auth/auth-service.js.map +1 -0
  17. package/dist/cloud/auth/brute-force.d.ts +36 -0
  18. package/dist/cloud/auth/brute-force.d.ts.map +1 -0
  19. package/dist/cloud/auth/brute-force.js +67 -0
  20. package/dist/cloud/auth/brute-force.js.map +1 -0
  21. package/dist/cloud/auth/index.d.ts +11 -0
  22. package/dist/cloud/auth/index.d.ts.map +1 -0
  23. package/dist/cloud/auth/index.js +11 -0
  24. package/dist/cloud/auth/index.js.map +1 -0
  25. package/dist/cloud/auth/jwt.d.ts +34 -0
  26. package/dist/cloud/auth/jwt.d.ts.map +1 -0
  27. package/dist/cloud/auth/jwt.js +68 -0
  28. package/dist/cloud/auth/jwt.js.map +1 -0
  29. package/dist/cloud/auth/oauth.d.ts +37 -0
  30. package/dist/cloud/auth/oauth.d.ts.map +1 -0
  31. package/dist/cloud/auth/oauth.js +120 -0
  32. package/dist/cloud/auth/oauth.js.map +1 -0
  33. package/dist/cloud/auth/passwords.d.ts +25 -0
  34. package/dist/cloud/auth/passwords.d.ts.map +1 -0
  35. package/dist/cloud/auth/passwords.js +50 -0
  36. package/dist/cloud/auth/passwords.js.map +1 -0
  37. package/dist/cloud/auth/rbac.d.ts +51 -0
  38. package/dist/cloud/auth/rbac.d.ts.map +1 -0
  39. package/dist/cloud/auth/rbac.js +89 -0
  40. package/dist/cloud/auth/rbac.js.map +1 -0
  41. package/dist/cloud/auth/tokens.d.ts +18 -0
  42. package/dist/cloud/auth/tokens.d.ts.map +1 -0
  43. package/dist/cloud/auth/tokens.js +29 -0
  44. package/dist/cloud/auth/tokens.js.map +1 -0
  45. package/dist/cloud/billing/billing-service.d.ts +44 -0
  46. package/dist/cloud/billing/billing-service.d.ts.map +1 -0
  47. package/dist/cloud/billing/billing-service.js +153 -0
  48. package/dist/cloud/billing/billing-service.js.map +1 -0
  49. package/dist/cloud/billing/index.d.ts +11 -0
  50. package/dist/cloud/billing/index.d.ts.map +1 -0
  51. package/dist/cloud/billing/index.js +11 -0
  52. package/dist/cloud/billing/index.js.map +1 -0
  53. package/dist/cloud/billing/invoice-service.d.ts +57 -0
  54. package/dist/cloud/billing/invoice-service.d.ts.map +1 -0
  55. package/dist/cloud/billing/invoice-service.js +123 -0
  56. package/dist/cloud/billing/invoice-service.js.map +1 -0
  57. package/dist/cloud/billing/plan-management.d.ts +46 -0
  58. package/dist/cloud/billing/plan-management.d.ts.map +1 -0
  59. package/dist/cloud/billing/plan-management.js +157 -0
  60. package/dist/cloud/billing/plan-management.js.map +1 -0
  61. package/dist/cloud/billing/quota-enforcement.d.ts +53 -0
  62. package/dist/cloud/billing/quota-enforcement.d.ts.map +1 -0
  63. package/dist/cloud/billing/quota-enforcement.js +143 -0
  64. package/dist/cloud/billing/quota-enforcement.js.map +1 -0
  65. package/dist/cloud/billing/stripe-client.d.ts +142 -0
  66. package/dist/cloud/billing/stripe-client.d.ts.map +1 -0
  67. package/dist/cloud/billing/stripe-client.js +169 -0
  68. package/dist/cloud/billing/stripe-client.js.map +1 -0
  69. package/dist/cloud/billing/trial-service.d.ts +47 -0
  70. package/dist/cloud/billing/trial-service.d.ts.map +1 -0
  71. package/dist/cloud/billing/trial-service.js +104 -0
  72. package/dist/cloud/billing/trial-service.js.map +1 -0
  73. package/dist/cloud/billing/usage-metering.d.ts +83 -0
  74. package/dist/cloud/billing/usage-metering.d.ts.map +1 -0
  75. package/dist/cloud/billing/usage-metering.js +174 -0
  76. package/dist/cloud/billing/usage-metering.js.map +1 -0
  77. package/dist/cloud/ingestion/backpressure.d.ts +107 -0
  78. package/dist/cloud/ingestion/backpressure.d.ts.map +1 -0
  79. package/dist/cloud/ingestion/backpressure.js +134 -0
  80. package/dist/cloud/ingestion/backpressure.js.map +1 -0
  81. package/dist/cloud/ingestion/batch-writer.d.ts +115 -0
  82. package/dist/cloud/ingestion/batch-writer.d.ts.map +1 -0
  83. package/dist/cloud/ingestion/batch-writer.js +319 -0
  84. package/dist/cloud/ingestion/batch-writer.js.map +1 -0
  85. package/dist/cloud/ingestion/dlq-manager.d.ts +116 -0
  86. package/dist/cloud/ingestion/dlq-manager.d.ts.map +1 -0
  87. package/dist/cloud/ingestion/dlq-manager.js +244 -0
  88. package/dist/cloud/ingestion/dlq-manager.js.map +1 -0
  89. package/dist/cloud/ingestion/event-queue.d.ts +105 -0
  90. package/dist/cloud/ingestion/event-queue.d.ts.map +1 -0
  91. package/dist/cloud/ingestion/event-queue.js +185 -0
  92. package/dist/cloud/ingestion/event-queue.js.map +1 -0
  93. package/dist/cloud/ingestion/gateway.d.ts +68 -0
  94. package/dist/cloud/ingestion/gateway.d.ts.map +1 -0
  95. package/dist/cloud/ingestion/gateway.js +198 -0
  96. package/dist/cloud/ingestion/gateway.js.map +1 -0
  97. package/dist/cloud/ingestion/index.d.ts +7 -0
  98. package/dist/cloud/ingestion/index.d.ts.map +1 -0
  99. package/dist/cloud/ingestion/index.js +7 -0
  100. package/dist/cloud/ingestion/index.js.map +1 -0
  101. package/dist/cloud/ingestion/rate-limiter.d.ts +73 -0
  102. package/dist/cloud/ingestion/rate-limiter.d.ts.map +1 -0
  103. package/dist/cloud/ingestion/rate-limiter.js +153 -0
  104. package/dist/cloud/ingestion/rate-limiter.js.map +1 -0
  105. package/dist/cloud/migrate.d.ts +45 -0
  106. package/dist/cloud/migrate.d.ts.map +1 -0
  107. package/dist/cloud/migrate.js +147 -0
  108. package/dist/cloud/migrate.js.map +1 -0
  109. package/dist/cloud/migration/export-import.d.ts +56 -0
  110. package/dist/cloud/migration/export-import.d.ts.map +1 -0
  111. package/dist/cloud/migration/export-import.js +289 -0
  112. package/dist/cloud/migration/export-import.js.map +1 -0
  113. package/dist/cloud/migration/index.d.ts +5 -0
  114. package/dist/cloud/migration/index.d.ts.map +1 -0
  115. package/dist/cloud/migration/index.js +5 -0
  116. package/dist/cloud/migration/index.js.map +1 -0
  117. package/dist/cloud/org-service.d.ts +68 -0
  118. package/dist/cloud/org-service.d.ts.map +1 -0
  119. package/dist/cloud/org-service.js +169 -0
  120. package/dist/cloud/org-service.js.map +1 -0
  121. package/dist/cloud/partition-maintenance.d.ts +29 -0
  122. package/dist/cloud/partition-maintenance.d.ts.map +1 -0
  123. package/dist/cloud/partition-maintenance.js +96 -0
  124. package/dist/cloud/partition-maintenance.js.map +1 -0
  125. package/dist/cloud/retention/index.d.ts +7 -0
  126. package/dist/cloud/retention/index.d.ts.map +1 -0
  127. package/dist/cloud/retention/index.js +7 -0
  128. package/dist/cloud/retention/index.js.map +1 -0
  129. package/dist/cloud/retention/partition-management.d.ts +61 -0
  130. package/dist/cloud/retention/partition-management.d.ts.map +1 -0
  131. package/dist/cloud/retention/partition-management.js +167 -0
  132. package/dist/cloud/retention/partition-management.js.map +1 -0
  133. package/dist/cloud/retention/retention-job.d.ts +70 -0
  134. package/dist/cloud/retention/retention-job.d.ts.map +1 -0
  135. package/dist/cloud/retention/retention-job.js +160 -0
  136. package/dist/cloud/retention/retention-job.js.map +1 -0
  137. package/dist/cloud/retention/retention-policy.d.ts +27 -0
  138. package/dist/cloud/retention/retention-policy.d.ts.map +1 -0
  139. package/dist/cloud/retention/retention-policy.js +36 -0
  140. package/dist/cloud/retention/retention-policy.js.map +1 -0
  141. package/dist/cloud/routes/api-key-routes.d.ts +38 -0
  142. package/dist/cloud/routes/api-key-routes.d.ts.map +1 -0
  143. package/dist/cloud/routes/api-key-routes.js +84 -0
  144. package/dist/cloud/routes/api-key-routes.js.map +1 -0
  145. package/dist/cloud/routes/audit-routes.d.ts +36 -0
  146. package/dist/cloud/routes/audit-routes.d.ts.map +1 -0
  147. package/dist/cloud/routes/audit-routes.js +47 -0
  148. package/dist/cloud/routes/audit-routes.js.map +1 -0
  149. package/dist/cloud/routes/billing-routes.d.ts +51 -0
  150. package/dist/cloud/routes/billing-routes.d.ts.map +1 -0
  151. package/dist/cloud/routes/billing-routes.js +114 -0
  152. package/dist/cloud/routes/billing-routes.js.map +1 -0
  153. package/dist/cloud/routes/onboarding-routes.d.ts +34 -0
  154. package/dist/cloud/routes/onboarding-routes.d.ts.map +1 -0
  155. package/dist/cloud/routes/onboarding-routes.js +58 -0
  156. package/dist/cloud/routes/onboarding-routes.js.map +1 -0
  157. package/dist/cloud/routes/org-routes.d.ts +80 -0
  158. package/dist/cloud/routes/org-routes.d.ts.map +1 -0
  159. package/dist/cloud/routes/org-routes.js +153 -0
  160. package/dist/cloud/routes/org-routes.js.map +1 -0
  161. package/dist/cloud/routes/usage-routes.d.ts +18 -0
  162. package/dist/cloud/routes/usage-routes.d.ts.map +1 -0
  163. package/dist/cloud/routes/usage-routes.js +66 -0
  164. package/dist/cloud/routes/usage-routes.js.map +1 -0
  165. package/dist/cloud/storage/adapter.d.ts +102 -0
  166. package/dist/cloud/storage/adapter.d.ts.map +1 -0
  167. package/dist/cloud/storage/adapter.js +21 -0
  168. package/dist/cloud/storage/adapter.js.map +1 -0
  169. package/dist/cloud/storage/index.d.ts +8 -0
  170. package/dist/cloud/storage/index.d.ts.map +1 -0
  171. package/dist/cloud/storage/index.js +7 -0
  172. package/dist/cloud/storage/index.js.map +1 -0
  173. package/dist/cloud/storage/postgres-adapter.d.ts +34 -0
  174. package/dist/cloud/storage/postgres-adapter.d.ts.map +1 -0
  175. package/dist/cloud/storage/postgres-adapter.js +544 -0
  176. package/dist/cloud/storage/postgres-adapter.js.map +1 -0
  177. package/dist/cloud/storage/sqlite-adapter.d.ts +29 -0
  178. package/dist/cloud/storage/sqlite-adapter.d.ts.map +1 -0
  179. package/dist/cloud/storage/sqlite-adapter.js +176 -0
  180. package/dist/cloud/storage/sqlite-adapter.js.map +1 -0
  181. package/dist/cloud/tenant-pool.d.ts +49 -0
  182. package/dist/cloud/tenant-pool.d.ts.map +1 -0
  183. package/dist/cloud/tenant-pool.js +61 -0
  184. package/dist/cloud/tenant-pool.js.map +1 -0
  185. package/package.json +1 -1
@@ -0,0 +1,120 @@
1
+ /**
2
+ * OAuth provider integration (Google + GitHub).
3
+ *
4
+ * This module handles:
5
+ * 1. Generating OAuth authorization URLs
6
+ * 2. Exchanging authorization codes for tokens
7
+ * 3. Fetching user profile from OAuth providers
8
+ * 4. Creating/linking user records on first login
9
+ * 5. Issuing JWT session cookies
10
+ */
11
+ // ═══════════════════════════════════════════
12
+ // Google OAuth
13
+ // ═══════════════════════════════════════════
14
+ const GOOGLE_AUTH_URL = 'https://accounts.google.com/o/oauth2/v2/auth';
15
+ const GOOGLE_TOKEN_URL = 'https://oauth2.googleapis.com/token';
16
+ const GOOGLE_USERINFO_URL = 'https://www.googleapis.com/oauth2/v2/userinfo';
17
+ export function getGoogleAuthUrl(config, state) {
18
+ const params = new URLSearchParams({
19
+ client_id: config.clientId,
20
+ redirect_uri: config.redirectUri,
21
+ response_type: 'code',
22
+ scope: 'openid email profile',
23
+ state,
24
+ access_type: 'offline',
25
+ });
26
+ return `${GOOGLE_AUTH_URL}?${params}`;
27
+ }
28
+ export async function exchangeGoogleCode(config, code) {
29
+ const resp = await fetch(GOOGLE_TOKEN_URL, {
30
+ method: 'POST',
31
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
32
+ body: new URLSearchParams({
33
+ client_id: config.clientId,
34
+ client_secret: config.clientSecret,
35
+ redirect_uri: config.redirectUri,
36
+ code,
37
+ grant_type: 'authorization_code',
38
+ }),
39
+ });
40
+ if (!resp.ok)
41
+ throw new Error(`Google token exchange failed: ${resp.status}`);
42
+ const data = await resp.json();
43
+ return { accessToken: data.access_token };
44
+ }
45
+ export async function getGoogleProfile(accessToken) {
46
+ const resp = await fetch(GOOGLE_USERINFO_URL, {
47
+ headers: { Authorization: `Bearer ${accessToken}` },
48
+ });
49
+ if (!resp.ok)
50
+ throw new Error(`Google profile fetch failed: ${resp.status}`);
51
+ const data = await resp.json();
52
+ return {
53
+ provider: 'google',
54
+ providerId: data.id,
55
+ email: data.email,
56
+ name: data.name ?? null,
57
+ avatarUrl: data.picture ?? null,
58
+ };
59
+ }
60
+ // ═══════════════════════════════════════════
61
+ // GitHub OAuth
62
+ // ═══════════════════════════════════════════
63
+ const GITHUB_AUTH_URL = 'https://github.com/login/oauth/authorize';
64
+ const GITHUB_TOKEN_URL = 'https://github.com/login/oauth/access_token';
65
+ const GITHUB_USER_URL = 'https://api.github.com/user';
66
+ const GITHUB_EMAILS_URL = 'https://api.github.com/user/emails';
67
+ export function getGithubAuthUrl(config, state) {
68
+ const params = new URLSearchParams({
69
+ client_id: config.clientId,
70
+ redirect_uri: config.redirectUri,
71
+ scope: 'user:email',
72
+ state,
73
+ });
74
+ return `${GITHUB_AUTH_URL}?${params}`;
75
+ }
76
+ export async function exchangeGithubCode(config, code) {
77
+ const resp = await fetch(GITHUB_TOKEN_URL, {
78
+ method: 'POST',
79
+ headers: {
80
+ 'Content-Type': 'application/json',
81
+ Accept: 'application/json',
82
+ },
83
+ body: JSON.stringify({
84
+ client_id: config.clientId,
85
+ client_secret: config.clientSecret,
86
+ code,
87
+ }),
88
+ });
89
+ if (!resp.ok)
90
+ throw new Error(`GitHub token exchange failed: ${resp.status}`);
91
+ const data = await resp.json();
92
+ if (data.error)
93
+ throw new Error(`GitHub OAuth error: ${data.error_description || data.error}`);
94
+ return { accessToken: data.access_token };
95
+ }
96
+ export async function getGithubProfile(accessToken) {
97
+ const [userResp, emailsResp] = await Promise.all([
98
+ fetch(GITHUB_USER_URL, { headers: { Authorization: `Bearer ${accessToken}`, Accept: 'application/json' } }),
99
+ fetch(GITHUB_EMAILS_URL, { headers: { Authorization: `Bearer ${accessToken}`, Accept: 'application/json' } }),
100
+ ]);
101
+ if (!userResp.ok)
102
+ throw new Error(`GitHub user fetch failed: ${userResp.status}`);
103
+ const user = await userResp.json();
104
+ let email = user.email;
105
+ if (!email && emailsResp.ok) {
106
+ const emails = await emailsResp.json();
107
+ const primary = emails.find((e) => e.primary && e.verified);
108
+ email = primary?.email ?? emails[0]?.email;
109
+ }
110
+ if (!email)
111
+ throw new Error('No email found from GitHub');
112
+ return {
113
+ provider: 'github',
114
+ providerId: String(user.id),
115
+ email,
116
+ name: user.name ?? user.login ?? null,
117
+ avatarUrl: user.avatar_url ?? null,
118
+ };
119
+ }
120
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../../src/cloud/auth/oauth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Password hashing and validation utilities.
3
+ * Uses Node.js built-in crypto (scrypt) — no external dependencies.
4
+ */
5
+ /**
6
+ * Hash a password using scrypt.
7
+ * Returns "salt:hash" in hex encoding.
8
+ */
9
+ export declare function hashPassword(password: string): Promise<string>;
10
+ /**
11
+ * Verify a password against a stored hash.
12
+ */
13
+ export declare function verifyPassword(password: string, storedHash: string): Promise<boolean>;
14
+ /**
15
+ * Password complexity requirements:
16
+ * - Min 8 characters
17
+ * - At least 1 uppercase letter
18
+ * - At least 1 lowercase letter
19
+ * - At least 1 digit
20
+ */
21
+ export declare function validatePasswordComplexity(password: string): {
22
+ valid: boolean;
23
+ errors: string[];
24
+ };
25
+ //# sourceMappingURL=passwords.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passwords.d.ts","sourceRoot":"","sources":["../../../src/cloud/auth/passwords.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH;;;GAGG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIpE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO3F;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAOjG"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Password hashing and validation utilities.
3
+ * Uses Node.js built-in crypto (scrypt) — no external dependencies.
4
+ */
5
+ import { scrypt, randomBytes, timingSafeEqual } from 'node:crypto';
6
+ import { promisify } from 'node:util';
7
+ const scryptAsync = promisify(scrypt);
8
+ const SALT_LENGTH = 32;
9
+ const KEY_LENGTH = 64;
10
+ /**
11
+ * Hash a password using scrypt.
12
+ * Returns "salt:hash" in hex encoding.
13
+ */
14
+ export async function hashPassword(password) {
15
+ const salt = randomBytes(SALT_LENGTH);
16
+ const derived = (await scryptAsync(password, salt, KEY_LENGTH));
17
+ return `${salt.toString('hex')}:${derived.toString('hex')}`;
18
+ }
19
+ /**
20
+ * Verify a password against a stored hash.
21
+ */
22
+ export async function verifyPassword(password, storedHash) {
23
+ const [saltHex, hashHex] = storedHash.split(':');
24
+ if (!saltHex || !hashHex)
25
+ return false;
26
+ const salt = Buffer.from(saltHex, 'hex');
27
+ const stored = Buffer.from(hashHex, 'hex');
28
+ const derived = (await scryptAsync(password, salt, KEY_LENGTH));
29
+ return timingSafeEqual(stored, derived);
30
+ }
31
+ /**
32
+ * Password complexity requirements:
33
+ * - Min 8 characters
34
+ * - At least 1 uppercase letter
35
+ * - At least 1 lowercase letter
36
+ * - At least 1 digit
37
+ */
38
+ export function validatePasswordComplexity(password) {
39
+ const errors = [];
40
+ if (password.length < 8)
41
+ errors.push('Password must be at least 8 characters');
42
+ if (!/[A-Z]/.test(password))
43
+ errors.push('Password must contain at least 1 uppercase letter');
44
+ if (!/[a-z]/.test(password))
45
+ errors.push('Password must contain at least 1 lowercase letter');
46
+ if (!/\d/.test(password))
47
+ errors.push('Password must contain at least 1 digit');
48
+ return { valid: errors.length === 0, errors };
49
+ }
50
+ //# sourceMappingURL=passwords.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passwords.js","sourceRoot":"","sources":["../../../src/cloud/auth/passwords.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AAEtC,MAAM,WAAW,GAAG,EAAE,CAAC;AACvB,MAAM,UAAU,GAAG,EAAE,CAAC;AAEtB;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,MAAM,IAAI,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,CAAC,MAAM,WAAW,CAAC,QAAQ,EAAE,IAAI,EAAE,UAAU,CAAC,CAAW,CAAC;IAC1E,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;AAC9D,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAgB,EAAE,UAAkB;IACvE,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjD,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IACvC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,CAAC,MAAM,WAAW,CAAC,QAAQ,EAAE,IAAI,EAAE,UAAU,CAAC,CAAW,CAAC;IAC1E,OAAO,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,0BAA0B,CAAC,QAAgB;IACzD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IAC/E,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;IAC9F,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;IAC9F,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IAChF,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;AAChD,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * RBAC Middleware (S-2.5)
3
+ *
4
+ * Role-based access control for dashboard API routes.
5
+ * Permission matrix:
6
+ * Owner = all actions
7
+ * Admin = all except billing, org deletion, ownership transfer
8
+ * Member = read dashboard, create sessions/benchmarks (no API keys, team mgmt, billing, settings)
9
+ * Viewer = read-only dashboard data
10
+ */
11
+ import type { AuditLogService } from './audit-log.js';
12
+ export type Role = 'owner' | 'admin' | 'member' | 'viewer';
13
+ export type ActionCategory = 'read' | 'write' | 'manage' | 'billing';
14
+ /**
15
+ * Permission matrix: which roles can perform which action categories.
16
+ */
17
+ export declare const PERMISSION_MATRIX: Record<ActionCategory, readonly Role[]>;
18
+ /**
19
+ * Map a route/action description to an action category.
20
+ * Used internally and exposed for testing.
21
+ */
22
+ export declare function categorizeAction(action: string): ActionCategory;
23
+ export interface RbacRequest {
24
+ orgId: string;
25
+ userId: string;
26
+ role: Role;
27
+ path?: string;
28
+ ip?: string;
29
+ }
30
+ export interface RbacResult {
31
+ allowed: boolean;
32
+ statusCode?: number;
33
+ error?: string;
34
+ }
35
+ /**
36
+ * Check if a role is allowed to perform an action category.
37
+ */
38
+ export declare function isRoleAllowed(role: Role, category: ActionCategory): boolean;
39
+ /**
40
+ * Create a requireRole middleware function.
41
+ *
42
+ * @param allowedRoles - Roles that are permitted for this route
43
+ * @param auditLog - Optional audit log service to log denials
44
+ * @returns Middleware-style check function
45
+ */
46
+ export declare function requireRole(allowedRoles: Role[], auditLog?: AuditLogService): (req: RbacRequest) => Promise<RbacResult>;
47
+ /**
48
+ * Convenience: create a requireRole check by action category.
49
+ */
50
+ export declare function requireActionCategory(category: ActionCategory, auditLog?: AuditLogService): (req: RbacRequest) => Promise<RbacResult>;
51
+ //# sourceMappingURL=rbac.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rbac.d.ts","sourceRoot":"","sources":["../../../src/cloud/auth/rbac.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtD,MAAM,MAAM,IAAI,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE3D,MAAM,MAAM,cAAc,GACtB,MAAM,GACN,OAAO,GACP,QAAQ,GACR,SAAS,CAAC;AAEd;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,cAAc,EAAE,SAAS,IAAI,EAAE,CAK5D,CAAC;AAEX;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAa/D;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAE3E;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,YAAY,EAAE,IAAI,EAAE,EACpB,QAAQ,CAAC,EAAE,eAAe,GACzB,CAAC,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CA+B3C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,cAAc,EACxB,QAAQ,CAAC,EAAE,eAAe,GACzB,CAAC,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAE3C"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * RBAC Middleware (S-2.5)
3
+ *
4
+ * Role-based access control for dashboard API routes.
5
+ * Permission matrix:
6
+ * Owner = all actions
7
+ * Admin = all except billing, org deletion, ownership transfer
8
+ * Member = read dashboard, create sessions/benchmarks (no API keys, team mgmt, billing, settings)
9
+ * Viewer = read-only dashboard data
10
+ */
11
+ /**
12
+ * Permission matrix: which roles can perform which action categories.
13
+ */
14
+ export const PERMISSION_MATRIX = {
15
+ read: ['owner', 'admin', 'member', 'viewer'],
16
+ write: ['owner', 'admin', 'member'],
17
+ manage: ['owner', 'admin'],
18
+ billing: ['owner'],
19
+ };
20
+ /**
21
+ * Map a route/action description to an action category.
22
+ * Used internally and exposed for testing.
23
+ */
24
+ export function categorizeAction(action) {
25
+ // Billing and destructive org ops
26
+ if (/billing|invoice|upgrade|downgrade|portal/.test(action))
27
+ return 'billing';
28
+ if (/org.*delete|delete.*org|org.*transfer|transfer.*ownership/.test(action))
29
+ return 'billing';
30
+ // Management actions
31
+ if (/api[_-]?key|member|invitation|invite|settings|audit|export|import|role/.test(action))
32
+ return 'manage';
33
+ // Write actions
34
+ if (/create|update|patch|post|put|configure/.test(action))
35
+ return 'write';
36
+ // Default: read
37
+ return 'read';
38
+ }
39
+ /**
40
+ * Check if a role is allowed to perform an action category.
41
+ */
42
+ export function isRoleAllowed(role, category) {
43
+ return PERMISSION_MATRIX[category].includes(role);
44
+ }
45
+ /**
46
+ * Create a requireRole middleware function.
47
+ *
48
+ * @param allowedRoles - Roles that are permitted for this route
49
+ * @param auditLog - Optional audit log service to log denials
50
+ * @returns Middleware-style check function
51
+ */
52
+ export function requireRole(allowedRoles, auditLog) {
53
+ return async (req) => {
54
+ if (allowedRoles.includes(req.role)) {
55
+ return { allowed: true };
56
+ }
57
+ // Log permission denied to audit log
58
+ if (auditLog) {
59
+ try {
60
+ await auditLog.write({
61
+ org_id: req.orgId,
62
+ actor_type: 'user',
63
+ actor_id: req.userId,
64
+ action: 'permission.denied',
65
+ resource_type: 'route',
66
+ resource_id: req.path ?? null,
67
+ details: { role: req.role, required_roles: allowedRoles },
68
+ ip_address: req.ip ?? null,
69
+ result: 'failure',
70
+ });
71
+ }
72
+ catch {
73
+ // Don't fail the request if audit logging fails
74
+ }
75
+ }
76
+ return {
77
+ allowed: false,
78
+ statusCode: 403,
79
+ error: 'Insufficient permissions',
80
+ };
81
+ };
82
+ }
83
+ /**
84
+ * Convenience: create a requireRole check by action category.
85
+ */
86
+ export function requireActionCategory(category, auditLog) {
87
+ return requireRole([...PERMISSION_MATRIX[category]], auditLog);
88
+ }
89
+ //# sourceMappingURL=rbac.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rbac.js","sourceRoot":"","sources":["../../../src/cloud/auth/rbac.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAYH;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA4C;IACxE,IAAI,EAAK,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC;IAC/C,KAAK,EAAI,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC;IACrC,MAAM,EAAG,CAAC,OAAO,EAAE,OAAO,CAAC;IAC3B,OAAO,EAAE,CAAC,OAAO,CAAC;CACV,CAAC;AAEX;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,kCAAkC;IAClC,IAAI,0CAA0C,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAC9E,IAAI,2DAA2D,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAE/F,qBAAqB;IACrB,IAAI,wEAAwE,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,QAAQ,CAAC;IAE3G,gBAAgB;IAChB,IAAI,wCAAwC,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,OAAO,CAAC;IAE1E,gBAAgB;IAChB,OAAO,MAAM,CAAC;AAChB,CAAC;AAgBD;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,IAAU,EAAE,QAAwB;IAChE,OAAQ,iBAAiB,CAAC,QAAQ,CAAuB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,YAAoB,EACpB,QAA0B;IAE1B,OAAO,KAAK,EAAE,GAAgB,EAAuB,EAAE;QACrD,IAAI,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAED,qCAAqC;QACrC,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC;gBACH,MAAM,QAAQ,CAAC,KAAK,CAAC;oBACnB,MAAM,EAAE,GAAG,CAAC,KAAK;oBACjB,UAAU,EAAE,MAAM;oBAClB,QAAQ,EAAE,GAAG,CAAC,MAAM;oBACpB,MAAM,EAAE,mBAAmB;oBAC3B,aAAa,EAAE,OAAO;oBACtB,WAAW,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI;oBAC7B,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE;oBACzD,UAAU,EAAE,GAAG,CAAC,EAAE,IAAI,IAAI;oBAC1B,MAAM,EAAE,SAAS;iBAClB,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,gDAAgD;YAClD,CAAC;QACH,CAAC;QAED,OAAO;YACL,OAAO,EAAE,KAAK;YACd,UAAU,EAAE,GAAG;YACf,KAAK,EAAE,0BAA0B;SAClC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAwB,EACxB,QAA0B;IAE1B,OAAO,WAAW,CAAC,CAAC,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;AACjE,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Token utilities for email verification and password reset.
3
+ * Uses crypto.randomBytes for secure token generation.
4
+ */
5
+ /**
6
+ * Generate a secure random token (URL-safe).
7
+ */
8
+ export declare function generateToken(bytes?: number): string;
9
+ /**
10
+ * Hash a token for storage (SHA-256).
11
+ * We store the hash, not the raw token — same pattern as API keys.
12
+ */
13
+ export declare function hashToken(token: string): string;
14
+ /**
15
+ * Verify a raw token against its stored hash.
16
+ */
17
+ export declare function verifyToken(token: string, storedHash: string): boolean;
18
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../../src/cloud/auth/tokens.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,SAAK,GAAG,MAAM,CAEhD;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAKtE"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Token utilities for email verification and password reset.
3
+ * Uses crypto.randomBytes for secure token generation.
4
+ */
5
+ import { randomBytes, createHash, timingSafeEqual } from 'node:crypto';
6
+ /**
7
+ * Generate a secure random token (URL-safe).
8
+ */
9
+ export function generateToken(bytes = 32) {
10
+ return randomBytes(bytes).toString('base64url');
11
+ }
12
+ /**
13
+ * Hash a token for storage (SHA-256).
14
+ * We store the hash, not the raw token — same pattern as API keys.
15
+ */
16
+ export function hashToken(token) {
17
+ return createHash('sha256').update(token).digest('hex');
18
+ }
19
+ /**
20
+ * Verify a raw token against its stored hash.
21
+ */
22
+ export function verifyToken(token, storedHash) {
23
+ const computed = Buffer.from(hashToken(token), 'hex');
24
+ const stored = Buffer.from(storedHash, 'hex');
25
+ if (computed.length !== stored.length)
26
+ return false;
27
+ return timingSafeEqual(computed, stored);
28
+ }
29
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../../src/cloud/auth/tokens.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEvE;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,KAAK,GAAG,EAAE;IACtC,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAClD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,UAAkB;IAC3D,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC9C,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACpD,OAAO,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Billing Service (S-6.1)
3
+ *
4
+ * Handles Stripe customer lifecycle, subscription management,
5
+ * and webhook processing.
6
+ */
7
+ import type { IStripeClient, TierName, StripeWebhookEvent } from './stripe-client.js';
8
+ import type { MigrationClient } from '../migrate.js';
9
+ export interface BillingServiceDeps {
10
+ stripe: IStripeClient;
11
+ db: MigrationClient;
12
+ }
13
+ export interface WebhookResult {
14
+ handled: boolean;
15
+ action?: string;
16
+ error?: string;
17
+ }
18
+ export declare class BillingService {
19
+ private deps;
20
+ constructor(deps: BillingServiceDeps);
21
+ /**
22
+ * Create a Stripe customer for an org (called on org creation).
23
+ * Stores stripe_customer_id on the orgs table.
24
+ */
25
+ createCustomerForOrg(orgId: string, email: string, name: string): Promise<string>;
26
+ /**
27
+ * Upgrade an org to a paid plan. Creates a Stripe subscription.
28
+ */
29
+ upgradePlan(orgId: string, newTier: TierName): Promise<void>;
30
+ /**
31
+ * Downgrade an org (cancels at period end, schedules free tier).
32
+ */
33
+ downgradePlan(orgId: string): Promise<void>;
34
+ /**
35
+ * Process a Stripe webhook event.
36
+ */
37
+ handleWebhook(event: StripeWebhookEvent): Promise<WebhookResult>;
38
+ private handleInvoicePaid;
39
+ private handlePaymentFailed;
40
+ private handleSubscriptionUpdated;
41
+ private handleSubscriptionDeleted;
42
+ private getOrg;
43
+ }
44
+ //# sourceMappingURL=billing-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing-service.d.ts","sourceRoot":"","sources":["../../../src/cloud/billing/billing-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAEtF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,aAAa,CAAC;IACtB,EAAE,EAAE,eAAe,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,cAAc;IACb,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,kBAAkB;IAE5C;;;OAGG;IACG,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAWvF;;OAEG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAmClE;;OAEG;IACG,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBjD;;OAEG;IACG,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC;YAqBxD,iBAAiB;YA2BjB,mBAAmB;YAqBnB,yBAAyB;YA6BzB,yBAAyB;YAuBzB,MAAM;CAcrB"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Billing Service (S-6.1)
3
+ *
4
+ * Handles Stripe customer lifecycle, subscription management,
5
+ * and webhook processing.
6
+ */
7
+ import { TIER_CONFIG } from './stripe-client.js';
8
+ export class BillingService {
9
+ deps;
10
+ constructor(deps) {
11
+ this.deps = deps;
12
+ }
13
+ /**
14
+ * Create a Stripe customer for an org (called on org creation).
15
+ * Stores stripe_customer_id on the orgs table.
16
+ */
17
+ async createCustomerForOrg(orgId, email, name) {
18
+ const customer = await this.deps.stripe.createCustomer(email, name, orgId);
19
+ await this.deps.db.query(`UPDATE orgs SET stripe_customer_id = $1 WHERE id = $2`, [customer.id, orgId]);
20
+ return customer.id;
21
+ }
22
+ /**
23
+ * Upgrade an org to a paid plan. Creates a Stripe subscription.
24
+ */
25
+ async upgradePlan(orgId, newTier) {
26
+ if (newTier === 'free') {
27
+ throw new Error('Cannot upgrade to free tier. Use downgradePlan instead.');
28
+ }
29
+ const tierConfig = TIER_CONFIG[newTier];
30
+ const org = await this.getOrg(orgId);
31
+ if (!org.stripe_customer_id) {
32
+ throw new Error('Org has no Stripe customer. Call createCustomerForOrg first.');
33
+ }
34
+ // Cancel existing subscription if any
35
+ if (org.stripe_subscription_id) {
36
+ await this.deps.stripe.cancelSubscription(org.stripe_subscription_id, false);
37
+ }
38
+ // Create new subscription
39
+ const items = [{ price: tierConfig.price_id }];
40
+ if (tierConfig.overage_price_id) {
41
+ items.push({ price: tierConfig.overage_price_id });
42
+ }
43
+ const subscription = await this.deps.stripe.createSubscription({
44
+ customer: org.stripe_customer_id,
45
+ items,
46
+ });
47
+ await this.deps.db.query(`UPDATE orgs SET plan = $1, stripe_subscription_id = $2, event_quota = $3, updated_at = now()
48
+ WHERE id = $4`, [newTier, subscription.id, tierConfig.event_quota, orgId]);
49
+ }
50
+ /**
51
+ * Downgrade an org (cancels at period end, schedules free tier).
52
+ */
53
+ async downgradePlan(orgId) {
54
+ const org = await this.getOrg(orgId);
55
+ if (org.stripe_subscription_id) {
56
+ await this.deps.stripe.cancelSubscription(org.stripe_subscription_id, true);
57
+ }
58
+ // Mark as pending downgrade — actual tier change happens via webhook
59
+ // when subscription period ends. For immediate effect in tests/mock:
60
+ await this.deps.db.query(`UPDATE orgs SET settings = jsonb_set(COALESCE(settings, '{}'), '{pending_downgrade}', '"free"'), updated_at = now()
61
+ WHERE id = $1`, [orgId]);
62
+ }
63
+ /**
64
+ * Process a Stripe webhook event.
65
+ */
66
+ async handleWebhook(event) {
67
+ try {
68
+ switch (event.type) {
69
+ case 'invoice.paid':
70
+ return await this.handleInvoicePaid(event);
71
+ case 'invoice.payment_failed':
72
+ return await this.handlePaymentFailed(event);
73
+ case 'customer.subscription.updated':
74
+ return await this.handleSubscriptionUpdated(event);
75
+ case 'customer.subscription.deleted':
76
+ return await this.handleSubscriptionDeleted(event);
77
+ default:
78
+ return { handled: false, action: 'ignored' };
79
+ }
80
+ }
81
+ catch (err) {
82
+ return { handled: false, error: String(err) };
83
+ }
84
+ }
85
+ // ── Webhook handlers ──
86
+ async handleInvoicePaid(event) {
87
+ const invoice = event.data.object;
88
+ const stripeInvoiceId = invoice.id;
89
+ const customerId = invoice.customer;
90
+ const amountPaid = invoice.amount_paid;
91
+ const periodStart = invoice.period_start;
92
+ const periodEnd = invoice.period_end;
93
+ // Find org by stripe_customer_id
94
+ const orgResult = await this.deps.db.query(`SELECT id FROM orgs WHERE stripe_customer_id = $1`, [customerId]);
95
+ const org = orgResult.rows[0];
96
+ if (!org)
97
+ return { handled: false, error: 'org_not_found' };
98
+ // Upsert invoice record
99
+ await this.deps.db.query(`INSERT INTO invoices (org_id, stripe_invoice_id, period_start, period_end, base_amount_cents, total_amount_cents, status)
100
+ VALUES ($1, $2, to_timestamp($3), to_timestamp($4), $5, $5, 'paid')
101
+ ON CONFLICT (stripe_invoice_id) DO UPDATE SET status = 'paid', total_amount_cents = $5`, [org.id, stripeInvoiceId, periodStart, periodEnd, amountPaid]);
102
+ return { handled: true, action: 'invoice_recorded' };
103
+ }
104
+ async handlePaymentFailed(event) {
105
+ const invoice = event.data.object;
106
+ const customerId = invoice.customer;
107
+ const orgResult = await this.deps.db.query(`SELECT id FROM orgs WHERE stripe_customer_id = $1`, [customerId]);
108
+ const org = orgResult.rows[0];
109
+ if (!org)
110
+ return { handled: false, error: 'org_not_found' };
111
+ // Mark org as past_due in settings
112
+ await this.deps.db.query(`UPDATE orgs SET settings = jsonb_set(COALESCE(settings, '{}'), '{payment_status}', '"past_due"')
113
+ WHERE id = $1`, [org.id]);
114
+ return { handled: true, action: 'payment_failed_recorded' };
115
+ }
116
+ async handleSubscriptionUpdated(event) {
117
+ const sub = event.data.object;
118
+ const customerId = sub.customer;
119
+ const subId = sub.id;
120
+ const cancelAtPeriodEnd = sub.cancel_at_period_end;
121
+ const orgResult = await this.deps.db.query(`SELECT id FROM orgs WHERE stripe_customer_id = $1`, [customerId]);
122
+ const org = orgResult.rows[0];
123
+ if (!org)
124
+ return { handled: false, error: 'org_not_found' };
125
+ await this.deps.db.query(`UPDATE orgs SET stripe_subscription_id = $1, updated_at = now() WHERE id = $2`, [subId, org.id]);
126
+ if (cancelAtPeriodEnd) {
127
+ await this.deps.db.query(`UPDATE orgs SET settings = jsonb_set(COALESCE(settings, '{}'), '{pending_downgrade}', '"free"')
128
+ WHERE id = $1`, [org.id]);
129
+ }
130
+ return { handled: true, action: 'subscription_updated' };
131
+ }
132
+ async handleSubscriptionDeleted(event) {
133
+ const sub = event.data.object;
134
+ const customerId = sub.customer;
135
+ const orgResult = await this.deps.db.query(`SELECT id FROM orgs WHERE stripe_customer_id = $1`, [customerId]);
136
+ const org = orgResult.rows[0];
137
+ if (!org)
138
+ return { handled: false, error: 'org_not_found' };
139
+ // Downgrade to free
140
+ await this.deps.db.query(`UPDATE orgs SET plan = 'free', stripe_subscription_id = NULL,
141
+ event_quota = $1, updated_at = now() WHERE id = $2`, [TIER_CONFIG.free.event_quota, org.id]);
142
+ return { handled: true, action: 'downgraded_to_free' };
143
+ }
144
+ // ── Helpers ──
145
+ async getOrg(orgId) {
146
+ const result = await this.deps.db.query(`SELECT id, plan, stripe_customer_id, stripe_subscription_id FROM orgs WHERE id = $1`, [orgId]);
147
+ const org = result.rows[0];
148
+ if (!org)
149
+ throw new Error(`Org ${orgId} not found`);
150
+ return org;
151
+ }
152
+ }
153
+ //# sourceMappingURL=billing-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing-service.js","sourceRoot":"","sources":["../../../src/cloud/billing/billing-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Billing Module Index (S-6.1 through S-6.6)
3
+ */
4
+ export { type IStripeClient, type StripeCustomer, type StripeSubscription, type StripeSubscriptionItem, type StripeInvoice, type StripeWebhookEvent, type CreateSubscriptionParams, type UsageRecordParams, type TierName, TIER_CONFIG, MockStripeClient, createStripeClient, } from './stripe-client.js';
5
+ export { BillingService, type BillingServiceDeps, type WebhookResult } from './billing-service.js';
6
+ export { UsageAccumulator, UsageQuery, reportOverageToStripe, type UsageMeteringDeps, type UsageSummary, type RedisUsageStore, } from './usage-metering.js';
7
+ export { QuotaEnforcer, type QuotaCheckResult, type QuotaEnforcerDeps, type OrgQuotaInfo, } from './quota-enforcement.js';
8
+ export { PlanManager, ANNUAL_PRICE_IDS, type PlanManagementDeps, type PlanChangeResult, } from './plan-management.js';
9
+ export { InvoiceService, ANNUAL_DISCOUNT, calculateAnnualPrice, type InvoiceServiceDeps, type InvoiceRecord, type InvoiceLineItem, } from './invoice-service.js';
10
+ export { TrialService, TRIAL_DURATION_DAYS, type TrialServiceDeps, type TrialStatus, } from './trial-service.js';
11
+ //# sourceMappingURL=index.d.ts.map