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
@@ -5,9 +5,10 @@
5
5
  * before import so the worker never knowingly executes modified bytes.
6
6
  */
7
7
  import { createHash } from "node:crypto";
8
- import { existsSync, readFileSync, realpathSync, rmSync } from "node:fs";
8
+ import { existsSync, readFileSync, realpathSync, rmSync, statSync } from "node:fs";
9
9
  import { isAbsolute, relative, resolve } from "node:path";
10
- import { cloudPoliciesDir } from "./fp-home";
10
+ import { cloudPoliciesDir, configFile } from "./fp-home";
11
+ import { agentTargetsMatch, parseAgentTargets, type AgentIdentity, type AgentTarget } from "./agent-targets";
11
12
  import { authorityFieldsOf } from "./policy-authority";
12
13
  import type { PolicyAuthority } from "./policy-types";
13
14
 
@@ -22,10 +23,10 @@ import type { PolicyAuthority } from "./policy-types";
22
23
  * enforced while every other signal says the machine is healthy. Reproduced
23
24
  * exactly that way while syncing this with AgentEye#559.
24
25
  *
25
- * 1 is accepted for files a pre-rename beta daemon left behind; 2 is what is
26
- * written now.
26
+ * 1 is accepted for files a pre-rename beta daemon left behind; 2 is
27
+ * unscoped and 3 is targeted. An old hook must reject 3.
27
28
  */
28
- const ACCEPTED_ACTIVE_SCHEMA_VERSIONS: readonly number[] = [1, 2];
29
+ const ACCEPTED_ACTIVE_SCHEMA_VERSIONS: readonly number[] = [1, 2, 3];
29
30
  const SHA256_RE = /^[a-f0-9]{64}$/;
30
31
  const POLICY_ID_RE = /^[A-Za-z0-9._-]{1,128}$/;
31
32
 
@@ -59,6 +60,7 @@ export interface CloudManagedPolicyArtifact {
59
60
  authority?: PolicyAuthority;
60
61
  /** The semantic policies that must all be asked and none answer `deny`; see `authority`. */
61
62
  reviewedBy?: string[];
63
+ agentTargets?: AgentTarget[];
62
64
  }
63
65
 
64
66
  interface ActiveManifest {
@@ -72,6 +74,7 @@ interface ActiveManifest {
72
74
  path: string;
73
75
  authority?: unknown;
74
76
  reviewedBy?: unknown;
77
+ agentTargets?: unknown;
75
78
  }>;
76
79
  }
77
80
 
@@ -82,6 +85,24 @@ export function cloudManagedPolicyRoot(): string {
82
85
  );
83
86
  }
84
87
 
88
+ /**
89
+ * An explicit disconnect vetoes an old deployment even when an operator's
90
+ * overridden policy directory is shared and therefore cannot be cleaned up.
91
+ * Missing or unreadable config does not veto older enrolled machines; this
92
+ * mirrors the daemon's `disconnected_by_config` rule.
93
+ */
94
+ function disconnectedByConfig(): boolean {
95
+ try {
96
+ const raw: unknown = JSON.parse(readFileSync(configFile(), "utf8"));
97
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
98
+ const mode = (raw as { mode?: unknown }).mode;
99
+ return !!mode && typeof mode === "object" && !Array.isArray(mode) &&
100
+ (mode as { kind?: unknown }).kind === "oss";
101
+ } catch {
102
+ return false;
103
+ }
104
+ }
105
+
85
106
  /**
86
107
  * A version-1 manifest, in the spelling a pre-rename daemon actually wrote.
87
108
  *
@@ -148,11 +169,18 @@ export function resolveManagedPath(root: string, candidate: string): string {
148
169
  /**
149
170
  * Stop enforcing cloud-managed policies on this machine.
150
171
  *
151
- * Removes `active.json` and the cached `desired-state.json`: a stopped daemon
152
- * must not rebuild a deployment after the machine disconnects. The deployment
153
- * directories and content-addressed artifacts are left
154
- * alone: they are large, hash-verified on use, and inert once nothing points
155
- * at them, so keeping them makes a reconnect cheap and offline-safe.
172
+ * Removes `desired-state.json` FIRST, then `active.json` — the manifest that
173
+ * says which deployment is live — both error reports and the Jev budget record.
174
+ * The content-addressed artifacts are left alone: they are large, hash-verified
175
+ * on use, and inert once nothing points at them, so keeping them makes a
176
+ * reconnect cheap.
177
+ *
178
+ * The snapshot has to go, and before the pointer. It is what the daemon's
179
+ * maintenance lane rebuilds a lost `active.json` from, and it used to be left
180
+ * behind: within one interval of `--disconnect` the old org's JS policies and
181
+ * Jev mode were back, on a machine whose owner had left (the daemon
182
+ * also refuses to rebuild on a machine that is not enrolled now, so neither
183
+ * half alone decides it).
156
184
  *
157
185
  * Called by `--disconnect`, which without it did not disconnect. Clearing the
158
186
  * credential stops the daemon REFRESHING policy; every artifact already on disk
@@ -164,36 +192,365 @@ export function resolveManagedPath(root: string, candidate: string): string {
164
192
  * Returns true when a manifest was actually removed.
165
193
  */
166
194
  export function clearActiveCloudManagedPolicies(): boolean {
195
+ // An override can point to a shared directory with unrelated files named
196
+ // active.json or errors.json. Never delete from a path the CLI does not own.
197
+ // `mode: oss` independently stops the hook from reading retained artifacts.
198
+ if (process.env.FAILPROOFAI_CLOUD_POLICY_DIR !== undefined) return false;
199
+ const root = cloudManagedPolicyRoot();
200
+ // The snapshot first, so nothing can rebuild the pointer from it in between.
201
+ // The error reports go too: they describe a deployment this machine no
202
+ // longer has, and a reconnect (possibly to another organisation) must not
203
+ // open by reporting the old one's problems. The Cloud Jev mode lives IN
204
+ // active.json, so removing it clears that too.
205
+ // Either manifest counts as a removed deployment: a stopped daemon would
206
+ // rebuild `active.json` from the snapshot alone.
167
207
  let removed = false;
168
- for (const name of ["active.json", "desired-state.json"]) {
169
- const path = resolve(cloudManagedPolicyRoot(), name);
208
+ for (const name of [DESIRED_STATE_FILE, CLOUD_POLICY_ERRORS_FILE, DAEMON_POLICY_ERRORS_FILE, JEV_BUDGET_FILE, "load-checked.json", "active.json"]) {
209
+ const path = resolve(root, name);
170
210
  if (!existsSync(path)) continue;
171
211
  try {
172
212
  rmSync(path, { force: true });
173
- removed = true;
213
+ if (name === DESIRED_STATE_FILE || name === "active.json") removed = true;
174
214
  } catch {
175
- // Try both independently: a failure removing one must not leave the
176
- // other referenced merely because it came later in the list.
215
+ // Best-effort and independent: a failure removing one file must not leave
216
+ // the others in place. `--disconnect` still clears the credentials, and
217
+ // reporting one failed removal would obscure that the rest succeeded.
177
218
  }
178
219
  }
220
+ // The org's policy source goes too (B15): the content-addressed artifacts
221
+ // are the departed organisation's code, and nothing on a disconnected
222
+ // machine may use them; a reconnect downloads what its deployment names.
223
+ // Only here, in the directory the CLI owns (an override returned above).
224
+ try {
225
+ rmSync(resolve(root, "artifacts"), { recursive: true, force: true });
226
+ } catch {
227
+ // Best-effort, like the files above.
228
+ }
179
229
  return removed;
180
230
  }
181
231
 
182
- export function readActiveCloudManagedPolicies(): CloudManagedPolicyArtifact[] {
232
+ /** The daemon's snapshot of the last desired state (`PolicyStore::desired_state_path`). */
233
+ export const DESIRED_STATE_FILE = "desired-state.json";
234
+ /** The CLI's error report, beside `active.json`. See `cloud-policy-errors.ts`. */
235
+ export const CLOUD_POLICY_ERRORS_FILE = "errors.json";
236
+ /** The daemon's own reconcile error state (`PolicyStore::daemon_errors_path`). */
237
+ export const DAEMON_POLICY_ERRORS_FILE = "daemon-errors.json";
238
+ /**
239
+ * Installed packs' Jev checks FailproofAI Cloud dropped from a request for the
240
+ * question budget, kept for the deployment they happened under so the report
241
+ * does not flap with each tool call's selection. See `cloud-policy-errors.ts`.
242
+ */
243
+ export const JEV_BUDGET_FILE = "jev-budget.json";
244
+
245
+ // ── FailproofAI Cloud Jev (CONTRACT C10) ─────────────────────────────────────
246
+ //
247
+ // Jev policies, and the Jev half of `both` policies, live ONLY on FailproofAI
248
+ // Cloud: nothing but the MODE reaches this machine. `active.json` carries
249
+ // `jevMode` (`off | observe | enforce`, or absent), and a `both` policy's JS
250
+ // half carries `authority: "reviewable"` with `reviewedBy` = the names of its
251
+ // own Cloud checks. With `observe`/`enforce` the hook path sends every gated
252
+ // tool call to FailproofAI Cloud, which asks the checks deployed to this
253
+ // machine and returns their verdict (`semantic/cloud-jev.ts`).
254
+
255
+ /** The Jev modes Cloud may set. `local` never reaches a machine (stored NULL). */
256
+ export type CloudJevMode = "off" | "observe" | "enforce";
257
+
258
+ /** What `errors.json` reports, one entry per problem (CONTRACT C4/C6). */
259
+ export type CloudPolicyErrorKind = "regex" | "jev" | "both" | "daemon";
260
+ export interface CloudPolicyError {
261
+ id: string;
262
+ version: number | null;
263
+ kind: CloudPolicyErrorKind;
264
+ message: string;
265
+ }
266
+
267
+ /** What this machine knows about FailproofAI Cloud's Jev: the mode, and nothing else. */
268
+ export interface CloudJevState {
269
+ /** Cloud's Jev mode, or null when Cloud does not set one (or there is no deployment). */
270
+ jevMode: CloudJevMode | null;
271
+ /** The deployment `active.json` names, or null without one. */
272
+ deployment: number | null;
273
+ /** A `jevMode` this build cannot read, reported rather than guessed at. */
274
+ errors: CloudPolicyError[];
275
+ }
276
+
277
+ const noCloudJev = (): CloudJevState => ({ jevMode: null, deployment: null, errors: [] });
278
+
279
+ function parseCloudJevMode(raw: unknown): CloudJevMode | null {
280
+ return raw === "off" || raw === "observe" || raw === "enforce" ? raw : null;
281
+ }
282
+
283
+ /** Whether Cloud's mode sends this machine's gated tool calls to FailproofAI Cloud Jev. */
284
+ export function cloudJevAsks(mode: CloudJevMode | null): mode is "observe" | "enforce" {
285
+ return mode === "observe" || mode === "enforce";
286
+ }
287
+
288
+ // ── Read once per change ─────────────────────────────────────────────────────
289
+ //
290
+ // The hook path asks about this deployment several times per event — the JS
291
+ // reader, the reviewer set, the Jev mode — and the warm worker does that on
292
+ // every tool call of every session. So `active.json` is parsed once per CHANGE
293
+ // of the file, keyed on its identity and version: device, inode, mode, size,
294
+ // and modification and change times to the nanosecond.
295
+ //
296
+ // Sound for this file in particular. The daemon writes it by rename, so a new
297
+ // deployment is a new inode, and an edit in place moves the change time, which
298
+ // nothing short of the system clock can set back.
299
+
300
+ /** A file's identity and version, or null when it does not exist. Throws on anything else. */
301
+ function fileVersion(path: string): string | null {
302
+ try {
303
+ const s = statSync(path, { bigint: true });
304
+ return `${s.dev}:${s.ino}:${s.mode}:${s.size}:${s.mtimeNs}:${s.ctimeNs}`;
305
+ } catch (err) {
306
+ const code = (err as NodeJS.ErrnoException).code;
307
+ if (code === "ENOENT" || code === "ENOTDIR") return null;
308
+ throw err;
309
+ }
310
+ }
311
+
312
+ let activeJsonCache: { path: string; version: string; value: unknown } | null = null;
313
+
314
+ /**
315
+ * `active.json` parsed, once per change of the file — or `undefined` when
316
+ * there is none (a file holding `null` is a bad manifest, not an absent one).
317
+ * Throws on a file that cannot be read or is not JSON (not cached: the next
318
+ * call tries again). Callers must not mutate what it returns.
319
+ */
320
+ function readActiveJson(): unknown {
321
+ if (disconnectedByConfig()) {
322
+ activeJsonCache = null;
323
+ return undefined;
324
+ }
325
+ const path = resolve(cloudManagedPolicyRoot(), "active.json");
326
+ const version = fileVersion(path);
327
+ if (version === null) {
328
+ activeJsonCache = null;
329
+ return undefined;
330
+ }
331
+ if (activeJsonCache && activeJsonCache.path === path && activeJsonCache.version === version) return activeJsonCache.value;
332
+ const value: unknown = JSON.parse(readFileSync(path, "utf8"));
333
+ activeJsonCache = { path, version, value };
334
+ return value;
335
+ }
336
+
337
+ /** Forget every cached read. Tests only: a test that rewrites a file in place can beat the clock's granularity. */
338
+ export function _resetCloudManagedCachesForTest(): void {
339
+ activeJsonCache = null;
340
+ }
341
+
342
+ /** `active.json` as untyped JSON, schema-checked, or null when there is none. Throws on a bad one. */
343
+ function readActiveRaw(): Record<string, unknown> | null {
344
+ const raw = readActiveJson();
345
+ if (raw === undefined) return null;
346
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) throw new Error("active manifest is not an object");
347
+ const record = raw as Record<string, unknown>;
348
+ if (!ACCEPTED_ACTIVE_SCHEMA_VERSIONS.includes(record.schemaVersion as number)) {
349
+ throw new Error(`unsupported active manifest schema ${String(record.schemaVersion)}`);
350
+ }
351
+ return record;
352
+ }
353
+
354
+ /** Schema 3 means at least one machine assignment is targeted, including a
355
+ * Jev-only one whose JS policies array is empty. Never reads any artifact. */
356
+ export function readCloudAgentScopeRequired(): boolean {
357
+ try {
358
+ return readActiveRaw()?.schemaVersion === 3;
359
+ } catch {
360
+ return false;
361
+ }
362
+ }
363
+
364
+ /**
365
+ * Cloud's Jev mode from `active.json`, or null — no deployment, no mode, or a
366
+ * file that cannot be read (which is then simply not a mode: the local
367
+ * `jev.json` decides, as it does on a machine Cloud never touched). Cheap and
368
+ * never throws: the hook path asks on every gate event.
369
+ */
370
+ export function readCloudJevMode(): CloudJevMode | null {
371
+ try {
372
+ return parseCloudJevMode(readActiveRaw()?.jevMode);
373
+ } catch {
374
+ return null;
375
+ }
376
+ }
377
+
378
+ /**
379
+ * The Cloud Jev state `active.json` carries: the mode, the deployment it came
380
+ * with, and a report of a mode this build cannot read. Never throws; an
381
+ * unreadable manifest is reported by the JS reader (and the handler files it),
382
+ * so it is not reported twice here.
383
+ */
384
+ export function readCloudJevState(): CloudJevState {
385
+ let active: Record<string, unknown> | null;
386
+ try {
387
+ active = readActiveRaw();
388
+ } catch {
389
+ return noCloudJev();
390
+ }
391
+ if (!active) return noCloudJev();
392
+ const rawMode = active.jevMode;
393
+ const jevMode = parseCloudJevMode(rawMode);
394
+ const errors: CloudPolicyError[] = [];
395
+ if (rawMode !== undefined && rawMode !== null && jevMode === null) {
396
+ // The daemon refuses such a state, so this is a hand-edited or foreign file.
397
+ errors.push({ id: "jevMode", version: null, kind: "daemon", message: `unknown Jev mode ${JSON.stringify(rawMode)} ignored` });
398
+ }
399
+ const deployment = Number.isSafeInteger(active.deployment) ? (active.deployment as number) : null;
400
+ return { jevMode, deployment, errors };
401
+ }
402
+
403
+ // ── `both` policies: reviewed by their OWN Cloud checks ─────────────────────
404
+
405
+ /**
406
+ * The reviewer name a FailproofAI Cloud policy's `reviewedBy` entry stands for
407
+ * on this machine: `cloud:<policyId>/<name>`. Pack check names cannot contain
408
+ * `:` or `/`, so this can never be a pack's check — and the Cloud review files
409
+ * a Cloud check's outcome under the same key (`toReview`, `jev-review.ts`),
410
+ * built from the outcome's own `origin.cloudPolicyId`. So a `both` policy's
411
+ * verdict can be cleared by exactly that policy's Cloud checks and nothing
412
+ * else: never by an installed pack's check of the same name (CONTRACT C10.5,
413
+ * C9.4), never by another Cloud policy's.
414
+ */
415
+ export function cloudReviewerName(policyId: string, name: string): string {
416
+ return `cloud:${policyId}/${name}`;
417
+ }
418
+
419
+ /** The authority fields of one Cloud JS assignment, as `active.json` carries them. */
420
+ export interface CloudAuthorityInput {
421
+ id: string;
422
+ effect?: PolicyEffect;
423
+ authority?: PolicyAuthority;
424
+ reviewedBy?: string[];
425
+ agentTargets?: AgentTarget[];
426
+ }
427
+
428
+ /** A name {@link cloudReviewerName} already made (a Jev check name can contain neither `:` nor `/`). */
429
+ const CLOUD_REVIEWER_RE = /^cloud:[^/]+\/./;
430
+
431
+ /**
432
+ * The authority a Cloud JS policy registers with on this machine:
433
+ *
434
+ * - declared `hard` (or nothing): as declared;
435
+ * - an `observe` assignment: `hard`, silently. FailproofAI Cloud does not ask
436
+ * an observe `both` policy's Jev half (C9.3), and an observe policy blocks
437
+ * nothing anyway;
438
+ * - Cloud's Jev mode is not `observe`/`enforce`: `hard`, silently. Nothing on
439
+ * this machine can ask a Cloud check, and that is the org's own choice, so
440
+ * it is not a warning;
441
+ * - otherwise `reviewable`, by its `reviewedBy` names as {@link cloudReviewerName}s
442
+ * (a name already translated is kept, so applying this twice is harmless).
443
+ *
444
+ * Pure. The handler applies it to every assignment BEFORE the loader merges
445
+ * two assignments that share one artifact — so each name keeps the policy it
446
+ * came from — and the reviewer set (`effective-reviewers.ts`) and the
447
+ * reviewability survey use it too, so none of them can disagree.
448
+ */
449
+ export function cloudAuthorityDeclaration(
450
+ policy: CloudAuthorityInput,
451
+ mode: CloudJevMode | null,
452
+ ): { authority?: PolicyAuthority; reviewedBy?: string[] } {
453
+ if (policy.authority !== "reviewable") return policy.authority ? { authority: policy.authority } : {};
454
+ if (policy.effect === "observe" || !cloudJevAsks(mode)) return { authority: "hard" };
455
+ return {
456
+ authority: "reviewable",
457
+ reviewedBy: (policy.reviewedBy ?? []).map((n) => (CLOUD_REVIEWER_RE.test(n) ? n : cloudReviewerName(policy.id, n))),
458
+ };
459
+ }
460
+
461
+ /**
462
+ * A Cloud JS assignment as this machine registers it: its `authority` and
463
+ * `reviewedBy` replaced by {@link cloudAuthorityDeclaration}'s. Pure.
464
+ */
465
+ export function withCloudAuthority<T extends CloudAuthorityInput>(policy: T, mode: CloudJevMode | null): T {
466
+ const { authority: _authority, reviewedBy: _reviewedBy, ...rest } = policy;
467
+ void _authority;
468
+ void _reviewedBy;
469
+ return { ...rest, ...cloudAuthorityDeclaration(policy, mode) } as T;
470
+ }
471
+
472
+ /**
473
+ * Every reviewer name the deployment's `both` policies may be cleared by on
474
+ * this machine — empty unless Cloud's Jev mode asks. Pure.
475
+ */
476
+ export function cloudReviewerNames(policies: ReadonlyArray<CloudAuthorityInput>, mode: CloudJevMode | null): string[] {
477
+ const out: string[] = [];
478
+ for (const policy of policies) {
479
+ const declared = cloudAuthorityDeclaration(policy, mode);
480
+ if (declared.authority === "reviewable") out.push(...(declared.reviewedBy ?? []));
481
+ }
482
+ return out;
483
+ }
484
+
485
+ /**
486
+ * The Cloud JS assignments' authority fields, read off the cached `active.json`
487
+ * parse — no artifact is read or hashed, so this is cheap enough for the
488
+ * reviewer set, which is rebuilt on every event. Never throws: an unreadable
489
+ * manifest has no assignments here (the JS reader reports it).
490
+ */
491
+ export function readCloudAuthorityInputs(agent: AgentIdentity | null = null): CloudAuthorityInput[] {
492
+ try {
493
+ const raw = readActiveJson();
494
+ if (raw === undefined) return [];
495
+ const manifest = parseManifest(raw);
496
+ return manifest.policies.flatMap((policy) => {
497
+ if (typeof policy.id !== "string") return [];
498
+ const targets = parseAgentTargets(policy.agentTargets, manifest.schemaVersion);
499
+ if (!agentTargetsMatch(targets, agent)) return [];
500
+ return [{
501
+ id: policy.id,
502
+ effect: policy.effect === "observe" ? "observe" : "enforce",
503
+ ...(targets ? { agentTargets: targets } : {}),
504
+ ...authorityFieldsOf(policy as unknown as Record<string, unknown>),
505
+ } satisfies CloudAuthorityInput];
506
+ });
507
+ } catch {
508
+ // A malformed selector invalidates the entire active manifest for the JS
509
+ // loader too. Do not keep reviewers from a partial set of that manifest:
510
+ // Cloud's JS has not loaded, and a subset would claim otherwise.
511
+ return [];
512
+ }
513
+ }
514
+
515
+ /**
516
+ * Every Cloud JS assignment in the deployment, whatever agent it targets — for
517
+ * LISTING only (`failproofai policies`), never for import: the hook path scopes
518
+ * with {@link readActiveCloudManagedPolicies} before any artifact is read.
519
+ * A listing that applied a hook's scope with no agent hid every agent-scoped
520
+ * policy (B4). Each artifact is still digest-checked, so a row is never shown
521
+ * for bytes that would be refused.
522
+ */
523
+ export function listActiveCloudManagedPolicies(): CloudManagedPolicyArtifact[] {
524
+ return readActiveCloudManagedPoliciesFor(() => true);
525
+ }
526
+
527
+ export function readActiveCloudManagedPolicies(agent: AgentIdentity | null = null): CloudManagedPolicyArtifact[] {
528
+ return readActiveCloudManagedPoliciesFor((targets) => agentTargetsMatch(targets, agent));
529
+ }
530
+
531
+ function readActiveCloudManagedPoliciesFor(
532
+ applies: (targets: ReturnType<typeof parseAgentTargets>) => boolean,
533
+ ): CloudManagedPolicyArtifact[] {
183
534
  const root = cloudManagedPolicyRoot();
184
- const activePath = resolve(root, "active.json");
185
- if (!existsSync(activePath)) return [];
186
535
 
536
+ // Parsed once per change of the file (`readActiveJson`). Each JS artifact is
537
+ // still read and hashed HERE, on every call: the loader imports what this
538
+ // returns, and the digest check is kept immediately before that import.
187
539
  let raw: unknown;
188
540
  try {
189
- raw = JSON.parse(readFileSync(activePath, "utf8"));
541
+ raw = readActiveJson();
190
542
  } catch (err) {
191
543
  throw new Error(`failed to read cloud-managed active manifest: ${err instanceof Error ? err.message : String(err)}`);
192
544
  }
545
+ if (raw === undefined) return [];
193
546
  const manifest = parseManifest(raw);
547
+ // Scope before reading or importing any artifact: a foreign agent must not
548
+ // execute policy code even to discover that it does not apply.
549
+ const applicable = manifest.policies.filter((policy) =>
550
+ applies(parseAgentTargets(policy.agentTargets, manifest.schemaVersion)));
194
551
  const seen = new Set<string>();
195
552
 
196
- return manifest.policies.map((policy) => {
553
+ return applicable.map((policy) => {
197
554
  if (!POLICY_ID_RE.test(policy.id) || policy.id === "." || policy.id === "..") {
198
555
  throw new Error(`unsafe cloud-managed policy id ${JSON.stringify(policy.id)}`);
199
556
  }
@@ -227,6 +584,9 @@ export function readActiveCloudManagedPolicies(): CloudManagedPolicyArtifact[] {
227
584
  sha256: policy.sha256,
228
585
  path,
229
586
  deployment: manifest.deployment,
587
+ ...(parseAgentTargets(policy.agentTargets, manifest.schemaVersion)
588
+ ? { agentTargets: parseAgentTargets(policy.agentTargets, manifest.schemaVersion) }
589
+ : {}),
230
590
  // Unlike `effect`, a malformed authority is dropped rather than refused:
231
591
  // dropping it makes this policy `hard`, the default that keeps enforcing,
232
592
  // while refusing would take the whole deployment down over an optional