failproofai 1.0.0-beta.5 → 1.0.0-beta.6

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 (367) 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 +3 -3
  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/server-reference-manifest.json +1 -1
  8. package/.next/standalone/.next/server/app/_global-error/page.js +3 -1
  9. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  10. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  13. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  14. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  15. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
  16. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  17. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  18. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  19. package/.next/standalone/.next/server/app/_not-found/page.js +3 -1
  20. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  21. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  22. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  23. package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
  24. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
  25. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  26. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
  27. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  28. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  29. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  30. package/.next/standalone/.next/server/app/api/audit/invite/route.js +3 -2
  31. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/api/audit/run/route.js +4 -3
  33. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/api/audit/status/route.js +1 -1
  35. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/auth/login-request/route.js +2 -1
  37. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +3 -2
  39. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/api/auth/logout/route.js +3 -2
  41. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/api/auth/reminder/route.js +3 -2
  43. package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/api/auth/status/route.js +3 -2
  45. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +1 -1
  47. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  49. package/.next/standalone/.next/server/app/audit/page.js +5 -3
  50. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  51. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  52. package/.next/standalone/.next/server/app/index.html +1 -1
  53. package/.next/standalone/.next/server/app/index.rsc +15 -15
  54. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  55. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
  56. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
  57. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
  58. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  59. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  60. package/.next/standalone/.next/server/app/page.js +3 -1
  61. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  62. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  63. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +10 -10
  64. package/.next/standalone/.next/server/app/policies/page.js +4 -2
  65. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  66. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  67. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  68. package/.next/standalone/.next/server/app/project/[name]/page.js +4 -2
  69. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  70. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  71. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  72. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  73. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +6 -4
  74. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  75. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  76. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  77. package/.next/standalone/.next/server/app/projects/page.js +4 -2
  78. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  79. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  80. package/.next/standalone/.next/server/app/settings/page/app-paths-manifest.json +3 -0
  81. package/.next/standalone/.next/server/app/settings/page/build-manifest.json +18 -0
  82. package/.next/standalone/.next/server/app/settings/page/next-font-manifest.json +6 -0
  83. package/.next/standalone/.next/server/app/settings/page/react-loadable-manifest.json +1 -0
  84. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +53 -0
  85. package/.next/standalone/.next/server/app/settings/page.js +18 -0
  86. package/.next/standalone/.next/server/app/settings/page.js.map +5 -0
  87. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -0
  88. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +3 -0
  89. package/.next/standalone/.next/server/app-paths-manifest.json +2 -1
  90. package/.next/standalone/.next/server/chunks/{[externals]__1nl3dvw._.js → [externals]__0r-zamh._.js} +2 -2
  91. package/.next/standalone/.next/server/chunks/[root-of-the-server]__06hexd0._.js +3 -0
  92. package/.next/standalone/.next/server/chunks/[root-of-the-server]__094p1f1._.js +3 -0
  93. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_0xu5z._.js +1 -1
  94. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ed01_d._.js +3 -0
  95. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0g0vcwt._.js +3 -0
  96. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0h3lfmp._.js → [root-of-the-server]__0ky_n0r._.js} +2 -2
  97. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__18d-9oi._.js → [root-of-the-server]__0lk_935._.js} +2 -2
  98. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1p7s8-d._.js → [root-of-the-server]__0pbp9fe._.js} +2 -2
  99. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q-v9z2._.js +1 -1
  100. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__10oa-v9._.js → [root-of-the-server]__0v2fpxe._.js} +2 -2
  101. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0sb_5m8._.js → [root-of-the-server]__131ebum._.js} +3 -3
  102. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0-dh5jy._.js → [root-of-the-server]__1_ps0jw._.js} +2 -2
  103. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0l4vuqm._.js → [root-of-the-server]__1a7i2q4._.js} +1 -1
  104. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ibjy5x._.js +3 -0
  105. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1iny24d._.js +3 -0
  106. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tvn4wf._.js +1 -1
  107. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tyedjt._.js +3 -0
  108. package/.next/standalone/.next/server/chunks/_0lxbzdq._.js +5 -0
  109. package/.next/standalone/.next/server/chunks/_1zuiiy3._.js +5 -0
  110. package/.next/standalone/.next/server/chunks/lib_telemetry_ts_0dctyyw._.js +5 -0
  111. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +5 -5
  112. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  113. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__06bp_fg._.js +5 -0
  114. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__074qmkp._.js +3 -0
  115. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0spkm68._.js +10 -10
  116. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1_a_gwn._.js +3 -0
  117. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1a2hcb_._.js +3 -0
  118. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1e7-pa7._.js +3 -0
  119. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0rtdfof._.js → [root-of-the-server]__1rdruw4._.js} +1 -1
  120. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1rv-sc9._.js +3 -0
  121. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1tyf0tc._.js +5 -0
  122. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1u-wx42._.js +4 -0
  123. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1v185mo._.js +3 -0
  124. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0rag5dg._.js → [root-of-the-server]__1yw368c._.js} +2 -2
  125. package/.next/standalone/.next/server/chunks/ssr/_0-yi74u._.js +3 -0
  126. package/.next/standalone/.next/server/chunks/ssr/_04mekdy._.js +3 -0
  127. package/.next/standalone/.next/server/chunks/ssr/_0igtyj5._.js +3 -0
  128. package/.next/standalone/.next/server/chunks/ssr/_0r-dsre._.js +3 -0
  129. package/.next/standalone/.next/server/chunks/ssr/_0rjgfln._.js +3 -0
  130. package/.next/standalone/.next/server/chunks/ssr/_0se484m._.js +3 -0
  131. package/.next/standalone/.next/server/chunks/ssr/_0uz7o9y._.js +3 -0
  132. package/.next/standalone/.next/server/chunks/ssr/_11_p9y8._.js +1 -1
  133. package/.next/standalone/.next/server/chunks/ssr/_1fahg9e._.js +3 -0
  134. package/.next/standalone/.next/server/chunks/ssr/_1gmzkwj._.js +5 -0
  135. package/.next/standalone/.next/server/chunks/ssr/_1w8sola._.js +3 -0
  136. package/.next/standalone/.next/server/chunks/ssr/_1w_6p9g._.js +3 -0
  137. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +2 -2
  138. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  139. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +2 -2
  140. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0dwo94s.js +4 -0
  141. package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +3 -0
  142. package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.js +5 -0
  143. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  144. package/.next/standalone/.next/server/middleware.js +2 -2
  145. package/.next/standalone/.next/server/pages/404.html +1 -1
  146. package/.next/standalone/.next/server/pages/500.html +1 -1
  147. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  148. package/.next/standalone/.next/server/server-reference-manifest.json +54 -12
  149. package/.next/standalone/.next/static/chunks/{2cqk4a9s893oy.js → 0_2n13i94rnw5.js} +1 -1
  150. package/.next/standalone/.next/static/chunks/1bm0q12hgs22l.css +2 -0
  151. package/.next/standalone/.next/static/chunks/1v1gqvpjk62jm.js +1 -0
  152. package/.next/standalone/.next/static/chunks/{1bw4dfzflelcv.js → 23557z4e6dtsr.js} +1 -1
  153. package/.next/standalone/.next/static/chunks/28zkwzu50puki.js +1 -0
  154. package/.next/standalone/.next/static/chunks/2uvhw57mf9lg_.css +2 -0
  155. package/.next/standalone/.next/static/chunks/3081gykdubv8b.js +1 -0
  156. package/.next/standalone/.next/static/chunks/{2k285z07qce47.js → 34fa65k0cldkj.js} +1 -1
  157. package/.next/standalone/.next/static/chunks/{34sjdw8lv46e3.js → 35v07j9gc1pvr.js} +2 -2
  158. package/.next/standalone/.next/static/chunks/{1bkynffp3q1f7.js → 3f_939wi3kfnx.js} +22 -22
  159. package/.next/standalone/.next/static/chunks/{2v1rpzrh2i1wv.js → 3p1vpm2_-tfwm.js} +1 -1
  160. package/.next/standalone/.next/static/chunks/{0cr85wuc9gc9k.js → 3rbpw_waieafm.js} +1 -1
  161. package/.next/standalone/.next/static/chunks/40ffnfpkeyvb0.js +1 -0
  162. package/.next/standalone/app/actions/get-hooks-config.ts +2 -1
  163. package/.next/standalone/app/actions/get-scheduled-audit.ts +70 -0
  164. package/.next/standalone/app/actions/update-scheduled-audit.ts +44 -0
  165. package/.next/standalone/app/api/audit/run/route.ts +28 -0
  166. package/.next/standalone/app/api/audit/status/route.ts +13 -1
  167. package/.next/standalone/app/api/auth/status/route.ts +1 -1
  168. package/.next/standalone/app/audit/_components/auth-dialog.css +159 -0
  169. package/.next/standalone/app/audit/_components/auth-dialog.tsx +3 -0
  170. package/.next/standalone/app/audit/audit-styles.css +6 -149
  171. package/.next/standalone/app/settings/page.tsx +31 -0
  172. package/.next/standalone/app/settings/settings-client.tsx +488 -0
  173. package/.next/standalone/components/navbar.tsx +2 -0
  174. package/.next/standalone/lib/auth/api-server-client.ts +2 -3
  175. package/.next/standalone/lib/auth/auth-store.ts +4 -4
  176. package/.next/standalone/lib/codex-sessions.ts +2 -1
  177. package/.next/standalone/lib/dashboard-host.ts +101 -0
  178. package/.next/standalone/lib/install-check.ts +22 -7
  179. package/.next/standalone/lib/pi-sessions.ts +99 -14
  180. package/.next/standalone/lib/telemetry-enabled.ts +54 -0
  181. package/.next/standalone/lib/telemetry-id.ts +52 -1
  182. package/.next/standalone/lib/telemetry.ts +8 -4
  183. package/.next/standalone/node_modules/react/cjs/react.development.js +1 -1
  184. package/.next/standalone/node_modules/react/cjs/react.production.js +1 -1
  185. package/.next/standalone/node_modules/react/package.json +3 -3
  186. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.js +1 -1
  187. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.node.production.js +1 -1
  188. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.browser.production.js +3 -3
  189. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.edge.production.js +3 -3
  190. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.node.production.js +3 -3
  191. package/.next/standalone/node_modules/react-dom/cjs/react-dom.production.js +1 -1
  192. package/.next/standalone/node_modules/react-dom/package.json +4 -4
  193. package/.next/standalone/package.json +7 -6
  194. package/.next/standalone/proxy.ts +89 -1
  195. package/.next/standalone/server.js +1 -1
  196. package/bin/failproofai.mjs +197 -80
  197. package/dist/cli.mjs +17636 -15284
  198. package/dist/worker.mjs +1620 -257
  199. package/lib/auth/api-server-client.ts +2 -3
  200. package/lib/auth/auth-store.ts +4 -4
  201. package/lib/codex-sessions.ts +2 -1
  202. package/lib/dashboard-host.ts +101 -0
  203. package/lib/install-check.ts +22 -7
  204. package/lib/pi-sessions.ts +99 -14
  205. package/lib/telemetry-enabled.ts +54 -0
  206. package/lib/telemetry-id.ts +52 -1
  207. package/lib/telemetry.ts +8 -4
  208. package/package.json +7 -6
  209. package/scripts/install-telemetry.mjs +8 -1
  210. package/scripts/launch.ts +25 -3
  211. package/scripts/parse-script-args.ts +17 -1
  212. package/scripts/prune-standalone.mjs +20 -0
  213. package/scripts/translate-docs/readme-translator.ts +163 -4
  214. package/scripts/validate-mdx.ts +153 -13
  215. package/src/audit/audit-lock.ts +285 -0
  216. package/src/audit/audit-schedule.ts +111 -0
  217. package/src/audit/cache.ts +18 -4
  218. package/src/audit/cli-adapters/goose.ts +2 -1
  219. package/src/audit/cli-adapters/hermes.ts +28 -10
  220. package/src/audit/cli.ts +191 -35
  221. package/src/audit/dashboard-cache.ts +2 -1
  222. package/src/hooks/builtin-policies.ts +100 -3
  223. package/src/hooks/cloud-connection.ts +160 -14
  224. package/src/hooks/cloud-enrollment-cli.ts +119 -21
  225. package/src/hooks/cloud-enrollment.ts +87 -17
  226. package/src/hooks/cloud-introspect.ts +147 -0
  227. package/src/hooks/cloud-managed-policies.ts +33 -2
  228. package/src/hooks/collector-config.ts +25 -43
  229. package/src/hooks/configure-wizard.ts +696 -318
  230. package/src/hooks/custom-hooks-loader.ts +125 -11
  231. package/src/hooks/daemon-client.ts +83 -17
  232. package/src/hooks/daemon-download.ts +54 -2
  233. package/src/hooks/daemon-service.ts +595 -27
  234. package/src/hooks/first-run-gate.ts +39 -0
  235. package/src/hooks/fp-config.ts +497 -0
  236. package/src/hooks/fp-home.ts +342 -0
  237. package/src/hooks/fp-reset.ts +332 -0
  238. package/src/hooks/handler.ts +42 -1
  239. package/src/hooks/hook-activity-store.ts +35 -20
  240. package/src/hooks/hook-logger.ts +2 -1
  241. package/src/hooks/hook-telemetry.ts +5 -1
  242. package/src/hooks/hooks-config.ts +4 -3
  243. package/src/hooks/loader-utils.ts +166 -5
  244. package/src/hooks/manager.ts +5 -4
  245. package/src/hooks/onboarding-lock.ts +119 -0
  246. package/src/hooks/policy-types.ts +0 -7
  247. package/src/hooks/session-pause-cli.ts +15 -13
  248. package/src/hooks/session-pause.ts +36 -4
  249. package/src/hooks/setup-state.ts +256 -0
  250. package/src/hooks/tui.ts +4 -4
  251. package/src/hooks/worker-server.ts +53 -1
  252. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0f8nu8d._.js +0 -3
  253. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0szqzl8._.js +0 -3
  254. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +0 -3
  255. package/.next/standalone/.next/server/chunks/[root-of-the-server]__19120tr._.js +0 -3
  256. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fwl2mz._.js +0 -3
  257. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1myjm-d._.js +0 -3
  258. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rhmvod._.js +0 -3
  259. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02r5bgf._.js +0 -4
  260. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__094nop3._.js +0 -3
  261. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e8sjqm._.js +0 -4
  262. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0lkzqax._.js +0 -4
  263. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ls0gsr._.js +0 -4
  264. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n_uvv0._.js +0 -3
  265. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qucxyj._.js +0 -4
  266. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0u02miy._.js +0 -4
  267. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__14dd6h8._.js +0 -3
  268. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1gak4pd._.js +0 -3
  269. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1j4u3yd._.js +0 -4
  270. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1zqz4v8._.js +0 -4
  271. package/.next/standalone/.next/server/chunks/ssr/_1m_p7pi._.js +0 -3
  272. package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_12c_2cz.js +0 -3
  273. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1ezd2jf._.js +0 -5
  274. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1tnuifj._.js +0 -5
  275. package/.next/standalone/.next/static/chunks/0h7auy7hzjyhw.js +0 -1
  276. package/.next/standalone/.next/static/chunks/1tp9dex23zs8y.js +0 -1
  277. package/.next/standalone/.next/static/chunks/2s9g1dsde_ts1.js +0 -1
  278. package/.next/standalone/.next/static/chunks/3i27c3hcriawq.css +0 -1
  279. package/.next/standalone/.next/static/chunks/3zdwnnthucs_1.css +0 -2
  280. package/.next/standalone/Cargo.lock +0 -2222
  281. package/.next/standalone/Cargo.toml +0 -9
  282. package/.next/standalone/crates/CLOUD_POLICIES.md +0 -136
  283. package/.next/standalone/crates/PROTOCOL.md +0 -122
  284. package/.next/standalone/crates/failproofaid/Cargo.toml +0 -25
  285. package/.next/standalone/crates/failproofaid/src/cloud_client.rs +0 -484
  286. package/.next/standalone/crates/failproofaid/src/cloud_policies.rs +0 -921
  287. package/.next/standalone/crates/failproofaid/src/lock.rs +0 -81
  288. package/.next/standalone/crates/failproofaid/src/main.rs +0 -639
  289. package/.next/standalone/crates/failproofaid/src/paths.rs +0 -201
  290. package/.next/standalone/crates/failproofaid/src/server.rs +0 -502
  291. package/.next/standalone/crates/failproofaid/src/worker.rs +0 -400
  292. package/.next/standalone/crates/failproofaid/tests/daemon_e2e.rs +0 -241
  293. package/.next/standalone/crates/fpai-collect/Cargo.toml +0 -43
  294. package/.next/standalone/crates/fpai-collect/src/config.rs +0 -420
  295. package/.next/standalone/crates/fpai-collect/src/cursor.rs +0 -520
  296. package/.next/standalone/crates/fpai-collect/src/delivery.rs +0 -472
  297. package/.next/standalone/crates/fpai-collect/src/filetail.rs +0 -487
  298. package/.next/standalone/crates/fpai-collect/src/health.rs +0 -369
  299. package/.next/standalone/crates/fpai-collect/src/lib.rs +0 -34
  300. package/.next/standalone/crates/fpai-collect/src/redact.rs +0 -516
  301. package/.next/standalone/crates/fpai-collect/src/sources/claude/mod.rs +0 -279
  302. package/.next/standalone/crates/fpai-collect/src/sources/claude/transform.rs +0 -619
  303. package/.next/standalone/crates/fpai-collect/src/sources/codex/mod.rs +0 -156
  304. package/.next/standalone/crates/fpai-collect/src/sources/codex/transform.rs +0 -715
  305. package/.next/standalone/crates/fpai-collect/src/sources/copilot/mod.rs +0 -158
  306. package/.next/standalone/crates/fpai-collect/src/sources/copilot/transform.rs +0 -512
  307. package/.next/standalone/crates/fpai-collect/src/sources/goose/mod.rs +0 -511
  308. package/.next/standalone/crates/fpai-collect/src/sources/goose/transform.rs +0 -586
  309. package/.next/standalone/crates/fpai-collect/src/sources/hermes/mod.rs +0 -318
  310. package/.next/standalone/crates/fpai-collect/src/sources/hermes/transform.rs +0 -579
  311. package/.next/standalone/crates/fpai-collect/src/sources/hooks/mod.rs +0 -314
  312. package/.next/standalone/crates/fpai-collect/src/sources/hooks/transform.rs +0 -448
  313. package/.next/standalone/crates/fpai-collect/src/sources/mod.rs +0 -23
  314. package/.next/standalone/crates/fpai-collect/src/sources/openclaw/mod.rs +0 -176
  315. package/.next/standalone/crates/fpai-collect/src/sources/openclaw/transform.rs +0 -500
  316. package/.next/standalone/crates/fpai-collect/src/sources/opencode/mod.rs +0 -315
  317. package/.next/standalone/crates/fpai-collect/src/sources/opencode/transform.rs +0 -493
  318. package/.next/standalone/crates/fpai-collect/src/sources/pi/mod.rs +0 -201
  319. package/.next/standalone/crates/fpai-collect/src/sources/pi/transform.rs +0 -533
  320. package/.next/standalone/crates/fpai-collect/src/spool.rs +0 -535
  321. package/.next/standalone/crates/fpai-collect/src/sqlitepoll.rs +0 -390
  322. package/.next/standalone/crates/fpai-collect/src/supervisor.rs +0 -423
  323. package/.next/standalone/crates/fpai-collect/src/uploader.rs +0 -600
  324. package/.next/standalone/crates/fpai-collect/tests/claude_source.rs +0 -739
  325. package/.next/standalone/crates/fpai-collect/tests/claude_subagents.rs +0 -394
  326. package/.next/standalone/crates/fpai-collect/tests/codex_source.rs +0 -976
  327. package/.next/standalone/crates/fpai-collect/tests/config.rs +0 -286
  328. package/.next/standalone/crates/fpai-collect/tests/copilot_source.rs +0 -1020
  329. package/.next/standalone/crates/fpai-collect/tests/delivery.rs +0 -281
  330. package/.next/standalone/crates/fpai-collect/tests/goose_source.rs +0 -1009
  331. package/.next/standalone/crates/fpai-collect/tests/hermes_source.rs +0 -1130
  332. package/.next/standalone/crates/fpai-collect/tests/hooks_source.rs +0 -622
  333. package/.next/standalone/crates/fpai-collect/tests/openclaw_source.rs +0 -855
  334. package/.next/standalone/crates/fpai-collect/tests/opencode_source.rs +0 -1478
  335. package/.next/standalone/crates/fpai-collect/tests/pi_source.rs +0 -1192
  336. package/.next/standalone/crates/fpai-collect/tests/supervisor.rs +0 -290
  337. package/.next/standalone/crates/fpai-collect/tests/uploader.rs +0 -506
  338. package/.next/standalone/crates/fpai-ipc/Cargo.toml +0 -16
  339. package/.next/standalone/crates/fpai-ipc/src/envelope.rs +0 -175
  340. package/.next/standalone/crates/fpai-ipc/src/framing.rs +0 -177
  341. package/.next/standalone/crates/fpai-ipc/src/lib.rs +0 -10
  342. package/.next/standalone/crates/fpai-ipc/src/peer.rs +0 -80
  343. package/.next/standalone/docker-hook-sync/Dockerfile +0 -79
  344. package/.next/standalone/docker-hook-sync/entrypoint.sh +0 -109
  345. package/.next/standalone/integration-suite/Dockerfile +0 -47
  346. package/.next/standalone/integration-suite/README.md +0 -129
  347. package/.next/standalone/integration-suite/canary-policies.mjs +0 -45
  348. package/.next/standalone/integration-suite/capture-tokens.sh +0 -48
  349. package/.next/standalone/integration-suite/ci-entrypoint.sh +0 -179
  350. package/.next/standalone/integration-suite/inject-tokens.sh +0 -44
  351. package/.next/standalone/integration-suite/install-clis.sh +0 -136
  352. package/.next/standalone/integration-suite/probe-cli.sh +0 -248
  353. package/.next/standalone/integration-suite/report.js +0 -120
  354. package/.next/standalone/integration-suite/run.sh +0 -159
  355. package/.next/standalone/openclaw-plugin/index.js +0 -223
  356. package/.next/standalone/openclaw-plugin/openclaw.plugin.json +0 -6
  357. package/.next/standalone/openclaw-plugin/package.json +0 -12
  358. package/.next/standalone/osv-scanner.toml +0 -17
  359. package/.next/standalone/pi-extension/index.ts +0 -524
  360. package/.next/standalone/pi-extension/package.json +0 -12
  361. package/.next/standalone/postcss.config.mjs +0 -8
  362. package/.next/standalone/readme-arch-hq.gif +0 -0
  363. package/.next/standalone/rust-toolchain.toml +0 -4
  364. package/src/auth/cli.ts +0 -371
  365. /package/.next/standalone/.next/static/{LOuwMmfomO6hQYfMQYs4K → Ptn8aBQl_cnNgOd0ebyv0}/_buildManifest.js +0 -0
  366. /package/.next/standalone/.next/static/{LOuwMmfomO6hQYfMQYs4K → Ptn8aBQl_cnNgOd0ebyv0}/_clientMiddlewareManifest.js +0 -0
  367. /package/.next/standalone/.next/static/{LOuwMmfomO6hQYfMQYs4K → Ptn8aBQl_cnNgOd0ebyv0}/_ssgManifest.js +0 -0
@@ -1,420 +0,0 @@
1
- //! Collector configuration: where to send events, and what to collect.
2
- //!
3
- //! # Two files, on purpose
4
- //!
5
- //! The credential lives alone in `~/.failproofai/ingest.json` at mode 0600.
6
- //! Everything else — which sources are on, backfill window, hook verbosity —
7
- //! lives in `policies-config.json` beside the rest of failproofai's settings,
8
- //! where it is readable, diffable and safe to commit to a dotfiles repo.
9
- //!
10
- //! That split is not tidiness. `policies-config.json` is written by
11
- //! `hooks-config.ts` with a bare `writeFileSync`, so it inherits the umask and
12
- //! lands at 0664 on a normal machine — inside `~/.failproofai/`, which is
13
- //! itself 0775. Putting an API key there would publish it to every local user
14
- //! on the box. `~/.agenteye/cli.json` already stores its session token at 0600,
15
- //! so the correct precedent existed; this follows it.
16
- //!
17
- //! # Disabled is the default, and it is a real default
18
- //!
19
- //! No `ingest.json`, or one with no key, means collection is off: no tasks, so
20
- //! no thread and no runtime (see [`crate::supervisor::spawn_supervised`]). A
21
- //! machine that has not opted in pays nothing for this code existing. Session
22
- //! collection additionally requires its own explicit opt-in, because
23
- //! transcripts carry prompts, file contents and whatever the user pasted into
24
- //! a terminal — configuring a key must not silently start shipping those.
25
-
26
- use std::fs;
27
- use std::io;
28
- use std::path::{Path, PathBuf};
29
-
30
- use serde::{Deserialize, Serialize};
31
-
32
- /// The hosted ingest endpoint. A COMPLETE endpoint including its path, not a
33
- /// base to join onto — byte-identical to what `agenteye-collector` defaults
34
- /// to, so a migrated config needs no rewriting and a self-hoster replaces the
35
- /// whole value with one of their own.
36
- pub const DEFAULT_INGEST_URL: &str = "https://server.befailproof.ai/events";
37
-
38
- /// Filename of the credential file inside the failproofai home.
39
- const INGEST_FILE: &str = "ingest.json";
40
- /// Filename of the shared settings file, owned by the TypeScript side.
41
- const POLICIES_FILE: &str = "policies-config.json";
42
-
43
- /// Mode the credential file must have. Anything wider is a finding.
44
- #[cfg(unix)]
45
- const CREDENTIAL_MODE: u32 = 0o600;
46
-
47
- /// What the daemon needs in order to ship anything at all.
48
- #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
49
- pub struct Ingest {
50
- /// Complete endpoint URL. Absent in the file means [`DEFAULT_INGEST_URL`].
51
- #[serde(default = "default_url")]
52
- pub url: String,
53
- /// An `events:add` API key, sent as a bearer token.
54
- pub key: String,
55
- }
56
-
57
- fn default_url() -> String {
58
- DEFAULT_INGEST_URL.to_string()
59
- }
60
-
61
- /// How much hook activity to ship.
62
- ///
63
- /// Measured on a real machine: 19,339 rows over 17 days from one developer on
64
- /// one CLI, of which 99.1% were plain `allow`. Emitting a triggered/completed
65
- /// pair per row is ~38,700 events for that one machine, almost all of it
66
- /// no-ops — hence a default that keeps every decision exact and rolls the rest
67
- /// up rather than dropping it.
68
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, Default)]
69
- #[serde(rename_all = "lowercase")]
70
- pub enum HooksVerbosity {
71
- /// Every hook invocation, in full.
72
- All,
73
- /// `deny` and `instruct` in full; `allow` aggregated per (session, event,
74
- /// tool) per minute. The aggregate carries a count, so the denominator
75
- /// survives — "we evaluated 19,000 calls and blocked 15" stays answerable.
76
- #[default]
77
- Decisions,
78
- /// No hook events at all.
79
- Off,
80
- }
81
-
82
- /// Client-side redaction strength.
83
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, Default)]
84
- #[serde(rename_all = "lowercase")]
85
- pub enum Redact {
86
- /// A fixed, deterministic pattern set over tool inputs and outputs.
87
- /// Deterministic is load-bearing, not incidental: the server dedups on a
88
- /// content hash, so a redaction that varied between reads of the same
89
- /// bytes would defeat it.
90
- #[default]
91
- Minimal,
92
- /// Ship verbatim.
93
- Off,
94
- }
95
-
96
- /// The non-secret half, read from `policies-config.json` under `"collector"`.
97
- #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
98
- #[serde(rename_all = "camelCase")]
99
- pub struct Settings {
100
- /// Ship agent session transcripts. Defaults to FALSE and is deliberately
101
- /// separate from having a key: transcripts carry prompts, file contents
102
- /// and pasted credentials, so configuring ingest must not silently start
103
- /// sending them.
104
- #[serde(default)]
105
- pub sessions: bool,
106
- /// Ship hook activity. Defaults to TRUE once ingest is configured — it
107
- /// carries decisions and tool names, never file contents, and it is the
108
- /// capability that justifies collecting from inside failproofai at all.
109
- #[serde(default = "default_true")]
110
- pub hooks: bool,
111
- #[serde(default)]
112
- pub hooks_verbosity: HooksVerbosity,
113
- #[serde(default)]
114
- pub redact: Redact,
115
- /// Label stamped on every event. Rejected if it contains a comma: the
116
- /// ingest endpoint skips any line whose `environment` has one, so a comma
117
- /// here would silently drop every event this machine produced.
118
- #[serde(default = "default_environment")]
119
- pub environment: String,
120
- /// The id of the machine this daemon runs on, written by
121
- /// `failproofai config --connect --machine-id <id>`. Stamped on every
122
- /// collected event so the server groups by machine rather than by
123
- /// `agent_id` (a per-project identity). Absent on config written before
124
- /// this field existed; such events carry no machine.
125
- #[serde(default, rename = "machineId")]
126
- pub machine_id: Option<String>,
127
- }
128
-
129
- fn default_true() -> bool {
130
- true
131
- }
132
-
133
- fn default_environment() -> String {
134
- "local".to_string()
135
- }
136
-
137
- impl Default for Settings {
138
- fn default() -> Self {
139
- Settings {
140
- sessions: false,
141
- hooks: true,
142
- hooks_verbosity: HooksVerbosity::default(),
143
- redact: Redact::default(),
144
- environment: default_environment(),
145
- machine_id: None,
146
- }
147
- }
148
- }
149
-
150
- /// Everything the collector needs, resolved.
151
- #[derive(Debug, Clone, PartialEq, Eq)]
152
- pub struct CollectorConfig {
153
- /// `None` means collection is off for this process.
154
- pub ingest: Option<Ingest>,
155
- pub settings: Settings,
156
- /// Directories watched for ready-to-upload event batches, in the order
157
- /// they are scanned.
158
- pub spool_dirs: Vec<PathBuf>,
159
- /// Where this daemon writes its own derived batches. Always the first
160
- /// entry of `spool_dirs`.
161
- pub own_spool_dir: PathBuf,
162
- /// Batches the server rejected, parked for retry.
163
- pub failed_dir: PathBuf,
164
- }
165
-
166
- impl CollectorConfig {
167
- /// True when there is a usable credential AND at least one stream enabled.
168
- /// This is what `collector_tasks()` keys off, so an unconfigured machine
169
- /// starts no thread and no runtime.
170
- pub fn is_enabled(&self) -> bool {
171
- self.ingest.is_some() && (self.settings.sessions || self.settings.hooks)
172
- }
173
- }
174
-
175
- #[derive(Debug)]
176
- pub enum ConfigError {
177
- Io(io::Error),
178
- /// The file exists but is not valid JSON. Deliberately NOT treated as
179
- /// "absent": silently disabling collection because someone fat-fingered a
180
- /// comma is the kind of quiet failure this project exists to remove.
181
- Malformed {
182
- path: PathBuf,
183
- detail: String,
184
- },
185
- /// A value is present but unusable.
186
- Invalid(String),
187
- }
188
-
189
- impl std::fmt::Display for ConfigError {
190
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
191
- match self {
192
- ConfigError::Io(e) => write!(f, "{e}"),
193
- ConfigError::Malformed { path, detail } => {
194
- write!(f, "{} is not valid JSON: {detail}", path.display())
195
- }
196
- ConfigError::Invalid(m) => write!(f, "{m}"),
197
- }
198
- }
199
- }
200
-
201
- impl std::error::Error for ConfigError {}
202
-
203
- impl From<io::Error> for ConfigError {
204
- fn from(e: io::Error) -> Self {
205
- ConfigError::Io(e)
206
- }
207
- }
208
-
209
- /// Resolve the collector's configuration.
210
- ///
211
- /// `home` is the failproofai home (`~/.failproofai`), passed rather than
212
- /// derived so tests need no environment mutation.
213
- ///
214
- /// Precedence for the endpoint and key is env → file → default, matching every
215
- /// other knob in this codebase. The env override exists for containers and for
216
- /// local development against a stack on `localhost`, where writing a file to a
217
- /// real home directory would be the wrong shape.
218
- pub fn load(home: &Path) -> Result<CollectorConfig, ConfigError> {
219
- let ingest = load_ingest(home)?;
220
- let settings = load_settings(home)?;
221
-
222
- if settings.environment.contains(',') {
223
- // Fail here rather than let ingest silently skip every line. The
224
- // server splits on commas, so this is unrecoverable downstream and
225
- // invisible upstream — exactly the shape of bug worth erroring on.
226
- return Err(ConfigError::Invalid(format!(
227
- "collector environment {:?} contains a comma, which the ingest endpoint rejects; \
228
- every event from this machine would be silently dropped",
229
- settings.environment
230
- )));
231
- }
232
-
233
- let own_spool_dir = home.join("spool");
234
- let failed_dir = home.join("failed");
235
-
236
- // Watch our own derived batches first, then the directory the Python SDK
237
- // and any custom agent already write to. Watching both is what lets
238
- // failproofaid supersede agenteye-collector without every SDK user having
239
- // to reconfigure anything: their events keep being collected, by a
240
- // different daemon, with no change on their side.
241
- let mut spool_dirs = vec![own_spool_dir.clone()];
242
- let sdk_spool = agenteye_events_dir();
243
- if !spool_dirs.contains(&sdk_spool) {
244
- spool_dirs.push(sdk_spool);
245
- }
246
-
247
- Ok(CollectorConfig {
248
- ingest,
249
- settings,
250
- spool_dirs,
251
- own_spool_dir,
252
- failed_dir,
253
- })
254
- }
255
-
256
- /// The directory the AgentEye Python SDK drops event batches into. Honors
257
- /// `AGENTEYE_HOME` for the same reason the SDK and collector do.
258
- fn agenteye_events_dir() -> PathBuf {
259
- let base = std::env::var_os("AGENTEYE_HOME")
260
- .map(PathBuf::from)
261
- .or_else(|| std::env::var_os("HOME").map(|h| PathBuf::from(h).join(".agenteye")))
262
- .unwrap_or_else(|| PathBuf::from(".agenteye"));
263
- base.join("events")
264
- }
265
-
266
- fn load_ingest(home: &Path) -> Result<Option<Ingest>, ConfigError> {
267
- let path = home.join(INGEST_FILE);
268
-
269
- let from_file: Option<Ingest> = match fs::read_to_string(&path) {
270
- Ok(text) => {
271
- warn_if_world_readable(&path);
272
- match serde_json::from_str::<Ingest>(&text) {
273
- Ok(v) => Some(v),
274
- Err(e) => {
275
- return Err(ConfigError::Malformed {
276
- path,
277
- detail: e.to_string(),
278
- });
279
- }
280
- }
281
- }
282
- Err(e) if e.kind() == io::ErrorKind::NotFound => None,
283
- Err(e) => return Err(ConfigError::Io(e)),
284
- };
285
-
286
- let key = env_nonempty("FAILPROOFAI_INGEST_KEY")
287
- .or_else(|| from_file.as_ref().map(|i| i.key.clone()));
288
- let url = env_nonempty("FAILPROOFAI_INGEST_URL")
289
- .or_else(|| from_file.as_ref().map(|i| i.url.clone()))
290
- .unwrap_or_else(default_url);
291
-
292
- // A file with an empty key is "configured but not really" — treat it as
293
- // absent rather than sending `Authorization: Bearer ` and collecting 401s.
294
- match key {
295
- Some(key) if !key.trim().is_empty() => Ok(Some(Ingest { url, key })),
296
- _ => Ok(None),
297
- }
298
- }
299
-
300
- fn load_settings(home: &Path) -> Result<Settings, ConfigError> {
301
- let path = home.join(POLICIES_FILE);
302
- let text = match fs::read_to_string(&path) {
303
- Ok(t) => t,
304
- Err(e) if e.kind() == io::ErrorKind::NotFound => return Ok(Settings::default()),
305
- Err(e) => return Err(ConfigError::Io(e)),
306
- };
307
-
308
- let root: serde_json::Value =
309
- serde_json::from_str(&text).map_err(|e| ConfigError::Malformed {
310
- path: path.clone(),
311
- detail: e.to_string(),
312
- })?;
313
-
314
- match root.get("collector") {
315
- None => Ok(Settings::default()),
316
- Some(v) => serde_json::from_value(v.clone()).map_err(|e| ConfigError::Malformed {
317
- path,
318
- detail: format!("the \"collector\" block is not usable: {e}"),
319
- }),
320
- }
321
- }
322
-
323
- fn env_nonempty(name: &str) -> Option<String> {
324
- std::env::var(name).ok().filter(|v| !v.trim().is_empty())
325
- }
326
-
327
- /// Log loudly if the credential file is readable by anyone but its owner.
328
- ///
329
- /// Warn rather than refuse: the key still works, and disabling collection over
330
- /// a permission bit would be a confusing failure for something the operator
331
- /// can fix in one command. But it is never silent — a credential readable by
332
- /// every local user is worth a line in the journal every startup.
333
- #[cfg(unix)]
334
- fn warn_if_world_readable(path: &Path) {
335
- use std::os::unix::fs::PermissionsExt;
336
- let Ok(meta) = fs::metadata(path) else { return };
337
- let mode = meta.permissions().mode() & 0o777;
338
- if mode & 0o077 != 0 {
339
- tracing::warn!(
340
- path = %path.display(),
341
- mode = format!("{mode:o}"),
342
- "the ingest credential is readable by other users on this machine; \
343
- tighten it with `chmod 600`"
344
- );
345
- }
346
- }
347
-
348
- #[cfg(not(unix))]
349
- fn warn_if_world_readable(_path: &Path) {}
350
-
351
- /// Write the credential file with owner-only permissions.
352
- ///
353
- /// Used by the setup wizard through the daemon, and by tests. The mode is set
354
- /// at CREATE time rather than chmod-ed afterwards, so the key is never briefly
355
- /// world-readable between the write and the fix.
356
- pub fn write_ingest(home: &Path, ingest: &Ingest) -> Result<PathBuf, ConfigError> {
357
- fs::create_dir_all(home)?;
358
- tighten_home(home);
359
-
360
- let path = home.join(INGEST_FILE);
361
- let body = serde_json::to_string_pretty(ingest)
362
- .map_err(|e| ConfigError::Invalid(format!("could not serialize ingest config: {e}")))?;
363
-
364
- write_private(&path, body.as_bytes())?;
365
- Ok(path)
366
- }
367
-
368
- #[cfg(unix)]
369
- fn write_private(path: &Path, bytes: &[u8]) -> Result<(), ConfigError> {
370
- use std::io::Write;
371
- use std::os::unix::fs::{OpenOptionsExt, PermissionsExt};
372
- let mut f = fs::OpenOptions::new()
373
- .write(true)
374
- .create(true)
375
- .truncate(true)
376
- .mode(CREDENTIAL_MODE)
377
- .open(path)?;
378
- f.write_all(bytes)?;
379
- f.sync_all()?;
380
- // `mode()` only applies when the file is CREATED, so an existing file that
381
- // was already too permissive would keep its mode. Set it explicitly too.
382
- fs::set_permissions(path, fs::Permissions::from_mode(CREDENTIAL_MODE))?;
383
- Ok(())
384
- }
385
-
386
- #[cfg(not(unix))]
387
- fn write_private(path: &Path, bytes: &[u8]) -> Result<(), ConfigError> {
388
- fs::write(path, bytes)?;
389
- Ok(())
390
- }
391
-
392
- /// Best-effort tightening of the failproofai home to owner-only.
393
- ///
394
- /// It is 0775 on a normal machine because nothing ever needed it otherwise.
395
- /// Once a credential lives inside it, a world-traversable parent undermines
396
- /// the 0600 on the file itself. Best-effort because failing to chmod a
397
- /// directory we do not own must not stop the daemon starting.
398
- #[cfg(unix)]
399
- fn tighten_home(home: &Path) {
400
- use std::os::unix::fs::PermissionsExt;
401
- let Ok(meta) = fs::metadata(home) else { return };
402
- let mode = meta.permissions().mode() & 0o777;
403
- if mode & 0o077 != 0 {
404
- match fs::set_permissions(home, fs::Permissions::from_mode(0o700)) {
405
- Ok(()) => tracing::info!(
406
- path = %home.display(),
407
- was = format!("{mode:o}"),
408
- "tightened the failproofai home to 0700 so the ingest credential inside it is not world-readable"
409
- ),
410
- Err(err) => tracing::warn!(
411
- path = %home.display(),
412
- %err,
413
- "could not tighten the failproofai home; the ingest credential's directory stays group/world-traversable"
414
- ),
415
- }
416
- }
417
- }
418
-
419
- #[cfg(not(unix))]
420
- fn tighten_home(_home: &Path) {}