failproofai 0.0.11-beta.8 → 0.0.11

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 (239) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +1 -0
  3. package/.next/standalone/.next/build-manifest.json +6 -6
  4. package/.next/standalone/.next/prerender-manifest.json +3 -3
  5. package/.next/standalone/.next/required-server-files.json +1 -1
  6. package/.next/standalone/.next/routes-manifest.json +6 -0
  7. package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +3 -3
  8. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  9. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  10. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  13. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  14. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  15. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
  16. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  17. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  18. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +3 -3
  19. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  20. package/.next/standalone/.next/server/app/_not-found/page.js +2 -2
  21. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  22. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  23. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  24. package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
  25. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
  26. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  27. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
  28. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  29. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  30. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  31. package/.next/standalone/.next/server/app/api/audit/invite/route/app-paths-manifest.json +3 -0
  32. package/.next/standalone/.next/server/app/api/audit/invite/route/build-manifest.json +9 -0
  33. package/.next/standalone/.next/server/app/api/audit/invite/route/server-reference-manifest.json +4 -0
  34. package/.next/standalone/.next/server/app/api/audit/invite/route.js +7 -0
  35. package/.next/standalone/.next/server/app/api/audit/invite/route.js.map +5 -0
  36. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -0
  37. package/.next/standalone/.next/server/app/api/audit/invite/route_client-reference-manifest.js +3 -0
  38. package/.next/standalone/.next/server/app/api/audit/run/route.js +1 -1
  39. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/api/auth/login-request/route.js +1 -1
  41. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +2 -2
  43. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/api/auth/logout/route.js +2 -2
  45. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/api/auth/reminder/route.js +2 -2
  47. package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/api/auth/status/route.js +2 -2
  49. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  50. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  51. package/.next/standalone/.next/server/app/audit/page/build-manifest.json +3 -3
  52. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  53. package/.next/standalone/.next/server/app/audit/page.js +2 -2
  54. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  56. package/.next/standalone/.next/server/app/index.html +1 -1
  57. package/.next/standalone/.next/server/app/index.rsc +15 -15
  58. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  59. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
  60. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
  61. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
  62. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  63. package/.next/standalone/.next/server/app/page/build-manifest.json +3 -3
  64. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  65. package/.next/standalone/.next/server/app/page.js +2 -2
  66. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  67. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  68. package/.next/standalone/.next/server/app/policies/page/build-manifest.json +3 -3
  69. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
  70. package/.next/standalone/.next/server/app/policies/page.js +2 -2
  71. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  72. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  73. package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +3 -3
  74. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  75. package/.next/standalone/.next/server/app/project/[name]/page.js +3 -3
  76. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  77. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  78. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +3 -3
  79. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  80. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  81. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +3 -3
  82. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  83. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  84. package/.next/standalone/.next/server/app/projects/page/build-manifest.json +3 -3
  85. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  86. package/.next/standalone/.next/server/app/projects/page.js +3 -3
  87. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  88. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  89. package/.next/standalone/.next/server/app-paths-manifest.json +1 -0
  90. package/.next/standalone/.next/server/chunks/[externals]__1_g_b3t._.js +3 -0
  91. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0dwpg-h._.js +3 -0
  92. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0lnenda._.js +3 -0
  93. package/.next/standalone/.next/server/chunks/[root-of-the-server]__13i_sva._.js +3 -0
  94. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1_mqemn._.js +1 -1
  95. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_audit_invite_route_actions_0-2n5sy.js +3 -0
  96. package/.next/standalone/.next/server/chunks/node_modules_0-tu4ot._.js +3 -0
  97. package/.next/standalone/.next/server/chunks/node_modules_0ttxbz7._.js +3 -0
  98. package/.next/standalone/.next/server/chunks/node_modules_1bnh1y0._.js +3 -0
  99. package/.next/standalone/.next/server/chunks/node_modules_1epycqa._.js +3 -0
  100. package/.next/standalone/.next/server/chunks/node_modules_1wpdcgo._.js +3 -0
  101. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +3 -3
  102. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +1 -1
  103. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +1 -1
  104. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  105. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1d4gx_t._.js → [root-of-the-server]__00uwqi6._.js} +2 -2
  106. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0808sha._.js +4 -0
  107. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1cd25c7._.js → [root-of-the-server]__0e4-6d8._.js} +3 -3
  108. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ehe24g._.js +4 -0
  109. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1-scthx._.js → [root-of-the-server]__0f62vu9._.js} +2 -2
  110. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0g253ve._.js +4 -0
  111. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0l13qf2._.js → [root-of-the-server]__0k65l27._.js} +1 -1
  112. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__15i0juc._.js → [root-of-the-server]__0kjb_s4._.js} +2 -2
  113. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0vxf0_g._.js +4 -0
  114. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__12mcauo._.js +4 -0
  115. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0989_dx._.js → [root-of-the-server]__1e-x7j4._.js} +2 -2
  116. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1mt35_w._.js +1 -1
  117. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1pcxxwg._.js +2 -2
  118. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1uvfwgr._.js +4 -0
  119. package/.next/standalone/.next/server/chunks/ssr/_05whahf._.js +1 -1
  120. package/.next/standalone/.next/server/chunks/ssr/_0il3fl1._.js +3 -0
  121. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +49 -21
  122. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  123. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +2 -2
  124. package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_0ihmbv4.js +3 -0
  125. package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_1ao30b1.js +3 -0
  126. package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +1 -1
  127. package/.next/standalone/.next/server/middleware-build-manifest.js +6 -6
  128. package/.next/standalone/.next/server/pages/404.html +1 -1
  129. package/.next/standalone/.next/server/pages/500.html +1 -1
  130. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  131. package/.next/standalone/.next/server/server-reference-manifest.json +10 -10
  132. package/.next/standalone/.next/static/chunks/{0d49wc5zca0u1.js → 02fywjt0by40a.js} +1 -1
  133. package/.next/standalone/.next/static/chunks/0f7d7hnbh4djs.js +1 -0
  134. package/.next/standalone/.next/static/chunks/0h7auy7hzjyhw.js +1 -0
  135. package/.next/standalone/.next/static/chunks/0xdx2ehtbdoeg.js +1 -0
  136. package/.next/standalone/.next/static/chunks/{1nd1e30h8s_mc.js → 1-a5rvq67k7ed.js} +1 -1
  137. package/.next/standalone/.next/static/chunks/{1m2yj97j7f_km.js → 15csyj1_rf0-w.js} +1 -1
  138. package/.next/standalone/.next/static/chunks/1o0xa47736gi9.css +2 -0
  139. package/.next/standalone/.next/static/chunks/24cv31x607n7k.js +1 -0
  140. package/.next/standalone/.next/static/chunks/{3w8d8k_dca5rp.js → 2h0dkzyy0vocp.js} +1 -1
  141. package/.next/standalone/.next/static/chunks/2n_s8v1ae38_a.js +69 -0
  142. package/.next/standalone/.next/static/chunks/2y-jmvrjxz60x.js +6 -0
  143. package/.next/standalone/.next/static/chunks/{24z-bgbisv379.js → 3eik_d9qrvoft.js} +1 -1
  144. package/.next/standalone/.next/static/chunks/3i27c3hcriawq.css +1 -0
  145. package/.next/standalone/.next/static/chunks/{0j969hb6nujdf.js → 3v61675vr6jav.js} +1 -1
  146. package/.next/standalone/.next/static/chunks/3zkg2s2vzxc3d.js +1 -0
  147. package/.next/standalone/.next/static/chunks/{turbopack-00qy7zfa7m--m.js → turbopack-3lrm4f20fz89b.js} +1 -1
  148. package/.next/standalone/app/api/audit/invite/route.ts +192 -0
  149. package/.next/standalone/app/api/audit/run/route.ts +35 -0
  150. package/.next/standalone/app/api/auth/login-request/route.ts +2 -2
  151. package/.next/standalone/app/api/auth/login-verify/route.ts +10 -2
  152. package/.next/standalone/app/audit/_components/audit-dashboard.tsx +39 -63
  153. package/.next/standalone/app/audit/_components/audit-poster.tsx +326 -0
  154. package/.next/standalone/app/audit/_components/auth-dialog.tsx +23 -49
  155. package/.next/standalone/app/audit/_components/come-back-better-section.tsx +336 -0
  156. package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +187 -0
  157. package/.next/standalone/app/audit/_components/invite-dialog.tsx +230 -0
  158. package/.next/standalone/app/audit/_components/quirks-section.tsx +75 -0
  159. package/.next/standalone/app/audit/_components/share-templates.ts +63 -32
  160. package/.next/standalone/app/audit/_components/sigil.tsx +9 -66
  161. package/.next/standalone/app/audit/_components/strengths-section.tsx +20 -32
  162. package/.next/standalone/app/audit/audit-styles.css +778 -1786
  163. package/.next/standalone/app/components/sessions-list.tsx +77 -80
  164. package/.next/standalone/app/globals.css +241 -34
  165. package/.next/standalone/app/layout.tsx +1 -10
  166. package/.next/standalone/app/policies/hooks-client.tsx +45 -28
  167. package/.next/standalone/app/project/[name]/page.tsx +23 -79
  168. package/.next/standalone/app/projects/page.tsx +14 -23
  169. package/.next/standalone/assets/audit/poster-styles.css +1 -1
  170. package/.next/standalone/assets/audit/styles.css +11 -11
  171. package/.next/standalone/components/navbar.tsx +2 -37
  172. package/.next/standalone/components/reach-developers.tsx +10 -25
  173. package/.next/standalone/lib/auth/api-server-client.ts +28 -0
  174. package/.next/standalone/lib/client-telemetry.ts +4 -0
  175. package/.next/standalone/node_modules/@next/env/package.json +2 -2
  176. package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
  177. package/.next/standalone/node_modules/next/dist/compiled/next-server/pages-turbo.runtime.prod.js +1 -1
  178. package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +3 -3
  179. package/.next/standalone/node_modules/next/dist/server/config.js +1 -1
  180. package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-turbopack.js +2 -2
  181. package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-webpack.js +1 -1
  182. package/.next/standalone/node_modules/next/dist/server/lib/app-info-log.js +1 -1
  183. package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
  184. package/.next/standalone/node_modules/next/dist/shared/lib/errors/canary-only-config-error.js +1 -1
  185. package/.next/standalone/node_modules/next/dist/telemetry/anonymous-meta.js +1 -1
  186. package/.next/standalone/node_modules/next/dist/telemetry/events/swc-load-failure.js +1 -1
  187. package/.next/standalone/node_modules/next/dist/telemetry/events/version.js +2 -2
  188. package/.next/standalone/node_modules/next/package.json +15 -15
  189. package/.next/standalone/package.json +19 -14
  190. package/.next/standalone/server.js +1 -1
  191. package/README.md +2 -2
  192. package/bin/failproofai.mjs +24 -5
  193. package/dist/cli.mjs +2328 -381
  194. package/lib/auth/api-server-client.ts +28 -0
  195. package/lib/client-telemetry.ts +4 -0
  196. package/package.json +19 -14
  197. package/scripts/launch.ts +30 -4
  198. package/scripts/postinstall.mjs +10 -1
  199. package/scripts/skew-log-filter.ts +46 -0
  200. package/scripts/validate-mdx.ts +139 -0
  201. package/src/audit/cli.ts +330 -0
  202. package/src/audit/open-browser.ts +69 -0
  203. package/src/audit/social-proof.ts +34 -0
  204. package/src/auth/cli.ts +16 -13
  205. package/.next/standalone/.next/server/chunks/[root-of-the-server]__07tgnzi._.js +0 -3
  206. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0oeun7z._.js +0 -3
  207. package/.next/standalone/.next/server/chunks/[root-of-the-server]__12pit4m._.js +0 -3
  208. package/.next/standalone/.next/server/chunks/[root-of-the-server]__13ra2jq._.js +0 -3
  209. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1b9z5-i._.js +0 -3
  210. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ixjiy8._.js +0 -3
  211. package/.next/standalone/.next/server/chunks/_1-1804f._.js +0 -3
  212. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__00jkjmt._.js +0 -4
  213. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013du6r._.js +0 -4
  214. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e85wxv._.js +0 -4
  215. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0gfxvb1._.js +0 -3
  216. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1hlrq6y._.js +0 -4
  217. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ihxdo5._.js +0 -4
  218. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1vvfde2._.js +0 -4
  219. package/.next/standalone/.next/server/chunks/ssr/node_modules_html2canvas_dist_html2canvas_esm_1k58rb_.js +0 -3
  220. package/.next/standalone/.next/server/chunks/ssr/node_modules_html2canvas_dist_html2canvas_esm_1n-0xws.js +0 -3
  221. package/.next/standalone/.next/static/chunks/09ueq8s1as8xs.css +0 -2
  222. package/.next/standalone/.next/static/chunks/0qassxjx1ef04.js +0 -1
  223. package/.next/standalone/.next/static/chunks/0qxb5czqxe-vu.js +0 -1
  224. package/.next/standalone/.next/static/chunks/1dh06515j265n.js +0 -41
  225. package/.next/standalone/.next/static/chunks/29gs4efgi3hme.js +0 -6
  226. package/.next/standalone/.next/static/chunks/2mni177pnjx6u.js +0 -1
  227. package/.next/standalone/.next/static/chunks/2so39wg7mjbi7.js +0 -1
  228. package/.next/standalone/.next/static/chunks/3gti1qdk5epqn.js +0 -1
  229. package/.next/standalone/.next/static/chunks/3wycox197ouus.css +0 -1
  230. package/.next/standalone/app/audit/_components/findings-section.tsx +0 -135
  231. package/.next/standalone/app/audit/_components/identity-section.tsx +0 -126
  232. package/.next/standalone/app/audit/_components/policies-section.tsx +0 -194
  233. package/.next/standalone/app/audit/_components/return-section.tsx +0 -416
  234. package/.next/standalone/app/audit/_components/score-section.tsx +0 -179
  235. package/.next/standalone/app/audit/_components/share-dock.tsx +0 -265
  236. package/.next/standalone/app/audit/_components/show-off-cta.tsx +0 -135
  237. /package/.next/standalone/.next/static/{CVv2A0hMd24t0c0x3V-W_ → P_MIRSeoE296wkbE-Icin}/_buildManifest.js +0 -0
  238. /package/.next/standalone/.next/static/{CVv2A0hMd24t0c0x3V-W_ → P_MIRSeoE296wkbE-Icin}/_clientMiddlewareManifest.js +0 -0
  239. /package/.next/standalone/.next/static/{CVv2A0hMd24t0c0x3V-W_ → P_MIRSeoE296wkbE-Icin}/_ssgManifest.js +0 -0
@@ -0,0 +1 @@
1
+ (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,66459,e=>{"use strict";let t;var r=e.i(47167);let n=(t=0,()=>(t+=1,`u${`0000${(1679616*Math.random()|0).toString(36)}`.slice(-4)}${t}`));function l(e){let t=[];for(let r=0,n=e.length;r<n;r++)t.push(e[r]);return t}let i=null;function a(e={}){return i||(i=e.includeStyleProperties?e.includeStyleProperties:l(window.getComputedStyle(document.documentElement)))}function o(e,t){let r=(e.ownerDocument.defaultView||window).getComputedStyle(e).getPropertyValue(t);return r?parseFloat(r.replace("px","")):0}function c(e,t={}){let r,n,l,i;return{width:t.width||(r=o(e,"border-left-width"),n=o(e,"border-right-width"),e.clientWidth+r+n),height:t.height||(l=o(e,"border-top-width"),i=o(e,"border-bottom-width"),e.clientHeight+l+i)}}function s(e){return new Promise((t,r)=>{let n=new Image;n.onload=()=>{n.decode().then(()=>{requestAnimationFrame(()=>t(n))})},n.onerror=r,n.crossOrigin="anonymous",n.decoding="async",n.src=e})}async function u(e){return Promise.resolve().then(()=>new XMLSerializer().serializeToString(e)).then(encodeURIComponent).then(e=>`data:image/svg+xml;charset=utf-8,${e}`)}async function h(e,t,r){let n="http://www.w3.org/2000/svg",l=document.createElementNS(n,"svg"),i=document.createElementNS(n,"foreignObject");return l.setAttribute("width",`${t}`),l.setAttribute("height",`${r}`),l.setAttribute("viewBox",`0 0 ${t} ${r}`),i.setAttribute("width","100%"),i.setAttribute("height","100%"),i.setAttribute("x","0"),i.setAttribute("y","0"),i.setAttribute("externalResourcesRequired","true"),l.appendChild(i),i.appendChild(e),u(l)}let d=(e,t)=>{if(e instanceof t)return!0;let r=Object.getPrototypeOf(e);return null!==r&&(r.constructor.name===t.name||d(r,t))};function f(e,t,r,l){let i,o,c,s=window.getComputedStyle(e,r),u=s.getPropertyValue("content");if(""===u||"none"===u)return;let h=n();try{t.className=`${t.className} ${h}`}catch(e){return}let d=document.createElement("style");d.appendChild((i=`.${h}:${r}`,c=s.cssText?(o=s.getPropertyValue("content"),`${s.cssText} content: '${o.replace(/'|"/g,"")}';`):a(l).map(e=>{let t=s.getPropertyValue(e),r=s.getPropertyPriority(e);return`${e}: ${t}${r?" !important":""};`}).join(" "),document.createTextNode(`${i}{${c}}`))),t.appendChild(d)}let m="application/font-woff",g="image/jpeg",p={woff:m,woff2:m,ttf:"application/font-truetype",eot:"application/vnd.ms-fontobject",png:"image/png",jpg:g,jpeg:g,gif:"image/gif",tiff:"image/tiff",svg:"image/svg+xml",webp:"image/webp"};function y(e){let t;return p[((t=/\.([^./]*?)$/g.exec(e))?t[1]:"").toLowerCase()]||""}function w(e){return -1!==e.search(/^(data:)/)}function b(e,t){return`data:${t};base64,${e}`}async function S(e,t,r){let n=await fetch(e,t);if(404===n.status)throw Error(`Resource "${n.url}" not found`);let l=await n.blob();return new Promise((e,t)=>{let i=new FileReader;i.onerror=t,i.onloadend=()=>{try{e(r({res:n,result:i.result}))}catch(e){t(e)}},i.readAsDataURL(l)})}let E={};async function x(e,t,r){var n,l,i;let a,o,c=(n=e,l=t,i=r.includeQueryParams,o=n.replace(/\?.*/,""),i&&(o=n),/ttf|otf|eot|woff2?/i.test(o)&&(o=o.replace(/.*\//,"")),l?`[${l}]${o}`:o);if(null!=E[c])return E[c];r.cacheBust&&(e+=(/\?/.test(e)?"&":"?")+new Date().getTime());try{let n=await S(e,r.fetchRequestInit,({res:e,result:r})=>(t||(t=e.headers.get("Content-Type")||""),r.split(/,/)[1]));a=b(n,t)}catch(n){a=r.imagePlaceholder||"";let t=`Failed to fetch resource: ${e}`;n&&(t="string"==typeof n?n:n.message),t&&console.warn(t)}return E[c]=a,a}async function $(e){let t=e.toDataURL();return"data:,"===t?e.cloneNode(!1):s(t)}async function v(e,t){if(e.currentSrc){let t=document.createElement("canvas"),r=t.getContext("2d");return t.width=e.clientWidth,t.height=e.clientHeight,null==r||r.drawImage(e,0,0,t.width,t.height),s(t.toDataURL())}let r=e.poster,n=y(r);return s(await x(r,n,t))}async function C(e,t){var r;try{if(null==(r=null==e?void 0:e.contentDocument)?void 0:r.body)return await N(e.contentDocument.body,t,!0)}catch(e){}return e.cloneNode(!1)}async function P(e,t){return d(e,HTMLCanvasElement)?$(e):d(e,HTMLVideoElement)?v(e,t):d(e,HTMLIFrameElement)?C(e,t):e.cloneNode(R(e))}let R=e=>null!=e.tagName&&"SVG"===e.tagName.toUpperCase();async function T(e,t,r){var n,i;if(R(t))return t;let a=[];return 0===(a=null!=e.tagName&&"SLOT"===e.tagName.toUpperCase()&&e.assignedNodes?l(e.assignedNodes()):d(e,HTMLIFrameElement)&&(null==(n=e.contentDocument)?void 0:n.body)?l(e.contentDocument.body.childNodes):l((null!=(i=e.shadowRoot)?i:e).childNodes)).length||d(e,HTMLVideoElement)||await a.reduce((e,n)=>e.then(()=>N(n,r)).then(e=>{e&&t.appendChild(e)}),Promise.resolve()),t}async function A(e,t){let r=e.querySelectorAll?e.querySelectorAll("use"):[];if(0===r.length)return e;let n={};for(let l=0;l<r.length;l++){let i=r[l].getAttribute("xlink:href");if(i){let r=e.querySelector(i),l=document.querySelector(i);r||!l||n[i]||(n[i]=await N(l,t,!0))}}let l=Object.values(n);if(l.length){let t="http://www.w3.org/1999/xhtml",r=document.createElementNS(t,"svg");r.setAttribute("xmlns",t),r.style.position="absolute",r.style.width="0",r.style.height="0",r.style.overflow="hidden",r.style.display="none";let n=document.createElementNS(t,"defs");r.appendChild(n);for(let e=0;e<l.length;e++)n.appendChild(l[e]);e.appendChild(r)}return e}async function N(e,t,r){return r||!t.filter||t.filter(e)?Promise.resolve(e).then(e=>P(e,t)).then(r=>T(e,r,t)).then(r=>(function(e,t,r){if(d(t,Element)&&(!function(e,t,r){let n=t.style;if(!n)return;let l=window.getComputedStyle(e);l.cssText?(n.cssText=l.cssText,n.transformOrigin=l.transformOrigin):a(r).forEach(r=>{let i=l.getPropertyValue(r);if("font-size"===r&&i.endsWith("px")){let e=Math.floor(parseFloat(i.substring(0,i.length-2)))-.1;i=`${e}px`}d(e,HTMLIFrameElement)&&"display"===r&&"inline"===i&&(i="block"),"d"===r&&t.getAttribute("d")&&(i=`path(${t.getAttribute("d")})`),n.setProperty(r,i,l.getPropertyPriority(r))})}(e,t,r),f(e,t,":before",r),f(e,t,":after",r),d(e,HTMLTextAreaElement)&&(t.innerHTML=e.value),d(e,HTMLInputElement)&&t.setAttribute("value",e.value),d(e,HTMLSelectElement))){let r=Array.from(t.children).find(t=>e.value===t.getAttribute("value"));r&&r.setAttribute("selected","")}return t})(e,r,t)).then(e=>A(e,t)):null}let L=/url\((['"]?)([^'"]+?)\1\)/g,k=/url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g,I=/src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g;async function H(e,t,r,n,l){try{let i,a,o=r?function(e,t){if(e.match(/^[a-z]+:\/\//i))return e;if(e.match(/^\/\//))return window.location.protocol+e;if(e.match(/^[a-z]+:/i))return e;let r=document.implementation.createHTMLDocument(),n=r.createElement("base"),l=r.createElement("a");return r.head.appendChild(n),r.body.appendChild(l),t&&(n.href=t),l.href=e,l.href}(t,r):t,c=y(t);if(l){let e=await l(o);i=b(e,c)}else i=await x(o,c,n);return e.replace((a=t.replace(/([.*+?^${}()|\[\]\/\\])/g,"\\$1"),RegExp(`(url\\(['"]?)(${a})(['"]?\\))`,"g")),`$1${i}$3`)}catch(e){}return e}function M(e){return -1!==e.search(L)}async function V(e,t,r){let n;if(!M(e))return e;let l=function(e,{preferredFontFormat:t}){return t?e.replace(I,e=>{for(;;){let[r,,n]=k.exec(e)||[];if(!n)return"";if(n===t)return`src: ${r};`}}):e}(e,r);return(n=[],l.replace(L,(e,t,r)=>(n.push(r),e)),n.filter(e=>!w(e))).reduce((e,n)=>e.then(e=>H(e,n,t,r)),Promise.resolve(l))}async function D(e,t,r){var n;let l=null==(n=t.style)?void 0:n.getPropertyValue(e);if(l){let n=await V(l,null,r);return t.style.setProperty(e,n,t.style.getPropertyPriority(e)),!0}return!1}async function F(e,t){await D("background",e,t)||await D("background-image",e,t),await D("mask",e,t)||await D("-webkit-mask",e,t)||await D("mask-image",e,t)||await D("-webkit-mask-image",e,t)}async function O(e,t){let r=d(e,HTMLImageElement);if(!(r&&!w(e.src))&&!(d(e,SVGImageElement)&&!w(e.href.baseVal)))return;let n=r?e.src:e.href.baseVal,l=await x(n,y(n),t);await new Promise((n,i)=>{e.onload=n,e.onerror=t.onImageErrorHandler?(...e)=>{try{n(t.onImageErrorHandler(...e))}catch(e){i(e)}}:i,e.decode&&(e.decode=n),"lazy"===e.loading&&(e.loading="eager"),r?(e.srcset="",e.src=l):e.href.baseVal=l})}async function U(e,t){let r=l(e.childNodes).map(e=>q(e,t));await Promise.all(r).then(()=>e)}async function q(e,t){d(e,Element)&&(await F(e,t),await O(e,t),await U(e,t))}let j={};async function B(e){let t=j[e];if(null!=t)return t;let r=await fetch(e);return t={url:e,cssText:await r.text()},j[e]=t,t}async function z(e,t){let r=e.cssText,n=/url\(["']?([^"')]+)["']?\)/g;return Promise.all((r.match(/url\([^)]+\)/g)||[]).map(async l=>{let i=l.replace(n,"$1");return i.startsWith("https://")||(i=new URL(i,e.url).href),S(i,t.fetchRequestInit,({result:e})=>(r=r.replace(l,`url(${e})`),[l,e]))})).then(()=>r)}function W(e){if(null==e)return[];let t=[],r=e.replace(/(\/\*[\s\S]*?\*\/)/gi,""),n=RegExp("((@.*?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})","gi");for(;;){let e=n.exec(r);if(null===e)break;t.push(e[0])}r=r.replace(n,"");let l=/@import[\s\S]*?url\([^)]*\)[\s\S]*?;/gi,i=RegExp("((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})","gi");for(;;){let e=l.exec(r);if(null===e){if(null===(e=i.exec(r)))break;l.lastIndex=i.lastIndex}else i.lastIndex=l.lastIndex;t.push(e[0])}return t}async function _(e,t){let r=[],n=[];return e.forEach(r=>{if("cssRules"in r)try{l(r.cssRules||[]).forEach((e,l)=>{if(e.type===CSSRule.IMPORT_RULE){let i=l+1,a=e.href,o=B(a).then(e=>z(e,t)).then(e=>W(e).forEach(e=>{try{r.insertRule(e,e.startsWith("@import")?i+=1:r.cssRules.length)}catch(t){console.error("Error inserting rule from remote css",{rule:e,error:t})}})).catch(e=>{console.error("Error loading remote css",e.toString())});n.push(o)}})}catch(i){let l=e.find(e=>null==e.href)||document.styleSheets[0];null!=r.href&&n.push(B(r.href).then(e=>z(e,t)).then(e=>W(e).forEach(e=>{l.insertRule(e,l.cssRules.length)})).catch(e=>{console.error("Error loading remote stylesheet",e)})),console.error("Error inlining remote css file",i)}}),Promise.all(n).then(()=>(e.forEach(e=>{if("cssRules"in e)try{l(e.cssRules||[]).forEach(e=>{r.push(e)})}catch(t){console.error(`Error while reading CSS rules from ${e.href}`,t)}}),r))}async function G(e,t){if(null==e.ownerDocument)throw Error("Provided element is not within a Document");let r=l(e.ownerDocument.styleSheets);return(await _(r,t)).filter(e=>e.type===CSSRule.FONT_FACE_RULE).filter(e=>M(e.style.getPropertyValue("src")))}function K(e){return e.trim().replace(/["']/g,"")}async function Q(e,t){let r,n=await G(e,t),l=(r=new Set,!function e(t){(t.style.fontFamily||getComputedStyle(t).fontFamily).split(",").forEach(e=>{r.add(K(e))}),Array.from(t.children).forEach(t=>{t instanceof HTMLElement&&e(t)})}(e),r);return(await Promise.all(n.filter(e=>l.has(K(e.style.fontFamily))).map(e=>{let r=e.parentStyleSheet?e.parentStyleSheet.href:null;return V(e.cssText,r,t)}))).join("\n")}async function X(e,t){let r=null!=t.fontEmbedCSS?t.fontEmbedCSS:t.skipFonts?null:await Q(e,t);if(r){let t=document.createElement("style"),n=document.createTextNode(r);t.appendChild(n),e.firstChild?e.insertBefore(t,e.firstChild):e.appendChild(t)}}async function J(e,t={}){let{width:r,height:n}=c(e,t),l=await N(e,t,!0);return await X(l,t),await q(l,t),!function(e,t){let{style:r}=e;t.backgroundColor&&(r.backgroundColor=t.backgroundColor),t.width&&(r.width=`${t.width}px`),t.height&&(r.height=`${t.height}px`);let n=t.style;null!=n&&Object.keys(n).forEach(e=>{r[e]=n[e]})}(l,t),await h(l,r,n)}async function Y(e,t={}){let{width:n,height:l}=c(e,t),i=await J(e,t),a=await s(i),o=document.createElement("canvas"),u=o.getContext("2d"),h=t.pixelRatio||function(){let e,t;try{t=r.default}catch(e){}let n=t&&t.env?t.env.devicePixelRatio:null;return n&&Number.isNaN(e=parseInt(n,10))&&(e=1),e||window.devicePixelRatio||1}(),d=t.canvasWidth||n,f=t.canvasHeight||l;return o.width=d*h,o.height=f*h,!t.skipAutoScale&&(o.width>16384||o.height>16384)&&(o.width>16384&&o.height>16384?o.width>o.height?(o.height*=16384/o.width,o.width=16384):(o.width*=16384/o.height,o.height=16384):o.width>16384?(o.height*=16384/o.width,o.width=16384):(o.width*=16384/o.height,o.height=16384)),o.style.width=`${d}`,o.style.height=`${f}`,t.backgroundColor&&(u.fillStyle=t.backgroundColor,u.fillRect(0,0,o.width,o.height)),u.drawImage(a,0,0,o.width,o.height),o}async function Z(e,t={}){let r=await Y(e,t);return await function(e,t={}){return new Promise(e.toBlob?r=>{e.toBlob(r,t.type?t.type:"image/png",t.quality?t.quality:1)}:r=>{let n=window.atob(e.toDataURL(t.type?t.type:void 0,t.quality?t.quality:void 0).split(",")[1]),l=n.length,i=new Uint8Array(l);for(let e=0;e<l;e+=1)i[e]=n.charCodeAt(e);r(new Blob([i],{type:t.type?t.type:"image/png"}))})}(r)}e.s(["toBlob",0,Z],66459)}]);
@@ -1 +1 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,{otherChunks:["static/chunks/0zbxssxh53n-3.js","static/chunks/1__i9af9g78vd.js","static/chunks/03fmihek9n986.js","static/chunks/3w8d8k_dca5rp.js","static/chunks/13f1kmjea-0md.js"],runtimeModuleIds:[94553]}]),(()=>{let e;if(!Array.isArray(globalThis.TURBOPACK))return;let t="/_next/",r=function(){if(null!=self.TURBOPACK_ASSET_SUFFIX)return self.TURBOPACK_ASSET_SUFFIX;let e=document?.currentScript?.getAttribute?.("src")??"",t=e.indexOf("?");return t>=0?e.slice(t):""}(),n=["NEXT_DEPLOYMENT_ID","NEXT_CLIENT_ASSET_SUFFIX"];var o,i=((o=i||{})[o.Runtime=0]="Runtime",o[o.Parent=1]="Parent",o[o.Update=2]="Update",o);let l=new WeakMap;function s(e,t){this.m=e,this.e=t}let u=s.prototype,a=Object.prototype.hasOwnProperty,c="u">typeof Symbol&&Symbol.toStringTag;function f(e,t,r){a.call(e,t)||Object.defineProperty(e,t,r)}function p(e,t){let r=e[t];return r||(r=h(t),e[t]=r),r}function h(e){return{exports:{},error:void 0,id:e,namespaceObject:void 0}}function d(e,t){f(e,"__esModule",{value:!0}),c&&f(e,c,{value:"Module"});let r=0;for(;r<t.length;){let n=t[r++],o=t[r++];if("number"==typeof o)if(0===o)f(e,n,{value:t[r++],enumerable:!0,writable:!1});else throw Error(`unexpected tag: ${o}`);else"function"==typeof t[r]?f(e,n,{get:o,set:t[r++],enumerable:!0}):f(e,n,{get:o,enumerable:!0})}Object.seal(e)}function m(e,t){(null!=t?p(this.c,t):this.m).exports=e}u.s=function(e,t){let r,n;null!=t?n=(r=p(this.c,t)).exports:(r=this.m,n=this.e),r.namespaceObject=n,d(n,e)},u.j=function(e,t){var r,n;let o,i,s;null!=t?i=(o=p(this.c,t)).exports:(o=this.m,i=this.e);let u=(r=o,n=i,(s=l.get(r))||(l.set(r,s=[]),r.exports=r.namespaceObject=new Proxy(n,{get(e,t){if(a.call(e,t)||"default"===t||"__esModule"===t)return Reflect.get(e,t);for(let e of s){let r=Reflect.get(e,t);if(void 0!==r)return r}},ownKeys(e){let t=Reflect.ownKeys(e);for(let e of s)for(let r of Reflect.ownKeys(e))"default"===r||t.includes(r)||t.push(r);return t}})),s);"object"==typeof e&&null!==e&&u.push(e)},u.v=m,u.n=function(e,t){let r;(r=null!=t?p(this.c,t):this.m).exports=r.namespaceObject=e};let b=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,y=[null,b({}),b([]),b(b)];function g(e,t,r){let n=[],o=-1;for(let t=e;("object"==typeof t||"function"==typeof t)&&!y.includes(t);t=b(t))for(let r of Object.getOwnPropertyNames(t))n.push(r,function(e,t){return()=>e[t]}(e,r)),-1===o&&"default"===r&&(o=n.length-1);return r&&o>=0||(o>=0?n.splice(o,1,0,e):n.push("default",0,e)),d(t,n),t}function O(e){let t=B(e,this.m);if(t.namespaceObject)return t.namespaceObject;let r=t.exports;return t.namespaceObject=g(r,"function"==typeof r?function(...e){return r.apply(this,e)}:Object.create(null),r&&r.__esModule)}function w(e){let t=e.indexOf("#");-1!==t&&(e=e.substring(0,t));let r=e.indexOf("?");return -1!==r&&(e=e.substring(0,r)),e}function k(){let e,t;return{promise:new Promise((r,n)=>{t=n,e=r}),resolve:e,reject:t}}u.i=O,u.A=function(e){return this.r(e)(O.bind(this))},u.t="function"==typeof require?require:function(){throw Error("Unexpected use of runtime require")},u.r=function(e){return B(e,this.m).exports},u.f=function(e){function t(t){if(t=w(t),a.call(e,t))return e[t].module();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r}return t.keys=()=>Object.keys(e),t.resolve=t=>{if(t=w(t),a.call(e,t))return e[t].id();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r},t.import=async e=>await t(e),t};let j=Symbol("turbopack queues"),U=Symbol("turbopack exports"),v=Symbol("turbopack error");function C(e){e&&1!==e.status&&(e.status=1,e.forEach(e=>e.queueCount--),e.forEach(e=>e.queueCount--?e.queueCount++:e()))}u.a=function(e,t){let r=this.m,n=t?Object.assign([],{status:-1}):void 0,o=new Set,{resolve:i,reject:l,promise:s}=k(),u=Object.assign(s,{[U]:r.exports,[j]:e=>{n&&e(n),o.forEach(e),u.catch(()=>{})}}),a={get:()=>u,set(e){e!==u&&(u[U]=e)}};Object.defineProperty(r,"exports",a),Object.defineProperty(r,"namespaceObject",a),e(function(e){let t=e.map(e=>{if(null!==e&&"object"==typeof e){if(j in e)return e;if(null!=e&&"object"==typeof e&&"then"in e&&"function"==typeof e.then){let t=Object.assign([],{status:0}),r={[U]:{},[j]:e=>e(t)};return e.then(e=>{r[U]=e,C(t)},e=>{r[v]=e,C(t)}),r}}return{[U]:e,[j]:()=>{}}}),r=()=>t.map(e=>{if(e[v])throw e[v];return e[U]}),{promise:i,resolve:l}=k(),s=Object.assign(()=>l(r),{queueCount:0});function u(e){e!==n&&!o.has(e)&&(o.add(e),e&&0===e.status&&(s.queueCount++,e.push(s)))}return t.map(e=>e[j](u)),s.queueCount?i:r()},function(e){e?l(u[v]=e):i(u[U]),C(n)}),n&&-1===n.status&&(n.status=0)};let P=function(e){let t=new URL(e,"x:/"),r={};for(let e in t)r[e]=t[e];for(let t in r.href=e,r.pathname=e.replace(/[?#].*/,""),r.origin=r.protocol="",r.toString=r.toJSON=(...t)=>e,r)Object.defineProperty(this,t,{enumerable:!0,configurable:!0,value:r[t]})};function R(e,t){throw Error(`Invariant: ${t(e)}`)}P.prototype=URL.prototype,u.U=P,u.z=function(e){throw Error("dynamic usage of require is not supported")},u.g=globalThis;let S=s.prototype,_=new Map;u.M=_;let $=new Map,E=new Map;async function T(e,t,r){let n;if("string"==typeof r)return M(e,t,N(r));let o=r.included||[],i=o.map(e=>!!_.has(e)||$.get(e));if(i.length>0&&i.every(e=>e))return void await Promise.all(i);let l=r.moduleChunks||[],s=l.map(e=>E.get(e)).filter(e=>e);if(s.length>0){if(s.length===l.length)return void await Promise.all(s);let r=new Set;for(let e of l)E.has(e)||r.add(e);for(let n of r){let r=M(e,t,N(n));E.set(n,r),s.push(r)}n=Promise.all(s)}else{for(let o of(n=M(e,t,N(r.path)),l))E.has(o)||E.set(o,n)}for(let e of o)$.has(e)||$.set(e,n);await n}S.l=function(e){return T(i.Parent,this.m.id,e)};let A=Promise.resolve(void 0),x=new WeakMap;function M(t,r,n){let o=e.loadChunkCached(t,n),l=x.get(o);if(void 0===l){let e=x.set.bind(x,o,A);l=o.then(e).catch(e=>{let o;switch(t){case i.Runtime:o=`as a runtime dependency of chunk ${r}`;break;case i.Parent:o=`from module ${r}`;break;case i.Update:o="from an HMR update";break;default:R(t,e=>`Unknown source type: ${e}`)}let l=Error(`Failed to load chunk ${n} ${o}${e?`: ${e}`:""}`,e?{cause:e}:void 0);throw l.name="ChunkLoadError",l}),x.set(o,l)}return l}function N(e){return`${t}${e.split("/").map(e=>encodeURIComponent(e)).join("/")}${r}`}S.L=function(e){return M(i.Parent,this.m.id,e)},S.R=function(e){let t=this.r(e);return t?.default??t},S.P=function(e){return`/ROOT/${e??""}`},S.q=function(e,t){m.call(this,`${e}${r}`,t)},S.b=function(e,t,o,i){let l="SharedWorker"===e.name,s=[o.map(e=>N(e)).reverse(),r];for(let e of n)s.push(globalThis[e]);let u=new URL(N(t),location.origin),a=JSON.stringify(s);return l?u.searchParams.set("params",a):u.hash="#params="+encodeURIComponent(a),new e(u,i?{...i,type:void 0}:void 0)};let K=/\.js(?:\?[^#]*)?(?:#.*)?$/,q=/\.css(?:\?[^#]*)?(?:#.*)?$/;function L(e){return q.test(e)}u.w=function(t,r,n){return e.loadWebAssembly(i.Parent,this.m.id,t,r,n)},u.u=function(t,r){return e.loadWebAssemblyModule(i.Parent,this.m.id,t,r)};let I={};u.c=I;let B=(e,t)=>{let r=I[e];if(r){if(r.error)throw r.error;return r}return W(e,i.Parent,t.id)};function W(e,t,r){let n=_.get(e);if("function"!=typeof n)throw Error(function(e,t,r){let n;switch(t){case 0:n=`as a runtime entry of chunk ${r}`;break;case 1:n=`because it was required from module ${r}`;break;case 2:n="because of an HMR update";break;default:R(t,e=>`Unknown source type: ${e}`)}return`Module ${e} was instantiated ${n}, but the module factory is not available.`}(e,t,r));let o=h(e),i=o.exports;I[e]=o;let l=new s(o,i);try{n(l,o,i)}catch(e){throw o.error=e,e}return o.namespaceObject&&o.exports!==o.namespaceObject&&g(o.exports,o.namespaceObject),o}function F(t){let r,n=function(e){if("string"==typeof e)return e;if(e)return{src:e.getAttribute("src")};if("u">typeof TURBOPACK_NEXT_CHUNK_URLS)return{src:TURBOPACK_NEXT_CHUNK_URLS.pop()};throw Error("chunk path empty but not in a worker")}(t[0]);return 2===t.length?r=t[1]:(r=void 0,!function(e,t){let r=1;for(;r<e.length;){let n,o=r+1;for(;o<e.length&&"function"!=typeof e[o];)o++;if(o===e.length)throw Error("malformed chunk format, expected a factory function");let i=e[o];for(let i=r;i<o;i++){let r=e[i],o=t.get(r);if(o){n=o;break}}let l=n??i,s=!1;for(let n=r;n<o;n++){let r=e[n];t.has(r)||(s||(l===i&&Object.defineProperty(i,"name",{value:"module evaluation"}),s=!0),t.set(r,l))}r=o+1}}(t,_)),e.registerChunk(n,r)}let X=new Map;function D(e){let t=X.get(e);if(!t){let r,n;t={resolved:!1,loadingStarted:!1,promise:new Promise((e,t)=>{r=e,n=t}),resolve:()=>{t.resolved=!0,r()},reject:n},X.set(e,t)}return t}e={async registerChunk(e,r){let n=function(e){if("string"==typeof e)return e;let r=decodeURIComponent(e.src.replace(/[?#].*$/,""));return r.startsWith(t)?r.slice(t.length):r}(e);if(D("string"==typeof e?N(e):e.src).resolve(),null!=r){for(let e of r.otherChunks)D(N("string"==typeof e?e:e.path));if(await Promise.all(r.otherChunks.map(e=>T(i.Runtime,n,e))),r.runtimeModuleIds.length>0)for(let e of r.runtimeModuleIds)!function(e,t){let r=I[t];if(r){if(r.error)throw r.error;return}W(t,i.Runtime,e)}(n,e)}},loadChunkCached:(e,t)=>(function(e,t){let r=D(t);if(r.loadingStarted)return r.promise;if(e===i.Runtime)return r.loadingStarted=!0,L(t)&&r.resolve(),r.promise;if("function"==typeof importScripts)if(L(t));else if(K.test(t))self.TURBOPACK_NEXT_CHUNK_URLS.push(t),importScripts(t);else throw Error(`can't infer type of chunk from URL ${t} in worker`);else{let e=decodeURI(t);if(L(t))if(document.querySelectorAll(`link[rel=stylesheet][href="${t}"],link[rel=stylesheet][href^="${t}?"],link[rel=stylesheet][href="${e}"],link[rel=stylesheet][href^="${e}?"]`).length>0)r.resolve();else{let e=document.createElement("link");e.rel="stylesheet",e.href=t,e.onerror=()=>{r.reject()},e.onload=()=>{r.resolve()},document.head.appendChild(e)}else if(K.test(t)){let n=document.querySelectorAll(`script[src="${t}"],script[src^="${t}?"],script[src="${e}"],script[src^="${e}?"]`);if(n.length>0)for(let e of Array.from(n))e.addEventListener("error",()=>{r.reject()});else{let e=document.createElement("script");e.src=t,e.onerror=()=>{r.reject()},document.head.appendChild(e)}}else throw Error(`can't infer type of chunk from URL ${t}`)}return r.loadingStarted=!0,r.promise})(e,t),async loadWebAssembly(e,t,r,n,o){let i=fetch(N(r)),{instance:l}=await WebAssembly.instantiateStreaming(i,o);return l.exports},async loadWebAssemblyModule(e,t,r,n){let o=fetch(N(r));return await WebAssembly.compileStreaming(o)}};let H=globalThis.TURBOPACK;globalThis.TURBOPACK={push:F},H.forEach(F)})();
1
+ (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,{otherChunks:["static/chunks/0zbxssxh53n-3.js","static/chunks/1__i9af9g78vd.js","static/chunks/13f1kmjea-0md.js","static/chunks/2h0dkzyy0vocp.js","static/chunks/03fmihek9n986.js"],runtimeModuleIds:[94553]}]),(()=>{let e;if(!Array.isArray(globalThis.TURBOPACK))return;let t="/_next/",r=function(){if(null!=self.TURBOPACK_ASSET_SUFFIX)return self.TURBOPACK_ASSET_SUFFIX;let e=document?.currentScript?.getAttribute?.("src")??"",t=e.indexOf("?");return t>=0?e.slice(t):""}(),n=["NEXT_DEPLOYMENT_ID","NEXT_CLIENT_ASSET_SUFFIX"];var o,i=((o=i||{})[o.Runtime=0]="Runtime",o[o.Parent=1]="Parent",o[o.Update=2]="Update",o);let l=new WeakMap;function s(e,t){this.m=e,this.e=t}let u=s.prototype,a=Object.prototype.hasOwnProperty,c="u">typeof Symbol&&Symbol.toStringTag;function f(e,t,r){a.call(e,t)||Object.defineProperty(e,t,r)}function p(e,t){let r=e[t];return r||(r=h(t),e[t]=r),r}function h(e){return{exports:{},error:void 0,id:e,namespaceObject:void 0}}function d(e,t){f(e,"__esModule",{value:!0}),c&&f(e,c,{value:"Module"});let r=0;for(;r<t.length;){let n=t[r++],o=t[r++];if("number"==typeof o)if(0===o)f(e,n,{value:t[r++],enumerable:!0,writable:!1});else throw Error(`unexpected tag: ${o}`);else"function"==typeof t[r]?f(e,n,{get:o,set:t[r++],enumerable:!0}):f(e,n,{get:o,enumerable:!0})}Object.seal(e)}function m(e,t){(null!=t?p(this.c,t):this.m).exports=e}u.s=function(e,t){let r,n;null!=t?n=(r=p(this.c,t)).exports:(r=this.m,n=this.e),r.namespaceObject=n,d(n,e)},u.j=function(e,t){var r,n;let o,i,s;null!=t?i=(o=p(this.c,t)).exports:(o=this.m,i=this.e);let u=(r=o,n=i,(s=l.get(r))||(l.set(r,s=[]),r.exports=r.namespaceObject=new Proxy(n,{get(e,t){if(a.call(e,t)||"default"===t||"__esModule"===t)return Reflect.get(e,t);for(let e of s){let r=Reflect.get(e,t);if(void 0!==r)return r}},ownKeys(e){let t=Reflect.ownKeys(e);for(let e of s)for(let r of Reflect.ownKeys(e))"default"===r||t.includes(r)||t.push(r);return t}})),s);"object"==typeof e&&null!==e&&u.push(e)},u.v=m,u.n=function(e,t){let r;(r=null!=t?p(this.c,t):this.m).exports=r.namespaceObject=e};let b=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,y=[null,b({}),b([]),b(b)];function g(e,t,r){let n=[],o=-1;for(let t=e;("object"==typeof t||"function"==typeof t)&&!y.includes(t);t=b(t))for(let r of Object.getOwnPropertyNames(t))n.push(r,function(e,t){return()=>e[t]}(e,r)),-1===o&&"default"===r&&(o=n.length-1);return r&&o>=0||(o>=0?n.splice(o,1,0,e):n.push("default",0,e)),d(t,n),t}function O(e){let t=B(e,this.m);if(t.namespaceObject)return t.namespaceObject;let r=t.exports;return t.namespaceObject=g(r,"function"==typeof r?function(...e){return r.apply(this,e)}:Object.create(null),r&&r.__esModule)}function w(e){let t=e.indexOf("#");-1!==t&&(e=e.substring(0,t));let r=e.indexOf("?");return -1!==r&&(e=e.substring(0,r)),e}function k(){let e,t;return{promise:new Promise((r,n)=>{t=n,e=r}),resolve:e,reject:t}}u.i=O,u.A=function(e){return this.r(e)(O.bind(this))},u.t="function"==typeof require?require:function(){throw Error("Unexpected use of runtime require")},u.r=function(e){return B(e,this.m).exports},u.f=function(e){function t(t){if(t=w(t),a.call(e,t))return e[t].module();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r}return t.keys=()=>Object.keys(e),t.resolve=t=>{if(t=w(t),a.call(e,t))return e[t].id();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r},t.import=async e=>await t(e),t};let j=Symbol("turbopack queues"),v=Symbol("turbopack exports"),U=Symbol("turbopack error");function C(e){e&&1!==e.status&&(e.status=1,e.forEach(e=>e.queueCount--),e.forEach(e=>e.queueCount--?e.queueCount++:e()))}u.a=function(e,t){let r=this.m,n=t?Object.assign([],{status:-1}):void 0,o=new Set,{resolve:i,reject:l,promise:s}=k(),u=Object.assign(s,{[v]:r.exports,[j]:e=>{n&&e(n),o.forEach(e),u.catch(()=>{})}}),a={get:()=>u,set(e){e!==u&&(u[v]=e)}};Object.defineProperty(r,"exports",a),Object.defineProperty(r,"namespaceObject",a),e(function(e){let t=e.map(e=>{if(null!==e&&"object"==typeof e){if(j in e)return e;if(null!=e&&"object"==typeof e&&"then"in e&&"function"==typeof e.then){let t=Object.assign([],{status:0}),r={[v]:{},[j]:e=>e(t)};return e.then(e=>{r[v]=e,C(t)},e=>{r[U]=e,C(t)}),r}}return{[v]:e,[j]:()=>{}}}),r=()=>t.map(e=>{if(e[U])throw e[U];return e[v]}),{promise:i,resolve:l}=k(),s=Object.assign(()=>l(r),{queueCount:0});function u(e){e!==n&&!o.has(e)&&(o.add(e),e&&0===e.status&&(s.queueCount++,e.push(s)))}return t.map(e=>e[j](u)),s.queueCount?i:r()},function(e){e?l(u[U]=e):i(u[v]),C(n)}),n&&-1===n.status&&(n.status=0)};let P=function(e){let t=new URL(e,"x:/"),r={};for(let e in t)r[e]=t[e];for(let t in r.href=e,r.pathname=e.replace(/[?#].*/,""),r.origin=r.protocol="",r.toString=r.toJSON=(...t)=>e,r)Object.defineProperty(this,t,{enumerable:!0,configurable:!0,value:r[t]})};function R(e,t){throw Error(`Invariant: ${t(e)}`)}P.prototype=URL.prototype,u.U=P,u.z=function(e){throw Error("dynamic usage of require is not supported")},u.g=globalThis;let S=s.prototype,$=new Map;u.M=$;let _=new Map,E=new Map;async function T(e,t,r){let n;if("string"==typeof r)return M(e,t,N(r));let o=r.included||[],i=o.map(e=>!!$.has(e)||_.get(e));if(i.length>0&&i.every(e=>e))return void await Promise.all(i);let l=r.moduleChunks||[],s=l.map(e=>E.get(e)).filter(e=>e);if(s.length>0){if(s.length===l.length)return void await Promise.all(s);let r=new Set;for(let e of l)E.has(e)||r.add(e);for(let n of r){let r=M(e,t,N(n));E.set(n,r),s.push(r)}n=Promise.all(s)}else{for(let o of(n=M(e,t,N(r.path)),l))E.has(o)||E.set(o,n)}for(let e of o)_.has(e)||_.set(e,n);await n}S.l=function(e){return T(i.Parent,this.m.id,e)};let A=Promise.resolve(void 0),x=new WeakMap;function M(t,r,n){let o=e.loadChunkCached(t,n),l=x.get(o);if(void 0===l){let e=x.set.bind(x,o,A);l=o.then(e).catch(e=>{let o;switch(t){case i.Runtime:o=`as a runtime dependency of chunk ${r}`;break;case i.Parent:o=`from module ${r}`;break;case i.Update:o="from an HMR update";break;default:R(t,e=>`Unknown source type: ${e}`)}let l=Error(`Failed to load chunk ${n} ${o}${e?`: ${e}`:""}`,e?{cause:e}:void 0);throw l.name="ChunkLoadError",l}),x.set(o,l)}return l}function N(e){return`${t}${e.split("/").map(e=>encodeURIComponent(e)).join("/")}${r}`}S.L=function(e){return M(i.Parent,this.m.id,e)},S.R=function(e){let t=this.r(e);return t?.default??t},S.P=function(e){return`/ROOT/${e??""}`},S.q=function(e,t){m.call(this,`${e}${r}`,t)},S.b=function(e,t,o,i){let l="SharedWorker"===e.name,s=[o.map(e=>N(e)).reverse(),r];for(let e of n)s.push(globalThis[e]);let u=new URL(N(t),location.origin),a=JSON.stringify(s);return l?u.searchParams.set("params",a):u.hash="#params="+encodeURIComponent(a),new e(u,i?{...i,type:void 0}:void 0)};let K=/\.js(?:\?[^#]*)?(?:#.*)?$/,q=/\.css(?:\?[^#]*)?(?:#.*)?$/;function L(e){return q.test(e)}u.w=function(t,r,n){return e.loadWebAssembly(i.Parent,this.m.id,t,r,n)},u.u=function(t,r){return e.loadWebAssemblyModule(i.Parent,this.m.id,t,r)};let I={};u.c=I;let B=(e,t)=>{let r=I[e];if(r){if(r.error)throw r.error;return r}return W(e,i.Parent,t.id)};function W(e,t,r){let n=$.get(e);if("function"!=typeof n)throw Error(function(e,t,r){let n;switch(t){case 0:n=`as a runtime entry of chunk ${r}`;break;case 1:n=`because it was required from module ${r}`;break;case 2:n="because of an HMR update";break;default:R(t,e=>`Unknown source type: ${e}`)}return`Module ${e} was instantiated ${n}, but the module factory is not available.`}(e,t,r));let o=h(e),i=o.exports;I[e]=o;let l=new s(o,i);try{n(l,o,i)}catch(e){throw o.error=e,e}return o.namespaceObject&&o.exports!==o.namespaceObject&&g(o.exports,o.namespaceObject),o}function F(t){let r,n=function(e){if("string"==typeof e)return e;if(e)return{src:e.getAttribute("src")};if("u">typeof TURBOPACK_NEXT_CHUNK_URLS)return{src:TURBOPACK_NEXT_CHUNK_URLS.pop()};throw Error("chunk path empty but not in a worker")}(t[0]);return 2===t.length?r=t[1]:(r=void 0,!function(e,t){let r=1;for(;r<e.length;){let n,o=r+1;for(;o<e.length&&"function"!=typeof e[o];)o++;if(o===e.length)throw Error("malformed chunk format, expected a factory function");let i=e[o];for(let i=r;i<o;i++){let r=e[i],o=t.get(r);if(o){n=o;break}}let l=n??i,s=!1;for(let n=r;n<o;n++){let r=e[n];t.has(r)||(s||(l===i&&Object.defineProperty(i,"name",{value:"module evaluation"}),s=!0),t.set(r,l))}r=o+1}}(t,$)),e.registerChunk(n,r)}let X=new Map;function D(e){let t=X.get(e);if(!t){let r,n;t={resolved:!1,loadingStarted:!1,promise:new Promise((e,t)=>{r=e,n=t}),resolve:()=>{t.resolved=!0,r()},reject:n},X.set(e,t)}return t}e={async registerChunk(e,r){let n=function(e){if("string"==typeof e)return e;let r=decodeURIComponent(e.src.replace(/[?#].*$/,""));return r.startsWith(t)?r.slice(t.length):r}(e);if(D("string"==typeof e?N(e):e.src).resolve(),null!=r){for(let e of r.otherChunks)D(N("string"==typeof e?e:e.path));if(await Promise.all(r.otherChunks.map(e=>T(i.Runtime,n,e))),r.runtimeModuleIds.length>0)for(let e of r.runtimeModuleIds)!function(e,t){let r=I[t];if(r){if(r.error)throw r.error;return}W(t,i.Runtime,e)}(n,e)}},loadChunkCached:(e,t)=>(function(e,t){let r=D(t);if(r.loadingStarted)return r.promise;if(e===i.Runtime)return r.loadingStarted=!0,L(t)&&r.resolve(),r.promise;if("function"==typeof importScripts)if(L(t));else if(K.test(t))self.TURBOPACK_NEXT_CHUNK_URLS.push(t),importScripts(t);else throw Error(`can't infer type of chunk from URL ${t} in worker`);else{let e=decodeURI(t);if(L(t))if(document.querySelectorAll(`link[rel=stylesheet][href="${t}"],link[rel=stylesheet][href^="${t}?"],link[rel=stylesheet][href="${e}"],link[rel=stylesheet][href^="${e}?"]`).length>0)r.resolve();else{let e=document.createElement("link");e.rel="stylesheet",e.href=t,e.onerror=()=>{r.reject()},e.onload=()=>{r.resolve()},document.head.appendChild(e)}else if(K.test(t)){let n=document.querySelectorAll(`script[src="${t}"],script[src^="${t}?"],script[src="${e}"],script[src^="${e}?"]`);if(n.length>0)for(let e of Array.from(n))e.addEventListener("error",()=>{r.reject()});else{let e=document.createElement("script");e.src=t,e.onerror=()=>{r.reject()},document.head.appendChild(e)}}else throw Error(`can't infer type of chunk from URL ${t}`)}return r.loadingStarted=!0,r.promise})(e,t),async loadWebAssembly(e,t,r,n,o){let i=fetch(N(r)),{instance:l}=await WebAssembly.instantiateStreaming(i,o);return l.exports},async loadWebAssemblyModule(e,t,r,n){let o=fetch(N(r));return await WebAssembly.compileStreaming(o)}};let H=globalThis.TURBOPACK;globalThis.TURBOPACK={push:F},H.forEach(F)})();
@@ -0,0 +1,192 @@
1
+ /**
2
+ * POST /api/audit/invite
3
+ *
4
+ * Browser-facing proxy for the api-server's POST /v0/invite — the user
5
+ * supplies a list of friend emails, the api-server composes invite emails
6
+ * (Cc'ing the sender so the recipient sees who invited them), and dispatches
7
+ * them through the same email infrastructure that backs the OTP flow.
8
+ *
9
+ * Auth: requires an active session — same cookie/refresh-token contract as
10
+ * /api/auth/reminder. Anonymous calls get 401 so the front-end can route to
11
+ * the AuthDialog before retrying.
12
+ *
13
+ * Validation: max 10 recipients per call, each must look like an email.
14
+ * Anything beyond that gets a 400 and never reaches upstream.
15
+ *
16
+ * Contract for the upstream endpoint is handed over to the platform team
17
+ * separately.
18
+ */
19
+ import { NextRequest, NextResponse } from "next/server";
20
+ import { whoAmI } from "@/lib/auth/auth-store";
21
+ import { AuthApiError, sendInvites } from "@/lib/auth/api-server-client";
22
+ import { initTelemetry, trackEvent } from "@/lib/telemetry";
23
+
24
+ export const dynamic = "force-dynamic";
25
+
26
+ const MAX_RECIPIENTS = 10;
27
+ const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
28
+
29
+ interface InviteBody {
30
+ to?: unknown;
31
+ score?: unknown;
32
+ }
33
+
34
+ export async function POST(req: NextRequest): Promise<NextResponse> {
35
+ await initTelemetry();
36
+ const who = await whoAmI();
37
+ if (!who) {
38
+ trackEvent("audit_invite_sent", { status: "unauthorized", source: "dashboard" });
39
+ return NextResponse.json(
40
+ { code: "unauthorized", message: "Sign in before sending invites." },
41
+ { status: 401 },
42
+ );
43
+ }
44
+
45
+ let body: InviteBody = {};
46
+ const raw = await req.text();
47
+ if (raw.trim().length > 0) {
48
+ try {
49
+ const parsed = JSON.parse(raw);
50
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
51
+ trackEvent("audit_invite_sent", {
52
+ status: "validation_error",
53
+ source: "dashboard",
54
+ reason: "not_an_object",
55
+ user_id: who.me.id,
56
+ });
57
+ return NextResponse.json(
58
+ { code: "validation_error", message: "Request body must be a JSON object." },
59
+ { status: 400 },
60
+ );
61
+ }
62
+ body = parsed as InviteBody;
63
+ } catch {
64
+ trackEvent("audit_invite_sent", {
65
+ status: "validation_error",
66
+ source: "dashboard",
67
+ reason: "malformed_json",
68
+ user_id: who.me.id,
69
+ });
70
+ return NextResponse.json(
71
+ { code: "validation_error", message: "Request body is not valid JSON." },
72
+ { status: 400 },
73
+ );
74
+ }
75
+ }
76
+
77
+ if (!Array.isArray(body.to)) {
78
+ trackEvent("audit_invite_sent", {
79
+ status: "validation_error",
80
+ source: "dashboard",
81
+ reason: "missing_to",
82
+ user_id: who.me.id,
83
+ });
84
+ return NextResponse.json(
85
+ { code: "validation_error", message: "`to` must be a list of email addresses." },
86
+ { status: 400 },
87
+ );
88
+ }
89
+
90
+ const normalised: string[] = [];
91
+ const seen = new Set<string>();
92
+ for (const entry of body.to) {
93
+ if (typeof entry !== "string") continue;
94
+ const e = entry.trim().toLowerCase();
95
+ if (!e || !EMAIL_RE.test(e)) continue;
96
+ if (e === who.me.email.toLowerCase()) continue; // can't invite yourself
97
+ if (seen.has(e)) continue;
98
+ seen.add(e);
99
+ normalised.push(e);
100
+ }
101
+
102
+ if (normalised.length === 0) {
103
+ trackEvent("audit_invite_sent", {
104
+ status: "validation_error",
105
+ source: "dashboard",
106
+ reason: "no_valid_recipients",
107
+ user_id: who.me.id,
108
+ input_count: Array.isArray(body.to) ? body.to.length : 0,
109
+ });
110
+ return NextResponse.json(
111
+ {
112
+ code: "validation_error",
113
+ message: "Provide at least one valid email address (other than your own).",
114
+ },
115
+ { status: 400 },
116
+ );
117
+ }
118
+
119
+ if (normalised.length > MAX_RECIPIENTS) {
120
+ trackEvent("audit_invite_sent", {
121
+ status: "validation_error",
122
+ source: "dashboard",
123
+ reason: "too_many_recipients",
124
+ user_id: who.me.id,
125
+ input_count: normalised.length,
126
+ });
127
+ return NextResponse.json(
128
+ {
129
+ code: "validation_error",
130
+ message: `Up to ${MAX_RECIPIENTS} recipients per invite batch. Please send the rest in a follow-up.`,
131
+ },
132
+ { status: 400 },
133
+ );
134
+ }
135
+
136
+ // Optional sender audit score (0–100), surfaced in the invite body. Coerce
137
+ // defensively — the value is client-supplied: ignore non-finite garbage,
138
+ // round, then clamp into range before forwarding upstream.
139
+ let score: number | undefined;
140
+ if (typeof body.score === "number" && Number.isFinite(body.score)) {
141
+ score = Math.max(0, Math.min(100, Math.round(body.score)));
142
+ }
143
+
144
+ try {
145
+ const result = await sendInvites(who.auth.access_token, normalised, score);
146
+ trackEvent("audit_invite_sent", {
147
+ status: "success",
148
+ source: "dashboard",
149
+ user_id: who.me.id,
150
+ sent_count: result.sent.length,
151
+ failed_count: result.failed.length,
152
+ });
153
+ return NextResponse.json(result, { status: 200 });
154
+ } catch (err) {
155
+ if (err instanceof AuthApiError) {
156
+ trackEvent("audit_invite_sent", {
157
+ status: "failed",
158
+ source: "dashboard",
159
+ user_id: who.me.id,
160
+ error_code: err.code,
161
+ http_status: err.status,
162
+ recipient_count: normalised.length,
163
+ });
164
+ const httpStatus = err.status >= 200 && err.status < 600 ? err.status : 504;
165
+ return NextResponse.json(
166
+ {
167
+ code: err.code,
168
+ message: err.message,
169
+ ...(err.retryAfterSecs !== undefined ? { retry_after_secs: err.retryAfterSecs } : {}),
170
+ },
171
+ { status: httpStatus },
172
+ );
173
+ }
174
+ // Don't surface the raw upstream message to either telemetry or the
175
+ // client. Network/DNS errors can carry internal hostnames, IPs, or
176
+ // fragment payload bytes that have no business leaving the proxy.
177
+ // Log the error name only (bounded) and return a stable generic.
178
+ const errorName = err instanceof Error ? err.name : "unknown";
179
+ trackEvent("audit_invite_sent", {
180
+ status: "failed",
181
+ source: "dashboard",
182
+ user_id: who.me.id,
183
+ error_code: "upstream_unreachable",
184
+ error_name: errorName.slice(0, 50),
185
+ recipient_count: normalised.length,
186
+ });
187
+ return NextResponse.json(
188
+ { code: "upstream_unreachable", message: "Invite service is unreachable. Please try again in a moment." },
189
+ { status: 502 },
190
+ );
191
+ }
192
+ }
@@ -17,6 +17,7 @@ import { writeDashboardCache } from "@/src/audit/dashboard-cache";
17
17
  import { INTEGRATION_TYPES, type IntegrationType } from "@/src/hooks/types";
18
18
  import type { RunAuditOptions } from "@/src/audit/types";
19
19
  import { finishRun, tryAcquireRun } from "../_state";
20
+ import { initTelemetry, trackEvent } from "@/lib/telemetry";
20
21
 
21
22
  export const dynamic = "force-dynamic";
22
23
 
@@ -52,6 +53,11 @@ function sanitize(body: RunBody): RunAuditOptions {
52
53
  }
53
54
 
54
55
  export async function POST(request: NextRequest): Promise<NextResponse> {
56
+ // initTelemetry never throws; init up front so every exit path (incl. the
57
+ // 400/409 rejections and the detached run task below) can report. The
58
+ // dashboard is a long-lived process, so trackEvent's background flush
59
+ // delivers even after this handler returns 202.
60
+ await initTelemetry();
55
61
  let body: RunBody = {};
56
62
  try {
57
63
  const raw = await request.text();
@@ -60,6 +66,7 @@ export async function POST(request: NextRequest): Promise<NextResponse> {
60
66
  // JSON.parse("null") returns null and JSON.parse("[]") returns an
61
67
  // array — both pass the catch but break sanitize()'s field access.
62
68
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
69
+ trackEvent("audit_run_rejected", { source: "dashboard", reason: "non_object_body" });
63
70
  return NextResponse.json(
64
71
  { error: "Request body must be a JSON object" },
65
72
  { status: 400 },
@@ -68,18 +75,31 @@ export async function POST(request: NextRequest): Promise<NextResponse> {
68
75
  body = parsed as RunBody;
69
76
  }
70
77
  } catch {
78
+ trackEvent("audit_run_rejected", { source: "dashboard", reason: "invalid_json" });
71
79
  return NextResponse.json({ error: "Invalid JSON body" }, { status: 400 });
72
80
  }
73
81
 
74
82
  const opts = sanitize(body);
75
83
 
76
84
  if (!tryAcquireRun()) {
85
+ trackEvent("audit_run_rejected", { source: "dashboard", reason: "already_running" });
77
86
  return NextResponse.json(
78
87
  { error: "Audit already running", status: "already-running" },
79
88
  { status: 409 },
80
89
  );
81
90
  }
82
91
 
92
+ // Mirror the CLI's cli_audit_* funnel for the dashboard path (which shares the
93
+ // same runAudit() core but previously emitted no server telemetry at all).
94
+ trackEvent("audit_run_started", {
95
+ source: "dashboard",
96
+ since: opts.since ?? null,
97
+ no_cache: opts.noCache === true,
98
+ cli_count: opts.clis?.length ?? 0,
99
+ project_count: opts.projects?.length ?? 0,
100
+ });
101
+ const startedAt = Date.now();
102
+
83
103
  // Fire-and-forget: a cold, all-history scan can run far longer than any HTTP
84
104
  // request should stay open — and longer than Node's `server.requestTimeout`
85
105
  // on the standalone production server. Start runAudit() as a detached task in
@@ -93,8 +113,23 @@ export async function POST(request: NextRequest): Promise<NextResponse> {
93
113
  // the client (the POST already returned 202), so a failed persist is a
94
114
  // failed run from the user's view — surface it instead of reporting OK.
95
115
  const persisted = writeDashboardCache(opts, result);
116
+ trackEvent("audit_run_completed", {
117
+ source: "dashboard",
118
+ duration_ms: Date.now() - startedAt,
119
+ events_scanned: result.eventsScanned,
120
+ sessions_scanned: result.transcripts.scanned,
121
+ projects_scanned: result.projectsScanned.length,
122
+ findings: result.results.length,
123
+ total_hits: result.totals.hits,
124
+ persisted,
125
+ });
96
126
  finishRun(persisted ? null : "audit finished but its result could not be saved");
97
127
  } catch (err) {
128
+ trackEvent("audit_run_failed", {
129
+ source: "dashboard",
130
+ duration_ms: Date.now() - startedAt,
131
+ error_type: err instanceof Error ? err.name : "unknown",
132
+ });
98
133
  finishRun(err instanceof Error ? err.message : String(err));
99
134
  }
100
135
  })();
@@ -21,11 +21,11 @@ export async function POST(req: NextRequest): Promise<NextResponse> {
21
21
  try {
22
22
  body = (await req.json()) as RequestBody;
23
23
  } catch {
24
- trackEvent("audit_otp_requested", { status: "validation_error", reason: "invalid_json" });
24
+ trackEvent("audit_otp_requested", { status: "validation_error", source: "dashboard", reason: "invalid_json" });
25
25
  return NextResponse.json({ code: "validation_error", message: "Invalid JSON body" }, { status: 400 });
26
26
  }
27
27
  if (typeof body.email !== "string" || !body.email.trim()) {
28
- trackEvent("audit_otp_requested", { status: "validation_error", reason: "missing_email" });
28
+ trackEvent("audit_otp_requested", { status: "validation_error", source: "dashboard", reason: "missing_email" });
29
29
  return NextResponse.json(
30
30
  { code: "validation_error", message: "email is required" },
31
31
  { status: 400 },
@@ -20,26 +20,32 @@ interface VerifyBody {
20
20
  }
21
21
 
22
22
  export async function POST(req: NextRequest): Promise<NextResponse> {
23
+ // `initTelemetry` never throws — its internal try/catch is total. Init up
24
+ // front so the validation-400 paths below are tracked too, mirroring
25
+ // /api/auth/login-request.
26
+ await initTelemetry();
23
27
  let body: VerifyBody = {};
24
28
  try {
25
29
  body = (await req.json()) as VerifyBody;
26
30
  } catch {
31
+ trackEvent("audit_otp_verified", { status: "validation_error", source: "dashboard", reason: "invalid_json" });
27
32
  return NextResponse.json({ code: "validation_error", message: "Invalid JSON body" }, { status: 400 });
28
33
  }
29
34
  if (typeof body.email !== "string" || !body.email.trim()) {
35
+ trackEvent("audit_otp_verified", { status: "validation_error", source: "dashboard", reason: "missing_email" });
30
36
  return NextResponse.json(
31
37
  { code: "validation_error", message: "email is required" },
32
38
  { status: 400 },
33
39
  );
34
40
  }
35
41
  if (typeof body.code !== "string" || !body.code.trim()) {
42
+ trackEvent("audit_otp_verified", { status: "validation_error", source: "dashboard", reason: "missing_code", email: body.email.trim().toLowerCase() });
36
43
  return NextResponse.json(
37
44
  { code: "validation_error", message: "code is required" },
38
45
  { status: 400 },
39
46
  );
40
47
  }
41
- // `initTelemetry` never throws — its internal try/catch is total.
42
- await initTelemetry();
48
+ const email = body.email.trim().toLowerCase();
43
49
  try {
44
50
  const tokens = await verifyLoginCode(body.email, body.code);
45
51
  writeAuth(authFromTokenResponse(tokens));
@@ -72,6 +78,7 @@ export async function POST(req: NextRequest): Promise<NextResponse> {
72
78
  trackEvent("audit_otp_verified", {
73
79
  status: "failed",
74
80
  source: "dashboard",
81
+ email,
75
82
  error_code: err.code,
76
83
  http_status: err.status,
77
84
  });
@@ -87,6 +94,7 @@ export async function POST(req: NextRequest): Promise<NextResponse> {
87
94
  trackEvent("audit_otp_verified", {
88
95
  status: "failed",
89
96
  source: "dashboard",
97
+ email,
90
98
  error_code: "upstream_unreachable",
91
99
  error_message: message.slice(0, 200),
92
100
  });
@@ -3,30 +3,31 @@
3
3
  /**
4
4
  * Top-level client wrapper for /audit.
5
5
  *
6
- * Composes the personality report: classify the agent into one of 8
7
- * archetypes, derive a score + tier, render the IdentitySection +
8
- * ShowOff + Strengths + Score (with leaderboard) + Findings + Policies
9
- * + Return-loop CTA.
6
+ * Composes the calm personality report: classify the agent into one of
7
+ * 8 archetypes, derive a score, and render the 5-section flow:
10
8
  *
11
- * Empty / running states fall back to the existing EmptyState and
12
- * RunProgress components.
9
+ * 01 AuditPoster single-screen shareable poster
10
+ * 02 StrengthsSection — what it's great at
11
+ * 03 QuirksSection — what slipped through
12
+ * 04 HowToImproveSection — install / configure
13
+ * 05 ComeBackBetterSection — reminder + perks
14
+ *
15
+ * Empty / running states fall back to EmptyState and RunProgress.
13
16
  */
14
17
  import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
15
18
  import { getAuditResultAction } from "@/app/actions/get-audit-result";
16
19
  import type { AuditResult, RunAuditOptions } from "@/src/audit/types";
17
20
  import { classifyAgent } from "@/src/audit/archetypes";
18
- import { COHORT_SIZE, deriveScore, gradeFor, projectedScore, type Grade } from "@/src/audit/scoring";
21
+ import { deriveScore, gradeFor, projectedScore } from "@/src/audit/scoring";
19
22
  import { deriveStrengths } from "@/src/audit/strengths";
20
23
  import { deriveFindings } from "@/src/audit/findings";
21
24
  import { usePostHog } from "@/contexts/PostHogContext";
22
25
 
23
- import { IdentitySection } from "./identity-section";
24
- import { ShareDock } from "./share-dock";
26
+ import { AuditPoster } from "./audit-poster";
25
27
  import { StrengthsSection } from "./strengths-section";
26
- import { ScoreSection } from "./score-section";
27
- import { FindingsSection } from "./findings-section";
28
- import { PoliciesSection } from "./policies-section";
29
- import { ReturnSection } from "./return-section";
28
+ import { QuirksSection } from "./quirks-section";
29
+ import { HowToImproveSection } from "./how-to-improve-section";
30
+ import { ComeBackBetterSection } from "./come-back-better-section";
30
31
  import { ReportFooter } from "./report-footer";
31
32
  import { EmptyState } from "./empty-state";
32
33
  import { RunProgress } from "./run-progress";
@@ -58,11 +59,6 @@ interface Props {
58
59
  totalCatalogSize: number;
59
60
  }
60
61
 
61
- function inferWindow(params: RunAuditOptions | undefined): string {
62
- if (!params?.since) return "all time";
63
- return params.since;
64
- }
65
-
66
62
  function inferProjectName(result: AuditResult, override?: string): string {
67
63
  if (override && override.trim()) return override;
68
64
  // Pick the cwd that appears in the most examples — proxy for "your
@@ -108,7 +104,8 @@ export function AuditDashboard({ initial, projectFromUrl, totalCatalogSize }: Pr
108
104
  if (running) return;
109
105
  capture("audit_rerun_clicked", { source, since: "all" });
110
106
  setRunning(true);
111
- setRerunStatus({ kind: "running", startedAt: Date.now() });
107
+ const startedAt = Date.now();
108
+ setRerunStatus({ kind: "running", startedAt });
112
109
  try {
113
110
  // noCache: an explicit re-audit bypasses the per-transcript cache and
114
111
  // re-scans from scratch — never a silent no-op that returns the identical
@@ -118,6 +115,11 @@ export function AuditDashboard({ initial, projectFromUrl, totalCatalogSize }: Pr
118
115
  // fast cached path — it's a first scan, not a re-audit.
119
116
  await triggerRun({ cli: [], since: "all", noCache: true });
120
117
  await refreshFromCache();
118
+ capture("audit_rerun_succeeded", {
119
+ source,
120
+ since: "all",
121
+ duration_ms: Date.now() - startedAt,
122
+ });
121
123
  setRerunStatus({ kind: "idle" });
122
124
  } catch (err) {
123
125
  const kind = err instanceof RerunError ? err.kind : "network";
@@ -126,6 +128,7 @@ export function AuditDashboard({ initial, projectFromUrl, totalCatalogSize }: Pr
126
128
  source,
127
129
  since: "all",
128
130
  cli_filter: "all",
131
+ duration_ms: Date.now() - startedAt,
129
132
  });
130
133
  setRerunStatus({ kind: "failed", reason: kind, failedAt: Date.now() });
131
134
  } finally {
@@ -249,9 +252,7 @@ export function AuditDashboard({ initial, projectFromUrl, totalCatalogSize }: Pr
249
252
  <MainReport
250
253
  result={result}
251
254
  cachedAt={cachedAt}
252
- params={params}
253
255
  projectFromUrl={projectFromUrl}
254
- totalCatalogSize={totalCatalogSize}
255
256
  isRunning={running}
256
257
  rerunStatus={rerunStatus}
257
258
  onRerun={(source) => startRerun(source)}
@@ -263,9 +264,7 @@ export function AuditDashboard({ initial, projectFromUrl, totalCatalogSize }: Pr
263
264
  interface MainReportProps {
264
265
  result: AuditResult;
265
266
  cachedAt: string | null;
266
- params: RunAuditOptions | undefined;
267
267
  projectFromUrl?: string;
268
- totalCatalogSize: number;
269
268
  isRunning: boolean;
270
269
  rerunStatus: RerunStatus;
271
270
  onRerun: (source: RerunSource) => void;
@@ -275,9 +274,7 @@ interface MainReportProps {
275
274
  function MainReport({
276
275
  result,
277
276
  cachedAt,
278
- params,
279
277
  projectFromUrl,
280
- totalCatalogSize,
281
278
  isRunning,
282
279
  rerunStatus,
283
280
  onRerun,
@@ -294,14 +291,10 @@ function MainReport({
294
291
  const projectedGrade = gradeFor(projected);
295
292
  const strengths = useMemo(() => deriveStrengths(result), [result]);
296
293
  const findings = useMemo(() => deriveFindings(result), [result]);
297
- // Renamed from `window` to avoid shadowing the browser global — any
298
- // future `window.*` reference added inside MainReport would silently
299
- // bind to a string and crash at runtime.
300
- const scopeWindow = inferWindow(params);
301
294
 
302
- // One pass over result.results derives both counts; score-section and
303
- // return-section also need `missing` but they take it from us via props
304
- // / `result` shape, so deduplicate the scan here.
295
+ // One pass over result.results: detectors triggered + missing prescribed
296
+ // policies. Both feed PostHog instrumentation; `missing` also feeds the
297
+ // poster's share-text template.
305
298
  const { detectorsTriggered, missing } = useMemo(() => {
306
299
  let detectorsTriggered = 0;
307
300
  let missing = 0;
@@ -340,54 +333,38 @@ function MainReport({
340
333
  detectorsTriggered,
341
334
  ]);
342
335
 
343
- /** Identity hero ref — captured to PNG by the share buttons. */
344
- const identityFrameRef = useRef<HTMLDivElement>(null);
336
+ /** Poster ref — captured to PNG by the poster's share buttons. */
337
+ const posterRef = useRef<HTMLDivElement>(null);
345
338
 
346
339
  return (
347
340
  <div className="app">
348
341
  <AuditProgressStrip status={rerunStatus} onDismiss={onDismissRerun} />
349
- <div className="scanline-overlay" />
350
342
  <div className="app-shell">
351
343
  <div className="report">
352
- <IdentitySection
353
- ref={identityFrameRef}
344
+ <AuditPoster
345
+ ref={posterRef}
354
346
  archetypeKey={classification.archetype}
355
- secondaryKey={classification.secondary}
356
- toolCalls={result.eventsScanned ?? 0}
357
- sessions={result.transcripts.scanned}
358
- window={scopeWindow}
359
347
  seed={classification.variantSeed}
360
- />
361
- <StrengthsSection
362
- strengths={strengths}
363
- totalDetectorsTriggered={detectorsTriggered}
364
- totalDetectorsAvailable={totalCatalogSize}
365
- />
366
- <ScoreSection
367
- result={result}
368
348
  score={score}
369
349
  grade={grade}
370
- archetypeKey={classification.archetype}
371
- project={project}
350
+ missing={missing}
351
+ auditedAt={cachedAt ?? new Date().toISOString()}
372
352
  />
373
- <ReturnSection
353
+ <StrengthsSection strengths={strengths} />
354
+ <QuirksSection findings={findings} />
355
+ <HowToImproveSection
374
356
  result={result}
357
+ projected={projected}
358
+ projectedGrade={projectedGrade}
359
+ />
360
+ <ComeBackBetterSection
375
361
  isRunning={isRunning}
376
362
  onRerun={() => onRerun("return_section")}
363
+ score={score}
377
364
  />
378
- <FindingsSection findings={findings} />
379
- <PoliciesSection result={result} projected={projected} projectedGrade={projectedGrade} />
380
365
  </div>
381
366
  <ReportFooter cachedAt={cachedAt} />
382
367
  </div>
383
- <ShareDock
384
- frameRef={identityFrameRef}
385
- archetypeKey={classification.archetype}
386
- seed={classification.variantSeed}
387
- score={score}
388
- grade={grade}
389
- missing={missing}
390
- />
391
368
  </div>
392
369
  );
393
370
  }
@@ -408,7 +385,6 @@ function ShellEmpty({ running, mode = "no-cache", rerunStatus, onDismissRerun, o
408
385
  return (
409
386
  <div className="app">
410
387
  <AuditProgressStrip status={rerunStatus} onDismiss={onDismissRerun} />
411
- <div className="scanline-overlay" />
412
388
  <div className="app-shell">
413
389
  <div className="report">
414
390
  {running ? (