failproofai 1.0.0-beta.2 → 1.0.0-beta.21

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 (381) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +2 -1
  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 +3 -1
  10. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  11. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  13. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  14. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  15. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  16. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
  17. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  18. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  19. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +3 -3
  20. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  21. package/.next/standalone/.next/server/app/_not-found/page.js +3 -1
  22. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  24. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  25. package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
  26. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
  27. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  28. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
  29. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  30. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  31. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  32. package/.next/standalone/.next/server/app/api/audit/invite/route.js +3 -2
  33. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/api/audit/run/route.js +4 -3
  35. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/audit/status/route.js +1 -1
  37. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/api/auth/login-request/route.js +3 -1
  39. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +3 -2
  41. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/api/auth/logout/route.js +3 -2
  43. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/api/auth/reminder/route.js +3 -2
  45. package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/api/auth/status/route.js +3 -2
  47. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +1 -1
  49. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  50. package/.next/standalone/.next/server/app/audit/page/build-manifest.json +3 -3
  51. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  52. package/.next/standalone/.next/server/app/audit/page.js +5 -3
  53. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  54. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  55. package/.next/standalone/.next/server/app/index.html +1 -1
  56. package/.next/standalone/.next/server/app/index.rsc +15 -15
  57. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  58. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
  59. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
  60. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
  61. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  62. package/.next/standalone/.next/server/app/page/build-manifest.json +3 -3
  63. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  64. package/.next/standalone/.next/server/app/page.js +3 -1
  65. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  66. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  67. package/.next/standalone/.next/server/app/policies/page/build-manifest.json +3 -3
  68. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +30 -18
  69. package/.next/standalone/.next/server/app/policies/page.js +5 -3
  70. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  71. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  72. package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +3 -3
  73. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  74. package/.next/standalone/.next/server/app/project/[name]/page.js +4 -2
  75. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  76. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  77. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +3 -3
  78. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  79. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  80. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +6 -4
  81. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  82. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  83. package/.next/standalone/.next/server/app/projects/page/build-manifest.json +3 -3
  84. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  85. package/.next/standalone/.next/server/app/projects/page.js +4 -2
  86. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  87. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  88. package/.next/standalone/.next/server/app/settings/page/app-paths-manifest.json +3 -0
  89. package/.next/standalone/.next/server/app/settings/page/build-manifest.json +18 -0
  90. package/.next/standalone/.next/server/app/settings/page/next-font-manifest.json +6 -0
  91. package/.next/standalone/.next/server/app/settings/page/react-loadable-manifest.json +1 -0
  92. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +53 -0
  93. package/.next/standalone/.next/server/app/settings/page.js +18 -0
  94. package/.next/standalone/.next/server/app/settings/page.js.map +5 -0
  95. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -0
  96. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +3 -0
  97. package/.next/standalone/.next/server/app-paths-manifest.json +2 -1
  98. package/.next/standalone/.next/server/chunks/[externals]__0h9_83k._.js +3 -0
  99. package/.next/standalone/.next/server/chunks/{[externals]__1nl3dvw._.js → [externals]__0r-zamh._.js} +2 -2
  100. package/.next/standalone/.next/server/chunks/[externals]__1ifpkx-._.js +3 -0
  101. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0l4vuqm._.js → [root-of-the-server]__00ni9za._.js} +2 -2
  102. package/.next/standalone/.next/server/chunks/[root-of-the-server]__06hexd0._.js +3 -0
  103. package/.next/standalone/.next/server/chunks/[root-of-the-server]__08y94xv._.js +3 -0
  104. package/.next/standalone/.next/server/chunks/[root-of-the-server]__094p1f1._.js +3 -0
  105. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_0xu5z._.js +1 -1
  106. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ed01_d._.js +3 -0
  107. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0-dh5jy._.js → [root-of-the-server]__0effm9m._.js} +2 -2
  108. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0g0vcwt._.js +3 -0
  109. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__18d-9oi._.js → [root-of-the-server]__0ix8gm7._.js} +2 -2
  110. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0h3lfmp._.js → [root-of-the-server]__0ji11a-._.js} +2 -2
  111. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__10oa-v9._.js → [root-of-the-server]__0ojwjxl._.js} +2 -2
  112. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__16le-kd._.js → [root-of-the-server]__0pbp9fe._.js} +2 -2
  113. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q-v9z2._.js +1 -1
  114. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0vb5fl2._.js +3 -0
  115. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0sb_5m8._.js → [root-of-the-server]__131ebum._.js} +4 -4
  116. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ibjy5x._.js +3 -0
  117. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tvn4wf._.js +1 -1
  118. package/.next/standalone/.next/server/chunks/[root-of-the-server]__20d06rh._.js +3 -0
  119. package/.next/standalone/.next/server/chunks/_0lxbzdq._.js +3 -0
  120. package/.next/standalone/.next/server/chunks/_1zuiiy3._.js +3 -0
  121. package/.next/standalone/.next/server/chunks/lib_telemetry_ts_0dctyyw._.js +3 -0
  122. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +5 -5
  123. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +2 -1
  124. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +2 -1
  125. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  126. package/.next/standalone/.next/server/chunks/ssr/[externals]__1aq139v._.js +3 -0
  127. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0-wfhrp._.js +3 -0
  128. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__06bp_fg._.js +5 -0
  129. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__074qmkp._.js +3 -0
  130. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1apb7k_._.js → [root-of-the-server]__0_1tiya._.js} +2 -2
  131. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__170799-._.js → [root-of-the-server]__0spkm68._.js} +11 -11
  132. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0t281d4._.js +3 -0
  133. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17itmx-._.js +5 -0
  134. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__01od0m6._.js → [root-of-the-server]__1n2vcv4._.js} +2 -2
  135. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1qapotl._.js +1 -1
  136. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1rv-sc9._.js +3 -0
  137. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1tlvv9a._.js +3 -0
  138. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1u-wx42._.js +4 -0
  139. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1v185mo._.js +3 -0
  140. package/.next/standalone/.next/server/chunks/ssr/_0-yi74u._.js +3 -0
  141. package/.next/standalone/.next/server/chunks/ssr/_0rjgfln._.js +3 -0
  142. package/.next/standalone/.next/server/chunks/ssr/_0vo2qyt._.js +3 -0
  143. package/.next/standalone/.next/server/chunks/ssr/_0xej-0e._.js +3 -0
  144. package/.next/standalone/.next/server/chunks/ssr/_10399ge._.js +3 -0
  145. package/.next/standalone/.next/server/chunks/ssr/_11_p9y8._.js +1 -1
  146. package/.next/standalone/.next/server/chunks/ssr/_149k9oy._.js +3 -0
  147. package/.next/standalone/.next/server/chunks/ssr/_1_hwp06._.js +3 -0
  148. package/.next/standalone/.next/server/chunks/ssr/_1ctse6u._.js +3 -0
  149. package/.next/standalone/.next/server/chunks/ssr/_1e19atl._.js +1 -1
  150. package/.next/standalone/.next/server/chunks/ssr/_1mnhi_r._.js +3 -0
  151. package/.next/standalone/.next/server/chunks/ssr/_1ror7k9._.js +3 -0
  152. package/.next/standalone/.next/server/chunks/ssr/_1sdgprl._.js +5 -0
  153. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +2 -2
  154. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  155. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +2 -2
  156. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0dwo94s.js +4 -0
  157. package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +2 -1
  158. package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +3 -0
  159. package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.js +4 -0
  160. package/.next/standalone/.next/server/middleware-build-manifest.js +6 -6
  161. package/.next/standalone/.next/server/middleware.js +2 -2
  162. package/.next/standalone/.next/server/pages/404.html +1 -1
  163. package/.next/standalone/.next/server/pages/500.html +1 -1
  164. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  165. package/.next/standalone/.next/server/server-reference-manifest.json +74 -20
  166. package/.next/standalone/.next/static/chunks/{03fmihek9n986.js → 06zgzyh3wv1ig.js} +1 -1
  167. package/.next/standalone/.next/static/chunks/0km-jn9o5xyqs.css +2 -0
  168. package/.next/standalone/.next/static/chunks/{1hdhteui932bq.js → 0qmo2t50kpb30.js} +1 -1
  169. package/.next/standalone/.next/static/chunks/{2sbelanzvxvv0.js → 113g8wtal6_c4.js} +22 -22
  170. package/.next/standalone/.next/static/chunks/16p68cybetr31.js +1 -0
  171. package/.next/standalone/.next/static/chunks/18wqn0_3mzylf.js +1 -0
  172. package/.next/standalone/.next/static/chunks/1v1gqvpjk62jm.js +1 -0
  173. package/.next/standalone/.next/static/chunks/{0fi645si-uiiq.js → 1xq1m8h14tnlj.js} +1 -1
  174. package/.next/standalone/.next/static/chunks/{3hp8ulqknybil.js → 1y3vwogqb88dx.js} +1 -1
  175. package/.next/standalone/.next/static/chunks/{3vs4ay36tjds_.js → 1zmh-b0ulrqu7.js} +1 -1
  176. package/.next/standalone/.next/static/chunks/23kev26by1e4f.js +1 -0
  177. package/.next/standalone/.next/static/chunks/299lhw60e8gr6.js +1 -0
  178. package/.next/standalone/.next/static/chunks/{18rvdw5v72364.js → 2adbpdaxp5ygq.js} +1 -1
  179. package/.next/standalone/.next/static/chunks/{2j94uwkb4s3qr.js → 2kbqcw-6swmav.js} +1 -1
  180. package/.next/standalone/.next/static/chunks/2n9n5m0963pdg.js +6 -0
  181. package/.next/standalone/.next/static/chunks/2uvhw57mf9lg_.css +2 -0
  182. package/.next/standalone/.next/static/chunks/{31feojxhjyjpl.js → 30nrrpwymht5m.js} +1 -1
  183. package/.next/standalone/.next/static/chunks/31coz11ia5vc4.js +1 -0
  184. package/.next/standalone/.next/static/chunks/{turbopack-1lsv92x7klwrn.js → turbopack-3diub4ctvn1n0.js} +1 -1
  185. package/.next/standalone/SECURITY.md +8 -2
  186. package/.next/standalone/app/actions/get-active-pauses.ts +16 -0
  187. package/.next/standalone/app/actions/get-hooks-config.ts +2 -2
  188. package/.next/standalone/app/actions/get-scheduled-audit.ts +70 -0
  189. package/.next/standalone/app/actions/update-scheduled-audit.ts +44 -0
  190. package/.next/standalone/app/api/audit/run/route.ts +28 -0
  191. package/.next/standalone/app/api/audit/status/route.ts +13 -1
  192. package/.next/standalone/app/api/auth/status/route.ts +1 -1
  193. package/.next/standalone/app/audit/_components/audit-dashboard.tsx +1 -3
  194. package/.next/standalone/app/audit/_components/audit-progress-strip.tsx +1 -1
  195. package/.next/standalone/app/audit/_components/auth-dialog.css +159 -0
  196. package/.next/standalone/app/audit/_components/auth-dialog.tsx +3 -0
  197. package/.next/standalone/app/audit/_components/come-back-better-section.tsx +1 -1
  198. package/.next/standalone/app/audit/_components/empty-state.tsx +0 -1
  199. package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +1 -1
  200. package/.next/standalone/app/audit/_components/quirks-section.tsx +0 -1
  201. package/.next/standalone/app/audit/_components/report-footer.tsx +0 -2
  202. package/.next/standalone/app/audit/_components/run-progress.tsx +1 -1
  203. package/.next/standalone/app/audit/_components/strengths-section.tsx +0 -1
  204. package/.next/standalone/app/audit/audit-styles.css +6 -149
  205. package/.next/standalone/app/components/pause-notices.tsx +111 -0
  206. package/.next/standalone/app/components/raw-log-viewer.tsx +1 -1
  207. package/.next/standalone/app/components/toast.tsx +1 -1
  208. package/.next/standalone/app/policies/hooks-client.tsx +84 -8
  209. package/.next/standalone/app/settings/page.tsx +31 -0
  210. package/.next/standalone/app/settings/settings-client.tsx +487 -0
  211. package/.next/standalone/components/navbar.tsx +2 -0
  212. package/.next/standalone/lib/auth/api-server-client.ts +2 -3
  213. package/.next/standalone/lib/auth/auth-store.ts +4 -5
  214. package/.next/standalone/lib/codex-sessions.ts +2 -1
  215. package/.next/standalone/lib/dashboard-host.ts +101 -0
  216. package/.next/standalone/lib/install-check.ts +22 -7
  217. package/.next/standalone/lib/pi-sessions.ts +99 -14
  218. package/.next/standalone/lib/telemetry-enabled.ts +54 -0
  219. package/.next/standalone/lib/telemetry-id.ts +52 -1
  220. package/.next/standalone/lib/telemetry.ts +8 -4
  221. package/.next/standalone/node_modules/react/cjs/react.development.js +1 -1
  222. package/.next/standalone/node_modules/react/cjs/react.production.js +1 -1
  223. package/.next/standalone/node_modules/react/package.json +3 -3
  224. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.js +1 -1
  225. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.node.production.js +1 -1
  226. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.browser.production.js +3 -3
  227. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.edge.production.js +3 -3
  228. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.node.production.js +3 -3
  229. package/.next/standalone/node_modules/react-dom/cjs/react-dom.production.js +1 -1
  230. package/.next/standalone/node_modules/react-dom/package.json +4 -4
  231. package/.next/standalone/package.json +23 -12
  232. package/.next/standalone/proxy.ts +111 -1
  233. package/.next/standalone/server.js +1 -1
  234. package/bin/failproofai-worker.mjs +1 -1
  235. package/bin/failproofai.mjs +1041 -81
  236. package/bin/failproofaid-shim.mjs +4 -4
  237. package/dist/cli.mjs +18513 -10474
  238. package/dist/worker.mjs +1223 -299
  239. package/lib/auth/api-server-client.ts +2 -3
  240. package/lib/auth/auth-store.ts +4 -5
  241. package/lib/codex-sessions.ts +2 -1
  242. package/lib/dashboard-host.ts +101 -0
  243. package/lib/install-check.ts +22 -7
  244. package/lib/pi-sessions.ts +99 -14
  245. package/lib/telemetry-enabled.ts +54 -0
  246. package/lib/telemetry-id.ts +52 -1
  247. package/lib/telemetry.ts +8 -4
  248. package/package.json +23 -12
  249. package/scripts/build-daemon-packages.mjs +247 -0
  250. package/scripts/daemon-platforms.mjs +42 -0
  251. package/scripts/dev-hook.mjs +46 -5
  252. package/scripts/install-telemetry.mjs +8 -1
  253. package/scripts/launch.ts +25 -3
  254. package/scripts/parse-script-args.ts +27 -1
  255. package/scripts/prune-standalone.mjs +26 -0
  256. package/scripts/publish-aliases.mjs +62 -41
  257. package/scripts/repro-npm-install.sh +155 -0
  258. package/scripts/translate-docs/cache.ts +1 -1
  259. package/scripts/translate-docs/cli.ts +2 -2
  260. package/scripts/translate-docs/mintlify-nav.ts +1 -1
  261. package/scripts/translate-docs/readme-translator.ts +163 -4
  262. package/scripts/validate-mdx.ts +153 -13
  263. package/src/audit/audit-lock.ts +285 -0
  264. package/src/audit/audit-schedule.ts +111 -0
  265. package/src/audit/cache.ts +18 -5
  266. package/src/audit/cli-adapters/goose.ts +2 -1
  267. package/src/audit/cli-adapters/hermes.ts +28 -10
  268. package/src/audit/cli.ts +191 -35
  269. package/src/audit/dashboard-cache.ts +2 -3
  270. package/src/audit/report.ts +0 -1
  271. package/src/hooks/backfill-cli.ts +247 -0
  272. package/src/hooks/builtin-policies.ts +391 -3
  273. package/src/hooks/cloud-connection.ts +354 -0
  274. package/src/hooks/cloud-enrollment-cli.ts +439 -0
  275. package/src/hooks/cloud-enrollment.ts +284 -0
  276. package/src/hooks/cloud-introspect.ts +147 -0
  277. package/src/hooks/cloud-managed-policies.ts +206 -0
  278. package/src/hooks/collector-config.ts +218 -0
  279. package/src/hooks/configure-wizard.ts +1211 -233
  280. package/src/hooks/custom-hooks-loader.ts +243 -37
  281. package/src/hooks/daemon-client.ts +136 -33
  282. package/src/hooks/daemon-download.ts +264 -31
  283. package/src/hooks/daemon-service.ts +1124 -76
  284. package/src/hooks/first-run-gate.ts +50 -0
  285. package/src/hooks/flush-cli.ts +180 -0
  286. package/src/hooks/fp-config.ts +835 -0
  287. package/src/hooks/fp-home.ts +714 -0
  288. package/src/hooks/fp-reset.ts +1363 -0
  289. package/src/hooks/handler.ts +185 -6
  290. package/src/hooks/harness-cli.ts +386 -0
  291. package/src/hooks/hook-activity-store.ts +171 -24
  292. package/src/hooks/hook-logger.ts +2 -2
  293. package/src/hooks/hook-telemetry.ts +5 -1
  294. package/src/hooks/hooks-config.ts +4 -3
  295. package/src/hooks/integrations.ts +0 -1
  296. package/src/hooks/loader-utils.ts +172 -9
  297. package/src/hooks/manager.ts +41 -5
  298. package/src/hooks/migrations.ts +450 -0
  299. package/src/hooks/onboarding-attempt.ts +195 -0
  300. package/src/hooks/onboarding-lock.ts +118 -0
  301. package/src/hooks/policy-types.ts +28 -0
  302. package/src/hooks/session-pause-cli.ts +159 -0
  303. package/src/hooks/session-pause.ts +267 -0
  304. package/src/hooks/setup-state.ts +256 -0
  305. package/src/hooks/tui.ts +209 -9
  306. package/src/hooks/uninstall-cli.ts +418 -0
  307. package/src/hooks/worker-server.ts +134 -15
  308. package/.next/standalone/.next/server/chunks/[externals]__14odj07._.js +0 -3
  309. package/.next/standalone/.next/server/chunks/[externals]__1s61mel._.js +0 -3
  310. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0id_xf7._.js +0 -3
  311. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0longh-._.js +0 -3
  312. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +0 -3
  313. package/.next/standalone/.next/server/chunks/[root-of-the-server]__19120tr._.js +0 -3
  314. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fwl2mz._.js +0 -3
  315. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1myjm-d._.js +0 -3
  316. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rhmvod._.js +0 -3
  317. package/.next/standalone/.next/server/chunks/ssr/[externals]__1_g_b3t._.js +0 -3
  318. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0114ewg._.js +0 -4
  319. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02r5bgf._.js +0 -4
  320. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e8sjqm._.js +0 -4
  321. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0lkzqax._.js +0 -4
  322. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0nb0syg._.js +0 -3
  323. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qucxyj._.js +0 -4
  324. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0u02miy._.js +0 -4
  325. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0uno39i._.js +0 -3
  326. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__14dd6h8._.js +0 -3
  327. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ath6v_._.js +0 -4
  328. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1psjybo._.js +0 -3
  329. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1zqz4v8._.js +0 -4
  330. package/.next/standalone/.next/server/chunks/ssr/_1m_p7pi._.js +0 -3
  331. package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_0oy_-36.js +0 -3
  332. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1ezd2jf._.js +0 -5
  333. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1tnuifj._.js +0 -5
  334. package/.next/standalone/.next/static/chunks/0h7auy7hzjyhw.js +0 -1
  335. package/.next/standalone/.next/static/chunks/0zbxssxh53n-3.js +0 -1
  336. package/.next/standalone/.next/static/chunks/2mazwb1qmur1p.js +0 -1
  337. package/.next/standalone/.next/static/chunks/2pujpnfx4pws6.css +0 -2
  338. package/.next/standalone/.next/static/chunks/33u59vf_8xpd-.js +0 -1
  339. package/.next/standalone/.next/static/chunks/3i27c3hcriawq.css +0 -1
  340. package/.next/standalone/.next/static/chunks/3s7myk_co0gbh.js +0 -1
  341. package/.next/standalone/.next/static/chunks/40k1_v4os4cw6.js +0 -6
  342. package/.next/standalone/Cargo.lock +0 -428
  343. package/.next/standalone/Cargo.toml +0 -9
  344. package/.next/standalone/crates/PROTOCOL.md +0 -122
  345. package/.next/standalone/crates/failproofaid/Cargo.toml +0 -18
  346. package/.next/standalone/crates/failproofaid/src/lock.rs +0 -81
  347. package/.next/standalone/crates/failproofaid/src/main.rs +0 -83
  348. package/.next/standalone/crates/failproofaid/src/paths.rs +0 -172
  349. package/.next/standalone/crates/failproofaid/src/server.rs +0 -502
  350. package/.next/standalone/crates/failproofaid/src/worker.rs +0 -400
  351. package/.next/standalone/crates/failproofaid/tests/daemon_e2e.rs +0 -241
  352. package/.next/standalone/crates/fpai-ipc/Cargo.toml +0 -16
  353. package/.next/standalone/crates/fpai-ipc/src/envelope.rs +0 -175
  354. package/.next/standalone/crates/fpai-ipc/src/framing.rs +0 -177
  355. package/.next/standalone/crates/fpai-ipc/src/lib.rs +0 -10
  356. package/.next/standalone/crates/fpai-ipc/src/peer.rs +0 -80
  357. package/.next/standalone/docker-hook-sync/Dockerfile +0 -79
  358. package/.next/standalone/docker-hook-sync/entrypoint.sh +0 -109
  359. package/.next/standalone/integration-suite/Dockerfile +0 -47
  360. package/.next/standalone/integration-suite/README.md +0 -129
  361. package/.next/standalone/integration-suite/canary-policies.mjs +0 -45
  362. package/.next/standalone/integration-suite/capture-tokens.sh +0 -48
  363. package/.next/standalone/integration-suite/ci-entrypoint.sh +0 -179
  364. package/.next/standalone/integration-suite/inject-tokens.sh +0 -44
  365. package/.next/standalone/integration-suite/install-clis.sh +0 -136
  366. package/.next/standalone/integration-suite/probe-cli.sh +0 -248
  367. package/.next/standalone/integration-suite/report.js +0 -120
  368. package/.next/standalone/integration-suite/run.sh +0 -159
  369. package/.next/standalone/openclaw-plugin/index.js +0 -223
  370. package/.next/standalone/openclaw-plugin/openclaw.plugin.json +0 -6
  371. package/.next/standalone/openclaw-plugin/package.json +0 -12
  372. package/.next/standalone/osv-scanner.toml +0 -17
  373. package/.next/standalone/pi-extension/index.ts +0 -524
  374. package/.next/standalone/pi-extension/package.json +0 -12
  375. package/.next/standalone/postcss.config.mjs +0 -8
  376. package/.next/standalone/readme-arch-hq.gif +0 -0
  377. package/.next/standalone/rust-toolchain.toml +0 -4
  378. package/src/auth/cli.ts +0 -371
  379. /package/.next/standalone/.next/static/{NWAjs0tHFyzk97gRGG09r → VjEdIL6W5uBsvEzknXqV9}/_buildManifest.js +0 -0
  380. /package/.next/standalone/.next/static/{NWAjs0tHFyzk97gRGG09r → VjEdIL6W5uBsvEzknXqV9}/_clientMiddlewareManifest.js +0 -0
  381. /package/.next/standalone/.next/static/{NWAjs0tHFyzk97gRGG09r → VjEdIL6W5uBsvEzknXqV9}/_ssgManifest.js +0 -0
@@ -1,502 +0,0 @@
1
- //! The Unix-socket server: bind, accept, verify the peer, dispatch one
2
- //! request per connection.
3
- //!
4
- //! `Hook` requests are relayed to the warm worker (see `worker.rs`); `Ping`
5
- //! is answered directly. Any failure to reach/use the worker becomes a
6
- //! client-facing `Error` response — never a hang, never a crash of the
7
- //! connection-handling thread.
8
-
9
- use crate::worker::Worker;
10
- use fpai_ipc::{ClientMessage, PROTOCOL_VERSION, ServerMessage, peer, read_message, write_message};
11
- use std::fs;
12
- use std::io;
13
- use std::os::unix::fs::PermissionsExt;
14
- use std::os::unix::net::{UnixListener, UnixStream};
15
- use std::path::{Path, PathBuf};
16
- use std::sync::Arc;
17
- use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
18
- use std::time::Duration;
19
-
20
- /// Bounds how long a single connection may hold its handler thread waiting
21
- /// on the peer. A client that connects and then sends nothing would
22
- /// otherwise park a thread for the daemon's entire lifetime, and those
23
- /// accumulate — the opposite of the "never a hang" promise above. Generous
24
- /// for a real client (which writes its request immediately after connect,
25
- /// over a local socket) and still bounded.
26
- const CONNECTION_IO_TIMEOUT: Duration = Duration::from_secs(10);
27
-
28
- /// Hard ceiling on connection-handling threads alive at once. The worker
29
- /// serializes evaluation anyway, so more than a handful in flight already
30
- /// means the daemon is badly backed up; refusing past this point turns
31
- /// "spawn threads until the process dies" into a bounded, logged overload
32
- /// that the client sees as an unreachable daemon (i.e. its own fail-closed
33
- /// path), which is the correct outcome for a daemon in that state.
34
- const MAX_INFLIGHT_CONNECTIONS: usize = 64;
35
-
36
- pub struct Server {
37
- listener: UnixListener,
38
- socket_path: PathBuf,
39
- worker: Arc<Worker>,
40
- }
41
-
42
- /// Decrements the in-flight connection count on scope exit, including
43
- /// during an unwind — a leaked count would permanently shrink the budget in
44
- /// [`MAX_INFLIGHT_CONNECTIONS`] and eventually wedge the daemon.
45
- struct InflightGuard(Arc<AtomicUsize>);
46
-
47
- impl Drop for InflightGuard {
48
- fn drop(&mut self) {
49
- self.0.fetch_sub(1, Ordering::Relaxed);
50
- }
51
- }
52
-
53
- impl Server {
54
- /// Binds a fresh listener at `socket_path`, replacing a stale socket
55
- /// file left behind by a process that didn't shut down cleanly (a live
56
- /// daemon is never listening on a leftover file — the singleton lock in
57
- /// `lock.rs` is what actually prevents two daemons; this only clears
58
- /// the debris of one that's already gone).
59
- pub fn bind(socket_path: &Path, worker: Arc<Worker>) -> io::Result<Self> {
60
- if socket_path.exists() {
61
- fs::remove_file(socket_path)?;
62
- }
63
- let listener = UnixListener::bind(socket_path)?;
64
- fs::set_permissions(socket_path, fs::Permissions::from_mode(0o600))?;
65
- Ok(Server {
66
- listener,
67
- socket_path: socket_path.to_path_buf(),
68
- worker,
69
- })
70
- }
71
-
72
- /// Accepts and handles connections, one thread per connection, until
73
- /// `shutdown` is set to `true`. A short accept timeout keeps the loop
74
- /// polling `shutdown` instead of blocking forever in `accept()`, which
75
- /// is what lets tests stop a server cleanly instead of leaking a
76
- /// blocked thread for the rest of the test process's life.
77
- pub fn run_until(&self, shutdown: Arc<AtomicBool>) -> io::Result<()> {
78
- self.listener.set_nonblocking(true)?;
79
- let inflight = Arc::new(AtomicUsize::new(0));
80
- while !shutdown.load(Ordering::Relaxed) {
81
- match self.listener.accept() {
82
- Ok((stream, _addr)) => {
83
- if inflight.load(Ordering::Relaxed) >= MAX_INFLIGHT_CONNECTIONS {
84
- log_connection_error(&io::Error::other(format!(
85
- "refusing connection: {MAX_INFLIGHT_CONNECTIONS} handlers already in flight"
86
- )));
87
- drop(stream);
88
- continue;
89
- }
90
- inflight.fetch_add(1, Ordering::Relaxed);
91
- let guard = InflightGuard(inflight.clone());
92
- let worker = self.worker.clone();
93
- std::thread::spawn(move || {
94
- let _guard = guard;
95
- if let Err(err) = handle_connection(stream, &worker) {
96
- log_connection_error(&err);
97
- }
98
- });
99
- }
100
- Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
101
- std::thread::sleep(std::time::Duration::from_millis(20));
102
- }
103
- Err(err) => return Err(err),
104
- }
105
- }
106
- Ok(())
107
- }
108
- }
109
-
110
- impl Drop for Server {
111
- fn drop(&mut self) {
112
- let _ = fs::remove_file(&self.socket_path);
113
- }
114
- }
115
-
116
- fn log_connection_error(err: &io::Error) {
117
- eprintln!("[failproofaid] connection error: {err}");
118
- }
119
-
120
- /// Handles exactly one request on `stream`: verify the peer is the same OS
121
- /// user, read one framed [`ClientMessage`], dispatch it, write back one
122
- /// framed [`ServerMessage`], then let the connection close.
123
- pub fn handle_connection(stream: UnixStream, worker: &Worker) -> io::Result<()> {
124
- match peer::is_same_user(&stream) {
125
- Ok(true) => {}
126
- Ok(false) => {
127
- // Different OS user: drop the connection with no response at
128
- // all, rather than an Error message that would confirm a
129
- // daemon is listening here to a peer that has no business
130
- // asking.
131
- return Ok(());
132
- }
133
- Err(err) => return Err(err),
134
- }
135
-
136
- // `run_until` puts the *listener* in non-blocking mode. On Linux that
137
- // doesn't reach accepted sockets (std uses `accept4`), but on
138
- // BSD-derived systems — macOS, which this daemon supports via launchd —
139
- // the accepted socket inherits `O_NONBLOCK` from the listener. Left
140
- // inherited, `read_message` below returns `WouldBlock` the instant the
141
- // client's bytes haven't landed yet, which this function would treat as
142
- // a malformed frame and answer with silence: every hook call on macOS
143
- // would fail closed. Set the mode explicitly rather than relying on
144
- // per-platform accept semantics.
145
- stream.set_nonblocking(false)?;
146
- // Bound the peer's share of this thread's life in both directions (see
147
- // CONNECTION_IO_TIMEOUT).
148
- stream.set_read_timeout(Some(CONNECTION_IO_TIMEOUT))?;
149
- stream.set_write_timeout(Some(CONNECTION_IO_TIMEOUT))?;
150
-
151
- let mut reader = stream.try_clone()?;
152
- let mut writer = stream;
153
-
154
- let request: ClientMessage = match read_message(&mut reader) {
155
- Ok(msg) => msg,
156
- Err(_) => return Ok(()), // malformed frame: nothing to respond to, nothing to act on
157
- };
158
-
159
- let response = dispatch(request, worker);
160
- write_message(&mut writer, &response)
161
- .map_err(|e| io::Error::other(format!("failed to write response: {e}")))
162
- }
163
-
164
- fn dispatch(request: ClientMessage, worker: &Worker) -> ServerMessage {
165
- if request.protocol_version() != PROTOCOL_VERSION {
166
- return ServerMessage::Error {
167
- protocol_version: PROTOCOL_VERSION,
168
- message: format!(
169
- "protocol version mismatch: daemon speaks {PROTOCOL_VERSION}, client sent {}",
170
- request.protocol_version()
171
- ),
172
- };
173
- }
174
-
175
- match request {
176
- ClientMessage::Ping { .. } => ServerMessage::Pong {
177
- protocol_version: PROTOCOL_VERSION,
178
- },
179
- ClientMessage::Hook {
180
- hook_event,
181
- cli,
182
- stdin,
183
- cwd,
184
- ..
185
- } => match worker.call(&hook_event, &cli, &stdin, cwd.as_deref()) {
186
- Ok(outcome) => ServerMessage::HookResult {
187
- protocol_version: PROTOCOL_VERSION,
188
- exit_code: outcome.exit_code,
189
- stdout: outcome.stdout,
190
- stderr: outcome.stderr,
191
- },
192
- Err(err) => ServerMessage::Error {
193
- protocol_version: PROTOCOL_VERSION,
194
- message: format!("worker call failed: {err}"),
195
- },
196
- },
197
- }
198
- }
199
-
200
- #[cfg(test)]
201
- mod tests {
202
- use super::*;
203
- use crate::worker::WorkerCommand;
204
- use std::sync::atomic::AtomicBool;
205
- use std::time::Duration;
206
-
207
- fn temp_socket_path(name: &str) -> PathBuf {
208
- std::env::temp_dir().join(format!(
209
- "failproofaid-server-test-{}-{}-{}",
210
- std::process::id(),
211
- name,
212
- fastrand_ish()
213
- ))
214
- }
215
-
216
- // Avoids pulling in a `rand` dependency just to de-collide temp socket
217
- // paths across tests running in parallel threads.
218
- fn fastrand_ish() -> u64 {
219
- use std::time::{SystemTime, UNIX_EPOCH};
220
- SystemTime::now()
221
- .duration_since(UNIX_EPOCH)
222
- .unwrap()
223
- .as_nanos() as u64
224
- }
225
-
226
- /// A `WorkerCommand` that never produces a working worker — for tests
227
- /// that don't care about Hook responses and just need *a* command
228
- /// (Ping never touches the worker at all).
229
- fn broken_worker_cmd() -> WorkerCommand {
230
- WorkerCommand::shell("true")
231
- }
232
-
233
- /// Owns a running test server + the worker it supervises. Shuts the
234
- /// server down and joins its thread on drop — including during an
235
- /// unwind from a failed `assert!`/`.unwrap()` — so a failing test
236
- /// cleans up its spawned worker process (via `Worker::drop`'s
237
- /// process-group kill, see worker.rs) exactly as reliably as a passing
238
- /// one. Before this guard existed, a panic between `start_test_server`
239
- /// and the manual `shutdown.store` + `handle.join()` at the end of a
240
- /// test permanently orphaned the server thread and its live `bun`
241
- /// worker subprocess — reproduced live: three orphaned
242
- /// `failproofai-worker.mjs` processes were still running, minutes
243
- /// later, from earlier iterations of this very test file.
244
- struct TestServerGuard {
245
- shutdown: Arc<AtomicBool>,
246
- handle: Option<std::thread::JoinHandle<()>>,
247
- }
248
-
249
- impl Drop for TestServerGuard {
250
- fn drop(&mut self) {
251
- self.shutdown.store(true, Ordering::Relaxed);
252
- if let Some(handle) = self.handle.take() {
253
- let _ = handle.join();
254
- }
255
- }
256
- }
257
-
258
- fn start_test_server_with_worker(
259
- socket_path: PathBuf,
260
- worker_cmd: WorkerCommand,
261
- ) -> TestServerGuard {
262
- let shutdown = Arc::new(AtomicBool::new(false));
263
- let shutdown_clone = shutdown.clone();
264
- let worker_socket_path = temp_socket_path("worker-internal");
265
- let handle = std::thread::spawn(move || {
266
- let worker = Arc::new(crate::worker::Worker::new(worker_socket_path, worker_cmd));
267
- let server = Server::bind(&socket_path, worker).expect("bind should succeed");
268
- server
269
- .run_until(shutdown_clone)
270
- .expect("run_until should not error");
271
- });
272
- // Give the background thread a moment to actually bind before the
273
- // test tries to connect.
274
- std::thread::sleep(Duration::from_millis(50));
275
- TestServerGuard {
276
- shutdown,
277
- handle: Some(handle),
278
- }
279
- }
280
-
281
- fn start_test_server(socket_path: PathBuf) -> TestServerGuard {
282
- start_test_server_with_worker(socket_path, broken_worker_cmd())
283
- }
284
-
285
- #[test]
286
- fn ping_gets_pong() {
287
- let socket_path = temp_socket_path("ping");
288
- let _guard = start_test_server(socket_path.clone());
289
-
290
- let mut stream = UnixStream::connect(&socket_path).unwrap();
291
- write_message(
292
- &mut stream,
293
- &ClientMessage::Ping {
294
- protocol_version: PROTOCOL_VERSION,
295
- },
296
- )
297
- .unwrap();
298
- let response: ServerMessage = read_message(&mut stream).unwrap();
299
- assert_eq!(
300
- response,
301
- ServerMessage::Pong {
302
- protocol_version: PROTOCOL_VERSION
303
- }
304
- );
305
- }
306
-
307
- #[test]
308
- fn hook_request_gets_an_error_when_the_worker_cannot_be_reached() {
309
- let socket_path = temp_socket_path("hook-broken-worker");
310
- let _guard = start_test_server(socket_path.clone());
311
-
312
- let mut stream = UnixStream::connect(&socket_path).unwrap();
313
- write_message(
314
- &mut stream,
315
- &ClientMessage::Hook {
316
- protocol_version: PROTOCOL_VERSION,
317
- hook_event: "PreToolUse".to_string(),
318
- cli: "claude".to_string(),
319
- stdin: "{}".to_string(),
320
- cwd: None,
321
- },
322
- )
323
- .unwrap();
324
- let response: ServerMessage = read_message(&mut stream).unwrap();
325
- match response {
326
- ServerMessage::Error { .. } => {}
327
- other => panic!("expected Error, got {other:?}"),
328
- }
329
- }
330
-
331
- /// The real end-to-end path: a real `failproofaid` server relaying a
332
- /// real Hook request to the real TypeScript worker (spawned via `bun`
333
- /// against this repo's own `bin/failproofai-worker.mjs`), which runs
334
- /// the actual, unmodified policy-evaluation engine. Proves Rust and TS
335
- /// sides of the wire protocol actually agree, not just that each side's
336
- /// own unit tests pass in isolation.
337
- #[test]
338
- fn relays_a_hook_request_to_the_real_typescript_worker_end_to_end() {
339
- let repo_root = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
340
- .parent()
341
- .and_then(|p| p.parent())
342
- .expect("crates/failproofaid should be two levels under the repo root")
343
- .to_path_buf();
344
- let worker_script = repo_root.join("bin").join("failproofai-worker.mjs");
345
- assert!(
346
- worker_script.exists(),
347
- "expected {worker_script:?} to exist"
348
- );
349
-
350
- // A real project dir with block-sudo enabled, so the response
351
- // proves real policy evaluation ran, not just that SOME response
352
- // came back.
353
- let project_dir = std::env::temp_dir().join(format!(
354
- "failproofaid-e2e-project-{}-{}",
355
- std::process::id(),
356
- fastrand_ish()
357
- ));
358
- std::fs::create_dir_all(project_dir.join(".failproofai")).unwrap();
359
- std::fs::write(
360
- project_dir
361
- .join(".failproofai")
362
- .join("policies-config.json"),
363
- r#"{"enabledPolicies":["block-sudo"]}"#,
364
- )
365
- .unwrap();
366
-
367
- let socket_path = temp_socket_path("hook-real-worker");
368
- let worker_cmd = WorkerCommand::shell(format!("bun {}", worker_script.display()));
369
- let _guard = start_test_server_with_worker(socket_path.clone(), worker_cmd);
370
-
371
- let stdin = serde_json::json!({
372
- "cwd": project_dir.to_string_lossy(),
373
- "tool_name": "Bash",
374
- "tool_input": { "command": "sudo rm -rf /" },
375
- })
376
- .to_string();
377
-
378
- let mut stream = UnixStream::connect(&socket_path).unwrap();
379
- stream
380
- .set_read_timeout(Some(Duration::from_secs(15)))
381
- .unwrap();
382
- write_message(
383
- &mut stream,
384
- &ClientMessage::Hook {
385
- protocol_version: PROTOCOL_VERSION,
386
- hook_event: "PreToolUse".to_string(),
387
- cli: "claude".to_string(),
388
- stdin,
389
- cwd: Some(project_dir.to_string_lossy().to_string()),
390
- },
391
- )
392
- .unwrap();
393
- let response: ServerMessage = read_message(&mut stream).unwrap();
394
- match response {
395
- ServerMessage::HookResult {
396
- exit_code, stdout, ..
397
- } => {
398
- // Claude's PreToolUse deny contract is JSON on stdout at
399
- // exit 0 (hookSpecificOutput.permissionDecision), not a
400
- // nonzero exit code.
401
- assert_eq!(exit_code, 0);
402
- assert!(
403
- stdout.contains("\"permissionDecision\":\"deny\""),
404
- "expected a real deny from block-sudo, got stdout: {stdout}"
405
- );
406
- }
407
- other => panic!("expected HookResult, got {other:?}"),
408
- }
409
-
410
- std::fs::remove_dir_all(&project_dir).ok();
411
- }
412
-
413
- #[test]
414
- fn mismatched_protocol_version_gets_an_explicit_error() {
415
- let socket_path = temp_socket_path("version-mismatch");
416
- let _guard = start_test_server(socket_path.clone());
417
-
418
- let mut stream = UnixStream::connect(&socket_path).unwrap();
419
- write_message(
420
- &mut stream,
421
- &ClientMessage::Ping {
422
- protocol_version: PROTOCOL_VERSION + 999,
423
- },
424
- )
425
- .unwrap();
426
- let response: ServerMessage = read_message(&mut stream).unwrap();
427
- match response {
428
- ServerMessage::Error { message, .. } => {
429
- assert!(message.contains("version"));
430
- }
431
- other => panic!("expected Error, got {other:?}"),
432
- }
433
- }
434
-
435
- #[test]
436
- fn bind_replaces_a_stale_socket_file() {
437
- let socket_path = temp_socket_path("stale");
438
- // Simulate a leftover file from a crashed daemon: not even a valid
439
- // socket, just a regular file at that path.
440
- std::fs::write(&socket_path, b"not a socket").unwrap();
441
-
442
- let worker = Arc::new(crate::worker::Worker::new(
443
- temp_socket_path("stale-worker"),
444
- broken_worker_cmd(),
445
- ));
446
- let server = Server::bind(&socket_path, worker).expect("bind should clear the stale file");
447
- drop(server);
448
- assert!(
449
- !socket_path.exists(),
450
- "Drop should clean up the socket file"
451
- );
452
- }
453
-
454
- #[test]
455
- fn bound_socket_file_is_owner_only() {
456
- let socket_path = temp_socket_path("perms");
457
- let worker = Arc::new(crate::worker::Worker::new(
458
- temp_socket_path("perms-worker"),
459
- broken_worker_cmd(),
460
- ));
461
- let server = Server::bind(&socket_path, worker).unwrap();
462
- let mode = std::fs::metadata(&socket_path)
463
- .unwrap()
464
- .permissions()
465
- .mode()
466
- & 0o777;
467
- assert_eq!(mode, 0o600);
468
- drop(server);
469
- }
470
-
471
- #[test]
472
- fn multiple_concurrent_pings_all_get_answered() {
473
- let socket_path = temp_socket_path("concurrent");
474
- let _guard = start_test_server(socket_path.clone());
475
-
476
- let clients: Vec<_> = (0..8)
477
- .map(|_| {
478
- let path = socket_path.clone();
479
- std::thread::spawn(move || {
480
- let mut stream = UnixStream::connect(&path).unwrap();
481
- write_message(
482
- &mut stream,
483
- &ClientMessage::Ping {
484
- protocol_version: PROTOCOL_VERSION,
485
- },
486
- )
487
- .unwrap();
488
- let response: ServerMessage = read_message(&mut stream).unwrap();
489
- assert_eq!(
490
- response,
491
- ServerMessage::Pong {
492
- protocol_version: PROTOCOL_VERSION
493
- }
494
- );
495
- })
496
- })
497
- .collect();
498
- for c in clients {
499
- c.join().unwrap();
500
- }
501
- }
502
- }