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
@@ -183,9 +183,14 @@ function IntegrationBadge({ integration }: { integration?: string }) {
183
183
 
184
184
  function ModeBadge({ mode }: { mode: string }) {
185
185
  const isDefault = mode === "default";
186
+ // inline-block + max-w-full + truncate: the pill fits its column for known
187
+ // modes (incl. the longest, "bypassPermissions") and, for any unexpectedly
188
+ // long / custom mode, ellipsizes inside the pill with a hover tooltip rather
189
+ // than being hard-clipped mid-word at the cell edge by .activity-data-row > td.
186
190
  return (
187
191
  <span
188
- className={`inline-flex items-center rounded px-1.5 py-0.5 text-[0.6rem] font-medium border ${
192
+ title={mode}
193
+ className={`inline-block max-w-full truncate rounded px-1.5 py-0.5 align-middle text-[0.6rem] font-medium border ${
189
194
  isDefault
190
195
  ? "bg-sky-500/10 text-sky-400 border-sky-500/20"
191
196
  : "bg-amber-500/10 text-amber-400 border-amber-500/20"
@@ -632,32 +637,36 @@ function ActivityTab({
632
637
  ) : (
633
638
  <div className="overflow-x-auto activity-table-wrap">
634
639
  <table className="w-full text-xs activity-table" style={{ tableLayout: "fixed" }}>
640
+ {/* Column widths (table-layout: fixed). Order must match <thead>:
641
+ chevron · time · decision · event · cli · tool · policy · reason · mode · duration · session.
642
+ Badge columns (decision/event/cli/mode) must stay wide enough for their widest
643
+ pill — mode holds "bypassPermissions", the longest badge text in the table. */}
635
644
  <colgroup>
636
645
  <col style={{ width: 32 }} />
637
- <col style={{ width: "8%" }} />
638
- <col style={{ width: "8%" }} />
639
- <col style={{ width: "8%" }} />
640
646
  <col style={{ width: "7%" }} />
641
- <col style={{ width: "18%" }} />
642
- <col style={{ width: "22%" }} />
643
- <col style={{ width: "6%" }} />
647
+ <col style={{ width: "9%" }} />
648
+ <col style={{ width: "12%" }} />
649
+ <col style={{ width: "11%" }} />
650
+ <col style={{ width: "9%" }} />
651
+ <col style={{ width: "13%" }} />
652
+ <col style={{ width: "12%" }} />
653
+ <col style={{ width: "11%" }} />
644
654
  <col style={{ width: "8%" }} />
645
655
  <col style={{ width: "8%" }} />
646
- <col style={{ width: "7%" }} />
647
656
  </colgroup>
648
657
  <thead className="activity-thead">
649
658
  <tr>
650
659
  <th className="px-4 py-3" />
660
+ <th className="px-3 py-3 activity-th">Time</th>
651
661
  <th className="px-3 py-3 activity-th">Decision</th>
652
662
  <th className="px-3 py-3 activity-th">Event</th>
653
663
  <th className="px-3 py-3 activity-th">CLI</th>
654
664
  <th className="px-3 py-3 activity-th">Tool</th>
655
665
  <th className="px-3 py-3 activity-th">Policy</th>
656
666
  <th className="px-3 py-3 activity-th">Reason</th>
667
+ <th className="px-3 py-3 activity-th">Mode</th>
657
668
  <th className="px-3 py-3 activity-th">Duration</th>
658
669
  <th className="px-3 py-3 activity-th">Session</th>
659
- <th className="px-3 py-3 activity-th">Mode</th>
660
- <th className="px-3 py-3 activity-th text-right">Time</th>
661
670
  </tr>
662
671
  </thead>
663
672
  <tbody className="divide-y divide-border/30">
@@ -669,7 +678,7 @@ function ActivityTab({
669
678
  <React.Fragment key={`${item.timestamp}-${i}`}>
670
679
  <tr
671
680
  onClick={() => toggleRow(i)}
672
- className={`cursor-pointer transition-colors ${
681
+ className={`activity-data-row cursor-pointer transition-colors ${
673
682
  isDeny
674
683
  ? "bg-red-500/[0.03] hover:bg-red-500/[0.07] border-l-2 border-l-red-500/40"
675
684
  : isInstruct
@@ -686,6 +695,12 @@ function ActivityTab({
686
695
  }`}
687
696
  />
688
697
  </td>
698
+ <td
699
+ className="px-3 py-2 text-muted-foreground whitespace-nowrap"
700
+ title={formatAbsoluteTime(item.timestamp)}
701
+ >
702
+ {formatRelativeTime(item.timestamp)}
703
+ </td>
689
704
  <td className="px-3 py-2">
690
705
  <DecisionBadge decision={item.decision} />
691
706
  </td>
@@ -714,6 +729,13 @@ function ActivityTab({
714
729
  >
715
730
  {item.reason ?? "\u2014"}
716
731
  </td>
732
+ <td className="px-3 py-2">
733
+ {item.permissionMode ? (
734
+ <ModeBadge mode={item.permissionMode} />
735
+ ) : (
736
+ "\u2014"
737
+ )}
738
+ </td>
717
739
  <td className="px-3 py-2">
718
740
  <DurationDisplay ms={item.durationMs} />
719
741
  </td>
@@ -725,19 +747,6 @@ function ActivityTab({
725
747
  cwd={item.cwd}
726
748
  />
727
749
  </td>
728
- <td className="px-3 py-2">
729
- {item.permissionMode ? (
730
- <ModeBadge mode={item.permissionMode} />
731
- ) : (
732
- "\u2014"
733
- )}
734
- </td>
735
- <td
736
- className="px-3 py-2 text-right text-muted-foreground whitespace-nowrap"
737
- title={formatAbsoluteTime(item.timestamp)}
738
- >
739
- {formatRelativeTime(item.timestamp)}
740
- </td>
741
750
  </tr>
742
751
  {isExpanded && <DetailPanel item={item} />}
743
752
  </React.Fragment>
@@ -1663,9 +1672,17 @@ export default function HooksClient({ initialTab = "activity" }: { initialTab?:
1663
1672
  return (
1664
1673
  <main className="report">
1665
1674
  <section className="section" data-screen-label="policies">
1666
- <h2 className="section-h" style={{ textTransform: "none" }}>
1667
- {activeTab === "activity" ? "Policies" : "what to stop them doing."}
1668
- {activeTab === "activity" && <span className="section-h-dot" aria-hidden />}
1675
+ <h2
1676
+ style={{
1677
+ fontFamily: "var(--font-mono)",
1678
+ fontSize: 24,
1679
+ fontWeight: 600,
1680
+ letterSpacing: "-0.01em",
1681
+ color: "var(--ink)",
1682
+ margin: "0 0 16px",
1683
+ }}
1684
+ >
1685
+ {activeTab === "activity" ? "Policies" : "Configure Policies"}
1669
1686
  </h2>
1670
1687
  {activeTab === "activity" ? (
1671
1688
  <div
@@ -1688,7 +1705,7 @@ export default function HooksClient({ initialTab = "activity" }: { initialTab?:
1688
1705
  minWidth: 0,
1689
1706
  }}
1690
1707
  >
1691
- {evaluationsHeading.toLowerCase()}
1708
+ {evaluationsHeading}
1692
1709
  {policyCounts && (
1693
1710
  <span style={{ color: "var(--dim)" }}>
1694
1711
  {" · "}enabled policies{" "}
@@ -116,97 +116,41 @@ export default async function ProjectPage({ params }: ProjectPageProps) {
116
116
  return (
117
117
  <main className="report">
118
118
  <section className="section" data-screen-label="project">
119
- <div className="section-mast">
120
- <Link
121
- href="/projects"
122
- className="btn"
123
- style={{ fontSize: 11, letterSpacing: "0.18em", textTransform: "uppercase" }}
124
- aria-label="Back to projects"
125
- >
126
- <span style={{ color: "var(--accent-pink)", letterSpacing: "-2px" }}>━━</span>
127
- back to projects
128
- </Link>
129
- <div className="section-meta">
130
- <span className="g">●</span> {sessionFiles.length} session{sessionFiles.length === 1 ? "" : "s"}
131
- </div>
132
- </div>
133
-
134
- <h1
135
- className="section-h"
136
- style={{ textTransform: "none", marginBottom: 18, wordBreak: "break-word" }}
119
+ <Link
120
+ href="/projects"
121
+ className="project-page-back"
122
+ aria-label="Back to projects"
137
123
  >
138
- {canonicalRoot}
139
- </h1>
124
+ <span className="arrow">←</span>
125
+ back to projects
126
+ </Link>
140
127
 
141
- <dl
142
- style={{
143
- display: "grid",
144
- gridTemplateColumns: "auto 1fr",
145
- gap: "8px 18px",
146
- margin: "0 0 36px",
147
- fontFamily: "var(--font-mono)",
148
- fontSize: 12,
149
- color: "var(--ink-2)",
150
- }}
151
- >
152
- <dt
153
- style={{
154
- color: "var(--accent-green)",
155
- letterSpacing: "0.2em",
156
- textTransform: "uppercase",
157
- fontSize: 10,
158
- alignSelf: "center",
159
- }}
160
- >
161
- path
162
- </dt>
163
- <dd style={{ margin: 0, wordBreak: "break-all" }}>{displayPath}</dd>
128
+ <h1 className="project-page-title">{canonicalRoot}</h1>
129
+
130
+ <div className="project-page-meta">
131
+ <span className="label">path</span>
132
+ <span className="path">{displayPath}</span>
164
133
  {lastModifiedFormatted && (
165
134
  <>
166
- <dt
167
- style={{
168
- color: "var(--accent-green)",
169
- letterSpacing: "0.2em",
170
- textTransform: "uppercase",
171
- fontSize: 10,
172
- alignSelf: "center",
173
- }}
174
- >
175
- modified
176
- </dt>
177
- <dd style={{ margin: 0 }}>{lastModifiedFormatted}</dd>
135
+ <span className="sep">·</span>
136
+ <span className="label">modified</span>
137
+ {lastModifiedFormatted}
178
138
  </>
179
139
  )}
180
- </dl>
181
-
182
- <div className="section-mast" style={{ marginBottom: 18 }}>
183
- <div className="section-label">
184
- <span className="glyph">━━</span> sessions
185
- </div>
140
+ <span className="sep">·</span>
141
+ <span className="label">sessions</span>
142
+ {sessionFiles.length}
186
143
  </div>
187
144
 
188
145
  {sessionFiles.length === 0 ? (
189
- <div
190
- className="panel"
191
- style={{ textAlign: "center", padding: "48px 32px" }}
192
- >
193
- <p style={{ color: "var(--ink-2)", marginBottom: 8 }}>
194
- no .jsonl files found in this project.
195
- </p>
196
- <p
197
- style={{
198
- color: "var(--dim)",
199
- fontSize: 12,
200
- letterSpacing: "0.05em",
201
- }}
202
- >
146
+ <div className="project-page-empty">
147
+ no .jsonl files found in this project.
148
+ <div className="hint">
203
149
  session files will appear here once they are created.
204
- </p>
150
+ </div>
205
151
  </div>
206
152
  ) : (
207
- <div className="panel" style={{ padding: 0 }}>
208
- <Suspense><SessionsList files={sessionFiles} projectName={name} /></Suspense>
209
- </div>
153
+ <Suspense><SessionsList files={sessionFiles} projectName={name} /></Suspense>
210
154
  )}
211
155
  </section>
212
156
  </main>
@@ -1,12 +1,4 @@
1
- /** Projects page — lists all Claude Agent SDK project folders.
2
- *
3
- * Wrapped in the audit `.report` + `.section` chrome so the page picks up
4
- * the unified design system: mono fonts, section masthead with the ━━
5
- * glyph + green eyebrow label, and the dashed-frame `.panel` around the
6
- * project list when it's populated. The inner ProjectList component is
7
- * unchanged — every Tailwind utility it uses (bg-card, text-foreground,
8
- * border-border, …) now resolves to the audit palette globally.
9
- */
1
+ /** Projects page — lists all Claude Agent SDK project folders. */
10
2
  import { Suspense } from "react";
11
3
  import { notFound } from "next/navigation";
12
4
  import { getCachedProjectFolders } from "@/lib/projects";
@@ -26,17 +18,17 @@ export default async function ProjectsPage() {
26
18
  return (
27
19
  <main className="report">
28
20
  <section className="section" data-screen-label="projects">
29
- <div className="section-mast">
30
- <div className="section-label">
31
- <span className="glyph">━━</span> projects
32
- </div>
33
- <div className="section-meta">
34
- <span className={count > 0 ? "g" : "p"}>●</span>{" "}
35
- {count} {count === 1 ? "folder" : "folders"}
36
- </div>
37
- </div>
38
- <h2 className="section-h" style={{ textTransform: "none" }}>
39
- your agent footprint.
21
+ <h2
22
+ style={{
23
+ fontFamily: "var(--font-mono)",
24
+ fontSize: 24,
25
+ fontWeight: 600,
26
+ letterSpacing: "-0.01em",
27
+ color: "var(--ink)",
28
+ margin: "0 0 24px",
29
+ }}
30
+ >
31
+ Projects
40
32
  </h2>
41
33
 
42
34
  {count === 0 ? (
@@ -54,7 +46,6 @@ export default async function ProjectsPage() {
54
46
  padding: 12,
55
47
  border: "1px solid var(--line-2)",
56
48
  background: "var(--bg)",
57
- boxShadow: "4px 4px 0 0 var(--accent-pink-shadow)",
58
49
  }}
59
50
  >
60
51
  {Array.from({ length: 36 }).map((_, i) => {
@@ -72,7 +63,7 @@ export default async function ProjectsPage() {
72
63
  </div>
73
64
  </div>
74
65
  <p style={{ color: "var(--ink-2)", marginBottom: 8 }}>
75
- no projects found in the <code style={{ color: "var(--accent-pink)" }}>.claude/projects</code> directory.
66
+ No projects found in the <code>.claude/projects</code> directory.
76
67
  </p>
77
68
  <p
78
69
  style={{
@@ -81,7 +72,7 @@ export default async function ProjectsPage() {
81
72
  letterSpacing: "0.05em",
82
73
  }}
83
74
  >
84
- run an agent in any folder and it will show up here.
75
+ Run an agent in any folder and it will show up here.
85
76
  </p>
86
77
  </div>
87
78
  ) : (
@@ -56,7 +56,7 @@
56
56
  .poster {
57
57
  position: relative;
58
58
  background:
59
- repeating-linear-gradient(0deg, rgba(228,88,125,0.03) 0 1px, transparent 1px 16px),
59
+ repeating-linear-gradient(0deg, rgba(228, 88, 124,0.03) 0 1px, transparent 1px 16px),
60
60
  repeating-linear-gradient(90deg, rgba(102,209,181,0.025) 0 1px, transparent 1px 16px),
61
61
  var(--bg-2);
62
62
  border: 1px solid var(--line-2);
@@ -21,10 +21,10 @@
21
21
  --dim: #5e5c58;
22
22
  --line: #25252b;
23
23
  --line-2: #32323a;
24
- --accent-pink: #e4587d;
25
- --accent-pink-soft: rgba(228, 88, 125, 0.7);
24
+ --accent-pink: #e4587c;
25
+ --accent-pink-soft: rgba(228, 88, 124, 0.7);
26
26
  --accent-pink-shadow: #a83a5a;
27
- --accent-pink-bg: rgba(228, 88, 125, 0.12);
27
+ --accent-pink-bg: rgba(228, 88, 124, 0.12);
28
28
  --accent-green: #66d1b5;
29
29
  --accent-green-shadow: #3e9a82;
30
30
  --accent-green-bg: rgba(102, 209, 181, 0.10);
@@ -52,7 +52,7 @@ html, body, #root {
52
52
  body {
53
53
  background-color: var(--bg);
54
54
  background-image:
55
- radial-gradient(ellipse 1200px 800px at 70% -10%, rgba(228, 88, 125, 0.055) 0%, transparent 60%),
55
+ radial-gradient(ellipse 1200px 800px at 70% -10%, rgba(228, 88, 124, 0.055) 0%, transparent 60%),
56
56
  radial-gradient(ellipse 1000px 700px at 0% 100%, rgba(102, 209, 181, 0.04) 0%, transparent 55%),
57
57
  radial-gradient(ellipse 100% 100% at 50% 50%, transparent 50%, rgba(0,0,0,0.45) 100%),
58
58
  linear-gradient(180deg, #16161a 0%, #0f0f12 100%);
@@ -216,7 +216,7 @@ a { color: inherit; text-decoration: none; }
216
216
  position: relative;
217
217
  border: 1px solid var(--line-2);
218
218
  background:
219
- repeating-linear-gradient(0deg, rgba(228,88,125,0.025) 0 1px, transparent 1px 16px),
219
+ repeating-linear-gradient(0deg, rgba(228, 88, 124,0.025) 0 1px, transparent 1px 16px),
220
220
  repeating-linear-gradient(90deg, rgba(102,209,181,0.025) 0 1px, transparent 1px 16px),
221
221
  var(--bg-2);
222
222
  padding: 56px 56px 48px;
@@ -805,8 +805,8 @@ a { color: inherit; text-decoration: none; }
805
805
  padding: 28px 32px;
806
806
  border: 1px solid var(--line-2);
807
807
  background:
808
- repeating-linear-gradient(0deg, rgba(228,88,125,0.025) 0 1px, transparent 1px 16px),
809
- repeating-linear-gradient(90deg, rgba(228,88,125,0.025) 0 1px, transparent 1px 16px),
808
+ repeating-linear-gradient(0deg, rgba(228, 88, 124,0.025) 0 1px, transparent 1px 16px),
809
+ repeating-linear-gradient(90deg, rgba(228, 88, 124,0.025) 0 1px, transparent 1px 16px),
810
810
  var(--bg-2);
811
811
  color: var(--ink);
812
812
  text-decoration: none;
@@ -816,8 +816,8 @@ a { color: inherit; text-decoration: none; }
816
816
  .showoff-cta:hover {
817
817
  border-color: var(--ink-2);
818
818
  background:
819
- repeating-linear-gradient(0deg, rgba(228,88,125,0.04) 0 1px, transparent 1px 16px),
820
- repeating-linear-gradient(90deg, rgba(228,88,125,0.04) 0 1px, transparent 1px 16px),
819
+ repeating-linear-gradient(0deg, rgba(228, 88, 124,0.04) 0 1px, transparent 1px 16px),
820
+ repeating-linear-gradient(90deg, rgba(228, 88, 124,0.04) 0 1px, transparent 1px 16px),
821
821
  var(--bg-3);
822
822
  }
823
823
  .showoff-cta::before {
@@ -995,8 +995,8 @@ a { color: inherit; text-decoration: none; }
995
995
  .share-card {
996
996
  border: 1px solid var(--accent-pink);
997
997
  background:
998
- repeating-linear-gradient(0deg, rgba(228,88,125,0.02) 0 1px, transparent 1px 16px),
999
- repeating-linear-gradient(90deg, rgba(228,88,125,0.02) 0 1px, transparent 1px 16px),
998
+ repeating-linear-gradient(0deg, rgba(228, 88, 124,0.02) 0 1px, transparent 1px 16px),
999
+ repeating-linear-gradient(90deg, rgba(228, 88, 124,0.02) 0 1px, transparent 1px 16px),
1000
1000
  var(--bg-2);
1001
1001
  padding: 32px;
1002
1002
  position: relative;
@@ -16,9 +16,9 @@ import { RefreshButton } from "@/app/components/refresh-button";
16
16
  import { usePostHog } from "@/contexts/PostHogContext";
17
17
 
18
18
  const NAV_LINKS = [
19
+ { href: "/projects", label: "projects" },
19
20
  { href: "/policies", label: "policies" },
20
21
  { href: "/audit", label: "audit" },
21
- { href: "/projects", label: "projects" },
22
22
  ];
23
23
 
24
24
  const REMOTE_LOGO_URL =
@@ -51,11 +51,7 @@ const useBrandLogo = (): string => {
51
51
 
52
52
  export const Navbar: React.FC<{
53
53
  disabledPages?: string[];
54
- /** Total slipping-through actions from the latest cached audit. When > 0
55
- * a small chip is rendered next to the Audit nav link. Undefined → no
56
- * chip (no cache yet, or audit disabled). */
57
- auditSlippingCount?: number;
58
- }> = ({ disabledPages = [], auditSlippingCount }) => {
54
+ }> = ({ disabledPages = [] }) => {
59
55
  const pathname = usePathname();
60
56
  const { capture } = usePostHog();
61
57
  const logoSrc = useBrandLogo();
@@ -90,10 +86,6 @@ export const Navbar: React.FC<{
90
86
  const active = href === "/projects"
91
87
  ? pathname === "/projects" || pathname.startsWith("/project/")
92
88
  : pathname.startsWith(href);
93
- const showAuditBadge =
94
- href === "/audit"
95
- && typeof auditSlippingCount === "number"
96
- && auditSlippingCount > 0;
97
89
  return (
98
90
  <Link
99
91
  key={href}
@@ -105,37 +97,10 @@ export const Navbar: React.FC<{
105
97
  capture("audit_nav_clicked", {
106
98
  from_path: pathname,
107
99
  is_active_tab: active,
108
- has_badge: showAuditBadge,
109
- slipping_count: typeof auditSlippingCount === "number" ? auditSlippingCount : null,
110
100
  });
111
101
  }}
112
102
  >
113
- <span style={{ color: "var(--dim)", letterSpacing: "-2px", marginRight: 2 }}>━━</span>
114
103
  {label}
115
- {showAuditBadge && (
116
- <span
117
- role="status"
118
- style={{
119
- display: "inline-flex",
120
- alignItems: "center",
121
- justifyContent: "center",
122
- minWidth: "1.4rem",
123
- height: "1rem",
124
- padding: "0 6px",
125
- fontFamily: "var(--font-mono)",
126
- fontSize: 10,
127
- letterSpacing: "0.05em",
128
- background: "var(--amber-bg)",
129
- color: "var(--amber)",
130
- border: "1px solid var(--amber)",
131
- marginLeft: 2,
132
- }}
133
- aria-label={`${auditSlippingCount} action${auditSlippingCount === 1 ? "" : "s"} slipping through your policies`}
134
- title={`${auditSlippingCount} slipping through`}
135
- >
136
- {auditSlippingCount}
137
- </span>
138
- )}
139
104
  </Link>
140
105
  );
141
106
  })}
@@ -2,10 +2,9 @@
2
2
  "use client";
3
3
 
4
4
  import React, { useState, useCallback } from "react";
5
- import { GitBranch, Lightbulb, Bug, MessageSquare, ChevronDown, Star, BookOpen, Hash } from "lucide-react";
5
+ import { GitBranch, ChevronDown, Star, BookOpen, MessageCircle, MessageSquareWarning } from "lucide-react";
6
6
  import { Button } from "@/components/ui/button";
7
7
 
8
- const GITHUB_REPO = "https://github.com/failproofai/failproofai";
9
8
  const CONTACT_EMAIL = "failproofai@exosphere.host";
10
9
 
11
10
  const options = [
@@ -19,38 +18,24 @@ const options = [
19
18
  {
20
19
  label: "Documentation",
21
20
  icon: BookOpen,
22
- href: "https://docs.befailproof.ai/",
21
+ href: "https://docs.befailproof.ai/introduction",
23
22
  color: "#60a5fa",
24
23
  bg: "rgba(96,165,250,0.08)",
25
24
  },
26
25
  {
27
- label: "Join our Slack",
28
- icon: Hash,
29
- href: "https://join.slack.com/t/failproofai/shared_invite/zt-3v63b7k5e-O3NBHmj8X6n9gZSGDx6ggQ",
30
- color: "#a78bfa",
31
- bg: "rgba(167,139,250,0.08)",
26
+ label: "Join our Discord",
27
+ icon: MessageCircle,
28
+ href: "https://discord.gg/2zjBZP7yQJ",
29
+ color: "#5865f2",
30
+ bg: "rgba(88,101,242,0.08)",
32
31
  },
33
32
  {
34
- label: "Request a Feature",
35
- icon: Lightbulb,
36
- href: `${GITHUB_REPO}/issues/new?labels=enhancement&title=Feature+Request%3A+`,
33
+ label: "Feedback & Issues",
34
+ icon: MessageSquareWarning,
35
+ href: "https://github.com/FailproofAI/failproofai/issues/new/choose",
37
36
  color: "#34d399",
38
37
  bg: "rgba(52,211,153,0.08)",
39
38
  },
40
- {
41
- label: "Report an Issue",
42
- icon: Bug,
43
- href: `${GITHUB_REPO}/issues/new?labels=bug&title=Bug+Report%3A+`,
44
- color: "#f87171",
45
- bg: "rgba(248,113,113,0.08)",
46
- },
47
- {
48
- label: "Ask a Question",
49
- icon: MessageSquare,
50
- href: `${GITHUB_REPO}/discussions/new?category=q-a`,
51
- color: "#fb923c",
52
- bg: "rgba(251,146,60,0.08)",
53
- },
54
39
  ] as const;
55
40
 
56
41
  export const ReachDevelopers: React.FC = () => {
@@ -239,6 +239,34 @@ export async function cancelReminder(accessToken: string): Promise<void> {
239
239
  throw await parseError(res);
240
240
  }
241
241
 
242
+ export interface InviteSendResult {
243
+ /** Recipients that were dispatched successfully. */
244
+ sent: string[];
245
+ /** Recipients that failed (bad address, bounce, rate-limit, etc.). */
246
+ failed: string[];
247
+ }
248
+
249
+ /**
250
+ * Send invite emails to a batch of friends. The api-server pulls the sender's
251
+ * email from the access-token claims and Cc's them on every outbound message
252
+ * so the recipient sees who invited them. `score` (the sender's audit score,
253
+ * 0–100) is forwarded so the invite body can show "mine came out at N/100";
254
+ * omit it and the api-server renders score-free copy.
255
+ *
256
+ * Contract is handed over to the platform team separately.
257
+ */
258
+ export async function sendInvites(
259
+ accessToken: string,
260
+ to: string[],
261
+ score?: number,
262
+ ): Promise<InviteSendResult> {
263
+ return postJson<InviteSendResult>(
264
+ "/v0/invite",
265
+ score === undefined ? { to } : { to, score },
266
+ { accessToken },
267
+ );
268
+ }
269
+
242
270
  interface JwtClaims {
243
271
  sub: string;
244
272
  email: string;
@@ -34,6 +34,10 @@ export function captureClientEvent(
34
34
  method: "POST",
35
35
  headers: { "Content-Type": "application/json" },
36
36
  body: payload,
37
+ // keepalive lets the request outlive a page navigation/unload — without it,
38
+ // events fired right before the page goes away (client_error / unhandled_*
39
+ // from an error boundary, or a share click that opens a new tab) are dropped.
40
+ keepalive: true,
37
41
  signal: AbortSignal.timeout(5000),
38
42
  }).catch(() => {});
39
43
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@next/env",
3
- "version": "16.2.7",
3
+ "version": "16.2.9",
4
4
  "keywords": [
5
5
  "react",
6
6
  "next",
@@ -33,4 +33,4 @@
33
33
  "dotenv": "16.3.1",
34
34
  "dotenv-expand": "10.0.0"
35
35
  }
36
- }
36
+ }
@@ -134,7 +134,7 @@ var HmrTarget = /*#__PURE__*/ function(HmrTarget) {
134
134
  HmrTarget["Server"] = "server";
135
135
  return HmrTarget;
136
136
  }({});
137
- const nextVersion = "16.2.7";
137
+ const nextVersion = "16.2.9";
138
138
  const ArchName = (0, _os.arch)();
139
139
  const PlatformName = (0, _os.platform)();
140
140
  function infoLog(...args) {