failproofai 1.0.11 → 1.0.12-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 (342) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +23 -23
  3. package/.next/standalone/.next/prerender-manifest.json +4 -4
  4. package/.next/standalone/.next/required-server-files.json +1 -1
  5. package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +3 -3
  6. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  7. package/.next/standalone/.next/server/app/_global-error/page.js +2 -2
  8. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  9. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.rsc +2 -2
  12. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  13. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +2 -2
  14. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +3 -3
  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 +3 -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 +3 -3
  22. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  23. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  24. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  25. package/.next/standalone/.next/server/app/api/audit/invite/route.js +5 -6
  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 +24 -24
  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 -5
  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 +6 -7
  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 +6 -7
  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 +5 -6
  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 +2 -2
  40. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/audit/page/build-manifest.json +3 -3
  42. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  43. package/.next/standalone/.next/server/app/audit/page.js +4 -4
  44. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  45. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  46. package/.next/standalone/.next/server/app/index.html +1 -1
  47. package/.next/standalone/.next/server/app/index.rsc +3 -3
  48. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  49. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +3 -3
  50. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  51. package/.next/standalone/.next/server/app/page/build-manifest.json +3 -3
  52. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  53. package/.next/standalone/.next/server/app/page.js +2 -2
  54. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  56. package/.next/standalone/.next/server/app/policies/page/build-manifest.json +3 -3
  57. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
  58. package/.next/standalone/.next/server/app/policies/page.js +7 -7
  59. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  60. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  61. package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +3 -3
  62. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  63. package/.next/standalone/.next/server/app/project/[name]/page.js +7 -7
  64. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  65. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  66. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +3 -3
  67. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  68. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  69. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +8 -8
  70. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  71. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  72. package/.next/standalone/.next/server/app/projects/page/build-manifest.json +3 -3
  73. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  74. package/.next/standalone/.next/server/app/projects/page.js +3 -3
  75. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  76. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  77. package/.next/standalone/.next/server/app/settings/page/build-manifest.json +3 -3
  78. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +8 -8
  79. package/.next/standalone/.next/server/app/settings/page.js +10 -10
  80. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  81. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  82. package/.next/standalone/.next/server/chunks/{[externals]__0qkp92tjfvw8r._.js → [externals]__0vt9i6fqinjne._.js} +1 -1
  83. package/.next/standalone/.next/server/chunks/[externals]__1x24dzcbbq6-g._.js +3 -0
  84. package/.next/standalone/.next/server/chunks/[root-of-the-server]__02vous7mpi2xm._.js +3 -0
  85. package/.next/standalone/.next/server/chunks/[root-of-the-server]__03i5o4a840guz._.js +3 -0
  86. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0__a_je8fsn65._.js +3 -0
  87. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_hsnj_a2mvl_._.js +3 -0
  88. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1izwqj_ij_9x_._.js → [root-of-the-server]__0f_4g-vazrvxv._.js} +1 -1
  89. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0l-oi4gdtmlo5._.js +3 -0
  90. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0swiyzbmvja2d._.js → [root-of-the-server]__0t9ufnv5hi2hq._.js} +5 -5
  91. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wg9dk8x8bnau._.js +3 -0
  92. package/.next/standalone/.next/server/chunks/[root-of-the-server]__12kq3x-h7t7i1._.js +3 -0
  93. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1a5zkndjwlc13._.js +3 -0
  94. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1r7kbfkiw2xmu._.js → [root-of-the-server]__1aaw59g-5uty7._.js} +12 -12
  95. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1hqpg6vgmfexv._.js +3 -0
  96. package/.next/standalone/.next/server/chunks/_09dz7xva4ce_2._.js +1 -1
  97. package/.next/standalone/.next/server/chunks/_0hf5q4xzyg40j._.js +1 -1
  98. package/.next/standalone/.next/server/chunks/_0tovk6q0miud6._.js +1 -1
  99. package/.next/standalone/.next/server/chunks/_0trp3ycqv17cl._.js +1 -1
  100. package/.next/standalone/.next/server/chunks/_19011-u44143j._.js +1 -1
  101. package/.next/standalone/.next/server/chunks/_1ek68lnh2daur._.js +1 -1
  102. package/.next/standalone/.next/server/chunks/_1vslkoe35wok6._.js +1 -1
  103. package/.next/standalone/.next/server/chunks/{_1ixl-kxq_ctsa._.js → _1y590mjzpkbos._.js} +2 -2
  104. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4vkpxxu7._.js +1 -1
  105. package/.next/standalone/.next/server/chunks/src_hooks_0_em82s16zfym._.js +5 -0
  106. package/.next/standalone/.next/server/chunks/src_hooks_builtin-policies_ts_1yq5ybgx1v98e._.js +3 -0
  107. package/.next/standalone/.next/server/chunks/src_hooks_custom-hooks-loader_ts_0lnb3n3h94wnn._.js +1 -1
  108. package/.next/standalone/.next/server/chunks/src_hooks_daemon-client_ts_0il_yu1zc0291._.js +1 -1
  109. package/.next/standalone/.next/server/chunks/src_hooks_fp-home_ts_09kv0bn_4twyh._.js +1 -1
  110. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01j58mdcdw0vn._.js +3 -0
  111. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0588st-tpiuia._.js +3 -0
  112. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__08ch3staq3ejw._.js +1 -1
  113. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_a8z2ldp2v3n._.js +3 -0
  114. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0vcyntk4snf0f._.js → [root-of-the-server]__0b78b0j8iyv6l._.js} +1 -1
  115. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0bigvy9xmv2ka._.js +1 -1
  116. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ffu2-38y03ic._.js +3 -0
  117. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0g8b0kyorya-t._.js +3 -0
  118. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h86bl2qf0k_o._.js +1 -1
  119. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1_xbg2kx30wp-._.js → [root-of-the-server]__0naevg4bcoh54._.js} +1 -1
  120. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0pia5h3p8re4c._.js +1 -1
  121. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__075uro8t92s0_._.js → [root-of-the-server]__0pwj2h2efe5f-._.js} +3 -3
  122. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0zn1d4blhd3bu._.js +3 -0
  123. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1-ey9fgesfbc0._.js +1 -1
  124. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__15usvs-ms-0hf._.js +1 -1
  125. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__16gb3_92zvk5x._.js +1 -1
  126. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17r4zrwanhp6r._.js +3 -0
  127. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1avi2kypusyb_._.js +1 -1
  128. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1lnfv02ucky7m._.js +3 -0
  129. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1mc9-zlnh656_._.js +3 -0
  130. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1r7drlqli-ado._.js +1 -1
  131. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1s2-ck3k3rsoo._.js +3 -0
  132. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1l1qgu5mfapkh._.js → [root-of-the-server]__1vx7o8ukefudh._.js} +1 -1
  133. package/.next/standalone/.next/server/chunks/ssr/_0eoura3_9gjb-._.js +1 -1
  134. package/.next/standalone/.next/server/chunks/ssr/_0pedwblqdoh58._.js +1 -1
  135. package/.next/standalone/.next/server/chunks/ssr/_128ebxr83nk6g._.js +3 -0
  136. package/.next/standalone/.next/server/chunks/ssr/_1_ozgifqv1ssi._.js +1 -1
  137. package/.next/standalone/.next/server/chunks/ssr/{_1gb0ifpkowwub._.js → _1a3tubds7s7ow._.js} +10 -9
  138. package/.next/standalone/.next/server/chunks/ssr/_1djqs9i27e4kg._.js +1 -1
  139. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo5_vm5f.js +2 -2
  140. package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9snixb5fd-._.js +1 -1
  141. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47q0xq5w._.js +1 -1
  142. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x33jqb6._.js +1 -1
  143. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpcz0uxur._.js +1 -1
  144. package/.next/standalone/.next/server/chunks/ssr/app_settings_02tf1h47jmhhd._.js +1 -1
  145. package/.next/standalone/.next/server/chunks/ssr/{node_modules_html-to-image_es_index_1f_ymmaonkksc.js → node_modules_html-to-image_es_index_1i8oid1gc7s1f.js} +1 -1
  146. package/.next/standalone/.next/server/chunks/ssr/package_json_[json]_cjs_013tntikdft59._.js +1 -1
  147. package/.next/standalone/.next/server/chunks/ssr/src_hooks_06kzv9ddabn3_._.js +1 -1
  148. package/.next/standalone/.next/server/chunks/ssr/src_hooks_0agdmptetetdt._.js +5 -0
  149. package/.next/standalone/.next/server/chunks/ssr/src_hooks_0mdwgjisv4fub._.js +5 -0
  150. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1cv9_c4l1tzrm._.js +1 -1
  151. package/.next/standalone/.next/server/chunks/ssr/src_hooks_daemon-client_ts_0k41_i7jg6ndv._.js +1 -1
  152. package/.next/standalone/.next/server/chunks/ssr/src_hooks_pack-cli_ts_0t7me658zqmh_._.js +1 -1
  153. package/.next/standalone/.next/server/middleware-build-manifest.js +23 -23
  154. package/.next/standalone/.next/server/middleware.js +2 -2
  155. package/.next/standalone/.next/server/pages/404.html +1 -1
  156. package/.next/standalone/.next/server/pages/500.html +1 -1
  157. package/.next/standalone/.next/server/preview-props.json +3 -3
  158. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  159. package/.next/standalone/.next/server/server-reference-manifest.json +23 -23
  160. package/.next/standalone/.next/static/chunks/{0frxv4_m-m2u5.js → 063al_q720fkj.js} +1 -1
  161. package/.next/standalone/.next/static/chunks/0_zfad4co-t2z.js +1 -0
  162. package/.next/standalone/.next/static/chunks/0jutamwqz8pg5.js +1 -0
  163. package/.next/standalone/.next/static/chunks/114hbolvrv94e.js +1 -0
  164. package/.next/standalone/.next/static/chunks/{37stoe-_yd852.js → 18433qz-8njv3.js} +1 -1
  165. package/.next/standalone/.next/static/chunks/{1kwj8uqxuv85t.js → 1b32-afqacaen.js} +1 -1
  166. package/.next/standalone/.next/static/chunks/{44a7k2_62qc-9.js → 1p-hsi58i-6h0.js} +2 -2
  167. package/.next/standalone/.next/static/chunks/{302llgh97ce6w.js → 2-tf6_7u623kd.js} +1 -1
  168. package/.next/standalone/.next/static/chunks/{1_c0dc7zqj1n7.js → 24w3x2da9sk49.js} +1 -1
  169. package/.next/standalone/.next/static/chunks/2tjfp9dirxnku.js +1 -0
  170. package/.next/standalone/.next/static/chunks/{16z6_d7sp61jm.js → 3-pku9qwv1yfu.js} +1 -1
  171. package/.next/standalone/.next/static/chunks/{15rm15u5a6dua.js → 42e8zab314654.js} +1 -1
  172. package/.next/standalone/fp-cloud-cli/CHANGELOG.md +41 -0
  173. package/.next/standalone/fp-cloud-cli/README.md +42 -1
  174. package/.next/standalone/fp-cloud-cli/fp_cli/client.py +117 -12
  175. package/.next/standalone/fp-cloud-cli/fp_cli/commands/fleet_cmds.py +285 -19
  176. package/.next/standalone/fp-cloud-cli/fp_cli/commands/policies_cmds.py +84 -18
  177. package/.next/standalone/fp-cloud-cli/fp_cli/enforcement.py +170 -6
  178. package/.next/standalone/fp-cloud-cli/fp_cli/models.py +89 -6
  179. package/.next/standalone/fp-cloud-cli/fp_cli/output.py +259 -21
  180. package/.next/standalone/fp-cloud-cli/fp_cli/policy_check.py +8 -5
  181. package/.next/standalone/fp-cloud-cli/skill/SKILL.md +2 -2
  182. package/.next/standalone/fp-cloud-cli/skill/references/commands.md +17 -9
  183. package/.next/standalone/fp-cloud-cli/tests/test_cloud_jev.py +692 -0
  184. package/.next/standalone/fp-cloud-cli/tests/test_enforcement_logic.py +46 -0
  185. package/.next/standalone/fp-cloud-cli/tests/test_output.py +23 -0
  186. package/.next/standalone/fp-cloud-cli/uv.lock +6 -6
  187. package/.next/standalone/hermes-plugin/README.md +6 -4
  188. package/.next/standalone/hermes-plugin/__init__.py +16 -0
  189. package/.next/standalone/hermes-plugin/client.py +5 -1
  190. package/.next/standalone/hermes-plugin/plugin.yaml +1 -1
  191. package/.next/standalone/node_modules/@next/env/package.json +1 -1
  192. package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/context.js +72 -0
  193. package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/diag.js +84 -0
  194. package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/metrics.js +50 -0
  195. package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/propagation.js +80 -0
  196. package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/trace.js +70 -0
  197. package/.next/standalone/node_modules/@opentelemetry/api/build/src/baggage/context-helpers.js +52 -0
  198. package/.next/standalone/node_modules/@opentelemetry/api/build/src/baggage/internal/baggage-impl.js +44 -0
  199. package/.next/standalone/node_modules/@opentelemetry/api/build/src/baggage/internal/symbol.js +12 -0
  200. package/.next/standalone/node_modules/@opentelemetry/api/build/src/baggage/utils.js +41 -0
  201. package/.next/standalone/node_modules/@opentelemetry/api/build/src/context/NoopContextManager.js +27 -0
  202. package/.next/standalone/node_modules/@opentelemetry/api/build/src/context/context.js +52 -0
  203. package/.next/standalone/node_modules/@opentelemetry/api/build/src/context-api.js +16 -0
  204. package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag/ComponentLogger.js +47 -0
  205. package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag/consoleLogger.js +73 -0
  206. package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag/internal/logLevelLogger.js +34 -0
  207. package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag/types.js +33 -0
  208. package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag-api.js +20 -0
  209. package/.next/standalone/node_modules/@opentelemetry/api/build/src/index.js +71 -0
  210. package/.next/standalone/node_modules/@opentelemetry/api/build/src/internal/global-utils.js +60 -0
  211. package/.next/standalone/node_modules/@opentelemetry/api/build/src/internal/semver.js +111 -0
  212. package/.next/standalone/node_modules/@opentelemetry/api/build/src/metrics/Metric.js +18 -0
  213. package/.next/standalone/node_modules/@opentelemetry/api/build/src/metrics/NoopMeter.js +118 -0
  214. package/.next/standalone/node_modules/@opentelemetry/api/build/src/metrics/NoopMeterProvider.js +20 -0
  215. package/.next/standalone/node_modules/@opentelemetry/api/build/src/metrics-api.js +17 -0
  216. package/.next/standalone/node_modules/@opentelemetry/api/build/src/propagation/NoopTextMapPropagator.js +23 -0
  217. package/.next/standalone/node_modules/@opentelemetry/api/build/src/propagation/TextMapPropagator.js +36 -0
  218. package/.next/standalone/node_modules/@opentelemetry/api/build/src/propagation-api.js +17 -0
  219. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/NonRecordingSpan.js +58 -0
  220. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/NoopTracer.js +68 -0
  221. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/NoopTracerProvider.js +21 -0
  222. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/ProxyTracer.js +46 -0
  223. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/ProxyTracerProvider.js +46 -0
  224. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/SamplingResult.js +33 -0
  225. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/context-utils.js +71 -0
  226. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/internal/tracestate-impl.js +94 -0
  227. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/internal/tracestate-validators.js +35 -0
  228. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/internal/utils.js +16 -0
  229. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/invalid-span-constants.js +25 -0
  230. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/span_kind.js +38 -0
  231. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/spancontext-utils.js +66 -0
  232. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/status.js +29 -0
  233. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/trace_flags.js +18 -0
  234. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace-api.js +17 -0
  235. package/.next/standalone/node_modules/@opentelemetry/api/build/src/version.js +10 -0
  236. package/.next/standalone/node_modules/@opentelemetry/api/package.json +96 -0
  237. package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
  238. package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js +2 -2
  239. package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo.runtime.prod.js +2 -2
  240. package/.next/standalone/node_modules/next/dist/compiled/next-server/app-route-turbo.runtime.prod.js +1 -1
  241. package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +3 -3
  242. package/.next/standalone/node_modules/next/dist/server/app-render/async-local-storage.js +1 -1
  243. package/.next/standalone/node_modules/next/dist/server/config.js +1 -1
  244. package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-turbopack.js +2 -2
  245. package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-webpack.js +1 -1
  246. package/.next/standalone/node_modules/next/dist/server/lib/app-info-log.js +1 -1
  247. package/.next/standalone/node_modules/next/dist/server/lib/generate-agent-files.js +3 -3
  248. package/.next/standalone/node_modules/next/dist/server/lib/router-server.js +1 -1
  249. package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
  250. package/.next/standalone/node_modules/next/dist/server/lib/trace/tracer.js +1 -1
  251. package/.next/standalone/node_modules/next/dist/server/typescript/rules/config.js +2 -2
  252. package/.next/standalone/node_modules/next/dist/server/use-cache/use-cache-wrapper.js +1 -1
  253. package/.next/standalone/node_modules/next/dist/telemetry/anonymous-meta.js +1 -1
  254. package/.next/standalone/node_modules/next/dist/telemetry/events/swc-load-failure.js +1 -1
  255. package/.next/standalone/node_modules/next/dist/telemetry/events/version.js +2 -2
  256. package/.next/standalone/node_modules/next/package.json +11 -11
  257. package/.next/standalone/package.json +11 -11
  258. package/.next/standalone/sdk/python/CHANGELOG.md +7 -0
  259. package/.next/standalone/sdk/python/failproofai_sdk/_version.py +1 -1
  260. package/.next/standalone/sdk/python/pyproject.toml +19 -0
  261. package/.next/standalone/sdk/python/uv.lock +520 -301
  262. package/.next/standalone/sdk/typescript/CHANGELOG.md +13 -0
  263. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package-lock.json +4 -13
  264. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package.json +2 -1
  265. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package-lock.json +4 -13
  266. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package.json +3 -0
  267. package/.next/standalone/sdk/typescript/package-lock.json +178 -162
  268. package/.next/standalone/sdk/typescript/package.json +1 -1
  269. package/.next/standalone/sdk/typescript/src/version.ts +1 -1
  270. package/.next/standalone/server.js +1 -1
  271. package/bin/failproofai.mjs +17 -1
  272. package/dist/cli.mjs +2866 -1124
  273. package/dist/worker.mjs +1450 -145
  274. package/hermes-plugin/README.md +6 -4
  275. package/hermes-plugin/__init__.py +16 -0
  276. package/hermes-plugin/client.py +5 -1
  277. package/hermes-plugin/plugin.yaml +1 -1
  278. package/package.json +11 -11
  279. package/src/hooks/agent-roster.ts +172 -0
  280. package/src/hooks/agent-targets.ts +60 -0
  281. package/src/hooks/cloud-connection.ts +97 -27
  282. package/src/hooks/cloud-enrollment-cli.ts +7 -4
  283. package/src/hooks/cloud-managed-policies.ts +380 -20
  284. package/src/hooks/cloud-policy-errors.ts +481 -0
  285. package/src/hooks/config-status.ts +1 -1
  286. package/src/hooks/custom-hooks-loader.ts +26 -3
  287. package/src/hooks/daemon-client.ts +9 -4
  288. package/src/hooks/daemon-service.ts +2 -1
  289. package/src/hooks/effective-reviewers.ts +22 -1
  290. package/src/hooks/fp-home.ts +6 -0
  291. package/src/hooks/handler.ts +235 -18
  292. package/src/hooks/health-probe.ts +15 -0
  293. package/src/hooks/integrations.ts +18 -11
  294. package/src/hooks/jev-cli.ts +197 -0
  295. package/src/hooks/jev-cloud-connection.ts +92 -0
  296. package/src/hooks/manager.ts +122 -16
  297. package/src/hooks/pack-failclosed.ts +2 -0
  298. package/src/hooks/pack-manifest.ts +8 -1
  299. package/src/hooks/policy-evaluator.ts +5 -1
  300. package/src/hooks/policy-registry.ts +3 -2
  301. package/src/hooks/policy-reviewability.ts +21 -5
  302. package/src/hooks/semantic/cloud-jev-health.ts +227 -0
  303. package/src/hooks/semantic/cloud-jev.ts +677 -0
  304. package/src/hooks/semantic/jev-client.ts +18 -1
  305. package/src/hooks/semantic/jev-config.ts +173 -3
  306. package/src/hooks/semantic/jev-review.ts +129 -10
  307. package/src/hooks/semantic/pack-policies.ts +2 -1
  308. package/src/hooks/semantic/types.ts +8 -0
  309. package/src/hooks/session-pause-cli.ts +1 -1
  310. package/src/hooks/worker-server.ts +5 -1
  311. package/.next/standalone/.next/server/chunks/[externals]__0hjaw70fchx66._.js +0 -3
  312. package/.next/standalone/.next/server/chunks/[root-of-the-server]__07l68zv0hqdiu._.js +0 -3
  313. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0car70pylmvor._.js +0 -3
  314. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0u3i025_setk_._.js +0 -3
  315. package/.next/standalone/.next/server/chunks/[root-of-the-server]__10a2f6s636yc7._.js +0 -3
  316. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qt5u58xrcuk6._.js +0 -3
  317. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_077n_4ip5__fu._.js +0 -3
  318. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_0mqvvxcn6v0op._.js +0 -3
  319. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_0pb7ds5g0vzgn._.js +0 -3
  320. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_1gasm5xkeqmm3._.js +0 -3
  321. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_1q1heqmkhh8l4._.js +0 -3
  322. package/.next/standalone/.next/server/chunks/src_hooks_1aveq0uhs2t1b._.js +0 -5
  323. package/.next/standalone/.next/server/chunks/src_hooks_1eem5a7cyqlb2._.js +0 -3
  324. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0888k4s6spfmh._.js +0 -3
  325. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_bflu046ep5j._.js +0 -3
  326. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_lbstb5x2t15._.js +0 -3
  327. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0fdwgktjfhedo._.js +0 -3
  328. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s4deza787asx._.js +0 -3
  329. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__18qe-hu0gwqm4._.js +0 -3
  330. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1_p_9xe520fex._.js +0 -3
  331. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1fmhm8_s9i4re._.js +0 -3
  332. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1g76awtnmimd1._.js +0 -3
  333. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1pczevlpk5lxh._.js +0 -3
  334. package/.next/standalone/.next/server/chunks/ssr/_0dc-of_bn0cim._.js +0 -3
  335. package/.next/standalone/.next/server/chunks/ssr/src_hooks_effective-reviewers_ts_1h4wtvo55j16x._.js +0 -5
  336. package/.next/standalone/.next/static/chunks/0m-tv1y6ghhtk.js +0 -1
  337. package/.next/standalone/.next/static/chunks/0ol2gj4ntfn56.js +0 -1
  338. package/.next/standalone/.next/static/chunks/3hj5_7i3nw4zj.js +0 -1
  339. package/.next/standalone/.next/static/chunks/3iyoapeoq_hup.js +0 -1
  340. /package/.next/standalone/.next/static/{kEFP3ybXwZdriNEQmWwlH → xq8UgF5yFxty1VWxY2hyn}/_buildManifest.js +0 -0
  341. /package/.next/standalone/.next/static/{kEFP3ybXwZdriNEQmWwlH → xq8UgF5yFxty1VWxY2hyn}/_clientMiddlewareManifest.js +0 -0
  342. /package/.next/standalone/.next/static/{kEFP3ybXwZdriNEQmWwlH → xq8UgF5yFxty1VWxY2hyn}/_ssgManifest.js +0 -0
@@ -0,0 +1,481 @@
1
+ /**
2
+ * `cloud-policies/errors.json` — what this machine could not load from its
3
+ * FailproofAI Cloud deployment, for the daemon to report on its next poll
4
+ * (`policyErrors`, CONTRACT C4–C6).
5
+ *
6
+ * Nothing here changes a verdict. Cloud policies are read fail-open: a JS
7
+ * policy that fails to import costs that one policy on this machine and
8
+ * nothing else, which is the right trade on the hook path and the wrong thing
9
+ * to keep quiet about. Before this file the only trace was a line in the local
10
+ * hook log, so a fleet page read "applied" for a deployment that was not. The
11
+ * same goes for FailproofAI Cloud's Jev (CONTRACT C10): a Jev mode this machine
12
+ * cannot act on, and an installed pack's check Cloud dropped for the question
13
+ * budget, are said here rather than only in a local log.
14
+ *
15
+ * ## One writer per file
16
+ *
17
+ * The CLI writes `errors.json`; the daemon keeps its own reconcile errors in
18
+ * `daemon-errors.json` and merges the two onto the wire. Neither writes the
19
+ * other's file, so there is no read-modify-write race between processes.
20
+ *
21
+ * ## Written on change, atomically
22
+ *
23
+ * Computed on every hook evaluation of a Cloud-managed machine, so the write
24
+ * has to be almost always a no-op: the new content is compared with what is on
25
+ * disk (and with what this process last wrote, to skip even that read in the
26
+ * warm worker) and written only when it differs — tmp file + rename, owner-only,
27
+ * so the daemon never reads half a file.
28
+ *
29
+ * A machine that never had a problem never gets the file at all: an empty list
30
+ * is written only to REPLACE a non-empty one, which is what clears the report
31
+ * on the server. That keeps the poll parameter absent on a healthy fleet.
32
+ */
33
+ import { randomUUID } from "node:crypto";
34
+ import { chmodSync, existsSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
35
+ import { homedir } from "node:os";
36
+ import { resolve } from "node:path";
37
+ import {
38
+ CLOUD_POLICY_ERRORS_FILE,
39
+ JEV_BUDGET_FILE,
40
+ cloudManagedPolicyRoot,
41
+ type CloudJevState,
42
+ type CloudManagedPolicyArtifact,
43
+ type CloudPolicyError,
44
+ type CloudPolicyErrorKind,
45
+ } from "./cloud-managed-policies";
46
+ import type { PolicyLoadFailure } from "./custom-hooks-loader";
47
+ import { packsRoot } from "./pack-manifest";
48
+
49
+ export type { CloudPolicyError, CloudPolicyErrorKind } from "./cloud-managed-policies";
50
+
51
+ /** The message the contract fixes for "Cloud set a Jev mode and this machine has no Cloud Jev credential". */
52
+ export const JEV_UNCONFIGURED = "jev_unconfigured";
53
+
54
+ /**
55
+ * The message the contract fixes for "Cloud set a Jev mode on a machine
56
+ * connected for decisions only" (`--no-transcripts`), which never runs Jev
57
+ * (CONTRACT C10.2).
58
+ */
59
+ export const TRANSCRIPTS_DISABLED = "transcripts_disabled";
60
+
61
+ /** How an installed pack's check FailproofAI Cloud dropped for the question budget is reported (C10.5). */
62
+ export const JEV_BUDGET = "jev_budget";
63
+
64
+ /**
65
+ * How an installed pack's check is reported when FailproofAI Cloud dropped it
66
+ * because one of the org's Cloud checks has the same name (Cloud wins the name,
67
+ * D-S-2). It is not a budget problem, and its remedy differs.
68
+ */
69
+ export const JEV_NAME_CLASH = "jev_name_clash";
70
+
71
+ /** Is `e` one of the pack-check drops `jev-budget.json` records? */
72
+ export function isPackDropEntry(e: Pick<CloudPolicyError, "id" | "message">): boolean {
73
+ return e.id.startsWith("pack:") && (e.message.startsWith(JEV_BUDGET) || e.message.startsWith(JEV_NAME_CLASH));
74
+ }
75
+
76
+ /**
77
+ * A message with no local path in it (CONTRACT C9.5): the home directory
78
+ * becomes `~`, and any other absolute path becomes its last segment.
79
+ *
80
+ * The report leaves the machine, and a path names the user — the home-relative
81
+ * artifact path in a missing-artifact message, a loader's temp path in an
82
+ * import error, the `chmod 600 <path>` hint of a refused `jev.json`. The daemon
83
+ * applies the same rule again on the way out (`redact_local_paths` in
84
+ * `cloud_client.rs`, whose tests pin the same cases), so a report never carries
85
+ * a username whichever side wrote it. The full text stays in the local hook
86
+ * log, where it is useful and goes nowhere.
87
+ *
88
+ * A path starts at a `/` that begins the text or follows whitespace, a quote,
89
+ * an opening bracket, `=`, `,` or `:` — but not a URL's `//host` after `:`,
90
+ * and never a `/` following any other character, so a URL (`https://host/path`)
91
+ * and a relative path (`a/b`) are left alone while `file:///tmp/x` and
92
+ * `open:/etc/x` are not — and runs to the next whitespace, quote, closing
93
+ * bracket, `,` or `;`.
94
+ */
95
+ export function redactLocalPaths(message: string, home: string | null = safeHomedir()): string {
96
+ let text = message;
97
+ const base = home?.replace(/\/+$/, "") ?? "";
98
+ if (base.length > 1) {
99
+ let out = "";
100
+ let rest = text;
101
+ for (let at = rest.indexOf(base); at >= 0; at = rest.indexOf(base)) {
102
+ const next = rest.charAt(at + base.length);
103
+ // `/home/al` must not match inside `/home/alice`.
104
+ const whole = next === "" || next === "/" || next === ":" || PATH_END.test(next);
105
+ out += rest.slice(0, at) + (whole ? "~" : base);
106
+ rest = rest.slice(at + base.length);
107
+ }
108
+ text = out + rest;
109
+ }
110
+ // `:(?!\/\/(?!\/))`: a `:` not followed by a URL's `//host` — `scheme://host`
111
+ // stays, while `file:///path` and `x:/path` are paths.
112
+ return text.replace(/(^|[\s"'`(\[<{=,]|:(?!\/\/(?!\/)))(\/[^\s"'`)\]>},;]*)/g, (_m, lead: string, path: string) => {
113
+ const last = path.replace(/\/+$/, "").split("/").pop() ?? "";
114
+ return lead + (last === "" ? "/" : last);
115
+ });
116
+ }
117
+
118
+ const PATH_END = /[\s"'`)\]>},;]/;
119
+
120
+ function safeHomedir(): string | null {
121
+ try {
122
+ return homedir();
123
+ } catch {
124
+ return null;
125
+ }
126
+ }
127
+
128
+ export function cloudPolicyErrorsPath(): string {
129
+ return resolve(cloudManagedPolicyRoot(), CLOUD_POLICY_ERRORS_FILE);
130
+ }
131
+
132
+ const KINDS: ReadonlySet<string> = new Set<CloudPolicyErrorKind>(["regex", "jev", "both", "daemon"]);
133
+
134
+ /** The file as the CLI last wrote it, or null when absent or unreadable. */
135
+ export function readCloudPolicyErrors(): CloudPolicyError[] | null {
136
+ try {
137
+ const raw = JSON.parse(readFileSync(cloudPolicyErrorsPath(), "utf8")) as { errors?: unknown };
138
+ if (!Array.isArray(raw.errors)) return null;
139
+ return raw.errors.filter(
140
+ (e): e is CloudPolicyError =>
141
+ !!e &&
142
+ typeof e === "object" &&
143
+ typeof (e as CloudPolicyError).id === "string" &&
144
+ typeof (e as CloudPolicyError).message === "string" &&
145
+ KINDS.has((e as CloudPolicyError).kind) &&
146
+ ((e as CloudPolicyError).version === null || Number.isSafeInteger((e as CloudPolicyError).version)),
147
+ );
148
+ } catch {
149
+ return null;
150
+ }
151
+ }
152
+
153
+ /** Text this process last wrote, so the warm worker's steady state reads nothing. */
154
+ let lastWritten: { path: string; text: string } | null = null;
155
+
156
+ /** Tests only. */
157
+ export function _resetCloudPolicyErrorsCacheForTest(): void {
158
+ lastWritten = null;
159
+ }
160
+
161
+ function serialize(errors: ReadonlyArray<CloudPolicyError>): string {
162
+ // Field order fixed, so equal lists are equal text. Redacted here as well as
163
+ // in `collectCloudPolicyErrors`: this is the one way into the file.
164
+ const list = errors.map((e) => ({ id: e.id, version: e.version, kind: e.kind, message: redactLocalPaths(e.message) }));
165
+ return `${JSON.stringify({ errors: list }, null, 2)}\n`;
166
+ }
167
+
168
+ /**
169
+ * Replace `errors.json` with `errors` when that changes it. Never throws.
170
+ *
171
+ * - `"skipped"`: nothing to report and no file to clear, or no deployment here
172
+ * (no `active.json` — a disconnected or never-managed machine gets no file).
173
+ * - `"unchanged"`: the file already says exactly this.
174
+ * - `"written"`: it did not, and now does.
175
+ * - `"failed"`: the write itself failed (logged nowhere: the next event retries).
176
+ */
177
+ export function writeCloudPolicyErrors(errors: ReadonlyArray<CloudPolicyError>): "written" | "unchanged" | "skipped" | "failed" {
178
+ try {
179
+ const root = cloudManagedPolicyRoot();
180
+ if (!existsSync(resolve(root, "active.json"))) return "skipped";
181
+ const path = cloudPolicyErrorsPath();
182
+ const text = serialize(errors);
183
+ if (lastWritten && lastWritten.path === path && lastWritten.text === text && existsSync(path)) return "unchanged";
184
+ let current: string | null = null;
185
+ try {
186
+ current = readFileSync(path, "utf8");
187
+ } catch {
188
+ current = null;
189
+ }
190
+ if (current === text) {
191
+ lastWritten = { path, text };
192
+ return "unchanged";
193
+ }
194
+ if (current === null && errors.length === 0) return "skipped";
195
+ writeAtomic(path, text);
196
+ lastWritten = { path, text };
197
+ return "written";
198
+ } catch {
199
+ // A report that cannot be written must not cost a hook its answer.
200
+ return "failed";
201
+ }
202
+ }
203
+
204
+ // ── Which Cloud JS policies a hook has load-checked (N4) ────────────────────
205
+ //
206
+ // `failproofai policies` must not draw a Cloud policy as ● on before any hook
207
+ // has imported it: only the hook path loads Cloud JavaScript, and only the hook
208
+ // path writes `errors.json`, so right after a deployment a broken policy has
209
+ // no error yet. The hook path records here which `id@version`s of which
210
+ // deployment it has load-checked (loaded, or failed into `errors.json`); the
211
+ // listing shows the rest as not loaded yet. Union across hooks, since an
212
+ // agent-scoped policy is only ever loaded by its own agent's hooks.
213
+
214
+ export const CLOUD_LOAD_CHECKED_FILE = "load-checked.json";
215
+
216
+ export interface CloudLoadChecked {
217
+ deployment: number;
218
+ checked: string[];
219
+ }
220
+
221
+ export function cloudLoadCheckedPath(): string {
222
+ return resolve(cloudManagedPolicyRoot(), CLOUD_LOAD_CHECKED_FILE);
223
+ }
224
+
225
+ /** The record, or null when absent or unreadable. */
226
+ export function readCloudLoadChecked(): CloudLoadChecked | null {
227
+ try {
228
+ const raw = JSON.parse(readFileSync(cloudLoadCheckedPath(), "utf8")) as Record<string, unknown>;
229
+ if (!Number.isSafeInteger(raw.deployment) || !Array.isArray(raw.checked)) return null;
230
+ return { deployment: raw.deployment as number, checked: raw.checked.filter((c): c is string => typeof c === "string") };
231
+ } catch {
232
+ return null;
233
+ }
234
+ }
235
+
236
+ /** Add `policies` to the record for `deployment` (a new deployment starts afresh). Never throws; writes only on change. */
237
+ export function recordCloudLoadChecked(deployment: number, policies: ReadonlyArray<{ id: string; version: number }>): void {
238
+ try {
239
+ if (!existsSync(resolve(cloudManagedPolicyRoot(), "active.json"))) return;
240
+ const path = cloudLoadCheckedPath();
241
+ const prior = readCloudLoadChecked();
242
+ const base = prior && prior.deployment === deployment ? prior.checked : [];
243
+ const next = [...new Set([...base, ...policies.map((p) => `${p.id}@${p.version}`)])].sort();
244
+ if (prior && prior.deployment === deployment && next.length === base.length) return;
245
+ const text = `${JSON.stringify({ deployment, checked: next }, null, 2)}\n`;
246
+ writeAtomic(path, text);
247
+ } catch {
248
+ // A record that cannot be written costs only the listing's accuracy.
249
+ }
250
+ }
251
+
252
+ export interface CloudPolicyErrorInputs {
253
+ /** `readActiveCloudManagedPolicies` threw: the whole JS half is not enforcing. */
254
+ manifestError?: string | null;
255
+ /** What the JS reader returned. */
256
+ jsPolicies: ReadonlyArray<CloudManagedPolicyArtifact>;
257
+ /** Import failures by Cloud policy id (`LoadAllResult.cloudFailures`). */
258
+ jsFailures?: ReadonlyMap<string, PolicyLoadFailure>;
259
+ /** Cloud's Jev state (its own problems — an unreadable mode — are in `errors`). */
260
+ jev: Pick<CloudJevState, "errors">;
261
+ /**
262
+ * Why Cloud's `observe`/`enforce` mode cannot run here: `transcripts_disabled`,
263
+ * `jev_unconfigured`, or `jev_unconfigured: <detail>`
264
+ * (`loadJevConfigForCloudMode`). Null when it runs, or Cloud's mode does not ask.
265
+ */
266
+ jevProblem?: string | null;
267
+ /** Installed packs' checks FailproofAI Cloud dropped for the budget ({@link readJevBudgetDrops}). */
268
+ budgetDrops?: ReadonlyArray<CloudPolicyError>;
269
+ /** FailproofAI Cloud Jev rate-limited or unavailable here (`semantic/cloud-jev-health.ts`). */
270
+ health?: ReadonlyArray<CloudPolicyError>;
271
+ /** Schema-3 deployment, but the running hook could not identify its agent. */
272
+ agentScopeUnresolved?: boolean;
273
+ }
274
+
275
+ /**
276
+ * A Cloud JS assignment's kind, as far as this machine can tell: `both` when
277
+ * the server derived a reviewer list for it (only a `both` policy gets one,
278
+ * CONTRACT C1), else `regex`.
279
+ */
280
+ function kindOf(policy: Pick<CloudManagedPolicyArtifact, "authority" | "reviewedBy">): CloudPolicyErrorKind {
281
+ return policy.authority === "reviewable" && (policy.reviewedBy?.length ?? 0) > 0 ? "both" : "regex";
282
+ }
283
+
284
+ /**
285
+ * Everything wrong with this machine's Cloud deployment, as `errors.json`
286
+ * entries: deduplicated, in a stable order. Pure.
287
+ *
288
+ * What is NOT here any more (CONTRACT C10): Jev artifact and declaration
289
+ * failures and a `reviewedBy` naming a missing check — the machine holds no
290
+ * Cloud Jev check to fail, and cannot tell which names Cloud has. A `both`
291
+ * policy on a machine whose Cloud mode does not ask simply stays hard; the
292
+ * server knows the mode it set.
293
+ */
294
+ export function collectCloudPolicyErrors(input: CloudPolicyErrorInputs): CloudPolicyError[] {
295
+ const out: CloudPolicyError[] = [];
296
+ if (input.manifestError) {
297
+ out.push({ id: "active.json", version: null, kind: "daemon", message: `Cloud policies could not be loaded: ${input.manifestError}` });
298
+ }
299
+ if (input.agentScopeUnresolved) {
300
+ out.push({
301
+ id: "agentScope", version: null, kind: "daemon",
302
+ message: "agent_scope_unresolved: this hook's agent profile is unknown; targeted Cloud policies did not match",
303
+ });
304
+ }
305
+ for (const policy of input.jsPolicies) {
306
+ const failure = input.jsFailures?.get(policy.id);
307
+ if (failure) {
308
+ out.push({ id: policy.id, version: policy.version, kind: kindOf(policy), message: `policy did not load (${failure.type}): ${failure.reason}` });
309
+ }
310
+ }
311
+ out.push(...input.jev.errors);
312
+ out.push(...(input.budgetDrops ?? []));
313
+ if (input.jevProblem) {
314
+ out.push({ id: "jevMode", version: null, kind: "daemon", message: input.jevProblem });
315
+ }
316
+ out.push(...(input.health ?? []));
317
+
318
+ const seen = new Set<string>();
319
+ return out
320
+ .map((e) => ({ ...e, message: redactLocalPaths(e.message) }))
321
+ .filter((e) => {
322
+ const key = `${e.id}\u0000${e.version}\u0000${e.kind}\u0000${e.message}`;
323
+ if (seen.has(key)) return false;
324
+ seen.add(key);
325
+ return true;
326
+ });
327
+ }
328
+
329
+ // ── Installed packs' checks FailproofAI Cloud dropped for the budget ─────────
330
+ //
331
+ // FailproofAI Cloud puts its own checks first in the one question budget and
332
+ // drops whole installed-pack question groups, last first, when the two do not
333
+ // fit together (CONTRACT C10.4 step 5); its reply names them (`droppedLocal`).
334
+ // Which groups a call carries depends on the tool, so a report of only the
335
+ // latest reply's drops would flap from call to call. So the drops are kept,
336
+ // as a union, in `jev-budget.json` for the machine, deployment and Jev mode
337
+ // they happened under — a new deployment or mode starts afresh, which is how
338
+ // a drop that no longer happens stops being reported — and `errors.json`
339
+ // carries them as `{id: "pack:<packId>", kind: "daemon", message: "jev_budget:
340
+ // dropped <name>"}`. A check dropped because an org Cloud check has its name
341
+ // is recorded the same way, as `jev_name_clash: <name> (the FailproofAI Cloud
342
+ // check is used)`. A drop of a pack no longer installed is not reported, here
343
+ // or by the daemon's poll, which also drops the report once the deployment it
344
+ // was recorded under is no longer the active one.
345
+
346
+ /** What a set of budget drops is keyed by: they are true of this deployment only. */
347
+ export interface JevBudgetKey {
348
+ machineId: string;
349
+ deployment: number | null;
350
+ jevMode: "observe" | "enforce";
351
+ }
352
+
353
+ /** One dropped pack check; `clash` when Cloud dropped it for a same-named Cloud check. */
354
+ export interface JevPackDrop {
355
+ packId: string;
356
+ name: string;
357
+ clash?: true;
358
+ }
359
+
360
+ interface JevBudgetRecord extends JevBudgetKey {
361
+ dropped: JevPackDrop[];
362
+ }
363
+
364
+ export function jevBudgetPath(): string {
365
+ return resolve(cloudManagedPolicyRoot(), JEV_BUDGET_FILE);
366
+ }
367
+
368
+ function readJevBudgetRecord(): JevBudgetRecord | null {
369
+ try {
370
+ const raw = JSON.parse(readFileSync(jevBudgetPath(), "utf8")) as Partial<JevBudgetRecord>;
371
+ if (
372
+ typeof raw.machineId !== "string" ||
373
+ !(raw.deployment === null || Number.isSafeInteger(raw.deployment)) ||
374
+ (raw.jevMode !== "observe" && raw.jevMode !== "enforce") ||
375
+ !Array.isArray(raw.dropped)
376
+ ) {
377
+ return null;
378
+ }
379
+ const dropped = raw.dropped
380
+ .filter((d): d is JevPackDrop => !!d && typeof d.packId === "string" && typeof d.name === "string")
381
+ .map((d) => ({ packId: d.packId, name: d.name, ...(d.clash === true ? { clash: true as const } : {}) }));
382
+ return { machineId: raw.machineId, deployment: raw.deployment as number | null, jevMode: raw.jevMode, dropped };
383
+ } catch {
384
+ return null;
385
+ }
386
+ }
387
+
388
+ const sameKey = (a: JevBudgetKey, b: JevBudgetKey): boolean =>
389
+ a.machineId === b.machineId && a.deployment === b.deployment && a.jevMode === b.jevMode;
390
+
391
+ const dropKey = (d: JevPackDrop): string => `${d.packId}\u0000${d.name}\u0000${d.clash === true}`;
392
+
393
+ function budgetEntries(dropped: ReadonlyArray<JevPackDrop>): CloudPolicyError[] {
394
+ return [...dropped]
395
+ .sort((a, b) => (dropKey(a) < dropKey(b) ? -1 : dropKey(a) > dropKey(b) ? 1 : 0))
396
+ .map((d) => ({
397
+ id: `pack:${d.packId}`,
398
+ version: null,
399
+ kind: "daemon" as const,
400
+ message: d.clash ? `${JEV_NAME_CLASH}: ${d.name} (the FailproofAI Cloud check is used)` : `${JEV_BUDGET}: dropped ${d.name}`,
401
+ }));
402
+ }
403
+
404
+ /**
405
+ * The ids of the installed packs, read straight off `installed.json` (no
406
+ * artifact is verified: only the ids are wanted). An empty set when no pack is
407
+ * installed; null when the file exists and cannot be read, which filters
408
+ * nothing ("cannot tell" is not "not installed"). Never throws.
409
+ */
410
+ export function installedPackIds(): ReadonlySet<string> | null {
411
+ try {
412
+ const path = resolve(packsRoot(), "installed.json");
413
+ if (!existsSync(path)) return new Set();
414
+ const raw = JSON.parse(readFileSync(path, "utf8")) as { packs?: unknown };
415
+ if (!Array.isArray(raw.packs)) return null;
416
+ return new Set(
417
+ raw.packs.map((p) => (p && typeof p === "object" ? (p as { id?: unknown }).id : null)).filter((id): id is string => typeof id === "string"),
418
+ );
419
+ } catch {
420
+ return null;
421
+ }
422
+ }
423
+
424
+ /**
425
+ * The drops recorded for exactly this machine, deployment and mode, as
426
+ * `errors.json` entries — none for any other key, and none of a pack that is
427
+ * no longer installed (`installed`, when known). Never throws.
428
+ */
429
+ export function readJevBudgetDrops(key: JevBudgetKey, installed: ReadonlySet<string> | null = null): CloudPolicyError[] {
430
+ const record = readJevBudgetRecord();
431
+ if (!record || !sameKey(record, key)) return [];
432
+ return budgetEntries(installed ? record.dropped.filter((d) => installed.has(d.packId)) : record.dropped);
433
+ }
434
+
435
+ /**
436
+ * Add the pack checks FailproofAI Cloud just dropped to the record for `key`
437
+ * (starting afresh when the key changed), and to `errors.json` at once, so the
438
+ * report does not wait for the next hook. Both writes are atomic, owner-only,
439
+ * and happen only when something changed. Never throws: a report must not
440
+ * cost a hook its answer.
441
+ */
442
+ export function recordJevBudgetDrops(key: JevBudgetKey, drops: ReadonlyArray<JevPackDrop>): void {
443
+ try {
444
+ if (drops.length === 0 || !existsSync(resolve(cloudManagedPolicyRoot(), "active.json"))) return;
445
+ const current = readJevBudgetRecord();
446
+ const base = current && sameKey(current, key) ? current.dropped : [];
447
+ const seen = new Set(base.map(dropKey));
448
+ const added: JevPackDrop[] = [];
449
+ for (const d of drops) {
450
+ const id = dropKey(d);
451
+ if (seen.has(id)) continue;
452
+ seen.add(id);
453
+ added.push({ packId: d.packId, name: d.name, ...(d.clash === true ? { clash: true as const } : {}) });
454
+ }
455
+ if (current && sameKey(current, key) && added.length === 0) return;
456
+ const record: JevBudgetRecord = { ...key, dropped: [...base, ...added] };
457
+ writeAtomic(jevBudgetPath(), `${JSON.stringify(record, null, 2)}\n`);
458
+ // Merged into the report as it stands: every other entry kept, the pack
459
+ // budget drops replaced by this deployment's.
460
+ const report = (readCloudPolicyErrors() ?? []).filter((e) => !isPackDropEntry(e));
461
+ writeCloudPolicyErrors([...report, ...budgetEntries(record.dropped)]);
462
+ } catch {
463
+ // The next event records it again.
464
+ }
465
+ }
466
+
467
+ function writeAtomic(path: string, text: string): void {
468
+ const tmp = `${path}.tmp-${process.pid}-${randomUUID()}`;
469
+ try {
470
+ writeFileSync(tmp, text, { mode: 0o600, flag: "wx" });
471
+ chmodSync(tmp, 0o600);
472
+ renameSync(tmp, path);
473
+ } catch (err) {
474
+ try {
475
+ rmSync(tmp, { force: true });
476
+ } catch {
477
+ // Nothing useful to do.
478
+ }
479
+ throw err;
480
+ }
481
+ }
@@ -578,7 +578,7 @@ export function renderStatusScreen(facts: StatusFacts, opts: ScreenKitOpts & { c
578
578
  `${pauseClockTime(pause.expiresAt, opts.clock)}${pause.cwd ? `${kit.sep}${pause.cwd}` : ""}`,
579
579
  ]),
580
580
  // An enforcement fact, not fine print: a pause suspends local policy only.
581
- ...(facts.pauses.length > 0 ? [["", "Cloud-managed policies keep enforcing."] as [string, string]] : []),
581
+ ...(facts.pauses.length > 0 ? [["", "Cloud-managed policies, and FailproofAI Cloud's Jev checks, keep enforcing."] as [string, string]] : []),
582
582
  ];
583
583
 
584
584
  const cloudRows: Array<[string, string]> =
@@ -176,7 +176,7 @@ async function importWithDeadline(fileUrl: string): Promise<void> {
176
176
  * Does NOT clear the registry — caller is responsible for that.
177
177
  */
178
178
  export interface PolicyLoadFailure {
179
- type: "module_not_found" | "syntax_error" | "load_timeout" | "runtime_error" | "path_missing";
179
+ type: "module_not_found" | "file_not_found" | "syntax_error" | "load_timeout" | "runtime_error" | "path_missing";
180
180
  reason: string;
181
181
  }
182
182
 
@@ -250,8 +250,13 @@ async function loadSingleFile(
250
250
  return null;
251
251
  } catch (err) {
252
252
  const msg = err instanceof Error ? err.message : String(err);
253
- const errorType = /Cannot find module|MODULE_NOT_FOUND|ENOENT/i.test(msg)
253
+ // An import that names no module, apart from a file the policy itself
254
+ // reads at load (a `readFileSync` of its data): both are ENOENT underneath,
255
+ // but "module not found" sent people looking for a missing package (B13).
256
+ const errorType = /Cannot find module|MODULE_NOT_FOUND|Cannot find package/i.test(msg)
254
257
  ? "module_not_found"
258
+ : /ENOENT/i.test(msg)
259
+ ? "file_not_found"
255
260
  : /SyntaxError|Unexpected token/i.test(msg)
256
261
  ? "syntax_error"
257
262
  : /timed out loading module/i.test(msg)
@@ -334,6 +339,13 @@ export interface LoadAllResult {
334
339
  * Only present for a path more than one pack resolved to.
335
340
  */
336
341
  packAliases: Map<string, string[]>;
342
+ /**
343
+ * Import failures of FailproofAI Cloud JS policies, keyed by Cloud policy id
344
+ * (every id behind a shared artifact). Fail-open like the rest of the Cloud
345
+ * read — nothing denies over them — but reported to Cloud in `errors.json`,
346
+ * so a deployment that is not actually enforcing says so.
347
+ */
348
+ cloudFailures?: Map<string, PolicyLoadFailure>;
337
349
  }
338
350
 
339
351
  export function customPolicyId(file: string, name: string): string {
@@ -456,8 +468,12 @@ export async function loadAllCustomHooks(
456
468
  // codebase exists to remove. It is also announced, so an operator can give the
457
469
  // two policies distinguishable source instead of living with the merge.
458
470
  const cloudManagedByPath = new Map<string, CloudManagedPolicyArtifact>();
471
+ /** Every Cloud policy id behind each artifact path, for `cloudFailures`. */
472
+ const cloudIdsByPath = new Map<string, string[]>();
473
+ const cloudFailures = new Map<string, PolicyLoadFailure>();
459
474
  for (const policy of opts?.cloudManagedPolicies ?? []) {
460
475
  const key = resolve(policy.path);
476
+ cloudIdsByPath.set(key, [...(cloudIdsByPath.get(key) ?? []), policy.id]);
461
477
  const existing = cloudManagedByPath.get(key);
462
478
  if (!existing) {
463
479
  cloudManagedByPath.set(key, policy);
@@ -660,6 +676,9 @@ export async function loadAllCustomHooks(
660
676
  if (failure && pack) {
661
677
  for (const id of packIdsByPath.get(absPath) ?? [pack.id]) packFailures.set(id, failure);
662
678
  }
679
+ if (failure && cloudManaged) {
680
+ for (const id of cloudIdsByPath.get(absPath) ?? [cloudManaged.id]) cloudFailures.set(id, failure);
681
+ }
663
682
  for (const hook of getCustomHooks().slice(hooksBefore)) {
664
683
  const tagged = hook as CustomHook & {
665
684
  __policyId?: string;
@@ -680,6 +699,10 @@ export async function loadAllCustomHooks(
680
699
  }
681
700
  } else {
682
701
  hookLogWarn(`custom policy path not found: ${absPath}`);
702
+ if (cloudManaged) {
703
+ const missing = { type: "path_missing", reason: `path missing: ${absPath}` } as const;
704
+ for (const id of cloudIdsByPath.get(absPath) ?? [cloudManaged.id]) cloudFailures.set(id, missing);
705
+ }
683
706
  if (pack) {
684
707
  const missing = { type: "path_missing", reason: `path missing: ${absPath}` } as const;
685
708
  for (const id of packIdsByPath.get(absPath) ?? [pack.id]) packFailures.set(id, missing);
@@ -830,5 +853,5 @@ export async function loadAllCustomHooks(
830
853
  const winner = packByPath.get(path);
831
854
  if (winner && ids.length > 1) packAliases.set(winner.id, ids);
832
855
  }
833
- return { hooks: allHooks, conventionSources, packFailures, packAliases };
856
+ return { hooks: allHooks, conventionSources, packFailures, packAliases, cloudFailures };
834
857
  }
@@ -16,7 +16,7 @@ import { existsSync } from "node:fs";
16
16
  import { daemonSocket as daemonSocketPath } from "./fp-home";
17
17
  import { readConfig } from "./fp-config";
18
18
 
19
- const PROTOCOL_VERSION = 1;
19
+ const PROTOCOL_VERSION = 2;
20
20
 
21
21
  /**
22
22
  * Reaching the daemon and getting an answer out of it are two different
@@ -56,6 +56,8 @@ export interface DaemonHookRequest {
56
56
  * hazard.
57
57
  */
58
58
  cwd?: string;
59
+ /** Settings path of the originating agent profile, not the daemon's. */
60
+ agentSettingsPath?: string;
59
61
  }
60
62
 
61
63
  export interface DaemonHookResponse {
@@ -98,6 +100,7 @@ export interface DaemonPolicyEvaluationRequest {
98
100
  event: string;
99
101
  payload: Record<string, unknown>;
100
102
  cwd?: string;
103
+ agentSettingsPath?: string;
101
104
  }
102
105
 
103
106
  export type DaemonPolicyEvaluationAttempt =
@@ -304,6 +307,7 @@ export async function attemptDaemonHook(
304
307
  cli: req.cli,
305
308
  stdin: req.stdin,
306
309
  cwd: req.cwd,
310
+ agentSettingsPath: req.agentSettingsPath,
307
311
  },
308
312
  opts,
309
313
  );
@@ -338,9 +342,9 @@ function isStringArray(value: unknown): value is string[] {
338
342
 
339
343
  /**
340
344
  * Attempts the structured request used by native in-process integrations.
341
- * A matching protocol version is not sufficient: pre-native v1 daemons speak
342
- * `hook` but cannot deserialize `policyEvaluation`, so only a complete,
343
- * well-shaped `policyResult` proves this capability exists.
345
+ * A matching protocol version is not sufficient: a broken or partial daemon
346
+ * may speak `hook` but not `policyEvaluation`, so only a complete, well-shaped
347
+ * `policyResult` proves this capability exists.
344
348
  */
345
349
  export async function attemptDaemonPolicyEvaluation(
346
350
  req: DaemonPolicyEvaluationRequest,
@@ -354,6 +358,7 @@ export async function attemptDaemonPolicyEvaluation(
354
358
  event: req.event,
355
359
  payload: req.payload,
356
360
  cwd: req.cwd,
361
+ agentSettingsPath: req.agentSettingsPath,
357
362
  },
358
363
  opts,
359
364
  );
@@ -7,6 +7,7 @@
7
7
  * `configure-wizard.ts` calls the functions here directly, the same
8
8
  * relationship it already has with `manager.ts`'s `installHooks()`.
9
9
  */
10
+ import { HEALTH_PROBE_SOURCE } from "./health-probe";
10
11
  import {
11
12
  existsSync,
12
13
  mkdirSync,
@@ -1030,7 +1031,7 @@ export async function probeDaemon(): Promise<DaemonProbe> {
1030
1031
  cli: "claude",
1031
1032
  stdin: JSON.stringify({
1032
1033
  hook_event_name: "SessionStart",
1033
- source: "failproofai-health-probe",
1034
+ source: HEALTH_PROBE_SOURCE,
1034
1035
  }),
1035
1036
  },
1036
1037
  { responseTimeoutMs: DAEMON_PROBE_TIMEOUT_MS },