@avi770/testteam 1.2.0 → 2.0.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 (300) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/README.md +53 -6
  3. package/agents/24-signup-onboarding-tester.ts +429 -0
  4. package/agents/25-crud-flow-tester.ts +302 -0
  5. package/agents/26-form-validator.ts +297 -0
  6. package/agents/27-search-filter-tester.ts +326 -0
  7. package/agents/28-navigation-routing-tester.ts +425 -0
  8. package/agents/29-responsive-interaction-tester.ts +350 -0
  9. package/agents/30-multi-user-scenario-tester.ts +319 -0
  10. package/agents/31-load-tester.ts +134 -0
  11. package/agents/32-memory-leak-detector.ts +194 -0
  12. package/agents/33-bundle-analyzer.ts +132 -0
  13. package/agents/34-xss-scanner.ts +191 -0
  14. package/agents/35-csrf-tester.ts +82 -0
  15. package/agents/36-auth-fuzzer.ts +194 -0
  16. package/agents/37-dependency-scanner.ts +176 -0
  17. package/agents/38-secrets-scanner.ts +137 -0
  18. package/agents/39-api-contract-tester.ts +199 -0
  19. package/agents/40-rate-limit-tester.ts +94 -0
  20. package/agents/41-api-pagination-tester.ts +97 -0
  21. package/agents/42-graphql-tester.ts +222 -0
  22. package/agents/43-data-consistency-checker.ts +205 -0
  23. package/agents/44-backup-recovery-tester.ts +152 -0
  24. package/agents/45-data-privacy-scanner.ts +125 -0
  25. package/agents/46-seo-auditor.ts +294 -0
  26. package/agents/47-social-preview-tester.ts +232 -0
  27. package/agents/48-lighthouse-auditor.ts +213 -0
  28. package/agents/49-i18n-tester.ts +198 -0
  29. package/agents/50-timezone-tester.ts +173 -0
  30. package/agents/51-error-recovery-tester.ts +155 -0
  31. package/agents/52-offline-mode-tester.ts +180 -0
  32. package/agents/53-graceful-degradation-tester.ts +156 -0
  33. package/agents/54-websocket-tester.ts +151 -0
  34. package/agents/55-realtime-sync-tester.ts +194 -0
  35. package/agents/56-file-upload-tester.ts +194 -0
  36. package/agents/57-export-tester.ts +174 -0
  37. package/agents/58-payment-flow-tester.ts +183 -0
  38. package/agents/59-ssl-tls-auditor.ts +141 -0
  39. package/agents/60-dns-cdn-tester.ts +117 -0
  40. package/agents/61-docker-health-checker.ts +111 -0
  41. package/agents/62-env-config-validator.ts +152 -0
  42. package/agents/63-log-quality-auditor.ts +136 -0
  43. package/agents/64-analytics-tracker-tester.ts +165 -0
  44. package/agents/65-gdpr-compliance-tester.ts +215 -0
  45. package/agents/66-soc2-control-validator.ts +210 -0
  46. package/agents/67-wcag-aaa-tester.ts +241 -0
  47. package/agents/68-dead-code-detector.ts +135 -0
  48. package/agents/69-type-safety-auditor.ts +164 -0
  49. package/agents/70-complexity-analyzer.ts +179 -0
  50. package/agents/__tests__/24-signup-onboarding-tester.test.ts +274 -0
  51. package/agents/__tests__/25-crud-flow-tester.test.ts +322 -0
  52. package/agents/__tests__/26-form-validator.test.ts +345 -0
  53. package/agents/__tests__/27-search-filter-tester.test.ts +311 -0
  54. package/agents/__tests__/28-navigation-routing-tester.test.ts +328 -0
  55. package/agents/__tests__/29-responsive-interaction-tester.test.ts +297 -0
  56. package/agents/__tests__/30-multi-user-scenario-tester.test.ts +328 -0
  57. package/agents/__tests__/31-load-tester.test.ts +189 -0
  58. package/agents/__tests__/32-memory-leak-detector.test.ts +251 -0
  59. package/agents/__tests__/33-bundle-analyzer.test.ts +237 -0
  60. package/agents/__tests__/34-xss-scanner.test.ts +258 -0
  61. package/agents/__tests__/35-csrf-tester.test.ts +200 -0
  62. package/agents/__tests__/36-auth-fuzzer.test.ts +214 -0
  63. package/agents/__tests__/37-dependency-scanner.test.ts +266 -0
  64. package/agents/__tests__/38-secrets-scanner.test.ts +224 -0
  65. package/agents/__tests__/39-api-contract-tester.test.ts +312 -0
  66. package/agents/__tests__/40-rate-limit-tester.test.ts +192 -0
  67. package/agents/__tests__/41-api-pagination-tester.test.ts +198 -0
  68. package/agents/__tests__/42-graphql-tester.test.ts +252 -0
  69. package/agents/__tests__/43-data-consistency-checker.test.ts +232 -0
  70. package/agents/__tests__/44-backup-recovery-tester.test.ts +222 -0
  71. package/agents/__tests__/45-data-privacy-scanner.test.ts +223 -0
  72. package/agents/__tests__/46-seo-auditor.test.ts +261 -0
  73. package/agents/__tests__/47-social-preview-tester.test.ts +245 -0
  74. package/agents/__tests__/48-lighthouse-auditor.test.ts +276 -0
  75. package/agents/__tests__/49-i18n-tester.test.ts +201 -0
  76. package/agents/__tests__/50-timezone-tester.test.ts +172 -0
  77. package/agents/__tests__/51-error-recovery-tester.test.ts +162 -0
  78. package/agents/__tests__/52-offline-mode-tester.test.ts +164 -0
  79. package/agents/__tests__/53-graceful-degradation-tester.test.ts +168 -0
  80. package/agents/__tests__/54-websocket-tester.test.ts +157 -0
  81. package/agents/__tests__/55-realtime-sync-tester.test.ts +181 -0
  82. package/agents/__tests__/56-file-upload-tester.test.ts +172 -0
  83. package/agents/__tests__/57-export-tester.test.ts +169 -0
  84. package/agents/__tests__/58-payment-flow-tester.test.ts +182 -0
  85. package/agents/__tests__/59-ssl-tls-auditor.test.ts +179 -0
  86. package/agents/__tests__/60-dns-cdn-tester.test.ts +176 -0
  87. package/agents/__tests__/61-docker-health-checker.test.ts +150 -0
  88. package/agents/__tests__/62-env-config-validator.test.ts +166 -0
  89. package/agents/__tests__/63-log-quality-auditor.test.ts +175 -0
  90. package/agents/__tests__/64-analytics-tracker-tester.test.ts +158 -0
  91. package/agents/__tests__/65-gdpr-compliance-tester.test.ts +174 -0
  92. package/agents/__tests__/66-soc2-control-validator.test.ts +183 -0
  93. package/agents/__tests__/67-wcag-aaa-tester.test.ts +190 -0
  94. package/agents/__tests__/68-dead-code-detector.test.ts +174 -0
  95. package/agents/__tests__/69-type-safety-auditor.test.ts +173 -0
  96. package/agents/__tests__/70-complexity-analyzer.test.ts +177 -0
  97. package/agents/__tests__/registry.test.ts +13 -13
  98. package/agents/registry.ts +146 -5
  99. package/core/__tests__/integration.test.ts +4 -4
  100. package/core/__tests__/orchestrator.test.ts +17 -16
  101. package/core/license.ts +208 -211
  102. package/core/orchestrator.ts +6 -4
  103. package/dist/agents/24-signup-onboarding-tester.d.ts +35 -0
  104. package/dist/agents/24-signup-onboarding-tester.d.ts.map +1 -0
  105. package/dist/agents/24-signup-onboarding-tester.js +357 -0
  106. package/dist/agents/24-signup-onboarding-tester.js.map +1 -0
  107. package/dist/agents/25-crud-flow-tester.d.ts +11 -0
  108. package/dist/agents/25-crud-flow-tester.d.ts.map +1 -0
  109. package/dist/agents/25-crud-flow-tester.js +253 -0
  110. package/dist/agents/25-crud-flow-tester.js.map +1 -0
  111. package/dist/agents/26-form-validator.d.ts +12 -0
  112. package/dist/agents/26-form-validator.d.ts.map +1 -0
  113. package/dist/agents/26-form-validator.js +257 -0
  114. package/dist/agents/26-form-validator.js.map +1 -0
  115. package/dist/agents/27-search-filter-tester.d.ts +20 -0
  116. package/dist/agents/27-search-filter-tester.d.ts.map +1 -0
  117. package/dist/agents/27-search-filter-tester.js +267 -0
  118. package/dist/agents/27-search-filter-tester.js.map +1 -0
  119. package/dist/agents/28-navigation-routing-tester.d.ts +32 -0
  120. package/dist/agents/28-navigation-routing-tester.d.ts.map +1 -0
  121. package/dist/agents/28-navigation-routing-tester.js +363 -0
  122. package/dist/agents/28-navigation-routing-tester.js.map +1 -0
  123. package/dist/agents/29-responsive-interaction-tester.d.ts +26 -0
  124. package/dist/agents/29-responsive-interaction-tester.d.ts.map +1 -0
  125. package/dist/agents/29-responsive-interaction-tester.js +272 -0
  126. package/dist/agents/29-responsive-interaction-tester.js.map +1 -0
  127. package/dist/agents/30-multi-user-scenario-tester.d.ts +24 -0
  128. package/dist/agents/30-multi-user-scenario-tester.d.ts.map +1 -0
  129. package/dist/agents/30-multi-user-scenario-tester.js +254 -0
  130. package/dist/agents/30-multi-user-scenario-tester.js.map +1 -0
  131. package/dist/agents/31-load-tester.d.ts +12 -0
  132. package/dist/agents/31-load-tester.d.ts.map +1 -0
  133. package/dist/agents/31-load-tester.js +110 -0
  134. package/dist/agents/31-load-tester.js.map +1 -0
  135. package/dist/agents/32-memory-leak-detector.d.ts +12 -0
  136. package/dist/agents/32-memory-leak-detector.d.ts.map +1 -0
  137. package/dist/agents/32-memory-leak-detector.js +167 -0
  138. package/dist/agents/32-memory-leak-detector.js.map +1 -0
  139. package/dist/agents/33-bundle-analyzer.d.ts +10 -0
  140. package/dist/agents/33-bundle-analyzer.d.ts.map +1 -0
  141. package/dist/agents/33-bundle-analyzer.js +111 -0
  142. package/dist/agents/33-bundle-analyzer.js.map +1 -0
  143. package/dist/agents/34-xss-scanner.d.ts +11 -0
  144. package/dist/agents/34-xss-scanner.d.ts.map +1 -0
  145. package/dist/agents/34-xss-scanner.js +164 -0
  146. package/dist/agents/34-xss-scanner.js.map +1 -0
  147. package/dist/agents/35-csrf-tester.d.ts +11 -0
  148. package/dist/agents/35-csrf-tester.d.ts.map +1 -0
  149. package/dist/agents/35-csrf-tester.js +70 -0
  150. package/dist/agents/35-csrf-tester.js.map +1 -0
  151. package/dist/agents/36-auth-fuzzer.d.ts +13 -0
  152. package/dist/agents/36-auth-fuzzer.d.ts.map +1 -0
  153. package/dist/agents/36-auth-fuzzer.js +163 -0
  154. package/dist/agents/36-auth-fuzzer.js.map +1 -0
  155. package/dist/agents/37-dependency-scanner.d.ts +11 -0
  156. package/dist/agents/37-dependency-scanner.d.ts.map +1 -0
  157. package/dist/agents/37-dependency-scanner.js +139 -0
  158. package/dist/agents/37-dependency-scanner.js.map +1 -0
  159. package/dist/agents/38-secrets-scanner.d.ts +11 -0
  160. package/dist/agents/38-secrets-scanner.d.ts.map +1 -0
  161. package/dist/agents/38-secrets-scanner.js +116 -0
  162. package/dist/agents/38-secrets-scanner.js.map +1 -0
  163. package/dist/agents/39-api-contract-tester.d.ts +12 -0
  164. package/dist/agents/39-api-contract-tester.d.ts.map +1 -0
  165. package/dist/agents/39-api-contract-tester.js +142 -0
  166. package/dist/agents/39-api-contract-tester.js.map +1 -0
  167. package/dist/agents/40-rate-limit-tester.d.ts +12 -0
  168. package/dist/agents/40-rate-limit-tester.d.ts.map +1 -0
  169. package/dist/agents/40-rate-limit-tester.js +79 -0
  170. package/dist/agents/40-rate-limit-tester.js.map +1 -0
  171. package/dist/agents/41-api-pagination-tester.d.ts +12 -0
  172. package/dist/agents/41-api-pagination-tester.d.ts.map +1 -0
  173. package/dist/agents/41-api-pagination-tester.js +79 -0
  174. package/dist/agents/41-api-pagination-tester.js.map +1 -0
  175. package/dist/agents/42-graphql-tester.d.ts +13 -0
  176. package/dist/agents/42-graphql-tester.d.ts.map +1 -0
  177. package/dist/agents/42-graphql-tester.js +187 -0
  178. package/dist/agents/42-graphql-tester.js.map +1 -0
  179. package/dist/agents/43-data-consistency-checker.d.ts +11 -0
  180. package/dist/agents/43-data-consistency-checker.d.ts.map +1 -0
  181. package/dist/agents/43-data-consistency-checker.js +176 -0
  182. package/dist/agents/43-data-consistency-checker.js.map +1 -0
  183. package/dist/agents/44-backup-recovery-tester.d.ts +11 -0
  184. package/dist/agents/44-backup-recovery-tester.d.ts.map +1 -0
  185. package/dist/agents/44-backup-recovery-tester.js +128 -0
  186. package/dist/agents/44-backup-recovery-tester.js.map +1 -0
  187. package/dist/agents/45-data-privacy-scanner.d.ts +11 -0
  188. package/dist/agents/45-data-privacy-scanner.d.ts.map +1 -0
  189. package/dist/agents/45-data-privacy-scanner.js +100 -0
  190. package/dist/agents/45-data-privacy-scanner.js.map +1 -0
  191. package/dist/agents/46-seo-auditor.d.ts +12 -0
  192. package/dist/agents/46-seo-auditor.d.ts.map +1 -0
  193. package/dist/agents/46-seo-auditor.js +275 -0
  194. package/dist/agents/46-seo-auditor.js.map +1 -0
  195. package/dist/agents/47-social-preview-tester.d.ts +11 -0
  196. package/dist/agents/47-social-preview-tester.d.ts.map +1 -0
  197. package/dist/agents/47-social-preview-tester.js +219 -0
  198. package/dist/agents/47-social-preview-tester.js.map +1 -0
  199. package/dist/agents/48-lighthouse-auditor.d.ts +11 -0
  200. package/dist/agents/48-lighthouse-auditor.d.ts.map +1 -0
  201. package/dist/agents/48-lighthouse-auditor.js +192 -0
  202. package/dist/agents/48-lighthouse-auditor.js.map +1 -0
  203. package/dist/agents/49-i18n-tester.d.ts +13 -0
  204. package/dist/agents/49-i18n-tester.d.ts.map +1 -0
  205. package/dist/agents/49-i18n-tester.js +172 -0
  206. package/dist/agents/49-i18n-tester.js.map +1 -0
  207. package/dist/agents/50-timezone-tester.d.ts +11 -0
  208. package/dist/agents/50-timezone-tester.d.ts.map +1 -0
  209. package/dist/agents/50-timezone-tester.js +152 -0
  210. package/dist/agents/50-timezone-tester.js.map +1 -0
  211. package/dist/agents/51-error-recovery-tester.d.ts +11 -0
  212. package/dist/agents/51-error-recovery-tester.d.ts.map +1 -0
  213. package/dist/agents/51-error-recovery-tester.js +134 -0
  214. package/dist/agents/51-error-recovery-tester.js.map +1 -0
  215. package/dist/agents/52-offline-mode-tester.d.ts +12 -0
  216. package/dist/agents/52-offline-mode-tester.d.ts.map +1 -0
  217. package/dist/agents/52-offline-mode-tester.js +161 -0
  218. package/dist/agents/52-offline-mode-tester.js.map +1 -0
  219. package/dist/agents/53-graceful-degradation-tester.d.ts +12 -0
  220. package/dist/agents/53-graceful-degradation-tester.d.ts.map +1 -0
  221. package/dist/agents/53-graceful-degradation-tester.js +130 -0
  222. package/dist/agents/53-graceful-degradation-tester.js.map +1 -0
  223. package/dist/agents/54-websocket-tester.d.ts +10 -0
  224. package/dist/agents/54-websocket-tester.d.ts.map +1 -0
  225. package/dist/agents/54-websocket-tester.js +132 -0
  226. package/dist/agents/54-websocket-tester.js.map +1 -0
  227. package/dist/agents/55-realtime-sync-tester.d.ts +11 -0
  228. package/dist/agents/55-realtime-sync-tester.d.ts.map +1 -0
  229. package/dist/agents/55-realtime-sync-tester.js +175 -0
  230. package/dist/agents/55-realtime-sync-tester.js.map +1 -0
  231. package/dist/agents/56-file-upload-tester.d.ts +12 -0
  232. package/dist/agents/56-file-upload-tester.d.ts.map +1 -0
  233. package/dist/agents/56-file-upload-tester.js +166 -0
  234. package/dist/agents/56-file-upload-tester.js.map +1 -0
  235. package/dist/agents/57-export-tester.d.ts +11 -0
  236. package/dist/agents/57-export-tester.d.ts.map +1 -0
  237. package/dist/agents/57-export-tester.js +155 -0
  238. package/dist/agents/57-export-tester.js.map +1 -0
  239. package/dist/agents/58-payment-flow-tester.d.ts +11 -0
  240. package/dist/agents/58-payment-flow-tester.d.ts.map +1 -0
  241. package/dist/agents/58-payment-flow-tester.js +159 -0
  242. package/dist/agents/58-payment-flow-tester.js.map +1 -0
  243. package/dist/agents/59-ssl-tls-auditor.d.ts +10 -0
  244. package/dist/agents/59-ssl-tls-auditor.d.ts.map +1 -0
  245. package/dist/agents/59-ssl-tls-auditor.js +132 -0
  246. package/dist/agents/59-ssl-tls-auditor.js.map +1 -0
  247. package/dist/agents/60-dns-cdn-tester.d.ts +10 -0
  248. package/dist/agents/60-dns-cdn-tester.d.ts.map +1 -0
  249. package/dist/agents/60-dns-cdn-tester.js +105 -0
  250. package/dist/agents/60-dns-cdn-tester.js.map +1 -0
  251. package/dist/agents/61-docker-health-checker.d.ts +10 -0
  252. package/dist/agents/61-docker-health-checker.d.ts.map +1 -0
  253. package/dist/agents/61-docker-health-checker.js +95 -0
  254. package/dist/agents/61-docker-health-checker.js.map +1 -0
  255. package/dist/agents/62-env-config-validator.d.ts +10 -0
  256. package/dist/agents/62-env-config-validator.d.ts.map +1 -0
  257. package/dist/agents/62-env-config-validator.js +132 -0
  258. package/dist/agents/62-env-config-validator.js.map +1 -0
  259. package/dist/agents/63-log-quality-auditor.d.ts +9 -0
  260. package/dist/agents/63-log-quality-auditor.d.ts.map +1 -0
  261. package/dist/agents/63-log-quality-auditor.js +121 -0
  262. package/dist/agents/63-log-quality-auditor.js.map +1 -0
  263. package/dist/agents/64-analytics-tracker-tester.d.ts +10 -0
  264. package/dist/agents/64-analytics-tracker-tester.d.ts.map +1 -0
  265. package/dist/agents/64-analytics-tracker-tester.js +146 -0
  266. package/dist/agents/64-analytics-tracker-tester.js.map +1 -0
  267. package/dist/agents/65-gdpr-compliance-tester.d.ts +13 -0
  268. package/dist/agents/65-gdpr-compliance-tester.d.ts.map +1 -0
  269. package/dist/agents/65-gdpr-compliance-tester.js +186 -0
  270. package/dist/agents/65-gdpr-compliance-tester.js.map +1 -0
  271. package/dist/agents/66-soc2-control-validator.d.ts +14 -0
  272. package/dist/agents/66-soc2-control-validator.d.ts.map +1 -0
  273. package/dist/agents/66-soc2-control-validator.js +178 -0
  274. package/dist/agents/66-soc2-control-validator.js.map +1 -0
  275. package/dist/agents/67-wcag-aaa-tester.d.ts +13 -0
  276. package/dist/agents/67-wcag-aaa-tester.d.ts.map +1 -0
  277. package/dist/agents/67-wcag-aaa-tester.js +207 -0
  278. package/dist/agents/67-wcag-aaa-tester.js.map +1 -0
  279. package/dist/agents/68-dead-code-detector.d.ts +9 -0
  280. package/dist/agents/68-dead-code-detector.d.ts.map +1 -0
  281. package/dist/agents/68-dead-code-detector.js +116 -0
  282. package/dist/agents/68-dead-code-detector.js.map +1 -0
  283. package/dist/agents/69-type-safety-auditor.d.ts +9 -0
  284. package/dist/agents/69-type-safety-auditor.d.ts.map +1 -0
  285. package/dist/agents/69-type-safety-auditor.js +148 -0
  286. package/dist/agents/69-type-safety-auditor.js.map +1 -0
  287. package/dist/agents/70-complexity-analyzer.d.ts +10 -0
  288. package/dist/agents/70-complexity-analyzer.d.ts.map +1 -0
  289. package/dist/agents/70-complexity-analyzer.js +154 -0
  290. package/dist/agents/70-complexity-analyzer.js.map +1 -0
  291. package/dist/agents/registry.d.ts +3 -3
  292. package/dist/agents/registry.d.ts.map +1 -1
  293. package/dist/agents/registry.js +146 -5
  294. package/dist/agents/registry.js.map +1 -1
  295. package/dist/core/license.js +2 -5
  296. package/dist/core/license.js.map +1 -1
  297. package/dist/core/orchestrator.d.ts.map +1 -1
  298. package/dist/core/orchestrator.js +6 -4
  299. package/dist/core/orchestrator.js.map +1 -1
  300. package/package.json +2 -2
package/core/license.ts CHANGED
@@ -1,211 +1,208 @@
1
- import * as crypto from 'node:crypto';
2
- import * as fs from 'node:fs';
3
- import * as path from 'node:path';
4
-
5
- /** License tiers supported by TestTeam. */
6
- export type LicenseTier = 'free' | 'pro' | 'enterprise';
7
-
8
- /** JWT payload embedded in a TestTeam license key. */
9
- export interface LicensePayload {
10
- tier: LicenseTier;
11
- exp: number;
12
- iat: number;
13
- sub: string;
14
- maxProjects: number;
15
- maxRunsPerMonth: number;
16
- features: string[];
17
- }
18
-
19
- /** In-memory cache so we only validate once per process. */
20
- let cachedLicense: LicensePayload | null | undefined;
21
-
22
- const LICENSE_FILENAME = '.testteam-license';
23
-
24
- // ── Base64url helpers ────────────────────────────────────────────────
25
-
26
- function base64urlEncode(data: Buffer): string {
27
- return data.toString('base64url');
28
- }
29
-
30
- function base64urlDecode(str: string): Buffer {
31
- return Buffer.from(str, 'base64url');
32
- }
33
-
34
- // ── JWT helpers (ES256 / ECDSA P-256 with SHA-256) ───────────────────
35
-
36
- /**
37
- * Decode and verify a JWT signed with ES256.
38
- * Returns the payload on success or `null` on any failure
39
- * (bad format, invalid signature, expired, malformed JSON).
40
- */
41
- export function validateLicense(
42
- key: string,
43
- publicKey: string,
44
- ): LicensePayload | null {
45
- try {
46
- const parts = key.trim().split('.');
47
- if (parts.length !== 3) return null;
48
-
49
- const [headerB64, payloadB64, signatureB64] = parts;
50
-
51
- // Verify header declares ES256
52
- const header: unknown = JSON.parse(
53
- base64urlDecode(headerB64).toString('utf8'),
54
- );
55
- if (
56
- typeof header !== 'object' ||
57
- header === null ||
58
- (header as Record<string, unknown>)['alg'] !== 'ES256'
59
- ) {
60
- return null;
61
- }
62
-
63
- // Verify signature
64
- const signedContent = `${headerB64}.${payloadB64}`;
65
- const signature = base64urlDecode(signatureB64);
66
-
67
- // ES256 produces a 64-byte raw (r || s) signature.
68
- // Node.js crypto.verify expects DER encoding, so convert if raw.
69
- const derSignature = rawToDer(signature);
70
-
71
- const verifier = crypto.createVerify('SHA256');
72
- verifier.update(signedContent);
73
- const valid = verifier.verify(
74
- { key: publicKey, dsaEncoding: 'der' },
75
- derSignature,
76
- );
77
- if (!valid) return null;
78
-
79
- // Decode payload
80
- const payloadJson = base64urlDecode(payloadB64).toString('utf8');
81
- const payload: unknown = JSON.parse(payloadJson);
82
-
83
- if (!isLicensePayload(payload)) return null;
84
-
85
- // Check expiry
86
- const nowSec = Math.floor(Date.now() / 1000);
87
- if (payload.exp <= nowSec) return null;
88
-
89
- return payload;
90
- } catch {
91
- return null;
92
- }
93
- }
94
-
95
- /**
96
- * Load a license from the `.testteam-license` file in the given directory.
97
- * The file must contain the JWT on the first non-empty line.
98
- * A second non-empty line, if present, is treated as the PEM public key
99
- * (or the public key can be embedded as `TF_LICENSE_PUBLIC_KEY` env var).
100
- */
101
- export function loadLicense(configDir: string): LicensePayload | null {
102
- // Return cached result if available
103
- if (cachedLicense !== undefined) return cachedLicense;
104
-
105
- try {
106
- const filePath = path.join(configDir, LICENSE_FILENAME);
107
- if (!fs.existsSync(filePath)) {
108
- cachedLicense = null;
109
- return null;
110
- }
111
-
112
- const content = fs.readFileSync(filePath, 'utf8').trim();
113
- if (!content) {
114
- cachedLicense = null;
115
- return null;
116
- }
117
-
118
- // Split into sections separated by blank lines
119
- const sections = content.split(/\n\s*\n/);
120
- const licenseKey = sections[0].trim();
121
-
122
- // Public key: either embedded after the JWT or from env
123
- let publicKey = process.env['TF_LICENSE_PUBLIC_KEY'] ?? '';
124
- if (sections.length > 1) {
125
- publicKey = sections.slice(1).join('\n\n').trim();
126
- }
127
-
128
- if (!publicKey) {
129
- cachedLicense = null;
130
- return null;
131
- }
132
-
133
- const result = validateLicense(licenseKey, publicKey);
134
- cachedLicense = result;
135
- return result;
136
- } catch {
137
- cachedLicense = null;
138
- return null;
139
- }
140
- }
141
-
142
- /**
143
- * Get the license tier for the current project.
144
- * Falls back to `'free'` when no valid license is found.
145
- */
146
- export function getLicenseTier(configDir?: string): LicenseTier {
147
- const dir = configDir ?? process.cwd();
148
- const license = loadLicense(dir);
149
- return license?.tier ?? 'free';
150
- }
151
-
152
- /** Reset the in-memory license cache (useful for testing). */
153
- export function resetLicenseCache(): void {
154
- cachedLicense = undefined;
155
- }
156
-
157
- // ── Internal helpers ─────────────────────────────────────────────────
158
-
159
- /** Type guard for LicensePayload. */
160
- function isLicensePayload(value: unknown): value is LicensePayload {
161
- if (typeof value !== 'object' || value === null) return false;
162
- const obj = value as Record<string, unknown>;
163
-
164
- if (!['free', 'pro', 'enterprise'].includes(obj['tier'] as string)) return false;
165
- if (typeof obj['exp'] !== 'number') return false;
166
- if (typeof obj['iat'] !== 'number') return false;
167
- if (typeof obj['sub'] !== 'string') return false;
168
- if (typeof obj['maxProjects'] !== 'number') return false;
169
- if (typeof obj['maxRunsPerMonth'] !== 'number') return false;
170
- if (!Array.isArray(obj['features'])) return false;
171
- if (!obj['features'].every((f: unknown) => typeof f === 'string')) return false;
172
-
173
- return true;
174
- }
175
-
176
- /**
177
- * Convert a raw ECDSA signature (r || s, 64 bytes for P-256) to DER encoding.
178
- * If the input is already DER-encoded (starts with 0x30), return as-is.
179
- */
180
- function rawToDer(raw: Buffer): Buffer {
181
- // If already DER-encoded, return as-is
182
- if (raw.length > 0 && raw[0] === 0x30) return raw;
183
-
184
- if (raw.length !== 64) return raw; // Not a valid raw P-256 signature
185
-
186
- const r = raw.subarray(0, 32);
187
- const s = raw.subarray(32, 64);
188
-
189
- const encodeInteger = (int: Buffer): Buffer => {
190
- // Strip leading zeros but keep at least one byte
191
- let start = 0;
192
- while (start < int.length - 1 && int[start] === 0) start++;
193
- let trimmed = int.subarray(start);
194
-
195
- // If high bit is set, prepend a 0x00 byte
196
- if (trimmed[0] & 0x80) {
197
- trimmed = Buffer.concat([Buffer.from([0x00]), trimmed]);
198
- }
199
-
200
- return Buffer.concat([
201
- Buffer.from([0x02, trimmed.length]),
202
- trimmed,
203
- ]);
204
- };
205
-
206
- const rDer = encodeInteger(r);
207
- const sDer = encodeInteger(s);
208
- const body = Buffer.concat([rDer, sDer]);
209
-
210
- return Buffer.concat([Buffer.from([0x30, body.length]), body]);
211
- }
1
+ import * as crypto from 'node:crypto';
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
4
+
5
+ /** License tiers supported by TestTeam. */
6
+ export type LicenseTier = 'free' | 'pro' | 'enterprise';
7
+
8
+ /** JWT payload embedded in a TestTeam license key. */
9
+ export interface LicensePayload {
10
+ tier: LicenseTier;
11
+ exp: number;
12
+ iat: number;
13
+ sub: string;
14
+ maxProjects: number;
15
+ maxRunsPerMonth: number;
16
+ features: string[];
17
+ }
18
+
19
+ /** In-memory cache so we only validate once per process. */
20
+ let cachedLicense: LicensePayload | null | undefined;
21
+
22
+ const LICENSE_FILENAME = '.testteam-license';
23
+
24
+ // ── Base64url helpers ────────────────────────────────────────────────
25
+
26
+ function base64urlEncode(data: Buffer): string {
27
+ return data.toString('base64url');
28
+ }
29
+
30
+ function base64urlDecode(str: string): Buffer {
31
+ return Buffer.from(str, 'base64url');
32
+ }
33
+
34
+ // ── JWT helpers (ES256 / ECDSA P-256 with SHA-256) ───────────────────
35
+
36
+ /**
37
+ * Decode and verify a JWT signed with ES256.
38
+ * Returns the payload on success or `null` on any failure
39
+ * (bad format, invalid signature, expired, malformed JSON).
40
+ */
41
+ export function validateLicense(
42
+ key: string,
43
+ publicKey: string,
44
+ ): LicensePayload | null {
45
+ try {
46
+ const parts = key.trim().split('.');
47
+ if (parts.length !== 3) return null;
48
+
49
+ const [headerB64, payloadB64, signatureB64] = parts;
50
+
51
+ // Verify header declares ES256
52
+ const header: unknown = JSON.parse(
53
+ base64urlDecode(headerB64).toString('utf8'),
54
+ );
55
+ if (
56
+ typeof header !== 'object' ||
57
+ header === null ||
58
+ (header as Record<string, unknown>)['alg'] !== 'ES256'
59
+ ) {
60
+ return null;
61
+ }
62
+
63
+ // Verify signature
64
+ const signedContent = `${headerB64}.${payloadB64}`;
65
+ const signature = base64urlDecode(signatureB64);
66
+
67
+ // ES256 produces a 64-byte raw (r || s) signature.
68
+ // Node.js crypto.verify expects DER encoding, so convert if raw.
69
+ const derSignature = rawToDer(signature);
70
+
71
+ const verifier = crypto.createVerify('SHA256');
72
+ verifier.update(signedContent);
73
+ const valid = verifier.verify(
74
+ { key: publicKey, dsaEncoding: 'der' },
75
+ derSignature,
76
+ );
77
+ if (!valid) return null;
78
+
79
+ // Decode payload
80
+ const payloadJson = base64urlDecode(payloadB64).toString('utf8');
81
+ const payload: unknown = JSON.parse(payloadJson);
82
+
83
+ if (!isLicensePayload(payload)) return null;
84
+
85
+ // Check expiry
86
+ const nowSec = Math.floor(Date.now() / 1000);
87
+ if (payload.exp <= nowSec) return null;
88
+
89
+ return payload;
90
+ } catch {
91
+ return null;
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Load a license from the `.testteam-license` file in the given directory.
97
+ * The file must contain the JWT on the first non-empty line.
98
+ * A second non-empty line, if present, is treated as the PEM public key
99
+ * (or the public key can be embedded as `TF_LICENSE_PUBLIC_KEY` env var).
100
+ */
101
+ export function loadLicense(configDir: string): LicensePayload | null {
102
+ // Return cached result if available
103
+ if (cachedLicense !== undefined) return cachedLicense;
104
+
105
+ try {
106
+ const filePath = path.join(configDir, LICENSE_FILENAME);
107
+ if (!fs.existsSync(filePath)) {
108
+ cachedLicense = null;
109
+ return null;
110
+ }
111
+
112
+ const content = fs.readFileSync(filePath, 'utf8').trim();
113
+ if (!content) {
114
+ cachedLicense = null;
115
+ return null;
116
+ }
117
+
118
+ // Split into sections separated by blank lines
119
+ const sections = content.split(/\n\s*\n/);
120
+ const licenseKey = sections[0].trim();
121
+
122
+ // Public key: either embedded after the JWT or from env
123
+ let publicKey = process.env['TF_LICENSE_PUBLIC_KEY'] ?? '';
124
+ if (sections.length > 1) {
125
+ publicKey = sections.slice(1).join('\n\n').trim();
126
+ }
127
+
128
+ if (!publicKey) {
129
+ cachedLicense = null;
130
+ return null;
131
+ }
132
+
133
+ const result = validateLicense(licenseKey, publicKey);
134
+ cachedLicense = result;
135
+ return result;
136
+ } catch {
137
+ cachedLicense = null;
138
+ return null;
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Get the license tier for the current project.
144
+ * Falls back to `'free'` when no valid license is found.
145
+ */
146
+ export function getLicenseTier(configDir?: string): LicenseTier {
147
+ const dir = configDir ?? process.cwd();
148
+ const license = loadLicense(dir);
149
+ return license?.tier ?? 'free';
150
+ }
151
+
152
+ /** Reset the in-memory license cache (useful for testing). */
153
+ export function resetLicenseCache(): void {
154
+ cachedLicense = undefined;
155
+ }
156
+
157
+ // ── Internal helpers ─────────────────────────────────────────────────
158
+
159
+ /** Type guard for LicensePayload. */
160
+ function isLicensePayload(value: unknown): value is LicensePayload {
161
+ if (typeof value !== 'object' || value === null) return false;
162
+ const obj = value as Record<string, unknown>;
163
+
164
+ if (!['free', 'pro', 'enterprise'].includes(obj['tier'] as string)) return false;
165
+ if (typeof obj['exp'] !== 'number') return false;
166
+ if (typeof obj['iat'] !== 'number') return false;
167
+ if (typeof obj['sub'] !== 'string') return false;
168
+ if (typeof obj['maxProjects'] !== 'number') return false;
169
+ if (typeof obj['maxRunsPerMonth'] !== 'number') return false;
170
+ if (!Array.isArray(obj['features'])) return false;
171
+ if (!obj['features'].every((f: unknown) => typeof f === 'string')) return false;
172
+
173
+ return true;
174
+ }
175
+
176
+ /**
177
+ * Convert a raw ECDSA signature (r || s, 64 bytes for P-256) to DER encoding.
178
+ * If the input is not exactly 64 bytes it is returned as-is (e.g. already DER).
179
+ */
180
+ function rawToDer(raw: Buffer): Buffer {
181
+ if (raw.length !== 64) return raw; // Not a valid raw P-256 signature; may already be DER
182
+
183
+ const r = raw.subarray(0, 32);
184
+ const s = raw.subarray(32, 64);
185
+
186
+ const encodeInteger = (int: Buffer): Buffer => {
187
+ // Strip leading zeros but keep at least one byte
188
+ let start = 0;
189
+ while (start < int.length - 1 && int[start] === 0) start++;
190
+ let trimmed = int.subarray(start);
191
+
192
+ // If high bit is set, prepend a 0x00 byte
193
+ if (trimmed[0] & 0x80) {
194
+ trimmed = Buffer.concat([Buffer.from([0x00]), trimmed]);
195
+ }
196
+
197
+ return Buffer.concat([
198
+ Buffer.from([0x02, trimmed.length]),
199
+ trimmed,
200
+ ]);
201
+ };
202
+
203
+ const rDer = encodeInteger(r);
204
+ const sDer = encodeInteger(s);
205
+ const body = Buffer.concat([rDer, sDer]);
206
+
207
+ return Buffer.concat([Buffer.from([0x30, body.length]), body]);
208
+ }
@@ -15,9 +15,9 @@ import * as path from 'path';
15
15
 
16
16
  /** Agent IDs to dispatch per phase, in execution order. */
17
17
  const PHASE_DISPATCH: Record<Phase, readonly number[]> = {
18
- alpha: [1, 2, 23, 3, 4, 5],
19
- beta: [5, 6, 7, 8, 12, 13, 14, 15, 16, 18, 19, 21, 22],
20
- uat: [5, 6, 12, 13, 14, 15, 18, 19, 20, 21, 22, 17],
18
+ alpha: [1, 2, 23, 24, 3, 4, 5, 37, 38, 62, 68, 69, 70],
19
+ beta: [5, 6, 7, 8, 12, 13, 14, 15, 16, 18, 19, 21, 22, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70],
20
+ uat: [5, 6, 12, 13, 14, 15, 18, 19, 20, 21, 22, 17, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 37, 38, 39, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70],
21
21
  release: [10],
22
22
  };
23
23
 
@@ -26,7 +26,9 @@ const PHASE_DISPATCH: Record<Phase, readonly number[]> = {
26
26
  * Agents that write data (2, 3, 5, 16) must run sequentially.
27
27
  */
28
28
  const PARALLEL_SAFE: ReadonlySet<number> = new Set([
29
- 6, 7, 8, 12, 13, 14, 15, 18, 19, 21, 22,
29
+ 6, 7, 8, 12, 13, 14, 15, 18, 19, 21, 22, 24, 25, 26, 27, 28, 29, 30,
30
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
31
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
30
32
  ]);
31
33
 
32
34
  /** Maximum number of fix-loop iterations per phase to prevent infinite heal/fix loops. */
@@ -0,0 +1,35 @@
1
+ import type { Finding } from '../core/types';
2
+ import { BaseAgent } from './base-agent';
3
+ export declare class SignupOnboardingTesterAgent extends BaseAgent {
4
+ readonly agentId = 24;
5
+ readonly agentName = "Signup & Onboarding Tester";
6
+ private baseUrl;
7
+ protected preFlight(): Promise<void>;
8
+ protected execute(): Promise<Finding[]>;
9
+ /**
10
+ * Test 1: Check if a registration page exists.
11
+ * Tries config.auth.registerUrl first, then common paths.
12
+ */
13
+ private testRegistrationPage;
14
+ /**
15
+ * Test 2: Submit empty registration form and expect validation errors.
16
+ */
17
+ private testRegistrationValidation;
18
+ /**
19
+ * Test 3: Verify the login page has expected elements.
20
+ */
21
+ private testLoginPage;
22
+ /**
23
+ * Test 4: Fill credentials and submit login form.
24
+ */
25
+ private testLoginFlow;
26
+ /**
27
+ * Test 5: After login, look for onboarding/welcome/tour modals.
28
+ */
29
+ private testOnboardingDetection;
30
+ /**
31
+ * Test 6: Check if forgot-password page exists with expected elements.
32
+ */
33
+ private testForgotPassword;
34
+ }
35
+ //# sourceMappingURL=24-signup-onboarding-tester.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"24-signup-onboarding-tester.d.ts","sourceRoot":"","sources":["../../agents/24-signup-onboarding-tester.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAqBzC,qBAAa,2BAA4B,SAAQ,SAAS;IACxD,QAAQ,CAAC,OAAO,MAAM;IACtB,QAAQ,CAAC,SAAS,gCAAgC;IAClD,OAAO,CAAC,OAAO,CAAM;cAEL,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;cAK1B,OAAO,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAqE7C;;;OAGG;YACW,oBAAoB;IAkElC;;OAEG;YACW,0BAA0B;IAqDxC;;OAEG;YACW,aAAa;IAwD3B;;OAEG;YACW,aAAa;IA+C3B;;OAEG;YACW,uBAAuB;IAuCrC;;OAEG;YACW,kBAAkB;CA8CjC"}