amliq-dashboard 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 (492) hide show
  1. package/.env.example +3 -0
  2. package/.env.production +1 -0
  3. package/Dockerfile +26 -0
  4. package/QUICK_START.md +267 -0
  5. package/README.md +161 -0
  6. package/TESTING_GUIDE.md +322 -0
  7. package/dist/.well-known/ai-plugin.json +15 -0
  8. package/dist/_headers +8 -0
  9. package/dist/_redirects +1 -0
  10. package/dist/assets/APIKeys-BvwFauIs.js +6 -0
  11. package/dist/assets/APIKeys-DaMSBZQL.js +1 -0
  12. package/dist/assets/AdverseMedia-DckXfMzS.js +4 -0
  13. package/dist/assets/AlertDetailPage-Bc2_zwu_.js +1 -0
  14. package/dist/assets/AlertQueue-DFtBiRoM.js +8 -0
  15. package/dist/assets/Analytics-DtruB5lQ.js +1 -0
  16. package/dist/assets/AuditTrail-BK68ePu0.js +1 -0
  17. package/dist/assets/AuthDivider-gRHEt7gx.js +1 -0
  18. package/dist/assets/Badge-B9VFkofy.js +1 -0
  19. package/dist/assets/BatchJobs-Bz6KFnXD.js +6 -0
  20. package/dist/assets/BillingPage-R9nQ5nFb.js +11 -0
  21. package/dist/assets/Card-Cw-T_-oU.js +1 -0
  22. package/dist/assets/CaseDetail-DYs7Zg_y.js +7 -0
  23. package/dist/assets/CaseManagement-B1Q4Dp1Y.js +1 -0
  24. package/dist/assets/ComplianceReport-Dhssqc9T.js +1 -0
  25. package/dist/assets/Configuration-B92kl9T0.js +1 -0
  26. package/dist/assets/CryptoScreening-C7yFlskC.js +1 -0
  27. package/dist/assets/Dashboard-w4-Nhv9q.js +17 -0
  28. package/dist/assets/DataSources-u3-Ri_5_.js +3 -0
  29. package/dist/assets/EDDWorkflow-CFzlEO0e.js +1 -0
  30. package/dist/assets/EmptyState-Do0xJAT9.js +6 -0
  31. package/dist/assets/ForgotPassword-BPYyQFQp.js +1 -0
  32. package/dist/assets/LandingPage-CjaP0zw4.js +41 -0
  33. package/dist/assets/ListsMarketplace-CG6KkT9B.js +6 -0
  34. package/dist/assets/Login-677LEGP1.js +1 -0
  35. package/dist/assets/MFASetup-BxqCPvui.js +1 -0
  36. package/dist/assets/Monitoring-9TN9MK4y.js +1 -0
  37. package/dist/assets/Onboarding-Cf0Y83lX.js +1 -0
  38. package/dist/assets/Operations-CcXwc2xw.js +10 -0
  39. package/dist/assets/Overview-B_Ky0VWV.js +1 -0
  40. package/dist/assets/PEPScreening-pUQjTH9c.js +1 -0
  41. package/dist/assets/PageHeader-BObHFn0i.js +1 -0
  42. package/dist/assets/PrivacyPolicy-DZ2xrKir.js +1 -0
  43. package/dist/assets/ResetPassword-AtxtpIG1.js +1 -0
  44. package/dist/assets/RiskAssessment-Dzuh1Usv.js +1 -0
  45. package/dist/assets/SARForm-D8w2ZGe-.js +1 -0
  46. package/dist/assets/SanctionsLists-CPA3UH2v.js +1 -0
  47. package/dist/assets/ScheduledTasks-Dsjk-6UR.js +1 -0
  48. package/dist/assets/ScreenEntity-D1U0YL7v.js +3 -0
  49. package/dist/assets/ScreeningProgress-BW49PzoB.js +66 -0
  50. package/dist/assets/SearchField-CulFKdiI.js +1 -0
  51. package/dist/assets/Signup-C0FmFOo_.js +1 -0
  52. package/dist/assets/SystemHealth-B_8u4eva.js +1 -0
  53. package/dist/assets/TaskHistory-BCmEM89q.js +3 -0
  54. package/dist/assets/Team-CUo_FlU7.js +1 -0
  55. package/dist/assets/TenantDetail-CgZQHUY8.js +1 -0
  56. package/dist/assets/Tenants-RB9E9ick.js +2 -0
  57. package/dist/assets/TermsOfService-BfL-kndX.js +1 -0
  58. package/dist/assets/TransactionMonitoring-DGh_T22s.js +14 -0
  59. package/dist/assets/TxnScreening-B7cm2-eh.js +1 -0
  60. package/dist/assets/UBOChain-falXAsCo.js +1 -0
  61. package/dist/assets/Users-Doakpg9c.js +1 -0
  62. package/dist/assets/Webhooks-BZpAfaxv.js +1 -0
  63. package/dist/assets/alert-triangle-YCFVm7B_.js +6 -0
  64. package/dist/assets/alerts-COUnTwWY.js +1 -0
  65. package/dist/assets/arrow-left-9ApLqP95.js +6 -0
  66. package/dist/assets/check-VTcvVtIU.js +6 -0
  67. package/dist/assets/check-circle-2-Dn-lG5YQ.js +6 -0
  68. package/dist/assets/code-DIJRWFVv.js +6 -0
  69. package/dist/assets/fingerprint-C0MGVtax.js +6 -0
  70. package/dist/assets/flag-B8_Gwxh6.js +6 -0
  71. package/dist/assets/index-CfdYcqRM.js +289 -0
  72. package/dist/assets/index-HPU_Rhdu.css +1 -0
  73. package/dist/assets/layers-zHz2o4vo.js +6 -0
  74. package/dist/assets/loader-B9_dNihg.js +6 -0
  75. package/dist/assets/mail-BijL2qwp.js +6 -0
  76. package/dist/assets/plus-i0oBIIPS.js +6 -0
  77. package/dist/assets/refresh-cw-CSuAwutt.js +6 -0
  78. package/dist/assets/useAnalytics-Bj8IONcw.js +72 -0
  79. package/dist/assets/x-circle-DLGKvijE.js +6 -0
  80. package/dist/favicon.svg +15 -0
  81. package/dist/index.html +51 -0
  82. package/dist/llms.txt +28 -0
  83. package/dist/logo.png +0 -0
  84. package/dist/logo.svg +17 -0
  85. package/dist/manifest.json +44 -0
  86. package/dist/robots.txt +15 -0
  87. package/dist/schema.json +13 -0
  88. package/dist/sitemap.xml +28 -0
  89. package/dist/sw.js +67 -0
  90. package/e2e/auth-setup.ts +20 -0
  91. package/e2e/billing.spec.ts +50 -0
  92. package/e2e/cases.spec.ts +53 -0
  93. package/e2e/compliance.spec.ts +65 -0
  94. package/e2e/config.spec.ts +56 -0
  95. package/e2e/dashboard.spec.ts +47 -0
  96. package/e2e/fixtures.ts +33 -0
  97. package/e2e/lists.spec.ts +43 -0
  98. package/e2e/login.spec.ts +64 -0
  99. package/e2e/media.spec.ts +48 -0
  100. package/e2e/mocks.ts +51 -0
  101. package/e2e/monitoring.spec.ts +44 -0
  102. package/e2e/navigation.spec.ts +56 -0
  103. package/e2e/onboarding.spec.ts +49 -0
  104. package/e2e/responsive.spec.ts +40 -0
  105. package/e2e/risk.spec.ts +61 -0
  106. package/e2e/screening.spec.ts +76 -0
  107. package/e2e/team.spec.ts +53 -0
  108. package/index.html +50 -0
  109. package/package.json +47 -0
  110. package/playwright.config.ts +35 -0
  111. package/postcss.config.js +6 -0
  112. package/public/.well-known/ai-plugin.json +15 -0
  113. package/public/_headers +8 -0
  114. package/public/_redirects +1 -0
  115. package/public/favicon.svg +15 -0
  116. package/public/llms.txt +28 -0
  117. package/public/logo.png +0 -0
  118. package/public/logo.svg +17 -0
  119. package/public/manifest.json +44 -0
  120. package/public/robots.txt +15 -0
  121. package/public/schema.json +13 -0
  122. package/public/sitemap.xml +28 -0
  123. package/public/sw.js +67 -0
  124. package/scripts/test-runner.sh +152 -0
  125. package/src/App.tsx +48 -0
  126. package/src/api/alerts.ts +19 -0
  127. package/src/api/analytics.ts +6 -0
  128. package/src/api/audit.ts +11 -0
  129. package/src/api/auth.ts +26 -0
  130. package/src/api/billing.ts +54 -0
  131. package/src/api/cases.ts +48 -0
  132. package/src/api/client.ts +50 -0
  133. package/src/api/config.ts +30 -0
  134. package/src/api/edd.ts +25 -0
  135. package/src/api/enforcement.ts +33 -0
  136. package/src/api/lists.ts +24 -0
  137. package/src/api/monitoring.ts +82 -0
  138. package/src/api/pep.ts +30 -0
  139. package/src/api/risk.ts +26 -0
  140. package/src/api/screening.ts +37 -0
  141. package/src/api/team.ts +27 -0
  142. package/src/api/transactions.ts +37 -0
  143. package/src/components/admin/TenantCards.tsx +51 -0
  144. package/src/components/alerts/AlertActions.test.tsx +80 -0
  145. package/src/components/alerts/AlertActions.tsx +68 -0
  146. package/src/components/alerts/AlertCard.test.tsx +86 -0
  147. package/src/components/alerts/AlertCard.tsx +60 -0
  148. package/src/components/alerts/AlertDetailSidebar.tsx +63 -0
  149. package/src/components/alerts/AlertFilters.test.tsx +73 -0
  150. package/src/components/alerts/AlertFilters.tsx +88 -0
  151. package/src/components/alerts/EntityDetailsCard.test.tsx +61 -0
  152. package/src/components/alerts/EntityDetailsCard.tsx +37 -0
  153. package/src/components/alerts/NotesCard.test.tsx +39 -0
  154. package/src/components/alerts/NotesCard.tsx +28 -0
  155. package/src/components/auth/AuthDivider.tsx +18 -0
  156. package/src/components/auth/LoginForm.tsx +62 -0
  157. package/src/components/auth/LoginLeftPanel.tsx +43 -0
  158. package/src/components/auth/PasswordStrength.tsx +26 -0
  159. package/src/components/auth/SignInButtons.tsx +46 -0
  160. package/src/components/auth/SignupLeftPanel.tsx +35 -0
  161. package/src/components/auth/countries.ts +17 -0
  162. package/src/components/charts/AreaChart.tsx +45 -0
  163. package/src/components/charts/BarChart.tsx +48 -0
  164. package/src/components/charts/DonutChart.tsx +47 -0
  165. package/src/components/compliance/CaseActions.tsx +74 -0
  166. package/src/components/compliance/CaseTimeline.tsx +68 -0
  167. package/src/components/compliance/MediaResultCard.tsx +87 -0
  168. package/src/components/compliance/PEPResultCard.tsx +78 -0
  169. package/src/components/config/MatchingModesCard.test.tsx +75 -0
  170. package/src/components/config/MatchingModesCard.tsx +40 -0
  171. package/src/components/config/ScreeningLayersCard.test.tsx +57 -0
  172. package/src/components/config/ScreeningLayersCard.tsx +36 -0
  173. package/src/components/config/ThresholdsCard.test.tsx +79 -0
  174. package/src/components/config/ThresholdsCard.tsx +51 -0
  175. package/src/components/dashboard/ActivityFeed.tsx +93 -0
  176. package/src/components/dashboard/DashboardGreeting.tsx +23 -0
  177. package/src/components/dashboard/DashboardSkeleton.tsx +35 -0
  178. package/src/components/dashboard/QuickActions.tsx +52 -0
  179. package/src/components/dashboard/TopEntitiesTable.tsx +63 -0
  180. package/src/components/data/ComplianceMetrics.test.tsx +32 -0
  181. package/src/components/data/ComplianceMetrics.tsx +40 -0
  182. package/src/components/data/ConfidenceScore.test.tsx +62 -0
  183. package/src/components/data/ConfidenceScore.tsx +27 -0
  184. package/src/components/data/StatCard.test.tsx +72 -0
  185. package/src/components/data/StatCard.tsx +63 -0
  186. package/src/components/data/StatusBadge.test.tsx +63 -0
  187. package/src/components/data/StatusBadge.tsx +39 -0
  188. package/src/components/layout/AppShell.tsx +48 -0
  189. package/src/components/layout/Breadcrumbs.tsx +48 -0
  190. package/src/components/layout/CommandPalette.tsx +81 -0
  191. package/src/components/layout/DashboardLayout.tsx +19 -0
  192. package/src/components/layout/MobileHeader.tsx +30 -0
  193. package/src/components/layout/NavGroup.test.tsx +63 -0
  194. package/src/components/layout/NavGroup.tsx +64 -0
  195. package/src/components/layout/NotificationBell.tsx +89 -0
  196. package/src/components/layout/PageHeader.test.tsx +61 -0
  197. package/src/components/layout/PageHeader.tsx +19 -0
  198. package/src/components/layout/ProtectedRoute.tsx +31 -0
  199. package/src/components/layout/PublicLayout.tsx +17 -0
  200. package/src/components/layout/Sidebar.test.tsx +67 -0
  201. package/src/components/layout/Sidebar.tsx +92 -0
  202. package/src/components/layout/Toolbar.test.tsx +47 -0
  203. package/src/components/layout/Toolbar.tsx +68 -0
  204. package/src/components/layout/navItems.ts +94 -0
  205. package/src/components/lists/ListCard.tsx +78 -0
  206. package/src/components/lists/ListMarketplaceCard.tsx +77 -0
  207. package/src/components/screening/CircularConfidence.tsx +38 -0
  208. package/src/components/screening/LimitReachedBanner.tsx +31 -0
  209. package/src/components/screening/ListSelector.tsx +64 -0
  210. package/src/components/screening/MatchDetailHeader.tsx +64 -0
  211. package/src/components/screening/MatchEntityInfo.tsx +56 -0
  212. package/src/components/screening/MatchEvidenceBars.tsx +65 -0
  213. package/src/components/screening/MatchMetadata.tsx +95 -0
  214. package/src/components/screening/ScreenResults.tsx +49 -0
  215. package/src/components/screening/ScreeningForm.test.tsx +83 -0
  216. package/src/components/screening/ScreeningForm.tsx +100 -0
  217. package/src/components/screening/ScreeningLayersList.test.tsx +33 -0
  218. package/src/components/screening/ScreeningLayersList.tsx +46 -0
  219. package/src/components/screening/ScreeningProgress.tsx +91 -0
  220. package/src/components/screening/ScreeningQuotaBanner.tsx +64 -0
  221. package/src/components/screening/ScreeningResultCard.tsx +47 -0
  222. package/src/components/screening/ScreeningResultRow.tsx +45 -0
  223. package/src/components/screening/ScreeningResults.test.tsx +37 -0
  224. package/src/components/screening/ScreeningResults.tsx +33 -0
  225. package/src/components/screening/ShareResults.tsx +103 -0
  226. package/src/components/screening/ThresholdSlider.tsx +23 -0
  227. package/src/components/transactions/WebhookCTA.tsx +63 -0
  228. package/src/components/ui/Avatar.test.tsx +47 -0
  229. package/src/components/ui/Avatar.tsx +35 -0
  230. package/src/components/ui/Badge.test.tsx +49 -0
  231. package/src/components/ui/Badge.tsx +33 -0
  232. package/src/components/ui/Button.test.tsx +56 -0
  233. package/src/components/ui/Button.tsx +46 -0
  234. package/src/components/ui/Card.test.tsx +61 -0
  235. package/src/components/ui/Card.tsx +29 -0
  236. package/src/components/ui/ConfirmModal.tsx +67 -0
  237. package/src/components/ui/Divider.test.tsx +24 -0
  238. package/src/components/ui/Divider.tsx +5 -0
  239. package/src/components/ui/EmptyState.test.tsx +49 -0
  240. package/src/components/ui/EmptyState.tsx +22 -0
  241. package/src/components/ui/ErrorBoundary.tsx +44 -0
  242. package/src/components/ui/ExportMenu.tsx +71 -0
  243. package/src/components/ui/LanguageSwitcher.tsx +37 -0
  244. package/src/components/ui/LoadingSpinner.test.tsx +41 -0
  245. package/src/components/ui/LoadingSpinner.tsx +21 -0
  246. package/src/components/ui/MetricCard.tsx +63 -0
  247. package/src/components/ui/ScoreRing.tsx +51 -0
  248. package/src/components/ui/SearchField.test.tsx +55 -0
  249. package/src/components/ui/SearchField.tsx +31 -0
  250. package/src/components/ui/SeverityBadge.tsx +57 -0
  251. package/src/components/ui/ThemeToggle.tsx +37 -0
  252. package/src/components/ui/Toast.test.tsx +79 -0
  253. package/src/components/ui/Toast.tsx +75 -0
  254. package/src/components/ui/Toggle.test.tsx +85 -0
  255. package/src/components/ui/Toggle.tsx +46 -0
  256. package/src/context/AuthContext.tsx +71 -0
  257. package/src/data/pepProfiles.ts +76 -0
  258. package/src/data/pepProfilesExtra.ts +58 -0
  259. package/src/hooks/useAlerts.ts +36 -0
  260. package/src/hooks/useAnalytics.ts +23 -0
  261. package/src/hooks/useApi.test.ts +79 -0
  262. package/src/hooks/useApi.ts +33 -0
  263. package/src/hooks/useAudit.ts +28 -0
  264. package/src/hooks/useBilling.ts +38 -0
  265. package/src/hooks/useConfig.ts +35 -0
  266. package/src/hooks/useDebounce.test.ts +84 -0
  267. package/src/hooks/useDebounce.ts +15 -0
  268. package/src/hooks/useDirection.ts +15 -0
  269. package/src/hooks/useLists.ts +34 -0
  270. package/src/hooks/useMediaQuery.test.ts +97 -0
  271. package/src/hooks/useMediaQuery.ts +28 -0
  272. package/src/hooks/useScreening.ts +33 -0
  273. package/src/hooks/useSidebar.ts +18 -0
  274. package/src/hooks/useUsage.ts +27 -0
  275. package/src/i18n/config.ts +33 -0
  276. package/src/i18n/locales/ar/admin.json +19 -0
  277. package/src/i18n/locales/ar/alerts.json +52 -0
  278. package/src/i18n/locales/ar/analytics.json +9 -0
  279. package/src/i18n/locales/ar/audit.json +12 -0
  280. package/src/i18n/locales/ar/auth.json +60 -0
  281. package/src/i18n/locales/ar/batch.json +5 -0
  282. package/src/i18n/locales/ar/billing.json +41 -0
  283. package/src/i18n/locales/ar/common.json +65 -0
  284. package/src/i18n/locales/ar/compliance.json +83 -0
  285. package/src/i18n/locales/ar/config.json +13 -0
  286. package/src/i18n/locales/ar/dashboard.json +19 -0
  287. package/src/i18n/locales/ar/errors.json +9 -0
  288. package/src/i18n/locales/ar/index.ts +29 -0
  289. package/src/i18n/locales/ar/legal.json +10 -0
  290. package/src/i18n/locales/ar/lists.json +6 -0
  291. package/src/i18n/locales/ar/marketing.json +110 -0
  292. package/src/i18n/locales/ar/monitoring.json +15 -0
  293. package/src/i18n/locales/ar/nav.json +35 -0
  294. package/src/i18n/locales/ar/onboarding.json +25 -0
  295. package/src/i18n/locales/ar/platform.json +23 -0
  296. package/src/i18n/locales/ar/screening.json +26 -0
  297. package/src/i18n/locales/ar/team.json +11 -0
  298. package/src/i18n/locales/en/admin.json +21 -0
  299. package/src/i18n/locales/en/alerts.json +52 -0
  300. package/src/i18n/locales/en/analytics.json +9 -0
  301. package/src/i18n/locales/en/audit.json +12 -0
  302. package/src/i18n/locales/en/auth.json +60 -0
  303. package/src/i18n/locales/en/batch.json +5 -0
  304. package/src/i18n/locales/en/billing.json +87 -0
  305. package/src/i18n/locales/en/common.json +65 -0
  306. package/src/i18n/locales/en/compliance.json +83 -0
  307. package/src/i18n/locales/en/config.json +29 -0
  308. package/src/i18n/locales/en/dashboard.json +23 -0
  309. package/src/i18n/locales/en/errors.json +9 -0
  310. package/src/i18n/locales/en/index.ts +29 -0
  311. package/src/i18n/locales/en/legal.json +114 -0
  312. package/src/i18n/locales/en/lists.json +6 -0
  313. package/src/i18n/locales/en/marketing.json +174 -0
  314. package/src/i18n/locales/en/monitoring.json +15 -0
  315. package/src/i18n/locales/en/nav.json +35 -0
  316. package/src/i18n/locales/en/onboarding.json +31 -0
  317. package/src/i18n/locales/en/platform.json +25 -0
  318. package/src/i18n/locales/en/screening.json +26 -0
  319. package/src/i18n/locales/en/team.json +12 -0
  320. package/src/i18n/locales/he/admin.json +19 -0
  321. package/src/i18n/locales/he/alerts.json +52 -0
  322. package/src/i18n/locales/he/analytics.json +9 -0
  323. package/src/i18n/locales/he/audit.json +12 -0
  324. package/src/i18n/locales/he/auth.json +60 -0
  325. package/src/i18n/locales/he/batch.json +5 -0
  326. package/src/i18n/locales/he/billing.json +41 -0
  327. package/src/i18n/locales/he/common.json +65 -0
  328. package/src/i18n/locales/he/compliance.json +83 -0
  329. package/src/i18n/locales/he/config.json +13 -0
  330. package/src/i18n/locales/he/dashboard.json +19 -0
  331. package/src/i18n/locales/he/errors.json +9 -0
  332. package/src/i18n/locales/he/index.ts +29 -0
  333. package/src/i18n/locales/he/legal.json +10 -0
  334. package/src/i18n/locales/he/lists.json +6 -0
  335. package/src/i18n/locales/he/marketing.json +110 -0
  336. package/src/i18n/locales/he/monitoring.json +15 -0
  337. package/src/i18n/locales/he/nav.json +35 -0
  338. package/src/i18n/locales/he/onboarding.json +25 -0
  339. package/src/i18n/locales/he/platform.json +23 -0
  340. package/src/i18n/locales/he/screening.json +26 -0
  341. package/src/i18n/locales/he/team.json +11 -0
  342. package/src/index.css +112 -0
  343. package/src/main.tsx +15 -0
  344. package/src/pages/APIKeys.tsx +120 -0
  345. package/src/pages/AddMonitorModal.tsx +30 -0
  346. package/src/pages/AdverseMedia.test.tsx +18 -0
  347. package/src/pages/AdverseMedia.tsx +89 -0
  348. package/src/pages/AlertDetailPage.tsx +64 -0
  349. package/src/pages/AlertQueue.test.tsx +48 -0
  350. package/src/pages/AlertQueue.tsx +63 -0
  351. package/src/pages/Analytics.tsx +50 -0
  352. package/src/pages/AuditTrail.tsx +64 -0
  353. package/src/pages/BatchJobs.tsx +79 -0
  354. package/src/pages/CaseDetail.tsx +72 -0
  355. package/src/pages/CaseManagement.test.tsx +31 -0
  356. package/src/pages/CaseManagement.tsx +92 -0
  357. package/src/pages/Configuration.test.tsx +96 -0
  358. package/src/pages/Configuration.tsx +123 -0
  359. package/src/pages/CryptoScreening.tsx +109 -0
  360. package/src/pages/Dashboard.test.tsx +51 -0
  361. package/src/pages/Dashboard.tsx +66 -0
  362. package/src/pages/EDDWorkflow.test.tsx +29 -0
  363. package/src/pages/EDDWorkflow.tsx +73 -0
  364. package/src/pages/ForgotPassword.test.tsx +49 -0
  365. package/src/pages/ForgotPassword.tsx +67 -0
  366. package/src/pages/ListsMarketplace.tsx +102 -0
  367. package/src/pages/Login.test.tsx +100 -0
  368. package/src/pages/Login.tsx +57 -0
  369. package/src/pages/MFASetup.tsx +114 -0
  370. package/src/pages/MonitorProfileCard.tsx +27 -0
  371. package/src/pages/Monitoring.tsx +68 -0
  372. package/src/pages/Onboarding.test.tsx +36 -0
  373. package/src/pages/Onboarding.tsx +60 -0
  374. package/src/pages/PEPScreening.test.tsx +15 -0
  375. package/src/pages/PEPScreening.tsx +100 -0
  376. package/src/pages/ResetPassword.tsx +81 -0
  377. package/src/pages/RiskAssessment.test.tsx +15 -0
  378. package/src/pages/RiskAssessment.tsx +108 -0
  379. package/src/pages/SanctionsLists.tsx +74 -0
  380. package/src/pages/ScreenEntity.test.tsx +82 -0
  381. package/src/pages/ScreenEntity.tsx +76 -0
  382. package/src/pages/Signup.test.tsx +98 -0
  383. package/src/pages/Signup.tsx +92 -0
  384. package/src/pages/TaskHistory.tsx +183 -0
  385. package/src/pages/Team.test.tsx +15 -0
  386. package/src/pages/Team.tsx +140 -0
  387. package/src/pages/TransactionMonitoring.test.tsx +18 -0
  388. package/src/pages/TransactionMonitoring.tsx +118 -0
  389. package/src/pages/TxnScreening.tsx +125 -0
  390. package/src/pages/UBOChain.test.tsx +35 -0
  391. package/src/pages/UBOChain.tsx +65 -0
  392. package/src/pages/Webhooks.tsx +137 -0
  393. package/src/pages/admin/DataSources.tsx +230 -0
  394. package/src/pages/admin/Operations.tsx +103 -0
  395. package/src/pages/admin/ScheduledTasks.tsx +155 -0
  396. package/src/pages/admin/SystemHealth.tsx +58 -0
  397. package/src/pages/admin/TenantDetail.tsx +62 -0
  398. package/src/pages/admin/Tenants.test.tsx +20 -0
  399. package/src/pages/admin/Tenants.tsx +63 -0
  400. package/src/pages/admin/opsRunners.ts +81 -0
  401. package/src/pages/admin/opsTerminal.tsx +63 -0
  402. package/src/pages/billing/ActiveSubscriptions.tsx +41 -0
  403. package/src/pages/billing/AddProductModal.tsx +99 -0
  404. package/src/pages/billing/BillingPage.test.tsx +30 -0
  405. package/src/pages/billing/BillingPage.tsx +67 -0
  406. package/src/pages/billing/CurrentPlan.tsx +50 -0
  407. package/src/pages/billing/InvoiceList.tsx +104 -0
  408. package/src/pages/billing/InvoiceRow.tsx +37 -0
  409. package/src/pages/billing/LemonSqueezySetup.tsx +51 -0
  410. package/src/pages/billing/PaymentAlert.tsx +33 -0
  411. package/src/pages/billing/PlanComparison.tsx +53 -0
  412. package/src/pages/billing/ProductUsage.tsx +43 -0
  413. package/src/pages/billing/PromoCodeInput.tsx +58 -0
  414. package/src/pages/billing/SeatManager.tsx +80 -0
  415. package/src/pages/billing/SeatRow.tsx +32 -0
  416. package/src/pages/billing/SubscriptionCard.tsx +73 -0
  417. package/src/pages/billing/UpgradeModal.tsx +53 -0
  418. package/src/pages/billing/UsageHistory.tsx +37 -0
  419. package/src/pages/billing/UsageMeter.tsx +26 -0
  420. package/src/pages/billing/UsageOverview.tsx +38 -0
  421. package/src/pages/legal/PrivacyPolicy.tsx +25 -0
  422. package/src/pages/legal/TermsOfService.tsx +25 -0
  423. package/src/pages/marketing/BundleCallout.tsx +24 -0
  424. package/src/pages/marketing/CTASection.tsx +48 -0
  425. package/src/pages/marketing/CaseStudy.tsx +37 -0
  426. package/src/pages/marketing/ComparisonTable.tsx +66 -0
  427. package/src/pages/marketing/CompetitiveEdge.tsx +55 -0
  428. package/src/pages/marketing/DataCoverage.tsx +54 -0
  429. package/src/pages/marketing/DataRain.tsx +30 -0
  430. package/src/pages/marketing/EnterpriseCTA.tsx +26 -0
  431. package/src/pages/marketing/FAQItem.tsx +27 -0
  432. package/src/pages/marketing/FAQSchema.tsx +43 -0
  433. package/src/pages/marketing/FAQSection.tsx +19 -0
  434. package/src/pages/marketing/FeatureDetail.tsx +19 -0
  435. package/src/pages/marketing/FeaturesGrid.tsx +60 -0
  436. package/src/pages/marketing/FeaturesSpotlight.tsx +68 -0
  437. package/src/pages/marketing/FooterSection.tsx +92 -0
  438. package/src/pages/marketing/GradientOrbs.tsx +26 -0
  439. package/src/pages/marketing/HeroSearch.tsx +113 -0
  440. package/src/pages/marketing/HeroSection.tsx +72 -0
  441. package/src/pages/marketing/LandingPage.tsx +45 -0
  442. package/src/pages/marketing/LogoCloud.tsx +31 -0
  443. package/src/pages/marketing/LogoMarquee.tsx +45 -0
  444. package/src/pages/marketing/MarketingNav.tsx +80 -0
  445. package/src/pages/marketing/MatchingLayers.tsx +78 -0
  446. package/src/pages/marketing/MobileMenu.tsx +45 -0
  447. package/src/pages/marketing/PricingCard.tsx +57 -0
  448. package/src/pages/marketing/PricingFeatureRow.tsx +16 -0
  449. package/src/pages/marketing/PricingSection.tsx +103 -0
  450. package/src/pages/marketing/PricingToggle.tsx +40 -0
  451. package/src/pages/marketing/ProductPricingCards.tsx +23 -0
  452. package/src/pages/marketing/ProductShowcase.tsx +81 -0
  453. package/src/pages/marketing/ProductTabs.tsx +45 -0
  454. package/src/pages/marketing/QuoteRotator.tsx +56 -0
  455. package/src/pages/marketing/StatsBar.tsx +81 -0
  456. package/src/pages/marketing/StatsSection.tsx +44 -0
  457. package/src/pages/marketing/TestimonialCard.tsx +38 -0
  458. package/src/pages/marketing/TestimonialsSection.tsx +32 -0
  459. package/src/pages/marketing/animations.tsx +56 -0
  460. package/src/pages/onboarding/CountryStep.tsx +38 -0
  461. package/src/pages/onboarding/ListsStep.tsx +44 -0
  462. package/src/pages/onboarding/StepIndicator.tsx +34 -0
  463. package/src/pages/onboarding/ThresholdStep.tsx +49 -0
  464. package/src/pages/platform/APIKeys.tsx +102 -0
  465. package/src/pages/platform/Overview.tsx +58 -0
  466. package/src/pages/platform/Users.tsx +110 -0
  467. package/src/pages/reporting/ComplianceReport.tsx +99 -0
  468. package/src/pages/reporting/SARForm.tsx +99 -0
  469. package/src/routes/appRoutes.tsx +60 -0
  470. package/src/routes/compliance.tsx +28 -0
  471. package/src/routes/lazyCompliance.ts +34 -0
  472. package/src/routes/lazyPages.ts +35 -0
  473. package/src/routes/lazyPlatform.ts +5 -0
  474. package/src/routes/platform.tsx +15 -0
  475. package/src/styles/effects.css +76 -0
  476. package/src/test/setup.ts +25 -0
  477. package/src/test/utils.tsx +49 -0
  478. package/src/types/alert.ts +31 -0
  479. package/src/types/analytics.ts +16 -0
  480. package/src/types/audit.ts +11 -0
  481. package/src/types/billing.ts +60 -0
  482. package/src/types/common.ts +15 -0
  483. package/src/types/config.ts +19 -0
  484. package/src/types/entity.ts +34 -0
  485. package/src/types/index.ts +8 -0
  486. package/src/types/list.ts +15 -0
  487. package/src/types/screening.ts +32 -0
  488. package/src/vite-env.d.ts +1 -0
  489. package/tailwind.config.js +65 -0
  490. package/tsconfig.json +22 -0
  491. package/vite.config.ts +11 -0
  492. package/vitest.config.ts +19 -0
@@ -0,0 +1,43 @@
1
+ import { test, expect } from './fixtures';
2
+ import { mockRaw } from './mocks';
3
+
4
+ test.describe('Sanctions Lists', () => {
5
+ test.beforeEach(async ({ page }) => {
6
+ await page.addInitScript(() => {
7
+ localStorage.setItem('amliq_token', 'fake.jwt.token');
8
+ });
9
+ await page.route('**/api/v1/auth/me', route =>
10
+ route.fulfill({
11
+ status: 200, contentType: 'application/json',
12
+ body: JSON.stringify({
13
+ data: { id: '1', email: 'a@b.com', role: 'admin', tenant_id: 'tnt_abc' },
14
+ }),
15
+ }),
16
+ );
17
+ await mockRaw(page, '/api/v1/lists', {
18
+ data: [
19
+ { id: 'ofac', name: 'OFAC SDN', entity_count: 12000, last_sync: '2026-04-04' },
20
+ { id: 'eu', name: 'EU FSF', entity_count: 8000, last_sync: '2026-04-04' },
21
+ { id: 'un', name: 'UN Consolidated', entity_count: 6000, last_sync: '2026-04-03' },
22
+ ],
23
+ });
24
+ });
25
+
26
+ test('shows sanctions lists page', async ({ page }) => {
27
+ await page.goto('/lists');
28
+ await expect(page.getByText(/list|sanction/i).first()).toBeVisible();
29
+ });
30
+
31
+ test('shows marketplace', async ({ page }) => {
32
+ await mockRaw(page, '/api/v1/lists/marketplace*', {
33
+ lists: [
34
+ { id: 'dfat', name: 'DFAT', jurisdiction: 'AU', enabled: false },
35
+ { id: 'interpol', name: 'Interpol', jurisdiction: 'Global', enabled: true },
36
+ ],
37
+ });
38
+ await page.goto('/lists/marketplace');
39
+ await page.waitForLoadState('networkidle');
40
+ const body = page.locator('body');
41
+ await expect(body).toBeVisible();
42
+ });
43
+ });
@@ -0,0 +1,64 @@
1
+ import { test, expect } from '@playwright/test';
2
+
3
+ test.describe('Login page', () => {
4
+ test('renders login form with email and password', async ({ page }) => {
5
+ await page.goto('/login');
6
+ await expect(page.getByText('Sign in to AMLIQ')).toBeVisible();
7
+ await expect(page.getByPlaceholder('Email')).toBeVisible();
8
+ await expect(page.getByPlaceholder('Password')).toBeVisible();
9
+ await expect(page.getByRole('button', { name: 'Sign In' })).toBeVisible();
10
+ });
11
+
12
+ test('shows sign up link', async ({ page }) => {
13
+ await page.goto('/login');
14
+ await expect(page.getByRole('link', { name: 'Sign up' })).toBeVisible();
15
+ });
16
+
17
+ test('shows error on invalid credentials', async ({ page }) => {
18
+ // Use 400 (not 401) to avoid fetchApi 401 redirect loop
19
+ await page.route('**/api/v1/auth/login', route =>
20
+ route.fulfill({
21
+ status: 400,
22
+ contentType: 'application/json',
23
+ body: JSON.stringify({
24
+ code: 'INVALID_CREDENTIALS',
25
+ message: 'Invalid credentials',
26
+ }),
27
+ }),
28
+ );
29
+ await page.goto('/login');
30
+ await page.getByPlaceholder('Email').fill('bad@test.com');
31
+ await page.getByPlaceholder('Password').fill('wrong');
32
+ await page.getByRole('button', { name: 'Sign In' }).click();
33
+ await expect(page.locator('.text-red-500')).toBeVisible();
34
+ });
35
+
36
+ test('redirects to dashboard on success', async ({ page }) => {
37
+ await page.route('**/api/v1/auth/login', route =>
38
+ route.fulfill({
39
+ status: 200,
40
+ contentType: 'application/json',
41
+ body: JSON.stringify({
42
+ data: { token: 'fake.jwt.token', user: { id: '1', role: 'admin' } },
43
+ }),
44
+ }),
45
+ );
46
+ await page.route('**/api/v1/auth/me', route =>
47
+ route.fulfill({
48
+ status: 200,
49
+ contentType: 'application/json',
50
+ body: JSON.stringify({
51
+ data: { id: '1', email: 'a@b.com', role: 'admin', tenant_id: 'tnt_abc' },
52
+ }),
53
+ }),
54
+ );
55
+ await page.route('**/api/v1/analytics*', route =>
56
+ route.fulfill({ status: 200, contentType: 'application/json', body: '{"data":{}}' }),
57
+ );
58
+ await page.goto('/login');
59
+ await page.getByPlaceholder('Email').fill('admin@aegis.test');
60
+ await page.getByPlaceholder('Password').fill('password');
61
+ await page.getByRole('button', { name: 'Sign In' }).click();
62
+ await page.waitForURL('**/dashboard');
63
+ });
64
+ });
@@ -0,0 +1,48 @@
1
+ import { test, expect } from '@playwright/test';
2
+ import { setupAuth } from './auth-setup';
3
+ import { mockAPI } from './mocks';
4
+
5
+ test.describe('Adverse Media', () => {
6
+ test.beforeEach(async ({ page }) => {
7
+ await setupAuth(page);
8
+ // AdverseMedia uses fields: title, url, detected_at
9
+ await mockAPI(page, '/api/v1/media/unreviewed*', {
10
+ hits: [
11
+ {
12
+ id: 'media_1', entity_id: 'ent_1', url: 'https://news.test',
13
+ title: 'Sanctions violation suspected', category: 'sanctions',
14
+ severity: 8, detected_at: '2025-02-01',
15
+ },
16
+ ],
17
+ });
18
+ });
19
+
20
+ test('shows adverse media title', async ({ page }) => {
21
+ await page.goto('/compliance/media');
22
+ await expect(page.getByRole('heading', { name: 'Adverse Media' })).toBeVisible();
23
+ });
24
+ });
25
+
26
+ test.describe('Transaction Monitoring', () => {
27
+ test.beforeEach(async ({ page }) => {
28
+ await setupAuth(page);
29
+ // TransactionMonitoring fetches /api/v1/transactions/alerts (not /txn/)
30
+ await mockAPI(page, '/api/v1/transactions/alerts/summary*', {
31
+ high_value: 3, rapid_movement: 1, structuring: 2, high_risk_country: 1,
32
+ });
33
+ await mockAPI(page, '/api/v1/transactions/alerts*', {
34
+ alerts: [
35
+ {
36
+ id: 'txalert_1', transaction_id: 'txn_1', alert_type: 'high_value',
37
+ severity: 8, description: 'Over $1M', created_at: '2025-03-01',
38
+ },
39
+ ],
40
+ total: 1,
41
+ });
42
+ });
43
+
44
+ test('shows transaction monitoring title', async ({ page }) => {
45
+ await page.goto('/compliance/txn');
46
+ await expect(page.getByText('Transaction Monitoring')).toBeVisible();
47
+ });
48
+ });
package/e2e/mocks.ts ADDED
@@ -0,0 +1,51 @@
1
+ import type { Page } from '@playwright/test';
2
+
3
+ /** Mock an API endpoint with a JSON response (wraps in { data }). */
4
+ export async function mockAPI(
5
+ page: Page,
6
+ pattern: string,
7
+ data: unknown,
8
+ status = 200,
9
+ ) {
10
+ await page.route(`**${pattern}`, route =>
11
+ route.fulfill({
12
+ status,
13
+ contentType: 'application/json',
14
+ body: JSON.stringify({ data }),
15
+ }),
16
+ );
17
+ }
18
+
19
+ /** Mock an API endpoint with raw JSON (no wrapper). */
20
+ export async function mockRaw(
21
+ page: Page,
22
+ pattern: string,
23
+ body: unknown,
24
+ status = 200,
25
+ ) {
26
+ await page.route(`**${pattern}`, route =>
27
+ route.fulfill({
28
+ status,
29
+ contentType: 'application/json',
30
+ body: JSON.stringify(body),
31
+ }),
32
+ );
33
+ }
34
+
35
+ /** Seed common dashboard API mocks. */
36
+ export async function mockDashboard(page: Page) {
37
+ // useAnalytics → api.get → fetchApi returns raw JSON
38
+ await mockRaw(page, '/api/v1/analytics*', {
39
+ totalAlerts: 42, clearedAlerts: 28, escalatedAlerts: 5,
40
+ avgResolutionTime: 2.5, screeningVolume: [],
41
+ dispositionBreakdown: [], riskDistribution: [],
42
+ topEntities: [
43
+ { name: 'Entity A', alerts: 10, risk: 'High' },
44
+ ],
45
+ });
46
+ // ComplianceMetrics → raw fetch → accesses resp.data
47
+ await mockAPI(page, '/api/v1/dashboard/compliance', {
48
+ openCases: 5, activeMonitors: 3, highRiskEntities: 2,
49
+ pendingEDD: 1, unreviewedMedia: 4, txnAlerts: 7,
50
+ });
51
+ }
@@ -0,0 +1,44 @@
1
+ import { test, expect } from './fixtures';
2
+ import { mockRaw } from './mocks';
3
+
4
+ test.describe('Continuous Monitoring', () => {
5
+ test.beforeEach(async ({ page }) => {
6
+ await page.addInitScript(() => {
7
+ localStorage.setItem('amliq_token', 'fake.jwt.token');
8
+ });
9
+ await page.route('**/api/v1/auth/me', route =>
10
+ route.fulfill({
11
+ status: 200, contentType: 'application/json',
12
+ body: JSON.stringify({
13
+ data: { id: '1', email: 'a@b.com', role: 'admin', tenant_id: 'tnt_abc' },
14
+ }),
15
+ }),
16
+ );
17
+ await mockRaw(page, '/api/v1/monitors', {
18
+ monitors: [
19
+ {
20
+ id: 'mon_1', entity_name: 'John Smith', entity_type: 'individual',
21
+ frequency: 'daily', status: 'active', created_at: '2026-01-01',
22
+ },
23
+ {
24
+ id: 'mon_2', entity_name: 'Acme Corp', entity_type: 'company',
25
+ frequency: 'weekly', status: 'paused', created_at: '2026-02-15',
26
+ },
27
+ ],
28
+ total: 2,
29
+ });
30
+ });
31
+
32
+ test('shows monitoring page with entities', async ({ page }) => {
33
+ await page.goto('/monitoring');
34
+ await expect(page.getByText(/monitor/i).first()).toBeVisible();
35
+ });
36
+
37
+ test('monitoring page loads without error', async ({ page }) => {
38
+ await page.goto('/monitoring');
39
+ await page.waitForLoadState('networkidle');
40
+ // No crash = page renders
41
+ const body = page.locator('body');
42
+ await expect(body).toBeVisible();
43
+ });
44
+ });
@@ -0,0 +1,56 @@
1
+ import { test, expect } from '@playwright/test';
2
+ import { setupAuth } from './auth-setup';
3
+ import { mockDashboard } from './mocks';
4
+
5
+ test.describe('Sidebar Navigation', () => {
6
+ test.beforeEach(async ({ page, isMobile }) => {
7
+ test.skip(!!isMobile, 'Sidebar nav labels hidden on mobile');
8
+ await setupAuth(page);
9
+ await mockDashboard(page);
10
+ // Mock all page APIs to avoid 404 flickers
11
+ await page.route('**/api/v1/**', route => {
12
+ if (!route.request().url().includes('auth/me') &&
13
+ !route.request().url().includes('analytics') &&
14
+ !route.request().url().includes('dashboard')) {
15
+ return route.fulfill({
16
+ status: 200, contentType: 'application/json',
17
+ body: JSON.stringify({ data: {} }),
18
+ });
19
+ }
20
+ return route.fallback();
21
+ });
22
+ });
23
+
24
+ test('renders all section titles', async ({ page }) => {
25
+ await page.goto('/dashboard');
26
+ await expect(page.getByText('Main')).toBeVisible();
27
+ await expect(page.getByText('Compliance')).toBeVisible();
28
+ await expect(page.getByText('System')).toBeVisible();
29
+ });
30
+
31
+ test('navigates to cases page', async ({ page }) => {
32
+ await page.goto('/dashboard');
33
+ await page.getByRole('link', { name: 'Cases' }).click();
34
+ await page.waitForURL('**/compliance/cases');
35
+ await expect(page.getByText('Case Management')).toBeVisible();
36
+ });
37
+
38
+ test('navigates to PEP screening', async ({ page }) => {
39
+ await page.goto('/dashboard');
40
+ await page.getByRole('link', { name: 'PEP Screening' }).click();
41
+ await page.waitForURL('**/compliance/pep');
42
+ await expect(page.getByRole('heading', { name: 'PEP Screening' })).toBeVisible();
43
+ });
44
+
45
+ test('navigates to risk assessment', async ({ page }) => {
46
+ await page.goto('/dashboard');
47
+ await page.getByRole('link', { name: 'Risk Assessment' }).click();
48
+ await page.waitForURL('**/compliance/risk');
49
+ });
50
+
51
+ test('navigates to analytics', async ({ page }) => {
52
+ await page.goto('/dashboard');
53
+ await page.getByRole('link', { name: 'Analytics' }).click();
54
+ await page.waitForURL('**/analytics');
55
+ });
56
+ });
@@ -0,0 +1,49 @@
1
+ import { test, expect } from './fixtures';
2
+
3
+ test.describe('Landing Page', () => {
4
+ test('renders hero section', async ({ page }) => {
5
+ await page.goto('/');
6
+ await expect(page.locator('body')).toBeVisible();
7
+ // Landing page should have a CTA
8
+ const cta = page.getByRole('link', { name: /start|try|demo|sign/i }).first();
9
+ if (await cta.isVisible()) {
10
+ await expect(cta).toBeEnabled();
11
+ }
12
+ });
13
+
14
+ test('navigation links work', async ({ page }) => {
15
+ await page.goto('/');
16
+ const links = page.getByRole('navigation').getByRole('link');
17
+ const count = await links.count();
18
+ expect(count).toBeGreaterThan(0);
19
+ });
20
+ });
21
+
22
+ test.describe('Login Flow', () => {
23
+ test('shows login form', async ({ page }) => {
24
+ await page.goto('/login');
25
+ await expect(page.locator('body')).toBeVisible();
26
+ });
27
+
28
+ test('shows signup form', async ({ page }) => {
29
+ await page.goto('/signup');
30
+ await expect(page.locator('body')).toBeVisible();
31
+ });
32
+
33
+ test('shows forgot password', async ({ page }) => {
34
+ await page.goto('/forgot-password');
35
+ await expect(page.locator('body')).toBeVisible();
36
+ });
37
+ });
38
+
39
+ test.describe('Legal Pages', () => {
40
+ test('terms of service loads', async ({ page }) => {
41
+ await page.goto('/terms');
42
+ await expect(page.getByText(/terms/i).first()).toBeVisible();
43
+ });
44
+
45
+ test('privacy policy loads', async ({ page }) => {
46
+ await page.goto('/privacy');
47
+ await expect(page.getByText(/privacy/i).first()).toBeVisible();
48
+ });
49
+ });
@@ -0,0 +1,40 @@
1
+ import { test, expect } from '@playwright/test';
2
+ import { setupAuth } from './auth-setup';
3
+ import { mockDashboard } from './mocks';
4
+
5
+ test.describe('Responsive layout', () => {
6
+ test.beforeEach(async ({ page }) => {
7
+ await setupAuth(page);
8
+ await mockDashboard(page);
9
+ });
10
+
11
+ test('desktop shows sidebar by default', async ({ page }) => {
12
+ await page.setViewportSize({ width: 1280, height: 800 });
13
+ await page.goto('/dashboard');
14
+ await expect(page.getByText('AMLIQ')).toBeVisible();
15
+ await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
16
+ });
17
+
18
+ test('mobile hides sidebar initially', async ({ page }) => {
19
+ await page.setViewportSize({ width: 375, height: 812 });
20
+ await page.goto('/dashboard');
21
+ // Sidebar should be off-screen (translated)
22
+ const sidebar = page.locator('div').filter({ hasText: 'AMLIQ' }).first();
23
+ await expect(sidebar).toBeDefined();
24
+ });
25
+
26
+ test('tablet viewport renders dashboard', async ({ page }) => {
27
+ await page.setViewportSize({ width: 768, height: 1024 });
28
+ await page.goto('/dashboard');
29
+ await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
30
+ await expect(page.getByText('Total Alerts')).toBeVisible();
31
+ });
32
+
33
+ test('landing page renders at all viewports', async ({ page }) => {
34
+ for (const width of [375, 768, 1024, 1440]) {
35
+ await page.setViewportSize({ width, height: 900 });
36
+ await page.goto('/');
37
+ await expect(page.locator('body')).toBeVisible();
38
+ }
39
+ });
40
+ });
@@ -0,0 +1,61 @@
1
+ import { test, expect } from '@playwright/test';
2
+ import { setupAuth } from './auth-setup';
3
+ import { mockAPI } from './mocks';
4
+
5
+ test.describe('Risk Assessment', () => {
6
+ test.beforeEach(async ({ page }) => {
7
+ await setupAuth(page);
8
+ });
9
+
10
+ test('shows risk assessment form', async ({ page }) => {
11
+ await page.goto('/compliance/risk');
12
+ await expect(page.getByRole('heading', { name: 'Risk Assessment' })).toBeVisible();
13
+ await expect(
14
+ page.getByRole('button', { name: 'Calculate Risk' }),
15
+ ).toBeVisible();
16
+ });
17
+
18
+ test('displays risk score after calculation', async ({ page }) => {
19
+ await mockAPI(page, '/api/v1/risk/score', {
20
+ composite_score: 0.85,
21
+ risk_level: 'critical',
22
+ factors: ['sanctions:90%', 'pep:80%'],
23
+ breakdown: { sanctions: 0.9, pep: 0.8, adverse_media: 0.5 },
24
+ });
25
+ await page.goto('/compliance/risk');
26
+ const entityInput = page.locator('input').first();
27
+ if (await entityInput.isVisible()) {
28
+ await entityInput.fill('ent_123');
29
+ }
30
+ await page.getByRole('button', { name: 'Calculate Risk' }).click();
31
+ });
32
+ });
33
+
34
+ test.describe('PEP Screening', () => {
35
+ test.beforeEach(async ({ page }) => {
36
+ await setupAuth(page);
37
+ });
38
+
39
+ test('shows PEP screening form', async ({ page }) => {
40
+ await page.goto('/compliance/pep');
41
+ await expect(page.getByRole('heading', { name: 'PEP Screening' })).toBeVisible();
42
+ await expect(
43
+ page.getByRole('button', { name: 'Screen' }),
44
+ ).toBeVisible();
45
+ });
46
+
47
+ test('shows result for known PEP', async ({ page }) => {
48
+ await mockAPI(page, '/api/v1/pep/screen', {
49
+ is_pep: true,
50
+ tier: 'Tier 1',
51
+ risk_weight: 1.0,
52
+ profile: { position: 'President', country: 'US', is_active: true },
53
+ });
54
+ await page.goto('/compliance/pep');
55
+ const input = page.locator('input').first();
56
+ if (await input.isVisible()) {
57
+ await input.fill('ent_1');
58
+ }
59
+ await page.getByRole('button', { name: 'Screen' }).click();
60
+ });
61
+ });
@@ -0,0 +1,76 @@
1
+ import { test, expect } from './fixtures';
2
+ import { mockAPI } from './mocks';
3
+
4
+ test.describe('Screening', () => {
5
+ test.beforeEach(async ({ page }) => {
6
+ await page.addInitScript(() => {
7
+ localStorage.setItem('amliq_token', 'fake.jwt.token');
8
+ });
9
+ await page.route('**/api/v1/auth/me', route =>
10
+ route.fulfill({
11
+ status: 200, contentType: 'application/json',
12
+ body: JSON.stringify({
13
+ data: { id: '1', email: 'a@b.com', role: 'admin', tenant_id: 'tnt_abc' },
14
+ }),
15
+ }),
16
+ );
17
+ });
18
+
19
+ test('shows screening form', async ({ page }) => {
20
+ await page.goto('/screen');
21
+ await expect(
22
+ page.getByRole('heading', { name: 'Screen Entity' }),
23
+ ).toBeVisible();
24
+ });
25
+
26
+ test('displays results after screening', async ({ page }) => {
27
+ await mockAPI(page, '/api/v1/screen', {
28
+ id: 'scr_1',
29
+ matches: [
30
+ {
31
+ listName: 'OFAC SDN', confidence: 0.92,
32
+ riskLevel: 'High', entityName: 'JOHN DOE',
33
+ layers: ['exact', 'fuzzy'],
34
+ },
35
+ ],
36
+ });
37
+ await page.goto('/screen');
38
+ const form = page.locator('form').first();
39
+ if (await form.isVisible()) {
40
+ const nameInput = page.getByPlaceholder(/first|name/i).first();
41
+ if (await nameInput.isVisible()) {
42
+ await nameInput.fill('John Doe');
43
+ }
44
+ }
45
+ });
46
+ });
47
+
48
+ test.describe('Alerts', () => {
49
+ test.beforeEach(async ({ page }) => {
50
+ await page.addInitScript(() => {
51
+ localStorage.setItem('amliq_token', 'fake.jwt.token');
52
+ });
53
+ await page.route('**/api/v1/auth/me', route =>
54
+ route.fulfill({
55
+ status: 200, contentType: 'application/json',
56
+ body: JSON.stringify({
57
+ data: { id: '1', email: 'a@b.com', role: 'admin', tenant_id: 'tnt_abc' },
58
+ }),
59
+ }),
60
+ );
61
+ await mockAPI(page, '/api/v1/alerts*', {
62
+ alerts: [
63
+ {
64
+ id: 'alt_1', entity_name: 'Suspect Corp',
65
+ status: 'pending', risk: 'High', created_at: '2025-03-01',
66
+ },
67
+ ],
68
+ total: 1,
69
+ });
70
+ });
71
+
72
+ test('shows alert queue', async ({ page }) => {
73
+ await page.goto('/alerts');
74
+ await expect(page.getByText('Alerts')).toBeVisible();
75
+ });
76
+ });
@@ -0,0 +1,53 @@
1
+ import { test, expect } from './fixtures';
2
+ import { mockRaw } from './mocks';
3
+
4
+ test.describe('Team Management', () => {
5
+ test.beforeEach(async ({ page }) => {
6
+ await page.addInitScript(() => {
7
+ localStorage.setItem('amliq_token', 'fake.jwt.token');
8
+ });
9
+ await page.route('**/api/v1/auth/me', route =>
10
+ route.fulfill({
11
+ status: 200, contentType: 'application/json',
12
+ body: JSON.stringify({
13
+ data: { id: '1', email: 'admin@test.com', role: 'admin', tenant_id: 'tnt_abc' },
14
+ }),
15
+ }),
16
+ );
17
+ await mockRaw(page, '/api/v1/team*', {
18
+ members: [
19
+ { id: 'u1', email: 'admin@test.com', role: 'admin' },
20
+ { id: 'u2', email: 'analyst@test.com', role: 'analyst' },
21
+ ],
22
+ });
23
+ });
24
+
25
+ test('shows team page', async ({ page }) => {
26
+ await page.goto('/team');
27
+ await expect(page.getByText(/team/i).first()).toBeVisible();
28
+ });
29
+ });
30
+
31
+ test.describe('Platform Admin', () => {
32
+ test.beforeEach(async ({ page }) => {
33
+ await page.addInitScript(() => {
34
+ localStorage.setItem('amliq_token', 'fake.jwt.token');
35
+ });
36
+ await page.route('**/api/v1/auth/me', route =>
37
+ route.fulfill({
38
+ status: 200, contentType: 'application/json',
39
+ body: JSON.stringify({
40
+ data: { id: '1', email: 'admin@test.com', role: 'admin', tenant_id: 'tnt_abc' },
41
+ }),
42
+ }),
43
+ );
44
+ });
45
+
46
+ test('shows platform overview', async ({ page }) => {
47
+ await mockRaw(page, '/api/v1/platform*', { tenants: 5, users: 20 });
48
+ await page.goto('/platform/overview');
49
+ await page.waitForLoadState('networkidle');
50
+ const body = page.locator('body');
51
+ await expect(body).toBeVisible();
52
+ });
53
+ });
package/index.html ADDED
@@ -0,0 +1,50 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
6
+ <meta name="description" content="Screen against OFAC, UN, EU, UK sanctions lists with 6-layer AI matching in under 50ms. Replace World-Check at 1/10th the cost.">
7
+ <meta name="keywords" content="AML screening, sanctions screening, OFAC screening API, KYC compliance, anti-money laundering, sanctions list screening, compliance software, World-Check alternative, PEP screening, CFT screening">
8
+ <meta name="robots" content="index, follow">
9
+ <meta name="theme-color" content="#00D4AA">
10
+ <meta name="apple-mobile-web-app-capable" content="yes">
11
+ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
12
+ <link rel="manifest" href="/manifest.json">
13
+ <link rel="apple-touch-icon" href="/logo.png">
14
+
15
+ <meta property="og:type" content="website">
16
+ <meta property="og:url" content="https://amliq.com">
17
+ <meta property="og:title" content="AMLIQ — AI-Powered Sanctions Screening for Financial Institutions">
18
+ <meta property="og:description" content="Screen against OFAC, UN, EU, UK sanctions lists with 6-layer AI matching in under 50ms. Replace World-Check at 1/10th the cost.">
19
+ <meta property="og:image" content="https://amliq.com/logo.png">
20
+
21
+ <meta name="twitter:card" content="summary_large_image">
22
+ <meta name="twitter:title" content="AMLIQ — AI-Powered Sanctions Screening for Financial Institutions">
23
+ <meta name="twitter:description" content="Screen against OFAC, UN, EU, UK sanctions lists with 6-layer AI matching in under 50ms. Replace World-Check at 1/10th the cost.">
24
+
25
+ <link rel="canonical" href="https://amliq.com">
26
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
27
+ <title>AMLIQ — AI-Powered Sanctions Screening for Financial Institutions</title>
28
+
29
+ <script type="application/ld+json">
30
+ {
31
+ "@context": "https://schema.org",
32
+ "@type": "Organization",
33
+ "name": "AMLIQ",
34
+ "url": "https://amliq.com",
35
+ "logo": "https://amliq.com/logo.png",
36
+ "description": "AI-powered AML/CFT sanctions screening platform for financial institutions",
37
+ "contactPoint": { "@type": "ContactPoint", "email": "support@amliq.com", "contactType": "customer support" }
38
+ }
39
+ </script>
40
+
41
+ <style>
42
+ html { background: #1C1C1E; color: #FFFFFF; }
43
+ body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui, sans-serif; }
44
+ </style>
45
+ </head>
46
+ <body>
47
+ <div id="root"></div>
48
+ <script type="module" src="/src/main.tsx"></script>
49
+ </body>
50
+ </html>