failproofai 1.0.0 → 1.0.1-beta.1

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 (238) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +0 -1
  3. package/.next/standalone/.next/build-manifest.json +3 -3
  4. package/.next/standalone/.next/prerender-manifest.json +5 -5
  5. package/.next/standalone/.next/required-server-files.json +1 -1
  6. package/.next/standalone/.next/routes-manifest.json +0 -6
  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 +4 -3
  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 +6 -6
  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/_tree.segment.rsc +1 -1
  16. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  17. package/.next/standalone/.next/server/app/_not-found/page.js +4 -3
  18. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  19. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  20. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  21. package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
  22. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
  23. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +14 -14
  24. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  25. package/.next/standalone/.next/server/app/api/audit/invite/route.js +2 -2
  26. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/audit/run/route.js +3 -3
  28. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/audit/status/route.js +2 -2
  30. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/auth/login-request/route.js +4 -3
  32. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +2 -2
  34. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/api/auth/logout/route.js +3 -2
  36. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/api/auth/status/route.js +4 -3
  38. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  41. package/.next/standalone/.next/server/app/audit/page.js +5 -3
  42. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  43. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  44. package/.next/standalone/.next/server/app/index.html +1 -1
  45. package/.next/standalone/.next/server/app/index.rsc +15 -15
  46. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +14 -14
  47. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
  48. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  49. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  50. package/.next/standalone/.next/server/app/page.js +4 -3
  51. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  52. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  53. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +10 -10
  54. package/.next/standalone/.next/server/app/policies/page.js +6 -5
  55. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  56. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  57. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  58. package/.next/standalone/.next/server/app/project/[name]/page.js +5 -4
  59. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  60. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  61. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  62. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  63. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +6 -4
  64. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  65. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  66. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  67. package/.next/standalone/.next/server/app/projects/page.js +5 -4
  68. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  69. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  70. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -4
  71. package/.next/standalone/.next/server/app/settings/page.js +6 -4
  72. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  73. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  74. package/.next/standalone/.next/server/app-paths-manifest.json +0 -1
  75. package/.next/standalone/.next/server/chunks/[root-of-the-server]__05ja_05._.js +3 -0
  76. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0agdw2a._.js +3 -0
  77. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d1u_na._.js +1 -1
  78. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0nne229._.js +3 -0
  79. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ny9q5d._.js +1 -1
  80. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0oy4kxb._.js +3 -0
  81. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0zf034w._.js +3 -0
  82. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +3 -0
  83. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1hstmft._.js +3 -0
  84. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1p8poxd._.js +3 -0
  85. package/.next/standalone/.next/server/chunks/_0lxbzdq._.js +1 -1
  86. package/.next/standalone/.next/server/chunks/_1ek68ln._.js +1 -1
  87. package/.next/standalone/.next/server/chunks/_1zuiiy3._.js +1 -1
  88. package/.next/standalone/.next/server/chunks/lib_telemetry_ts_0dctyyw._.js +1 -1
  89. package/.next/standalone/.next/server/chunks/{node_modules_posthog-node_dist_entrypoints_index_node_mjs_0jx6cp6._.js → node_modules_posthog-node_dist_entrypoints_index_node_mjs_0f-x2b0._.js} +1 -1
  90. package/.next/standalone/.next/server/chunks/{node_modules_posthog-node_dist_entrypoints_index_node_mjs_1f290jp._.js → node_modules_posthog-node_dist_entrypoints_index_node_mjs_0hwvl7e._.js} +1 -1
  91. package/.next/standalone/.next/server/chunks/{node_modules_posthog-node_dist_entrypoints_index_node_mjs_1g2ji1t._.js → node_modules_posthog-node_dist_entrypoints_index_node_mjs_1ctjdzl._.js} +1 -1
  92. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  93. package/.next/standalone/.next/server/chunks/src_hooks_fp-home_ts_09kv0bn._.js +3 -0
  94. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__03eykvd._.js +5 -0
  95. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__07175vb._.js → [root-of-the-server]__07oh8b5._.js} +1 -1
  96. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0cxe_2_._.js +2 -2
  97. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0kgy9da._.js +4 -0
  98. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0m98kzy._.js +4 -0
  99. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0oa1lav._.js +3 -0
  100. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0sjzdjg._.js +3 -0
  101. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0spkm68._.js +2 -2
  102. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0v5_91z._.js +4 -0
  103. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1-a3135._.js +4 -0
  104. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1hvwiw8._.js → [root-of-the-server]__11z_299._.js} +1 -1
  105. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1apc90t._.js → [root-of-the-server]__15c_z97._.js} +1 -1
  106. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1wmno1q._.js → [root-of-the-server]__17d_ffl._.js} +1 -1
  107. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1_dfocn._.js +4 -0
  108. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1e5g_ur._.js +4 -0
  109. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1hmqefd._.js +4 -0
  110. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1jiwfsj._.js +1 -1
  111. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1kzapg5._.js +6 -0
  112. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1zvtylo._.js +3 -0
  113. package/.next/standalone/.next/server/chunks/ssr/_04j57fb._.js +3 -0
  114. package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +3 -0
  115. package/.next/standalone/.next/server/chunks/ssr/_0hom1s1._.js +3 -0
  116. package/.next/standalone/.next/server/chunks/ssr/_0qk91ba._.js +3 -0
  117. package/.next/standalone/.next/server/chunks/ssr/_1q7j05x._.js +3 -0
  118. package/.next/standalone/.next/server/chunks/ssr/_1wboum1._.js +23 -0
  119. package/.next/standalone/.next/server/chunks/ssr/_1ylae7o._.js +3 -0
  120. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +2 -2
  121. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  122. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +2 -2
  123. package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +3 -0
  124. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_1n3w9lb._.js +1 -1
  125. package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +1 -1
  126. package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.js +4 -0
  127. package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-home_ts_0je3xkv._.js +3 -0
  128. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  129. package/.next/standalone/.next/server/pages/404.html +1 -1
  130. package/.next/standalone/.next/server/pages/500.html +1 -1
  131. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  132. package/.next/standalone/.next/server/server-reference-manifest.json +15 -15
  133. package/.next/standalone/.next/static/chunks/{2676v-lyzgo91.js → 01b0vu6t3wtfh.js} +1 -1
  134. package/.next/standalone/.next/static/chunks/0u64yey446k4f.css +1 -0
  135. package/.next/standalone/.next/static/chunks/0w-2enf8raksk.js +1 -0
  136. package/.next/standalone/.next/static/chunks/{2kopjq_or743g.js → 13pe0rgzztjxa.js} +2 -2
  137. package/.next/standalone/.next/static/chunks/{3xvtgz6arztp_.js → 1cn6xl9lfp3ei.js} +1 -1
  138. package/.next/standalone/.next/static/chunks/{0zi8zjav5a4rq.js → 1e_2h_-zvxnke.js} +1 -1
  139. package/.next/standalone/.next/static/chunks/1eyl7fzkmnkf_.js +1 -0
  140. package/.next/standalone/.next/static/chunks/{0zm3_8jpqitxy.js → 1x9238y5kw9vi.js} +22 -22
  141. package/.next/standalone/.next/static/chunks/1xajksrefvav8.js +1 -0
  142. package/.next/standalone/.next/static/chunks/{1hfocb0sdl85c.js → 25c48grb44a-n.js} +1 -1
  143. package/.next/standalone/.next/static/chunks/{2ouq44jv_0x04.js → 28bdm54bngvc7.js} +1 -1
  144. package/.next/standalone/.next/static/chunks/29-iqnp9v_axt.css +1 -0
  145. package/.next/standalone/.next/static/chunks/{31k3yxpy57_fy.js → 2hhselnqeo4ll.js} +1 -1
  146. package/.next/standalone/.next/static/chunks/2k9f4tyv04809.css +1 -0
  147. package/.next/standalone/.next/static/chunks/3qfoeqhy5l10x.js +1 -0
  148. package/.next/standalone/.next/static/chunks/{0km-jn9o5xyqs.css → 3wq9x0c-7ld5d.css} +1 -1
  149. package/.next/standalone/app/actions/get-scheduled-audit.ts +65 -6
  150. package/.next/standalone/app/actions/update-scheduled-audit.ts +90 -17
  151. package/.next/standalone/app/api/auth/status/route.ts +7 -17
  152. package/.next/standalone/app/audit/_components/audit-dashboard.tsx +2 -6
  153. package/.next/standalone/app/audit/_components/come-back-better-section.tsx +101 -281
  154. package/.next/standalone/app/audit/_components/empty-state.tsx +2 -2
  155. package/.next/standalone/app/audit/_components/run-progress.tsx +1 -1
  156. package/.next/standalone/app/audit/audit-styles.css +150 -26
  157. package/.next/standalone/app/globals.css +39 -1
  158. package/.next/standalone/app/settings/page.tsx +38 -21
  159. package/.next/standalone/app/settings/settings-client.tsx +583 -392
  160. package/.next/standalone/app/settings/settings.css +354 -0
  161. package/.next/standalone/components/navbar.tsx +33 -4
  162. package/.next/standalone/lib/auth/api-server-client.ts +51 -29
  163. package/.next/standalone/lib/auth/auth-store.ts +44 -59
  164. package/.next/standalone/lib/telemetry.ts +45 -40
  165. package/.next/standalone/package.json +12 -10
  166. package/.next/standalone/server.js +1 -1
  167. package/bin/failproofai.mjs +6 -0
  168. package/bin/failproofaid-shim.mjs +0 -0
  169. package/dist/cli.mjs +1915 -472
  170. package/dist/worker.mjs +27 -5
  171. package/lib/auth/api-server-client.ts +51 -29
  172. package/lib/auth/auth-store.ts +44 -59
  173. package/lib/telemetry.ts +45 -40
  174. package/package.json +12 -10
  175. package/scripts/docs-audit.ts +493 -0
  176. package/scripts/translate-docs/cli.ts +16 -2
  177. package/scripts/translate-docs/mdx-translator.ts +6 -1
  178. package/scripts/translate-docs/readme-translator.ts +4 -2
  179. package/src/audit/cli-login.ts +330 -0
  180. package/src/audit/cli.ts +164 -31
  181. package/src/audit/dashboard-cache.ts +44 -8
  182. package/src/audit/harm-report.ts +260 -0
  183. package/src/audit/machine-store.ts +120 -0
  184. package/src/audit/redact-example.ts +312 -0
  185. package/src/audit/report-harm.ts +167 -0
  186. package/src/audit/schedule-cli.ts +352 -0
  187. package/src/hooks/builtin-policies.ts +26 -0
  188. package/src/hooks/daemon-service.ts +76 -0
  189. package/src/hooks/fp-config.ts +96 -5
  190. package/src/hooks/fp-home.ts +118 -8
  191. package/src/hooks/fp-reset.ts +79 -9
  192. package/src/hooks/hook-telemetry.ts +3 -2
  193. package/src/hooks/migrations.ts +241 -4
  194. package/src/hooks/tui.ts +61 -3
  195. package/.next/standalone/.next/server/app/api/auth/reminder/route/app-paths-manifest.json +0 -3
  196. package/.next/standalone/.next/server/app/api/auth/reminder/route/build-manifest.json +0 -12
  197. package/.next/standalone/.next/server/app/api/auth/reminder/route/server-reference-manifest.json +0 -4
  198. package/.next/standalone/.next/server/app/api/auth/reminder/route.js +0 -9
  199. package/.next/standalone/.next/server/app/api/auth/reminder/route.js.map +0 -5
  200. package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +0 -1
  201. package/.next/standalone/.next/server/app/api/auth/reminder/route_client-reference-manifest.js +0 -3
  202. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-xggru._.js +0 -3
  203. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00ds05_._.js +0 -3
  204. package/.next/standalone/.next/server/chunks/[root-of-the-server]__094p1f1._.js +0 -3
  205. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1dxagv_._.js +0 -3
  206. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fgqj1_._.js +0 -3
  207. package/.next/standalone/.next/server/chunks/_084toou._.js +0 -3
  208. package/.next/standalone/.next/server/chunks/_0g4t8c9._.js +0 -3
  209. package/.next/standalone/.next/server/chunks/_0km521a._.js +0 -3
  210. package/.next/standalone/.next/server/chunks/_0t8kefc._.js +0 -3
  211. package/.next/standalone/.next/server/chunks/_16dwkfn._.js +0 -3
  212. package/.next/standalone/.next/server/chunks/_1phm9ui._.js +0 -3
  213. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_auth_reminder_route_actions_1kjgxf8.js +0 -3
  214. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0dk8r_l._.js +0 -3
  215. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0kviq2m._.js +0 -3
  216. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ogyhu0._.js +0 -3
  217. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1-rfu32._.js +0 -5
  218. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1mmefsr._.js +0 -5
  219. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1t62w37._.js +0 -3
  220. package/.next/standalone/.next/server/chunks/ssr/_032wo7w._.js +0 -3
  221. package/.next/standalone/.next/server/chunks/ssr/_08840em._.js +0 -3
  222. package/.next/standalone/.next/server/chunks/ssr/_0gl2ujp._.js +0 -3
  223. package/.next/standalone/.next/server/chunks/ssr/_0j0ggkc._.js +0 -3
  224. package/.next/standalone/.next/server/chunks/ssr/_0kbv5-q._.js +0 -3
  225. package/.next/standalone/.next/server/chunks/ssr/_0r1jgvp._.js +0 -3
  226. package/.next/standalone/.next/server/chunks/ssr/_0t5xq1b._.js +0 -3
  227. package/.next/standalone/.next/server/chunks/ssr/_0w_be0g._.js +0 -3
  228. package/.next/standalone/.next/server/chunks/ssr/_15gba46._.js +0 -5
  229. package/.next/standalone/.next/server/chunks/ssr/_1qyhb9r._.js +0 -23
  230. package/.next/standalone/.next/server/chunks/ssr/_1vel2ey._.js +0 -3
  231. package/.next/standalone/.next/static/chunks/0wd503tv801gy.js +0 -1
  232. package/.next/standalone/.next/static/chunks/1v1gqvpjk62jm.js +0 -1
  233. package/.next/standalone/.next/static/chunks/2uvhw57mf9lg_.css +0 -2
  234. package/.next/standalone/.next/static/chunks/2ynl0-6aqng_b.js +0 -1
  235. package/.next/standalone/app/api/auth/reminder/route.ts +0 -213
  236. /package/.next/standalone/.next/static/{Aulh3DRWwRfwh2POCvZR_ → zMC0Yqypg3GF82-3KN6ul}/_buildManifest.js +0 -0
  237. /package/.next/standalone/.next/static/{Aulh3DRWwRfwh2POCvZR_ → zMC0Yqypg3GF82-3KN6ul}/_clientMiddlewareManifest.js +0 -0
  238. /package/.next/standalone/.next/static/{Aulh3DRWwRfwh2POCvZR_ → zMC0Yqypg3GF82-3KN6ul}/_ssgManifest.js +0 -0
package/dist/worker.mjs CHANGED
@@ -370,7 +370,7 @@ function failproofaiHome(home) {
370
370
  return resolve(home, ".failproofai");
371
371
  return process.env.FAILPROOFAI_HOME || resolve(homedir(), ".failproofai");
372
372
  }
373
- var LAYOUT_VERSION = 3, at = (...parts) => resolve(failproofaiHome(), ...parts), atHome = (home, ...parts) => home ? resolve(failproofaiHome(home), ...parts) : at(...parts), versionFile = (home) => atHome(home, "VERSION"), configFile = (home) => atHome(home, "config.json"), policiesDir = (home) => atHome(home, "policies"), customPoliciesDir, globalPolicyConfigFile = (home) => atHome(home, "policies-config.json"), cloudPoliciesDir = (home) => resolve(policiesDir(home), "cloud-policies"), hookActivityDir = (home) => atHome(home, "hook-activity"), stateDir = (home) => atHome(home, "state"), shimsDir = (home) => resolve(stateDir(home), "shims"), sessionPauseDir = () => resolve(stateDir(), "sessions"), telemetryIdFile = (home) => resolve(stateDir(home), "telemetry-id"), codexSessionPathsFile = (home) => resolve(stateDir(home), "codex-session-paths.json"), logsDir = (home) => atHome(home, "logs"), legacy;
373
+ var LAYOUT_VERSION = 4, at = (...parts) => resolve(failproofaiHome(), ...parts), atHome = (home, ...parts) => home ? resolve(failproofaiHome(home), ...parts) : at(...parts), versionFile = (home) => atHome(home, "VERSION"), configFile = (home) => atHome(home, "config.json"), policiesDir = (home) => atHome(home, "policies"), customPoliciesDir, globalPolicyConfigFile = (home) => atHome(home, "policies-config.json"), cloudPoliciesDir = (home) => resolve(policiesDir(home), "cloud-policies"), hookActivityDir = (home) => atHome(home, "hook-activity"), stateDir = (home) => atHome(home, "state"), shimsDir = (home) => resolve(stateDir(home), "shims"), sessionPauseDir = () => resolve(stateDir(), "sessions"), telemetryIdFile = (home) => resolve(stateDir(home), "telemetry-id"), codexSessionPathsFile = (home) => resolve(stateDir(home), "codex-session-paths.json"), logsDir = (home) => atHome(home, "logs"), legacy;
374
374
  var init_fp_home = __esm(() => {
375
375
  customPoliciesDir = policiesDir;
376
376
  legacy = {
@@ -386,6 +386,10 @@ var init_fp_home = __esm(() => {
386
386
  launcherMarker: () => at(".launcher-configured"),
387
387
  lastVersion: () => at("last-version"),
388
388
  auditDashboard: () => at("audit-dashboard.json"),
389
+ authJson: () => at("auth.json"),
390
+ nextAudit: () => at("next-audit.json"),
391
+ auditReminder: () => at("audit", "reminder.json"),
392
+ auditSchedule: () => at("state", "audit-schedule.json"),
389
393
  cacheDir: () => at("cache"),
390
394
  hookActivityDir: () => at("cache", "hook-activity"),
391
395
  auditCacheDir: () => at("cache", "audit"),
@@ -1831,7 +1835,7 @@ function registerBuiltinPolicies(enabledNames) {
1831
1835
  }
1832
1836
  }
1833
1837
  }
1834
- var isClaudeInternalPath, isClaudeSettingsFile, SHELL_OPERATORS, SHELL_METACHAR_RE, JWT_RE, API_KEY_PATTERNS, CONNECTION_STRING_RE, PRIVATE_KEY_RE, BEARER_TOKEN_RE, SQL_TOOL_RE, DESTRUCTIVE_SQL_RE, DELETE_NO_WHERE_RE, SQL_WHERE_RE, SCHEMA_ALTER_RE, PUBLISH_CMD_RE, ENV_PRINTENV_RE, ECHO_ENV_RE, EXPORT_RE, PS_ENV_VAR_RE, PS_CHILDITEM_ENV_RE, DOTNET_GETENV_RE, CMD_ECHO_ENV_RE, ENV_FILE_PATH_RE, ENV_CMD_RE, PS_ELEVATION_RE, RUNAS_RE, CURL_PIPE_SH_RE, SEGMENT_SEPARATORS, COMMAND_PREFIX_TOKENS, SELF_BINARY_TOKEN_RE, CONFIG_SUBCOMMAND_RE, PAUSE_FLAG_RE, ENV_ASSIGNMENT_RE, RUNNER_OPERAND_RE, PS_WEB_PIPE_RE, SHORT_FLAG_BUNDLE_RE, SAFE_FORCE_PREFIXES, SECRET_FILE_RE, SECRET_FILE_ID_RSA_RE, SECRET_FILE_CREDENTIALS_RE, GIT_COMMIT_MERGE_RE, FAILPROOFAI_CLI_RE, FAILPROOFAI_UNINSTALL_RE, GIT_AMEND_RE, GIT_STASH_DROP_RE, GIT_ADD_ALL_RE, NPM_GLOBAL_RE, YARN_GLOBAL_RE, PNPM_GLOBAL_RE, BUN_GLOBAL_RE, CARGO_INSTALL_RE, PIP_SYSTEM_RE, PKG_MANAGER_DETECTORS, NOHUP_RE, SCREEN_DETACH_RE, TMUX_DETACH_RE, DISOWN_RE, BACKGROUND_AMPERSAND_RE, KUBECTL_RE, TERRAFORM_RE, AWS_CLI_RE, GCLOUD_RE, AZ_CLI_RE, HELM_RE, GH_PIPELINE_RE, gitBranchCache, GIT_BRANCH_CACHE_MAX_ENTRIES = 500, EVAL_FLAG_RE, HOME_PREFIX_RE, RM_CMD_RE, FIND_CMD_RE, FIND_EXEC_RE, FIND_GLOBAL_OPT_RE, FIND_EXPR_START_RE, SCRATCH_ROOTS, CATASTROPHIC_DEPTH = 2, READ_LIKE_CMDS, TOOL_CALL_TRACKER_MAX_BYTES = 65536, SEGMENT_SPLIT_RE, BUILTIN_POLICIES;
1838
+ var isClaudeInternalPath, isClaudeSettingsFile, SHELL_OPERATORS, SHELL_METACHAR_RE, JWT_RE, API_KEY_PATTERNS, CONNECTION_STRING_RE, PRIVATE_KEY_RE, BEARER_TOKEN_RE, SECRET_PATTERNS, SQL_TOOL_RE, DESTRUCTIVE_SQL_RE, DELETE_NO_WHERE_RE, SQL_WHERE_RE, SCHEMA_ALTER_RE, PUBLISH_CMD_RE, ENV_PRINTENV_RE, ECHO_ENV_RE, EXPORT_RE, PS_ENV_VAR_RE, PS_CHILDITEM_ENV_RE, DOTNET_GETENV_RE, CMD_ECHO_ENV_RE, ENV_FILE_PATH_RE, ENV_CMD_RE, PS_ELEVATION_RE, RUNAS_RE, CURL_PIPE_SH_RE, SEGMENT_SEPARATORS, COMMAND_PREFIX_TOKENS, SELF_BINARY_TOKEN_RE, CONFIG_SUBCOMMAND_RE, PAUSE_FLAG_RE, ENV_ASSIGNMENT_RE, RUNNER_OPERAND_RE, PS_WEB_PIPE_RE, SHORT_FLAG_BUNDLE_RE, SAFE_FORCE_PREFIXES, SECRET_FILE_RE, SECRET_FILE_ID_RSA_RE, SECRET_FILE_CREDENTIALS_RE, GIT_COMMIT_MERGE_RE, FAILPROOFAI_CLI_RE, FAILPROOFAI_UNINSTALL_RE, GIT_AMEND_RE, GIT_STASH_DROP_RE, GIT_ADD_ALL_RE, NPM_GLOBAL_RE, YARN_GLOBAL_RE, PNPM_GLOBAL_RE, BUN_GLOBAL_RE, CARGO_INSTALL_RE, PIP_SYSTEM_RE, PKG_MANAGER_DETECTORS, NOHUP_RE, SCREEN_DETACH_RE, TMUX_DETACH_RE, DISOWN_RE, BACKGROUND_AMPERSAND_RE, KUBECTL_RE, TERRAFORM_RE, AWS_CLI_RE, GCLOUD_RE, AZ_CLI_RE, HELM_RE, GH_PIPELINE_RE, gitBranchCache, GIT_BRANCH_CACHE_MAX_ENTRIES = 500, EVAL_FLAG_RE, HOME_PREFIX_RE, RM_CMD_RE, FIND_CMD_RE, FIND_EXEC_RE, FIND_GLOBAL_OPT_RE, FIND_EXPR_START_RE, SCRATCH_ROOTS, CATASTROPHIC_DEPTH = 2, READ_LIKE_CMDS, TOOL_CALL_TRACKER_MAX_BYTES = 65536, SEGMENT_SPLIT_RE, BUILTIN_POLICIES;
1835
1839
  var init_builtin_policies = __esm(() => {
1836
1840
  init_hook_logger();
1837
1841
  isClaudeInternalPath = isAgentInternalPath;
@@ -1853,6 +1857,13 @@ var init_builtin_policies = __esm(() => {
1853
1857
  CONNECTION_STRING_RE = /(?:postgresql|postgres|mysql|mongodb(?:\+srv)?|redis|amqps?|smtps?):\/\/[^@\s]+@/;
1854
1858
  PRIVATE_KEY_RE = /-----BEGIN (?:[A-Z]+ )?PRIVATE KEY-----/;
1855
1859
  BEARER_TOKEN_RE = /Authorization:\s*Bearer\s+[A-Za-z0-9\-._~+/]{20,}/i;
1860
+ SECRET_PATTERNS = [
1861
+ [PRIVATE_KEY_RE, "private key"],
1862
+ [JWT_RE, "JWT"],
1863
+ [BEARER_TOKEN_RE, "bearer token"],
1864
+ [CONNECTION_STRING_RE, "database credentials"],
1865
+ ...API_KEY_PATTERNS
1866
+ ];
1856
1867
  SQL_TOOL_RE = /\b(?:psql|mysql|sqlite3|pgcli|clickhouse-client)\b/;
1857
1868
  DESTRUCTIVE_SQL_RE = /\b(?:DROP\s+(?:TABLE|DATABASE|SCHEMA)|TRUNCATE\b)/i;
1858
1869
  DELETE_NO_WHERE_RE = /\bDELETE\s+FROM\b/i;
@@ -2511,7 +2522,7 @@ var init_builtin_policies = __esm(() => {
2511
2522
  });
2512
2523
 
2513
2524
  // package.json
2514
- var version = "1.0.0";
2525
+ var version = "1.0.1-beta.1";
2515
2526
  var init_package = () => {};
2516
2527
 
2517
2528
  // src/posthog-key.ts
@@ -2527,10 +2538,17 @@ function detectLayout() {
2527
2538
  return raw.layout > LAYOUT_VERSION ? { kind: "future", found: raw.layout } : { kind: "stale", found: raw.layout };
2528
2539
  }
2529
2540
  if (existsSync3(configFile())) {
2541
+ const layoutThreePositions = [
2542
+ legacy.authJson(),
2543
+ legacy.nextAudit(),
2544
+ legacy.auditSchedule()
2545
+ ];
2546
+ if (layoutThreePositions.some((p) => existsSync3(p)))
2547
+ return { kind: "stale", found: 3 };
2530
2548
  return { kind: "current", version: { layout: LAYOUT_VERSION, cli: "" }, inferred: true };
2531
2549
  }
2532
2550
  if (existsSync3(legacy.configToml()))
2533
- return { kind: "stale", found: LAYOUT_VERSION - 1 };
2551
+ return { kind: "stale", found: 2 };
2534
2552
  const layoutOneMarkers = [
2535
2553
  legacy.policyConfig(),
2536
2554
  legacy.cacheDir(),
@@ -2622,7 +2640,11 @@ function projectConfig(parsed) {
2622
2640
  sources: readSources(collector.sources)
2623
2641
  },
2624
2642
  telemetry: { enabled: telemetry.enabled !== false },
2625
- audit: { auto: audit.auto === true, intervalDays: readIntervalDays(audit.interval_days) }
2643
+ audit: {
2644
+ auto: audit.auto === true,
2645
+ intervalDays: readIntervalDays(audit.interval_days),
2646
+ reportsConsentedAt: typeof audit.reports_consented_at === "number" && Number.isFinite(audit.reports_consented_at) ? audit.reports_consented_at : undefined
2647
+ }
2626
2648
  };
2627
2649
  }
2628
2650
  }
@@ -107,7 +107,7 @@ async function parseError(res: Response): Promise<AuthApiError> {
107
107
  return new AuthApiError(res.status, code, message, retryAfterSecs);
108
108
  }
109
109
 
110
- /** Hard cap on every auth/reminder HTTP call. Without this, a wedged DNS
110
+ /** Hard cap on every auth/report HTTP call. Without this, a wedged DNS
111
111
  * resolver or a hung server keeps the CLI / dashboard route stuck forever. */
112
112
  const REQUEST_TIMEOUT_MS = 10_000;
113
113
 
@@ -210,34 +210,6 @@ export async function fetchMe(accessToken: string): Promise<MeResponse> {
210
210
  return getJson<MeResponse>("/v0/auth/me", accessToken);
211
211
  }
212
212
 
213
- export interface ServerReminder {
214
- user_id: string;
215
- email: string;
216
- fire_at: number; // unix seconds
217
- set_at: number; // unix seconds
218
- }
219
-
220
- export async function scheduleReminder(
221
- accessToken: string,
222
- body: { in_days?: number; at?: number },
223
- ): Promise<ServerReminder> {
224
- const res = await postJson<{ reminder: ServerReminder }>(
225
- "/v0/reminders",
226
- body,
227
- { accessToken },
228
- );
229
- return res.reminder;
230
- }
231
-
232
- export async function cancelReminder(accessToken: string): Promise<void> {
233
- const res = await fetchWithTimeout(`${getApiBase()}/v0/reminders`, {
234
- method: "DELETE",
235
- headers: { authorization: `Bearer ${accessToken}` },
236
- });
237
- if (res.status === 204 || res.ok) return;
238
- throw await parseError(res);
239
- }
240
-
241
213
  export interface InviteSendResult {
242
214
  /** Recipients that were dispatched successfully. */
243
215
  sent: string[];
@@ -266,6 +238,56 @@ export async function sendInvites(
266
238
  );
267
239
  }
268
240
 
241
+ export interface AuditReportBody {
242
+ machine_id: string;
243
+ label?: string;
244
+ platform?: string;
245
+ window_from?: string;
246
+ window_to: string;
247
+ harmful: {
248
+ policy: string;
249
+ category: string;
250
+ title: string;
251
+ hits: number;
252
+ first_seen?: string;
253
+ last_seen?: string;
254
+ examples: string[];
255
+ }[];
256
+ }
257
+
258
+ export interface AuditReportResult {
259
+ report_id: string;
260
+ /** Whether this report produced an email. */
261
+ emailed: boolean;
262
+ /** `below_threshold`, `cooldown`, `send_failed`, or null when mail went out. */
263
+ reason: string | null;
264
+ /**
265
+ * Where the next window starts, per the SERVER.
266
+ *
267
+ * Persisted verbatim rather than computed locally. The server anchors it on
268
+ * the last DELIVERED digest, so a report held by the cooldown — or one whose
269
+ * send failed — correctly leaves the watermark where it was, and its findings
270
+ * turn up in the next digest instead of falling into a gap. A machine that
271
+ * lost `machine.json` also resyncs here rather than re-reporting from the
272
+ * beginning of time.
273
+ */
274
+ next_window_from: string;
275
+ }
276
+
277
+ /**
278
+ * Submit one scheduled scan's harmful findings.
279
+ *
280
+ * Called only by the audit child, and only on `--scheduled`. The destination
281
+ * address is never sent: the api-server takes it from the access-token claims,
282
+ * so a report cannot name where its digest goes.
283
+ */
284
+ export async function submitAuditReport(
285
+ accessToken: string,
286
+ body: AuditReportBody,
287
+ ): Promise<AuditReportResult> {
288
+ return postJson<AuditReportResult>("/v0/audit-reports", body, { accessToken });
289
+ }
290
+
269
291
  interface JwtClaims {
270
292
  sub: string;
271
293
  email: string;
@@ -1,16 +1,17 @@
1
1
  /**
2
- * Persistence layer for the FailproofAI auth.json file.
2
+ * Persistence layer for the signed-in session.
3
3
  *
4
- * Tokens live at ~/.failproofai/auth.json with mode 0600. The dashboard's
5
- * Next.js API routes read and write through here, so a session survives across
6
- * dashboard runs.
4
+ * Tokens live at `~/.failproofai/audit/session.json` with mode 0600 (layout 4;
5
+ * `auth.json` at the home root before that). The dashboard's Next.js API routes
6
+ * and the audit child both read and write through here, so a session survives
7
+ * across dashboard runs and is the same one a scheduled report uses.
7
8
  */
8
9
 
9
- import { existsSync, readFileSync, rmSync } from "node:fs";
10
- import { join } from "node:path";
10
+ import { existsSync, readFileSync, readdirSync, rmSync } from "node:fs";
11
+ import { join, resolve } from "node:path";
11
12
 
12
13
  import { writeJsonAtomically } from "../atomic-write";
13
- import { failproofaiHome } from "../../src/hooks/fp-home";
14
+ import { auditDir, auditSessionFile, migrationsDir } from "../../src/hooks/fp-home";
14
15
  import {
15
16
  AuthApiError,
16
17
  decodeJwt,
@@ -27,62 +28,24 @@ export interface StoredAuth {
27
28
  user: { id: string; email: string };
28
29
  }
29
30
 
31
+ /**
32
+ * Where the session file lives.
33
+ *
34
+ * `FAILPROOFAI_AUTH_DIR` overrides it OUTRIGHT — the override names the
35
+ * directory the two files sit in directly, with no `audit/` beneath it, which is
36
+ * the contract it has always had and what every test using it expects. Without
37
+ * the override the paths come from `fp-home.ts`, which as of layout 4 puts them
38
+ * under `audit/` with the rest of what the audit owns.
39
+ */
30
40
  export function getAuthDir(): string {
31
41
  const override = process.env.FAILPROOFAI_AUTH_DIR;
32
42
  if (override) return override;
33
- return failproofaiHome();
43
+ return auditDir();
34
44
  }
35
45
 
36
46
  export function getAuthFilePath(): string {
37
- return join(getAuthDir(), "auth.json");
38
- }
39
-
40
- /** Location of the persisted re-audit reminder (separate from auth.json so
41
- * the reminder survives unrelated session refreshes). */
42
- export function getReminderFilePath(): string {
43
- return join(getAuthDir(), "next-audit.json");
44
- }
45
-
46
- export interface StoredReminder {
47
- /** Unix seconds. */
48
- next_audit_at: number;
49
- /** Email the reminder was set for. Used to invalidate the reminder if the
50
- * active session belongs to a different user. */
51
- user_email: string;
52
- /** Unix seconds. */
53
- set_at: number;
54
- }
55
-
56
- export function readReminder(): StoredReminder | null {
57
- const p = getReminderFilePath();
58
- if (!existsSync(p)) return null;
59
- try {
60
- const raw = readFileSync(p, "utf-8");
61
- const parsed = JSON.parse(raw) as Partial<StoredReminder>;
62
- if (
63
- typeof parsed.next_audit_at !== "number" ||
64
- typeof parsed.user_email !== "string" ||
65
- typeof parsed.set_at !== "number"
66
- ) {
67
- return null;
68
- }
69
- return {
70
- next_audit_at: parsed.next_audit_at,
71
- user_email: parsed.user_email,
72
- set_at: parsed.set_at,
73
- };
74
- } catch {
75
- return null;
76
- }
77
- }
78
-
79
- export function writeReminder(reminder: StoredReminder): void {
80
- writeJsonAtomically(getReminderFilePath(), reminder);
81
- }
82
-
83
- export function deleteReminder(): void {
84
- const p = getReminderFilePath();
85
- if (existsSync(p)) rmSync(p, { force: true });
47
+ const override = process.env.FAILPROOFAI_AUTH_DIR;
48
+ return override ? join(override, "session.json") : auditSessionFile();
86
49
  }
87
50
 
88
51
  export function readAuth(): StoredAuth | null {
@@ -127,6 +90,28 @@ export function writeAuth(auth: StoredAuth): void {
127
90
  export function deleteAuth(): void {
128
91
  const p = getAuthFilePath();
129
92
  if (existsSync(p)) rmSync(p, { force: true });
93
+
94
+ // Also any copy a migration took and could not clean up.
95
+ //
96
+ // The layout-4 step backs `auth.json` up before moving it, and a chain that
97
+ // FAILED deliberately keeps that copy — it is the only insurance against a
98
+ // half-moved credential. But "sign me out" has to mean the token is off this
99
+ // machine, and `migrationsDir` is classed `identity`, so nothing else will
100
+ // ever remove it: without this sweep a dashboard sign-out, a 401 auto-delete
101
+ // and `failproofai reset` all left a live bearer and refresh token on disk,
102
+ // to be carried into every dotfile backup and container image after it.
103
+ try {
104
+ const root = migrationsDir();
105
+ if (!existsSync(root)) return;
106
+ for (const entry of readdirSync(root)) {
107
+ if (!entry.startsWith("backup-layout")) continue;
108
+ const copy = resolve(root, entry, "auth.json");
109
+ if (existsSync(copy)) rmSync(copy, { force: true });
110
+ }
111
+ } catch {
112
+ // Sign-out must succeed even if the sweep cannot. The live token — the one
113
+ // that actually authenticates a request — is already gone above.
114
+ }
130
115
  }
131
116
 
132
117
  /** Convert verify/refresh response into the on-disk shape. */
@@ -161,8 +146,8 @@ const REFRESH_LEEWAY_SECS = 60;
161
146
 
162
147
  /**
163
148
  * In-flight refresh dedup. Without this, two concurrent callers (e.g.
164
- * the dashboard's `/api/auth/status` poll and a `/api/auth/reminder`
165
- * POST in flight) both observe the same expired access token, both call
149
+ * the dashboard's `/api/auth/status` poll and a scheduled audit's report
150
+ * in flight) both observe the same expired access token, both call
166
151
  * `refreshAccessToken(auth.refresh_token)` with the same refresh token,
167
152
  * and the api-server treats the second call as token-replay and revokes
168
153
  * every session for that user — a silent logout. Keying on the refresh
package/lib/telemetry.ts CHANGED
@@ -38,41 +38,6 @@ interface PostHogOptions {
38
38
  requestTimeout?: number;
39
39
  fetchRetryCount?: number;
40
40
  fetchRetryDelay?: number;
41
- fetch?: (url: string, options: Record<string, unknown>) => Promise<Response>;
42
- }
43
-
44
- /**
45
- * Wraps native fetch with retry logic and silent failure for non-critical telemetry.
46
- * Prevents posthog-node's internal console.error from firing on network errors.
47
- */
48
- async function resilientFetch(
49
- url: string,
50
- options: Record<string, unknown>,
51
- ): Promise<Response> {
52
- const MAX_ATTEMPTS = 5;
53
- const BASE_DELAY_MS = 1000;
54
- const TIMEOUT_MS = 5000;
55
-
56
- for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
57
- try {
58
- const { signal: _, ...rest } = options;
59
- const res = await fetch(url, {
60
- ...(rest as RequestInit),
61
- signal: AbortSignal.timeout(TIMEOUT_MS),
62
- });
63
- if (res.ok) return res;
64
- // Non-2xx (e.g. 502) — treat like a transient failure and retry
65
- } catch {
66
- // Network error (ETIMEDOUT, etc.) — retry
67
- }
68
- if (attempt < MAX_ATTEMPTS) {
69
- const delay = Math.min(BASE_DELAY_MS * 2 ** (attempt - 1), 8000);
70
- await new Promise((r) => setTimeout(r, delay));
71
- }
72
- }
73
- // All attempts failed — return fake OK so PostHog doesn't log errors.
74
- // This is anonymous telemetry; silently dropping events is acceptable.
75
- return new Response("{}", { status: 200 });
76
41
  }
77
42
 
78
43
  /**
@@ -101,17 +66,57 @@ export async function initTelemetry(): Promise<void> {
101
66
  await import("posthog-node");
102
67
  const apiKey = process.env.FAILPROOFAI_POSTHOG_KEY ?? DEFAULT_API_KEY;
103
68
  const host = process.env.FAILPROOFAI_POSTHOG_HOST ?? DEFAULT_HOST;
69
+ // Delivery-critical options. Every one of these was previously set to a
70
+ // value that lost events; see __tests__/lib/telemetry-delivery.test.ts,
71
+ // which pins the contract against the REAL library rather than a mock.
72
+ //
73
+ // No custom `fetch`. There used to be a `resilientFetch` wrapper here that
74
+ // retried five times over ~40s and then returned a synthetic 200 so
75
+ // posthog-node would never log a network error. It could not work: the
76
+ // library does not merely hand its abort signal to an injected fetch, it
77
+ // *races* that fetch against its own `requestTimeout` deadline
78
+ // (`Promise.race([fetchPromise, deadline])`) precisely because an injected
79
+ // fetch may ignore the signal — which ours did, by stripping it. With a
80
+ // ~40s budget racing a 5s deadline the wrapper could never return in time,
81
+ // so the synthetic 200 was unreachable, the `console.error` it existed to
82
+ // prevent fired anyway, and its retries ran on detached from the client that
83
+ // had already given up. Plain global fetch is what the library expects.
84
+ //
85
+ // `fetchRetryCount` was 0, which disabled retries entirely and left the
86
+ // wrapper above as the only thing retrying — the wrong layer. The library
87
+ // retries inside a single flush, knows which errors are retryable, and
88
+ // keeps its queue coherent while doing it.
89
+ //
90
+ // `flushInterval` was 0, which is falsy and therefore disables the flush
91
+ // timer completely. That is the one that actually stranded events: on a
92
+ // network error posthog-node deliberately does NOT dequeue the batch (it
93
+ // treats the failure as transient and keeps it for a later attempt), so
94
+ // with no timer armed those retained events had nothing scheduled to
95
+ // resend them and sat in memory until an unrelated later event happened to
96
+ // trigger a flush.
97
+ //
98
+ // `flushAt: 1` is deliberate and stays. Volume here is a handful of events
99
+ // per process, so batching buys nothing, and posthog-node's queue is
100
+ // memory-only (`PostHogMemoryStorage`) — anything still queued when the
101
+ // process dies is gone. Sending immediately is the best available defense.
104
102
  globalThis.__FAILPROOFAI_POSTHOG__ = new mod.PostHog(apiKey, {
105
103
  host,
106
104
  flushAt: 1,
107
- flushInterval: 0,
108
- requestTimeout: 5000,
109
- fetchRetryCount: 0,
110
- fetch: resilientFetch,
105
+ flushInterval: 10_000,
106
+ requestTimeout: 10_000,
107
+ fetchRetryCount: 3,
108
+ fetchRetryDelay: 3_000,
111
109
  });
112
110
 
113
- // Flush pending events when the process exits
111
+ // Flush pending events when the process exits. This drain is the last line
112
+ // of defense for the memory-only queue, so it must not fight itself:
113
+ // `beforeExit` re-fires every time a handler schedules more async work, and
114
+ // an unguarded handler starts a fresh `shutdown()` — each with its own 30s
115
+ // budget — on every one of those passes.
116
+ let draining = false;
114
117
  const onExit = () => {
118
+ if (draining) return;
119
+ draining = true;
115
120
  globalThis.__FAILPROOFAI_POSTHOG__?.shutdown().catch(() => {});
116
121
  };
117
122
  process.on("beforeExit", onExit);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "failproofai",
3
- "version": "1.0.0",
3
+ "version": "1.0.1-beta.1",
4
4
  "description": "The easiest way to manage policies that keep your AI agents reliable, on-task, and running autonomously — for Claude Code & the Agents SDK",
5
5
  "bin": {
6
6
  "failproofai": "./dist/cli.mjs",
@@ -40,7 +40,8 @@
40
40
  "translate:docs": "bun scripts/translate-docs/cli.ts --docs-only",
41
41
  "translate:dry-run": "bun scripts/translate-docs/cli.ts --dry-run",
42
42
  "translate:validate": "bun scripts/translate-docs/cli.ts --validate",
43
- "validate:mdx": "bun scripts/validate-mdx.ts"
43
+ "validate:mdx": "bun scripts/validate-mdx.ts",
44
+ "docs:audit": "bun scripts/docs-audit.ts"
44
45
  },
45
46
  "keywords": [
46
47
  "claude",
@@ -104,6 +105,7 @@
104
105
  "yaml": "^2.9.0"
105
106
  },
106
107
  "overrides": {
108
+ "nanoid": "3.3.18",
107
109
  "postcss": "8.5.26",
108
110
  "eslint-plugin-react-hooks": "7.0.1",
109
111
  "vite": "8.0.16",
@@ -112,15 +114,15 @@
112
114
  "sharp": "0.35.0"
113
115
  },
114
116
  "optionalDependencies": {
115
- "@failproofai/failproofaid-linux-x64": "1.0.0",
116
- "@failproofai/failproofaid-linux-arm64": "1.0.0",
117
- "@failproofai/failproofaid-darwin-x64": "1.0.0",
118
- "@failproofai/failproofaid-darwin-arm64": "1.0.0"
117
+ "@failproofai/failproofaid-linux-x64": "1.0.1-beta.1",
118
+ "@failproofai/failproofaid-linux-arm64": "1.0.1-beta.1",
119
+ "@failproofai/failproofaid-darwin-x64": "1.0.1-beta.1",
120
+ "@failproofai/failproofaid-darwin-arm64": "1.0.1-beta.1"
119
121
  },
120
122
  "failproofaidBinaries": {
121
- "linux-x64": "67d9404812145b8b13dc97debd33cd667a5de347989b2c9c47bbdfcb5e99344c",
122
- "linux-arm64": "ca003a2ca755f5d696e2d6f4ddd8eedc0f8c4914f972101aa9803986ec409000",
123
- "darwin-x64": "53f1ed8710da69c2e3d3668d3b62380383a46328471870093936f53fc0a4fb05",
124
- "darwin-arm64": "682c22084906877760285e925b232d3563a1874a7a1f42c4c27deb1b7b74fb6f"
123
+ "linux-x64": "cf623441aa67363e423a1dba7db734d3e9243f0abff5e63a9ed7ddc096213e51",
124
+ "linux-arm64": "339281280ae8e60d03415da88a372ff4d3fb356c375f0e1f9eea17063233d52b",
125
+ "darwin-x64": "b972c37a9ca83b085d11d1312b3fa8487dead09dbc81e1e115000d2614051248",
126
+ "darwin-arm64": "597cbdae5f564fd0c7c917b2b0b94a91ba8465e568487da0d1cac0508b94cee5"
125
127
  }
126
128
  }