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,175 +0,0 @@
1
- //! The JSON envelope carried inside each [`crate::framing`] frame.
2
- //!
3
- //! This mirrors the `(argv --hook <Event> --cli <cli>, stdin JSON payload)
4
- //! -> (stdout, stderr, exitCode)` contract every hook invocation already
5
- //! has today — see `src/hooks/handler.ts`'s `handleHookEvent`. The daemon
6
- //! adds nothing to that contract; it only relays it over a socket instead
7
- //! of a fresh process's argv/stdin/stdout.
8
-
9
- use serde::{Deserialize, Serialize};
10
-
11
- /// Bumped whenever a wire-incompatible change is made to either message
12
- /// enum below. The client treats any mismatch identically to "daemon
13
- /// unreachable" (see `docs/configuration.mdx` and the failproofaid plan) —
14
- /// there is no negotiation, only agree-or-fall-back.
15
- pub const PROTOCOL_VERSION: u32 = 1;
16
-
17
- #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
18
- #[serde(tag = "type", rename_all = "camelCase")]
19
- pub enum ClientMessage {
20
- /// Cheap liveness/handshake check — used by tests and by a client that
21
- /// only wants to confirm a compatible daemon is listening.
22
- #[serde(rename_all = "camelCase")]
23
- Ping { protocol_version: u32 },
24
- /// One hook evaluation request, corresponding 1:1 to one
25
- /// `failproofai --hook <Event> --cli <cli>` invocation.
26
- #[serde(rename_all = "camelCase")]
27
- Hook {
28
- protocol_version: u32,
29
- hook_event: String,
30
- cli: String,
31
- /// The raw stdin payload the calling agent CLI wrote to the
32
- /// one-shot `failproofai` process — forwarded verbatim.
33
- stdin: String,
34
- /// Best-effort cwd of the *originating* CLI process, not the
35
- /// daemon's own cwd (the daemon is a single long-lived process; its
36
- /// own `cwd` does not vary per request and must never be used to
37
- /// resolve project config or custom policies).
38
- cwd: Option<String>,
39
- },
40
- }
41
-
42
- #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
43
- #[serde(tag = "type", rename_all = "camelCase")]
44
- pub enum ServerMessage {
45
- #[serde(rename_all = "camelCase")]
46
- Pong { protocol_version: u32 },
47
- #[serde(rename_all = "camelCase")]
48
- HookResult {
49
- protocol_version: u32,
50
- exit_code: i32,
51
- stdout: String,
52
- stderr: String,
53
- },
54
- /// The daemon accepted the connection and parsed the request, but could
55
- /// not produce a verdict (e.g. the worker is down/hung). Distinct from
56
- /// `HookResult` so a client can tell "ran and decided" apart from
57
- /// "daemon couldn't evaluate at all" — the latter is what drives the
58
- /// client's fail-closed path.
59
- #[serde(rename_all = "camelCase")]
60
- Error {
61
- protocol_version: u32,
62
- message: String,
63
- },
64
- }
65
-
66
- impl ClientMessage {
67
- pub fn protocol_version(&self) -> u32 {
68
- match self {
69
- ClientMessage::Ping { protocol_version } => *protocol_version,
70
- ClientMessage::Hook {
71
- protocol_version, ..
72
- } => *protocol_version,
73
- }
74
- }
75
- }
76
-
77
- impl ServerMessage {
78
- pub fn protocol_version(&self) -> u32 {
79
- match self {
80
- ServerMessage::Pong { protocol_version } => *protocol_version,
81
- ServerMessage::HookResult {
82
- protocol_version, ..
83
- } => *protocol_version,
84
- ServerMessage::Error {
85
- protocol_version, ..
86
- } => *protocol_version,
87
- }
88
- }
89
- }
90
-
91
- #[cfg(test)]
92
- mod tests {
93
- use super::*;
94
-
95
- #[test]
96
- fn ping_serializes_with_a_type_tag() {
97
- let msg = ClientMessage::Ping {
98
- protocol_version: PROTOCOL_VERSION,
99
- };
100
- let json = serde_json::to_value(&msg).unwrap();
101
- assert_eq!(json["type"], "ping");
102
- assert_eq!(json["protocolVersion"], PROTOCOL_VERSION);
103
- }
104
-
105
- #[test]
106
- fn hook_request_uses_camel_case_field_names_on_the_wire() {
107
- let msg = ClientMessage::Hook {
108
- protocol_version: PROTOCOL_VERSION,
109
- hook_event: "PreToolUse".to_string(),
110
- cli: "claude".to_string(),
111
- stdin: "{}".to_string(),
112
- cwd: Some("/repo".to_string()),
113
- };
114
- let json = serde_json::to_value(&msg).unwrap();
115
- assert_eq!(json["type"], "hook");
116
- assert_eq!(json["hookEvent"], "PreToolUse");
117
- assert_eq!(json["cli"], "claude");
118
- assert_eq!(json["cwd"], "/repo");
119
- }
120
-
121
- #[test]
122
- fn hook_request_cwd_is_optional() {
123
- let json = serde_json::json!({
124
- "type": "hook",
125
- "protocolVersion": 1,
126
- "hookEvent": "Stop",
127
- "cli": "codex",
128
- "stdin": "{}"
129
- });
130
- let msg: ClientMessage = serde_json::from_value(json).unwrap();
131
- match msg {
132
- ClientMessage::Hook { cwd, .. } => assert_eq!(cwd, None),
133
- _ => panic!("expected Hook variant"),
134
- }
135
- }
136
-
137
- #[test]
138
- fn unknown_message_type_fails_to_deserialize() {
139
- let json = serde_json::json!({ "type": "bogus", "protocolVersion": 1 });
140
- let result: Result<ClientMessage, _> = serde_json::from_value(json);
141
- assert!(result.is_err());
142
- }
143
-
144
- #[test]
145
- fn server_hook_result_round_trips() {
146
- let msg = ServerMessage::HookResult {
147
- protocol_version: PROTOCOL_VERSION,
148
- exit_code: 2,
149
- stdout: String::new(),
150
- stderr: "blocked".to_string(),
151
- };
152
- let json = serde_json::to_string(&msg).unwrap();
153
- let decoded: ServerMessage = serde_json::from_str(&json).unwrap();
154
- assert_eq!(decoded, msg);
155
- }
156
-
157
- #[test]
158
- fn protocol_version_accessor_matches_every_variant() {
159
- assert_eq!(
160
- ClientMessage::Ping {
161
- protocol_version: 7
162
- }
163
- .protocol_version(),
164
- 7
165
- );
166
- assert_eq!(
167
- ServerMessage::Error {
168
- protocol_version: 9,
169
- message: "x".to_string()
170
- }
171
- .protocol_version(),
172
- 9
173
- );
174
- }
175
- }
@@ -1,177 +0,0 @@
1
- //! Length-prefixed JSON framing shared by the daemon and every client of it.
2
- //!
3
- //! Frame = 4-byte big-endian `u32` byte length, followed by that many bytes
4
- //! of UTF-8 JSON. One frame in, one frame out, per connection — the daemon
5
- //! never keeps a connection open across multiple logical requests, so there
6
- //! is no need for a request-id-multiplexed protocol.
7
-
8
- use serde::Serialize;
9
- use serde::de::DeserializeOwned;
10
- use std::io::{self, Read, Write};
11
-
12
- /// Hard cap on a single frame's declared length. A hook payload is at most
13
- /// 1 MiB (see `handler.ts`'s own stdin cap); 16 MiB leaves headroom without
14
- /// letting a corrupt or hostile length prefix trigger an unbounded
15
- /// allocation before a single byte of the body has even been read.
16
- pub const MAX_FRAME_LEN: u32 = 16 * 1024 * 1024;
17
-
18
- #[derive(Debug)]
19
- pub enum FramingError {
20
- Io(io::Error),
21
- FrameTooLarge { declared: u32, max: u32 },
22
- Json(serde_json::Error),
23
- }
24
-
25
- impl std::fmt::Display for FramingError {
26
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27
- match self {
28
- FramingError::Io(e) => write!(f, "io error: {e}"),
29
- FramingError::FrameTooLarge { declared, max } => {
30
- write!(f, "frame length {declared} exceeds max {max}")
31
- }
32
- FramingError::Json(e) => write!(f, "invalid JSON frame: {e}"),
33
- }
34
- }
35
- }
36
-
37
- impl std::error::Error for FramingError {}
38
-
39
- impl From<io::Error> for FramingError {
40
- fn from(e: io::Error) -> Self {
41
- FramingError::Io(e)
42
- }
43
- }
44
-
45
- impl From<serde_json::Error> for FramingError {
46
- fn from(e: serde_json::Error) -> Self {
47
- FramingError::Json(e)
48
- }
49
- }
50
-
51
- /// Serializes `value` to JSON and writes it as one length-prefixed frame.
52
- pub fn write_message<W: Write, T: Serialize>(
53
- writer: &mut W,
54
- value: &T,
55
- ) -> Result<(), FramingError> {
56
- let body = serde_json::to_vec(value)?;
57
- let len = u32::try_from(body.len()).map_err(|_| FramingError::FrameTooLarge {
58
- declared: u32::MAX,
59
- max: MAX_FRAME_LEN,
60
- })?;
61
- if len > MAX_FRAME_LEN {
62
- return Err(FramingError::FrameTooLarge {
63
- declared: len,
64
- max: MAX_FRAME_LEN,
65
- });
66
- }
67
- writer.write_all(&len.to_be_bytes())?;
68
- writer.write_all(&body)?;
69
- writer.flush()?;
70
- Ok(())
71
- }
72
-
73
- /// Reads one length-prefixed frame and deserializes it as `T`. Rejects the
74
- /// frame (without allocating a body buffer) if the declared length exceeds
75
- /// [`MAX_FRAME_LEN`], so a corrupt or adversarial length prefix can't be
76
- /// used to force a large allocation.
77
- pub fn read_message<R: Read, T: DeserializeOwned>(reader: &mut R) -> Result<T, FramingError> {
78
- let mut len_bytes = [0u8; 4];
79
- reader.read_exact(&mut len_bytes)?;
80
- let len = u32::from_be_bytes(len_bytes);
81
- if len > MAX_FRAME_LEN {
82
- return Err(FramingError::FrameTooLarge {
83
- declared: len,
84
- max: MAX_FRAME_LEN,
85
- });
86
- }
87
- let mut body = vec![0u8; len as usize];
88
- reader.read_exact(&mut body)?;
89
- let value = serde_json::from_slice(&body)?;
90
- Ok(value)
91
- }
92
-
93
- #[cfg(test)]
94
- mod tests {
95
- use super::*;
96
- use serde::Deserialize;
97
- use std::io::Cursor;
98
-
99
- #[derive(Debug, Serialize, Deserialize, PartialEq)]
100
- struct Sample {
101
- a: u32,
102
- b: String,
103
- }
104
-
105
- #[test]
106
- fn round_trips_a_simple_value() {
107
- let mut buf = Vec::new();
108
- let msg = Sample {
109
- a: 42,
110
- b: "hello".to_string(),
111
- };
112
- write_message(&mut buf, &msg).unwrap();
113
- let mut cursor = Cursor::new(buf);
114
- let decoded: Sample = read_message(&mut cursor).unwrap();
115
- assert_eq!(decoded, msg);
116
- }
117
-
118
- #[test]
119
- fn round_trips_empty_string_fields() {
120
- let mut buf = Vec::new();
121
- let msg = Sample {
122
- a: 0,
123
- b: String::new(),
124
- };
125
- write_message(&mut buf, &msg).unwrap();
126
- let mut cursor = Cursor::new(buf);
127
- let decoded: Sample = read_message(&mut cursor).unwrap();
128
- assert_eq!(decoded, msg);
129
- }
130
-
131
- #[test]
132
- fn rejects_a_declared_length_over_the_cap_without_reading_a_body() {
133
- let mut buf = Vec::new();
134
- buf.extend_from_slice(&(MAX_FRAME_LEN + 1).to_be_bytes());
135
- // Deliberately no body bytes follow — if `read_message` tried to
136
- // allocate/read the declared length before checking the cap, this
137
- // would hang or panic on the short read instead of erroring cleanly.
138
- let mut cursor = Cursor::new(buf);
139
- let result: Result<Sample, _> = read_message(&mut cursor);
140
- assert!(matches!(result, Err(FramingError::FrameTooLarge { .. })));
141
- }
142
-
143
- #[test]
144
- fn refuses_to_write_a_frame_over_the_cap() {
145
- #[derive(Serialize)]
146
- struct Big {
147
- data: String,
148
- }
149
- let big = Big {
150
- data: "x".repeat((MAX_FRAME_LEN as usize) + 1),
151
- };
152
- let mut buf = Vec::new();
153
- let result = write_message(&mut buf, &big);
154
- assert!(matches!(result, Err(FramingError::FrameTooLarge { .. })));
155
- }
156
-
157
- #[test]
158
- fn rejects_truncated_frames() {
159
- let mut buf = Vec::new();
160
- buf.extend_from_slice(&10u32.to_be_bytes());
161
- buf.extend_from_slice(b"short"); // fewer than the declared 10 bytes
162
- let mut cursor = Cursor::new(buf);
163
- let result: Result<Sample, _> = read_message(&mut cursor);
164
- assert!(matches!(result, Err(FramingError::Io(_))));
165
- }
166
-
167
- #[test]
168
- fn rejects_malformed_json_inside_a_valid_frame() {
169
- let mut buf = Vec::new();
170
- let body = b"not json";
171
- buf.extend_from_slice(&(body.len() as u32).to_be_bytes());
172
- buf.extend_from_slice(body);
173
- let mut cursor = Cursor::new(buf);
174
- let result: Result<Sample, _> = read_message(&mut cursor);
175
- assert!(matches!(result, Err(FramingError::Json(_))));
176
- }
177
- }
@@ -1,10 +0,0 @@
1
- //! Wire protocol shared by `failproofaid` and every client/test that talks
2
- //! to it: message framing, the JSON envelope, and Unix-socket peer
3
- //! verification.
4
-
5
- pub mod envelope;
6
- pub mod framing;
7
- pub mod peer;
8
-
9
- pub use envelope::{ClientMessage, PROTOCOL_VERSION, ServerMessage};
10
- pub use framing::{FramingError, MAX_FRAME_LEN, read_message, write_message};
@@ -1,80 +0,0 @@
1
- //! Verifies that a Unix socket peer is running as the same OS user as this
2
- //! process.
3
- //!
4
- //! failproofaid is user-scope only (see the plan: "no elevation, the daemon
5
- //! spawns the worker because the daemon already runs as the user"): the
6
- //! socket directory is `0700` and the socket file `0600`, which is the
7
- //! actual access-control boundary. This check is a second, defense-in-depth
8
- //! layer against the narrow window between a socket file existing and its
9
- //! permissions having been fully applied, and against misconfigured
10
- //! filesystems (e.g. a shared mount with unexpectedly loose permissions).
11
- //! It is not a stronger security boundary than the filesystem permissions
12
- //! already provide — same OS user can always reach this daemon regardless.
13
-
14
- use std::io;
15
- use std::os::unix::io::AsRawFd;
16
- use std::os::unix::net::UnixStream;
17
-
18
- /// Returns the effective UID of the process on the other end of `stream`.
19
- #[cfg(target_os = "linux")]
20
- pub fn peer_uid(stream: &UnixStream) -> io::Result<u32> {
21
- use std::mem;
22
-
23
- let fd = stream.as_raw_fd();
24
- let mut cred: libc::ucred = unsafe { mem::zeroed() };
25
- let mut len = mem::size_of::<libc::ucred>() as libc::socklen_t;
26
-
27
- let ret = unsafe {
28
- libc::getsockopt(
29
- fd,
30
- libc::SOL_SOCKET,
31
- libc::SO_PEERCRED,
32
- &mut cred as *mut libc::ucred as *mut libc::c_void,
33
- &mut len,
34
- )
35
- };
36
- if ret != 0 {
37
- return Err(io::Error::last_os_error());
38
- }
39
- Ok(cred.uid)
40
- }
41
-
42
- /// Returns the effective UID of the process on the other end of `stream`.
43
- #[cfg(target_os = "macos")]
44
- pub fn peer_uid(stream: &UnixStream) -> io::Result<u32> {
45
- let fd = stream.as_raw_fd();
46
- let mut uid: libc::uid_t = 0;
47
- let mut gid: libc::gid_t = 0;
48
-
49
- let ret = unsafe { libc::getpeereid(fd, &mut uid, &mut gid) };
50
- if ret != 0 {
51
- return Err(io::Error::last_os_error());
52
- }
53
- Ok(uid)
54
- }
55
-
56
- /// Returns this process's own effective UID, for comparison against
57
- /// [`peer_uid`].
58
- pub fn own_uid() -> u32 {
59
- unsafe { libc::geteuid() }
60
- }
61
-
62
- /// `true` if `stream`'s peer is running as this process's own OS user.
63
- pub fn is_same_user(stream: &UnixStream) -> io::Result<bool> {
64
- Ok(peer_uid(stream)? == own_uid())
65
- }
66
-
67
- #[cfg(test)]
68
- mod tests {
69
- use super::*;
70
-
71
- #[test]
72
- fn a_local_socketpair_peer_is_always_the_same_user() {
73
- // socketpair() connects two ends of the same process — the peer
74
- // UID must equal our own, on every CI runner regardless of who's
75
- // executing the test.
76
- let (a, _b) = UnixStream::pair().unwrap();
77
- assert!(is_same_user(&a).unwrap());
78
- assert_eq!(peer_uid(&a).unwrap(), own_uid());
79
- }
80
- }
@@ -1,79 +0,0 @@
1
- # Self-contained failproofai hook-sync container.
2
- #
3
- # A single-shot daily job (run by a k8s CronJob) that clones failproofai, runs
4
- # Claude Code in `--effort ultracode` mode to detect drift between every agent-CLI
5
- # harness we integrate with and this repo, and opens ONE auto-PR with the fix.
6
- #
7
- # Bundles:
8
- # - Node 20 + npm (npm is a fallback bun installer for scripts/dev-hook.mjs;
9
- # node runs the launcher itself)
10
- # - bun (STILL REQUIRED: the cloned repo's .claude/settings.json fires hooks via
11
- # `node "$CLAUDE_PROJECT_DIR/scripts/dev-hook.mjs" --hook <Event>`, and that
12
- # launcher only *locates* bun — it cannot conjure one. Without this layer the
13
- # dogfooded require-*-before-stop policies never fire and the auto-PR is
14
- # never committed/pushed. We install to BUN_INSTALL=/home/appuser/.bun, which
15
- # the launcher probes explicitly, so enforcement survives a broken PATH.)
16
- # - Claude Code CLI (`claude`) — run headless with --effort ultracode
17
- # - failproofai@latest on PATH (belt-and-suspenders; the dogfood hooks actually
18
- # run the clone's SOURCE via bun, not this global)
19
- # - git + gh + jq + dumb-init + `script` (PTY wrap for stream-json)
20
- #
21
- # Build: docker build -t hook-sync:latest docker-hook-sync/
22
- # Run: docker run --rm -e CLAUDE_CODE_OAUTH_TOKEN=... -e GH_TOKEN=... hook-sync:latest
23
- #
24
- # Every dependency is installed at build time. The daily GitHub Actions rebuild
25
- # (.github/workflows/build-image.yml) keeps claude-code@latest + failproofai@latest fresh.
26
- FROM node:20-bookworm-slim
27
-
28
- ENV DEBIAN_FRONTEND=noninteractive \
29
- HOME=/home/appuser \
30
- BUN_INSTALL=/home/appuser/.bun \
31
- FAILPROOFAI_TELEMETRY_DISABLED=1 \
32
- PATH="/home/appuser/.bun/bin:/home/appuser/.local/bin:${PATH}"
33
-
34
- # Layer 1: apt deps. dumb-init for PID 1 signal handling; git+gh for the agent's
35
- # clone/branch/push/PR flow AND the require-*-before-stop hooks; jq for the
36
- # entrypoint's policy-config edit; bsdextrautils provides `script` (PTY wrap so
37
- # Node line-flushes --output-format stream-json); curl/gnupg for the gh apt key
38
- # and the bun installer; unzip is required by the bun installer.
39
- RUN apt-get update \
40
- && apt-get install -y --no-install-recommends \
41
- ca-certificates curl gnupg dumb-init jq git bsdextrautils unzip \
42
- && rm -rf /var/lib/apt/lists/*
43
-
44
- # Layer 2: GitHub CLI (gh). Used by the agent for `gh pr create/list` and by the
45
- # require-pr-before-stop hook.
46
- RUN install -d /etc/apt/keyrings \
47
- && curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
48
- | gpg --dearmor -o /etc/apt/keyrings/githubcli-archive-keyring.gpg \
49
- && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
50
- > /etc/apt/sources.list.d/github-cli.list \
51
- && apt-get update \
52
- && apt-get install -y --no-install-recommends gh \
53
- && rm -rf /var/lib/apt/lists/*
54
-
55
- # Layer 3: npm globals. Claude Code CLI + failproofai, pinned to latest at build
56
- # time; the daily workflow rebuild keeps them fresh. Root install so symlinks land
57
- # in /usr/local/bin (executable by the non-root appuser).
58
- RUN npm install -g --omit=dev \
59
- @anthropic-ai/claude-code@latest \
60
- failproofai@latest \
61
- && npm cache clean --force
62
-
63
- # Layer 4: non-root user + chowned workspace.
64
- RUN useradd --create-home --uid 10001 --shell /bin/bash appuser \
65
- && mkdir -p /workspace \
66
- && chown -R appuser:appuser /workspace /home/appuser
67
-
68
- COPY entrypoint.sh /usr/local/bin/entrypoint.sh
69
- RUN chmod 0755 /usr/local/bin/entrypoint.sh
70
-
71
- USER appuser
72
- WORKDIR /home/appuser
73
-
74
- # Layer 5: bun (installs into $BUN_INSTALL=/home/appuser/.bun, on PATH per ENV).
75
- # The dogfood hook fast-path runs TypeScript from src/ directly — bun executes TS
76
- # natively, so no build step is needed for the hooks to work.
77
- RUN curl -fsSL https://bun.sh/install | bash
78
-
79
- ENTRYPOINT ["dumb-init", "--", "/usr/local/bin/entrypoint.sh"]
@@ -1,109 +0,0 @@
1
- #!/usr/bin/env bash
2
- #
3
- # failproofai hook-sync entrypoint (runs as PID 1 under dumb-init).
4
- #
5
- # Lifecycle:
6
- # 1. Validate env (CLAUDE_CODE_OAUTH_TOKEN, GH_TOKEN).
7
- # 2. gh auth setup-git + git identity.
8
- # 3. Clone failproofai --depth=1; cut a fresh auto/sync-cli-harnesses-<UTC> branch.
9
- # 4. NEUTRALIZE two policies in the THROWAWAY clone's .failproofai config
10
- # (require-ci-green-before-stop, block-read-outside-cwd) via jq, then
11
- # `git update-index --skip-worktree` so the edit is invisible to
12
- # git status/add and never enters the agent's commit/PR — while failproofai
13
- # reads the edited WORKTREE file at runtime and sees them gone. The
14
- # require-commit/push/pr-before-stop gates stay ACTIVE (dogfooding).
15
- # 5. exec `claude --effort ultracode -p <prompt>` wrapped in a PTY so
16
- # --output-format stream-json line-flushes to `kubectl logs -f`.
17
- # 6. Exit with claude's return code (all output streams to stdout / the pod log).
18
- #
19
- # Exit codes: 0 = agent finished (claude's rc) · 64 = missing required env ·
20
- # 65 = prompt file missing in clone · 66 = unsafe WORKSPACE · else = claude's rc.
21
- set -euo pipefail
22
-
23
- CLAUDE_CODE_OAUTH_TOKEN="${CLAUDE_CODE_OAUTH_TOKEN:-}"
24
- GH_TOKEN="${GH_TOKEN:-}"
25
- REPO_URL="${REPO_URL:-https://github.com/failproofai/failproofai.git}"
26
- REPO_BRANCH_FROM="${REPO_BRANCH_FROM:-main}"
27
- WORKSPACE="${WORKSPACE:-/workspace}"
28
- PROMPT_PATH="${PROMPT_PATH:-scripts/sync-agent-cli-harnesses-prompt.md}"
29
- CLAUDE_MODEL="${CLAUDE_MODEL:-claude-opus-4-8}"
30
-
31
- export HOME="${HOME:-/home/appuser}"
32
- export CLAUDE_CODE_OAUTH_TOKEN
33
- export GH_TOKEN
34
- export GITHUB_TOKEN="${GITHUB_TOKEN:-$GH_TOKEN}"
35
- export FAILPROOFAI_TELEMETRY_DISABLED=1
36
- # Keep ultracode background subagents alive in headless -p mode (default is ~10 min).
37
- export CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS="${CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS:-1800000}"
38
-
39
- log() { printf '[entrypoint %s] %s\n' "$(date -u +%FT%TZ)" "$*"; }
40
-
41
- # ---------------- 1. env validation ----------------
42
- if [ -z "$CLAUDE_CODE_OAUTH_TOKEN" ]; then log "ERROR: CLAUDE_CODE_OAUTH_TOKEN not set"; exit 64; fi
43
- if [ -z "$GH_TOKEN" ]; then log "ERROR: GH_TOKEN not set"; exit 64; fi
44
-
45
- # ---------------- 2. gh + git auth ----------------
46
- log "authenticating gh"
47
- gh auth setup-git >/dev/null
48
- git config --global user.name "failproofai-hook-sync"
49
- git config --global user.email "hook-sync-bot@exosphere.host"
50
- git config --global init.defaultBranch main
51
-
52
- # ---------------- 3. clone + fresh branch ----------------
53
- case "$WORKSPACE" in
54
- ""|"/"|"."|"..") log "ERROR: refusing unsafe WORKSPACE '$WORKSPACE'"; exit 66 ;;
55
- esac
56
- mkdir -p "$WORKSPACE"
57
- if [ -n "$(ls -A "$WORKSPACE" 2>/dev/null)" ]; then
58
- find "$WORKSPACE" -mindepth 1 -maxdepth 1 -exec rm -rf {} +
59
- fi
60
- log "cloning $REPO_URL@$REPO_BRANCH_FROM -> $WORKSPACE"
61
- git clone --depth=1 --branch "$REPO_BRANCH_FROM" "$REPO_URL" "$WORKSPACE"
62
- cd "$WORKSPACE"
63
- # Fetch the base ref (shallow) so require-*-before-stop can diff against origin/<base>.
64
- git fetch --depth=1 origin "$REPO_BRANCH_FROM" >/dev/null 2>&1 || true
65
- BRANCH="auto/sync-cli-harnesses-$(date -u +%Y%m%dT%H%M%SZ)"
66
- git checkout -b "$BRANCH"
67
- log "working on branch $BRANCH"
68
-
69
- # ---------------- 4. policy-config neutralization ----------------
70
- # enabledPolicies is a UNION across scopes with no disable field, so a policy must
71
- # be removed from the file that lists it. --skip-worktree then hides that edit from
72
- # git status/add (so it never lands in the PR) while failproofai still reads the
73
- # edited worktree file at runtime. Keeps require-commit/push/pr-before-stop active.
74
- CFG=".failproofai/policies-config.json"
75
- if [ -f "$CFG" ]; then
76
- cfg_tmp="$(mktemp)"
77
- jq '.enabledPolicies |= map(select(. != "require-ci-green-before-stop" and . != "block-read-outside-cwd"))' "$CFG" > "$cfg_tmp" && mv "$cfg_tmp" "$CFG"
78
- git update-index --skip-worktree "$CFG"
79
- log "neutralized require-ci-green-before-stop + block-read-outside-cwd for this run (skip-worktree; not committed)"
80
- else
81
- log "WARN: $CFG not found; running with the repo's default policy set"
82
- fi
83
-
84
- # ---------------- 5. invoke claude (ULTRACODE, headless, PTY-wrapped) ----------------
85
- PROMPT_FILE="$WORKSPACE/$PROMPT_PATH"
86
- if [ ! -f "$PROMPT_FILE" ]; then log "ERROR: prompt missing at $PROMPT_FILE"; exit 65; fi
87
-
88
- # Node block-buffers stdout when it's a pipe; `script -qefc ... /dev/null` gives
89
- # claude a PTY so --output-format stream-json line-flushes to the pod logs. `-e`
90
- # ties script's exit code to claude's.
91
- RUN_SH="$(mktemp /tmp/run-claude.XXXXXX.sh)"
92
- cat >"$RUN_SH" <<EOF
93
- #!/usr/bin/env bash
94
- exec claude --effort ultracode --model ${CLAUDE_MODEL} \\
95
- --verbose --output-format stream-json \\
96
- --dangerously-skip-permissions \\
97
- -p "\$(cat "$PROMPT_FILE")" 2>&1
98
- EOF
99
- chmod +x "$RUN_SH"
100
-
101
- log "invoking claude --effort ultracode --model ${CLAUDE_MODEL} (prompt: $PROMPT_PATH)"
102
- set +e
103
- script -qefc "$RUN_SH" /dev/null
104
- rc=$?
105
- set -e
106
- rm -f "$RUN_SH"
107
- log "claude exited $rc"
108
-
109
- exit "$rc"
@@ -1,47 +0,0 @@
1
- # failproofai CLI-canary sandbox — base image
2
- #
3
- # Design goals (see failproofai-cli-canary-design.md §4):
4
- # - SAFE: non-root user, NO sudo installed, no host FS mounted at runtime.
5
- # The canary fires `sudo whoami` / `.env`-read deny-probes; here they
6
- # are inert BY CONSTRUCTION even on a day enforcement is broken.
7
- # - LIGHT: ephemeral daily container (`docker run --rm`), not a daemon.
8
- # Only this image + one named volume persist; zero idle CPU/RAM.
9
- # - FRESH: CLIs are NOT baked in — they are `@latest`-installed into the
10
- # persistent HOME volume at run time (the whole point of the canary),
11
- # so this base image rebuilds rarely.
12
- #
13
- # The HOME volume (mounted at /home/canary) holds: npm-global CLIs, every
14
- # vendor login/token, and per-CLI config — so logins survive across daily runs.
15
-
16
- FROM node:22-bookworm-slim
17
-
18
- # bun from the official image — no `curl | bash` needed at build time.
19
- COPY --from=oven/bun:latest /usr/local/bin/bun /usr/local/bin/bun
20
-
21
- # Minimal tooling for the various vendor CLI installers. Deliberately NO sudo.
22
- # Tooling for the various vendor installers. Deliberately NO sudo.
23
- # bzip2/xz-utils : goose extracts its Rust binary with these
24
- # libsecret-1-0 : antigravity caches login tokens via libsecret (best-effort)
25
- RUN apt-get update -qq \
26
- && apt-get install -y -qq --no-install-recommends \
27
- git ca-certificates curl unzip bzip2 xz-utils libsecret-1-0 \
28
- && rm -rf /var/lib/apt/lists/*
29
-
30
- # Unprivileged user. HOME is the mount point for the persistent named volume;
31
- # because the image ships a canary-owned /home/canary, an empty named volume
32
- # mounted here is initialised canary-owned (Docker copies image content+owner).
33
- # node:22-slim already ships a `node` user at UID 1000, so pin canary to 1001.
34
- RUN useradd --create-home --uid 1001 --shell /bin/bash canary
35
- USER canary
36
- WORKDIR /home/canary
37
- RUN mkdir -p /home/canary/.npm-global/bin /home/canary/.local/bin
38
-
39
- # NPM_CONFIG_PREFIX via ENV (not `npm config set`) so it survives the volume
40
- # mount shadowing /home/canary at runtime. Runtime `npm i -g` lands in the volume.
41
- ENV NPM_CONFIG_PREFIX=/home/canary/.npm-global
42
- ENV PATH=/home/canary/.npm-global/bin:/home/canary/.local/bin:/usr/local/bin:/usr/bin:/bin
43
-
44
- # Sanity: fail the build if bun/node/npm aren't all runnable as the canary user.
45
- RUN bun --version && node --version && npm --version
46
-
47
- CMD ["bash"]