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
@@ -4,6 +4,36 @@
4
4
 
5
5
  ### Added
6
6
 
7
+ - `fp fleet deploy --target POLICY=INTEGRATION[/agt_ID]` scopes a machine's assignment; repeat the flag to include multiple alternatives. `--all-agents POLICY` explicitly clears its scope. Deploy plans, show, history, rollback and JSON readback retain assignment targets.
8
+ - `fp policies publish <id> --kind regex|jev|both [--source f.mjs] [--semantic f.json]`: a
9
+ FailproofAI Cloud policy can carry Jev checks — `jev` (declarations only, no JavaScript) or
10
+ `both` (JavaScript reviewable by exactly its own checks; the server derives the authority).
11
+ The kind follows from what is given when `--kind` is omitted, and a kind that contradicts its
12
+ inputs is exit 2 before anything is sent. The positional source still works.
13
+ - `fp fleet deploy … --jev-mode off|observe|enforce|local` sets the machine's Jev mode from
14
+ FailproofAI Cloud (overriding the machine's own; `local` hands it back). Omitted, the request
15
+ carries no `jevMode` and the mode is unchanged; `--jev-mode` alone is a valid deploy. An
16
+ `observe` effect on a `jev` policy is refused (exit 2) — Jev is observed through the mode.
17
+ - `fp fleet jev-mode <machine…|--all> <mode>` changes only the Jev mode, through its own
18
+ route (`PUT /api/enforcement/deployments/{id}/jev-mode`), never the policy set — and
19
+ `fp fleet deploy --jev-mode` with no change to the set now uses it too. A deploy is a full
20
+ replace of the set the CLI read, which leaves out disabled policies' assignments, so a
21
+ mode change sent as a deploy deleted them and reverted concurrent edits.
22
+ - `fp fleet rollback` says which Jev mode it restores (`jev mode <now> → <then>`, and
23
+ `jevModeBefore` in `--json`); `fp fleet history` shows each generation's Jev mode and marks a
24
+ mode-only generation as a change.
25
+ - The `--jev-mode` and `fleet jev-mode` help says what `enforce` does: Jev's checks block calls
26
+ as well as clearing what they review, machine-wide (installed packs' checks included); an
27
+ `observe` effect on a `both` policy withholds its Jev checks.
28
+ - The `fleet deploy`, `fleet jev-mode` and `policies publish` help says Jev checks run on
29
+ FailproofAI Cloud and nothing is installed on the machine, and `fleet show`/`fleet jev-mode`
30
+ name the reasons a machine with a mode cannot ask (`jev_unconfigured`, `transcripts_disabled`)
31
+ and the `jev_budget` report.
32
+ - `fp policies list/show` print each version's kind and Jev check names (`show` also the
33
+ declarations); `fp fleet list/show` print the machine's Jev mode and the policy errors it
34
+ reported, and `--json` carries `kind`/`semantic`/`semanticSha256`/`authority`/`reviewedBy`,
35
+ `jevMode` and `policyErrors`/`policyErrorsAt` when the server sends them.
36
+
7
37
  - `jev:evaluate` is a known permission — Jev through FailproofAI Cloud, charged to the
8
38
  org's plan — so `fp keys` and `fp users` accept it instead of refusing it as unknown,
9
39
  and the `admin` preset carries it, as the server's built-in admin set now does. The
@@ -13,9 +43,15 @@
13
43
  (`events:add` + `policies:pull` + `jev:evaluate`), for an enrolled machine using Jev through
14
44
  FailproofAI Cloud. `fp keys` also refuses `jev:evaluate` without both prerequisites itself
15
45
  (exit 2, naming what is missing) instead of sending the key for the server's 422. (#833)
46
+ - `fp policies list` and `fp policies show` print what a `jev`/`both` version's checks take of a
47
+ machine's Jev question budget (`jevChars`), and a deploy refused with `jev_budget_exceeded`
48
+ lists each Jev policy's share, largest first (the `hint` under `--json`), so the refusal says
49
+ which policy to leave off.
16
50
 
17
51
  ### Changed
18
52
 
53
+ - `fp policies publish`'s refusal of Jev fields in the JavaScript now says where Jev checks go:
54
+ the policy's own declarations, `--kind both --semantic checks.json`.
19
55
  - `fp guardrails summary` shows how many machines run Jev in each mode, reading the summary's
20
56
  `jev.machines.observe` and `jev.machines.enforce`.
21
57
  - `fp policies publish` (and `policies compose --publish`) refuses a source carrying Jev
@@ -27,6 +63,11 @@
27
63
  same comment-aware detection, as the dashboard's publish form; the server does not read
28
64
  the source, so nothing else refuses it for `fp`. (#833)
29
65
 
66
+ ### Fixed
67
+
68
+ - `fp fleet history` keeps `gen`, `when` and `jev` visible at 80 columns (rollback needs `gen`): the policy list is shortened, then dropped, and `change` wraps first.
69
+ - `fp fleet show` and `fp fleet history` name an exact-profile target by the profile label the machine reports (`claude/.claude-work`, with the `agt_…` id kept in `show`), falling back to the bare id.
70
+
30
71
  ## 0.0.1 — 2026-09-22
31
72
 
32
73
  **First stable release.** `0.0.1b1` and `0.0.1b2` are the two betas behind it; the
@@ -139,6 +139,48 @@ fp fleet deploy ci-runner-01 --add no-force-push
139
139
  fp guardrails summary --since 24h
140
140
  ```
141
141
 
142
+ A policy has a **kind**: `regex` (JavaScript — the default, and what every
143
+ earlier version is), `jev` (Jev checks only, from a JSON file of declarations —
144
+ each exactly a failproofai pack manifest's semantic entry), or `both`
145
+ (JavaScript whose verdict its own Jev checks may clear, deployed as one).
146
+ Jev checks run on FailproofAI Cloud; nothing is installed on the machine.
147
+ `--jev-mode` sets a machine's Jev mode from FailproofAI Cloud, overriding the
148
+ machine's own; omit it and the mode is left alone. Under `observe` or `enforce`
149
+ the machine sends each checked tool call to FailproofAI Cloud, which asks the
150
+ checks deployed to it. The mode is the machine's, so it covers installed packs'
151
+ checks too, and in `enforce` Jev's checks **block** calls as well as clearing
152
+ the regex verdicts they review. `fp fleet jev-mode` changes only the mode, and
153
+ never rewrites a machine's policy set.
154
+
155
+ ```bash
156
+ fp policies publish prod-db-intent --kind jev --semantic ./checks.json
157
+ fp policies publish no-prod-db --kind both --source ./rule.mjs --semantic ./checks.json
158
+ fp fleet deploy ci-runner-01 --add prod-db-intent --jev-mode observe
159
+ fp fleet jev-mode --all enforce # the mode alone, every machine with a deployment
160
+ fp fleet show ci-runner-01 # its Jev mode, and any policy errors it reported
161
+ ```
162
+
163
+ Published policy versions do not contain agent-routing code. Each assignment
164
+ can instead target every agent (the default), an integration including future
165
+ profiles, or a particular profile reported by that machine. The same target
166
+ applies to the regex and Jev parts of a `both` policy:
167
+
168
+ ```bash
169
+ fp fleet deploy ci-runner-01 --add no-prod-db --target no-prod-db=hermes
170
+ fp fleet deploy ci-runner-01 --target no-prod-db=hermes/agt_1234567890abcdef
171
+ fp fleet deploy ci-runner-01 --all-agents no-prod-db # explicitly remove targeting
172
+ ```
173
+
174
+ Repeat `--target` for multiple alternatives on one assignment. `fp fleet
175
+ show` and `fp fleet history` display the assigned scope; `--json` includes
176
+ `agentTargets` on each targeted policy. A machine must report agent-scoping
177
+ support before accepting a new target. When its identity cannot be resolved,
178
+ a targeted policy does not match; unscoped policy remains in force.
179
+ Newly installed shell hooks carry their settings scope. Reinstall older hooks
180
+ to add the hint; without it, or for an integration that cannot report the
181
+ source of multiple installed scopes, the machine reports
182
+ `agent_scope_unresolved` rather than guessing which profile ran the call.
183
+
142
184
  **A deploy REPLACES a machine's whole policy set.** The server takes the full
143
185
  list and does not merge, so `fleet deploy` reads what the machine currently runs,
144
186
  applies your `--add`/`--remove`, prints the complete resulting set, and writes
@@ -256,4 +298,3 @@ working as an opt-out if it is ever switched back on. See
256
298
  cd fp-cloud-cli
257
299
  uv run --extra dev pytest
258
300
  ```
259
-
@@ -23,7 +23,7 @@ import re
23
23
  import uuid
24
24
  from dataclasses import dataclass
25
25
  from enum import Enum
26
- from typing import Any, Callable, Dict, Iterator, List, Optional, Sequence, Union
26
+ from typing import Any, Callable, Dict, Iterator, List, Optional, Sequence, Tuple, Union
27
27
 
28
28
  import httpx
29
29
 
@@ -487,9 +487,39 @@ def _raise_for_status(response: httpx.Response, ctx: ClientContext) -> None:
487
487
  message or f"Request failed with status {response.status_code}.",
488
488
  status=response.status_code,
489
489
  request_id=request_id,
490
+ hint=_jev_budget_breakdown(response),
490
491
  )
491
492
 
492
493
 
494
+ def _jev_budget_breakdown(response: httpx.Response) -> Optional[str]:
495
+ """The per-policy breakdown of a deploy's ``jev_budget_exceeded`` refusal.
496
+
497
+ The message carries only the total (``used``/``budget``); the body also lists
498
+ every Jev policy version the machine would carry with its question
499
+ characters (``policies: [{id, version, chars}]``), which is what tells an
500
+ operator WHICH policy to leave off. Largest first. ``None`` for any other
501
+ error, and for a publish refusal, which names no other policies.
502
+ """
503
+ try:
504
+ data = response.json()
505
+ except Exception:
506
+ return None
507
+ if not isinstance(data, dict) or data.get("code") != "jev_budget_exceeded":
508
+ return None
509
+ rows = [
510
+ (str(p.get("id", "")), p.get("version"), p["chars"])
511
+ for p in data.get("policies") or []
512
+ if isinstance(p, dict) and isinstance(p.get("chars"), int)
513
+ ]
514
+ if not rows:
515
+ return None
516
+ rows.sort(key=lambda row: -row[2])
517
+ parts = [f"{pid}@{version} {chars:,}" if version is not None else f"{pid} {chars:,}"
518
+ for pid, version, chars in rows]
519
+ return ("Jev question characters per policy: " + " · ".join(parts)
520
+ + " — deploy fewer of these Jev policies to this machine")
521
+
522
+
493
523
  def _get_json(ctx: ClientContext, path: str, params: Optional[Dict[str, Any]] = None) -> Any:
494
524
  clean = {k: v for k, v in (params or {}).items() if v is not None}
495
525
  url = _path(ctx, path) # chokepoint 1 of 4 for the /api -> /v1 rewrite
@@ -1643,22 +1673,43 @@ def list_policies(ctx: ClientContext) -> List[PolicyVersion]:
1643
1673
 
1644
1674
 
1645
1675
  def publish_policy(
1646
- ctx: ClientContext, policy_id: str, source: str, description: str = ""
1676
+ ctx: ClientContext,
1677
+ policy_id: str,
1678
+ source: Optional[str],
1679
+ description: str = "",
1680
+ *,
1681
+ kind: Optional[str] = None,
1682
+ semantic: Optional[List[Any]] = None,
1647
1683
  ) -> PolicyVersion:
1648
1684
  """POST /api/enforcement/policies — mints a NEW VERSION; never edits in place.
1649
1685
 
1650
- Refuses Jev fields a cloud policy never reads before anything is sent, here
1651
- because `policies publish` and `policies compose --publish` both route through
1652
- it — and regardless of `--no-verify`, which only skips the syntax check.
1686
+ ``kind`` is ``regex`` (JavaScript ``source`` only — what an omitted kind
1687
+ means to the server), ``jev`` (Jev declarations in ``semantic``, no
1688
+ ``source``) or ``both`` (the two together: the JavaScript is reviewable by
1689
+ exactly its own checks). ``authority``/``reviewedBy`` are derived by the
1690
+ server from the kind and are never sent.
1691
+
1692
+ Refuses Jev fields in the JAVASCRIPT before anything is sent, here because
1693
+ `policies publish` and `policies compose --publish` both route through it —
1694
+ and regardless of `--no-verify`, which only skips the syntax check. Jev
1695
+ checks belong in ``semantic``, where they take effect.
1653
1696
  """
1654
- problem = cloud_publish_problem(source)
1697
+ problem = cloud_publish_problem(source or "")
1655
1698
  if problem:
1656
1699
  raise ApiError(
1657
1700
  f"{policy_id} cannot be published as a cloud policy: {problem}",
1658
- hint=("Jev checks ship in a failproofai pack — `failproofai publish` — where "
1659
- "semanticPolicies.add and authority: \"reviewable\" take effect"),
1701
+ hint=("put Jev checks in the policy's Jev declarations — `--kind both --semantic "
1702
+ "checks.json` — or ship them in a failproofai pack with `failproofai publish`"),
1660
1703
  )
1661
- body = {"id": policy_id, "source": source, "description": description}
1704
+ body: Dict[str, Any] = {"id": policy_id, "description": description}
1705
+ # `source` is omitted for a Jev-only policy: the server takes absent (or
1706
+ # empty) as "no JavaScript", which is what a `jev` version is.
1707
+ if source:
1708
+ body["source"] = source
1709
+ if kind is not None:
1710
+ body["kind"] = kind
1711
+ if semantic is not None:
1712
+ body["semantic"] = semantic
1662
1713
  return PolicyVersion.from_dict(_post_json(ctx, "/api/enforcement/policies", body) or {})
1663
1714
 
1664
1715
 
@@ -1681,6 +1732,29 @@ def list_machines(ctx: ClientContext) -> List[Machine]:
1681
1732
  return [Machine.from_dict(m) for m in items]
1682
1733
 
1683
1734
 
1735
+ def machine_agents(ctx: ClientContext, machine_id: str) -> List[Dict[str, Any]]:
1736
+ """GET /api/enforcement/machines/{id}/agents — the agent profiles the daemon
1737
+ last reported: `[{instanceId, integration, profileLabel, scope, ...}]`."""
1738
+ data = _get_json(ctx, f"/api/enforcement/machines/{machine_id}/agents")
1739
+ items = data if isinstance(data, list) else (data or {}).get("agents", [])
1740
+ return [a for a in items if isinstance(a, dict)]
1741
+
1742
+
1743
+ def agent_labels(ctx: ClientContext, machine_id: str) -> Dict[str, str]:
1744
+ """`{instanceId: profileLabel}` for one machine, or `{}` when unavailable.
1745
+
1746
+ Best effort on purpose: it only names the `agt_…` ids an exact-profile
1747
+ assignment carries. A server without the roster route, or a machine that
1748
+ never reported one, falls back to the bare id rather than failing the view.
1749
+ """
1750
+ try:
1751
+ agents = machine_agents(ctx, machine_id)
1752
+ except Exception: # noqa: BLE001 — a missing label must never fail the read
1753
+ return {}
1754
+ return {str(a["instanceId"]): str(a["profileLabel"])
1755
+ for a in agents if a.get("instanceId") and a.get("profileLabel")}
1756
+
1757
+
1684
1758
  def rename_machine(ctx: ClientContext, machine_id: str, label: str) -> Dict[str, Any]:
1685
1759
  """PATCH /api/enforcement/machines/{id} — a human label, not the id."""
1686
1760
  path = f"/api/enforcement/machines/{machine_id}"
@@ -1708,14 +1782,45 @@ def get_deployment(ctx: ClientContext, machine_id: str) -> Optional[Deployment]:
1708
1782
 
1709
1783
 
1710
1784
  def deploy_policies(
1711
- ctx: ClientContext, machine_id: str, policies: Sequence[PolicyRef]
1785
+ ctx: ClientContext,
1786
+ machine_id: str,
1787
+ policies: Sequence[PolicyRef],
1788
+ jev_mode: Optional[str] = None,
1712
1789
  ) -> Deployment:
1713
- """PUT /api/enforcement/deployments/{id} — REPLACES the machine's whole set."""
1790
+ """PUT /api/enforcement/deployments/{id} — REPLACES the machine's whole set.
1791
+
1792
+ ``jev_mode`` (``off|observe|enforce|local``) is sent only when given: the
1793
+ server reads an ABSENT ``jevMode`` as "keep the machine's current one", so a
1794
+ deploy that says nothing about Jev never changes it. ``local`` stops
1795
+ FailproofAI Cloud overriding the machine's own mode.
1796
+ """
1714
1797
  path = f"/api/enforcement/deployments/{machine_id}"
1715
- body = {"policies": [p.to_dict() for p in policies]}
1798
+ body: Dict[str, Any] = {"policies": [p.to_dict() for p in policies]}
1799
+ if jev_mode is not None:
1800
+ body["jevMode"] = jev_mode
1716
1801
  return Deployment.from_dict(_request_json(ctx, "PUT", path, json_body=body) or {})
1717
1802
 
1718
1803
 
1804
+ def set_jev_mode(ctx: ClientContext, machine_id: str, jev_mode: str) -> Tuple[Deployment, bool]:
1805
+ """PUT /api/enforcement/deployments/{id}/jev-mode — change ONLY the Jev mode.
1806
+
1807
+ ``jev_mode`` is ``off|observe|enforce|local`` (``local`` stops FailproofAI
1808
+ Cloud overriding the machine's own mode). Unlike a deploy, this never
1809
+ touches the machine's policy set: a deploy is a full replace of the set, and
1810
+ the set a client can read leaves out disabled policies' assignments, so a
1811
+ mode change sent as a deploy deleted them — and reverted any edit made since
1812
+ the set was read. It still mints a new generation, which is how the machine
1813
+ picks the mode up.
1814
+
1815
+ Returns the deployment and whether anything changed: setting the mode the
1816
+ machine already has changes nothing and mints nothing (``changed: false``).
1817
+ A machine with no deployment is a 404 — a deploy is how it gets its first.
1818
+ """
1819
+ path = f"/api/enforcement/deployments/{machine_id}/jev-mode"
1820
+ data = _request_json(ctx, "PUT", path, json_body={"jevMode": jev_mode}) or {}
1821
+ return Deployment.from_dict(data), bool(data.get("changed", True))
1822
+
1823
+
1719
1824
  def deployment_history(ctx: ClientContext, machine_id: str) -> List[Dict[str, Any]]:
1720
1825
  """GET /api/enforcement/deployments/{id}/history — every generation, newest first."""
1721
1826
  path = f"/api/enforcement/deployments/{machine_id}/history"