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
@@ -28,20 +28,38 @@ re-reads rather than reporting a success that erased somebody.
28
28
  """
29
29
  from __future__ import annotations
30
30
 
31
+ import json
31
32
  import re
32
33
  import sys
33
- from dataclasses import dataclass
34
- from typing import Dict, Iterable, List, Optional, Sequence, Tuple
34
+ from dataclasses import dataclass, replace as dataclass_replace
35
+ from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple
35
36
 
36
37
  from .errors import ApiError
37
38
  from .models import PolicyRef, PolicyVersion
38
39
 
39
40
  VALID_EFFECTS = ("enforce", "observe")
40
41
 
42
+ #: What a policy version carries: JavaScript (`regex`), Jev checks (`jev`), or
43
+ #: JavaScript reviewable by its own Jev checks (`both`).
44
+ VALID_KINDS = ("regex", "jev", "both")
45
+
46
+ #: The Jev modes a deployment may set. `local` stops FailproofAI Cloud
47
+ #: overriding the machine's own mode (the server stores it as no value).
48
+ JEV_MODES = ("off", "observe", "enforce", "local")
49
+
50
+ #: The server's (and the machine's) cap on Jev declarations per policy version.
51
+ MAX_JEV_DECLARATIONS = 24
52
+ AGENT_INTEGRATIONS = frozenset({
53
+ "claude", "codex", "copilot", "cursor", "opencode", "pi",
54
+ "hermes", "openclaw", "factory", "devin", "antigravity", "goose",
55
+ })
56
+ AGENT_ID = re.compile(r"^agt_[0-9a-f]{16,32}$")
57
+
41
58
  #: `id`, `id@3`, `id:observe`, `id@3:observe`. The id charset mirrors the
42
59
  #: server's `safe_identifier`, so a ref this accepts is one the server will too
43
60
  #: — a rejection should come from the policy not existing, not from parsing.
44
61
  _REF = re.compile(r"^(?P<id>[A-Za-z0-9._-]{1,128})(?:@(?P<version>\d+))?(?:[:](?P<effect>[a-z]+))?$")
62
+ _POLICY_ID = re.compile(r"^[A-Za-z0-9._-]{1,128}$")
45
63
 
46
64
 
47
65
  class RefError(ValueError):
@@ -102,13 +120,34 @@ class DeployPlan:
102
120
  removed: List[PolicyRef]
103
121
  changed: List[Tuple[PolicyRef, PolicyRef]]
104
122
  unchanged: List[PolicyRef]
123
+ #: `--jev-mode` as given (`off|observe|enforce|local`), or None when the
124
+ #: command said nothing about Jev — which the server reads as "keep it".
125
+ jev_mode: Optional[str] = None
126
+ #: The mode FailproofAI Cloud sets on the machine now (None = local).
127
+ jev_mode_before: Optional[str] = None
128
+
129
+ @property
130
+ def jev_mode_after(self) -> Optional[str]:
131
+ """What the machine's Cloud-set mode will be (None = local)."""
132
+ if self.jev_mode is None:
133
+ return self.jev_mode_before
134
+ return None if self.jev_mode == "local" else self.jev_mode
135
+
136
+ @property
137
+ def jev_mode_changes(self) -> bool:
138
+ return self.jev_mode is not None and self.jev_mode_after != self.jev_mode_before
139
+
140
+ @property
141
+ def set_changes(self) -> bool:
142
+ """Whether the POLICY SET changes — anything added, removed or moved."""
143
+ return bool(self.added or self.removed or self.changed)
105
144
 
106
145
  @property
107
146
  def is_noop(self) -> bool:
108
- return not (self.added or self.removed or self.changed)
147
+ return not (self.set_changes or self.jev_mode_changes)
109
148
 
110
149
  def to_dict(self) -> Dict[str, object]:
111
- return {
150
+ out: Dict[str, object] = {
112
151
  "machineId": self.machine_id,
113
152
  "base": self.base,
114
153
  "result": [p.to_dict() for p in self.result],
@@ -118,6 +157,14 @@ class DeployPlan:
118
157
  "unchanged": [p.to_dict() for p in self.unchanged],
119
158
  "noop": self.is_noop,
120
159
  }
160
+ if self.jev_mode is not None:
161
+ # `local` on both sides: the wire word, not the stored NULL.
162
+ out["jevMode"] = {
163
+ "from": self.jev_mode_before or "local",
164
+ "to": self.jev_mode_after or "local",
165
+ "changed": self.jev_mode_changes,
166
+ }
167
+ return out
121
168
 
122
169
 
123
170
  def latest_versions(policies: Iterable[PolicyVersion]) -> Dict[str, int]:
@@ -174,7 +221,10 @@ def resolve_ref(
174
221
  )
175
222
  if effect is None:
176
223
  effect = existing.effect if existing else "enforce"
177
- return PolicyRef(id=pid, version=version, effect=effect)
224
+ return PolicyRef(
225
+ id=pid, version=version, effect=effect,
226
+ agent_targets=existing.agent_targets if existing else None,
227
+ )
178
228
 
179
229
 
180
230
  def plan_deploy(
@@ -187,13 +237,28 @@ def plan_deploy(
187
237
  replace: Optional[Sequence[str]] = None,
188
238
  latest: Optional[Dict[str, int]] = None,
189
239
  disabled: Optional[set] = None,
240
+ jev_mode: Optional[str] = None,
241
+ current_jev_mode: Optional[str] = None,
242
+ kinds: Optional[Dict[Tuple[str, int], str]] = None,
243
+ targets: Sequence[str] = (),
244
+ all_agents: Sequence[str] = (),
190
245
  ) -> DeployPlan:
191
246
  """Compute the full resulting set, plus the diff to show before writing.
192
247
 
193
248
  `replace` (`--set`) is exclusive with `add`/`remove`: mixing "these exactly"
194
249
  with "these as well" has no single obvious reading, and guessing one would
195
250
  be guessing about somebody's fleet.
251
+
252
+ `jev_mode` is `--jev-mode`; `current_jev_mode` what Cloud sets now (None =
253
+ local). `kinds` maps `(id, version)` to the version's kind, so an `observe`
254
+ effect on a Jev-only version — which the server refuses, because a Jev
255
+ rollout is observed through the Jev MODE — is refused here, before a plan is
256
+ drawn and confirmed for a write that cannot happen.
196
257
  """
258
+ if jev_mode is not None and jev_mode not in JEV_MODES:
259
+ raise RefUsageError(
260
+ f"--jev-mode {jev_mode!r} is not one of {', '.join(JEV_MODES)}"
261
+ )
197
262
  latest = latest or {}
198
263
  current_list = list(current or [])
199
264
  current_map = {p.id: p for p in current_list}
@@ -220,13 +285,48 @@ def plan_deploy(
220
285
  ref = resolve_ref(token, latest=latest, current=current_map, disabled=disabled)
221
286
  result_map[ref.id] = ref
222
287
 
288
+ grouped: Dict[str, List[Dict[str, str]]] = {}
289
+ for token in targets:
290
+ if "=" not in token:
291
+ raise RefUsageError(f"--target {token!r} must be POLICY=INTEGRATION[/agt_ID]")
292
+ pid, selector = token.split("=", 1)
293
+ if not _POLICY_ID.fullmatch(pid):
294
+ raise RefUsageError(f"--target policy id {pid!r} is invalid")
295
+ integration, _, instance_id = selector.partition("/")
296
+ if integration not in AGENT_INTEGRATIONS or ("/" in selector and not AGENT_ID.fullmatch(instance_id)):
297
+ raise RefUsageError(f"--target {token!r} has an unknown integration or invalid profile ID")
298
+ entry = {"integration": integration}
299
+ if instance_id:
300
+ entry["instanceId"] = instance_id
301
+ collection = grouped.setdefault(pid, [])
302
+ if entry in collection or len(collection) == 32:
303
+ raise RefUsageError("--target has a duplicate selector or more than 32 selectors for a policy")
304
+ collection.append(entry)
305
+ clears = set(all_agents)
306
+ if clears.intersection(grouped):
307
+ raise RefUsageError("--all-agents and --target cannot name the same policy")
308
+ for pid in clears:
309
+ if not _POLICY_ID.fullmatch(pid):
310
+ raise RefUsageError(f"--all-agents policy id {pid!r} is invalid")
311
+ for pid in grouped.keys() | clears:
312
+ if pid not in result_map:
313
+ raise RefUsageError(f"{pid!r} is not in the resulting set — add or keep it before targeting")
314
+ result_map[pid] = dataclass_replace(result_map[pid], agent_targets=grouped.get(pid))
315
+
223
316
  result = sorted(result_map.values(), key=lambda p: p.id)
317
+ for ref in result:
318
+ if ref.effect == "observe" and (kinds or {}).get((ref.id, ref.version)) == "jev":
319
+ raise RefUsageError(
320
+ f"{ref.id}@{ref.version} is a Jev policy, and an effect does not apply to Jev "
321
+ "checks — deploy it as enforce and use --jev-mode observe to watch Jev without "
322
+ "it deciding anything"
323
+ )
224
324
  added, removed, changed, unchanged = [], [], [], []
225
325
  for pid, ref in sorted(result_map.items()):
226
326
  was = current_map.get(pid)
227
327
  if was is None:
228
328
  added.append(ref)
229
- elif (was.version, was.effect) != (ref.version, ref.effect):
329
+ elif (was.version, was.effect, was.agent_targets) != (ref.version, ref.effect, ref.agent_targets):
230
330
  changed.append((was, ref))
231
331
  else:
232
332
  unchanged.append(ref)
@@ -242,9 +342,73 @@ def plan_deploy(
242
342
  removed=removed,
243
343
  changed=changed,
244
344
  unchanged=unchanged,
345
+ jev_mode=jev_mode,
346
+ jev_mode_before=current_jev_mode,
245
347
  )
246
348
 
247
349
 
350
+ def jev_mode_after(mode: str) -> Optional[str]:
351
+ """What a `--jev-mode`/`jev-mode` word leaves stored: `local` is None (Cloud stops overriding)."""
352
+ return None if mode == "local" else mode
353
+
354
+
355
+ def version_kinds(policies: Iterable[PolicyVersion]) -> Dict[Tuple[str, int], str]:
356
+ """`{(id, version): kind}` for every published version."""
357
+ return {(p.id, p.version): p.kind for p in policies}
358
+
359
+
360
+ def resolve_kind(kind: Optional[str], *, has_source: bool, has_semantic: bool) -> str:
361
+ """The kind a publish is, checked against what it was given.
362
+
363
+ Explicit wins; otherwise it follows from the inputs — JavaScript alone is
364
+ `regex` (what `publish` has always done), declarations alone `jev`, both
365
+ together `both`. A kind that contradicts its inputs is a usage error: a
366
+ `jev` policy has no JavaScript, and `regex` has no declarations.
367
+ """
368
+ if kind is None:
369
+ kind = "both" if (has_source and has_semantic) else ("jev" if has_semantic else "regex")
370
+ if kind not in VALID_KINDS:
371
+ raise RefUsageError(f"--kind {kind!r} is not one of {', '.join(VALID_KINDS)}")
372
+ if kind == "regex" and has_semantic:
373
+ raise RefUsageError("--kind regex takes no --semantic; use --kind both for JavaScript plus Jev checks")
374
+ if kind == "jev" and has_source:
375
+ raise RefUsageError("--kind jev takes no JavaScript source; use --kind both for JavaScript plus Jev checks")
376
+ if kind in ("jev", "both") and not has_semantic:
377
+ raise RefUsageError(f"--kind {kind} needs --semantic <file.json> with its Jev declarations")
378
+ return kind
379
+
380
+
381
+ def parse_semantic(text: str, *, what: str = "--semantic") -> List[Any]:
382
+ """The Jev declarations in a `--semantic` file: a JSON array of declaration
383
+ objects (a `{"semantic": [...]}` wrapper is accepted too).
384
+
385
+ Deliberately a SHAPE check only — 1 to 24 objects, each with a name. What a
386
+ declaration may say (modes, probes, caps, reserved names) is checked by the
387
+ server, and authoritatively by each machine's own parser; a third copy of
388
+ those rules here is a third thing to drift. The server's refusal names the
389
+ declaration and the rule.
390
+ """
391
+ try:
392
+ value = json.loads(text)
393
+ except ValueError as exc:
394
+ raise RefUsageError(f"{what} is not valid JSON: {exc}")
395
+ if isinstance(value, dict) and isinstance(value.get("semantic"), list):
396
+ value = value["semantic"]
397
+ if not isinstance(value, list):
398
+ raise RefUsageError(f"{what} must be a JSON array of Jev declarations")
399
+ if not value:
400
+ raise RefUsageError(f"{what} holds no Jev declarations")
401
+ if len(value) > MAX_JEV_DECLARATIONS:
402
+ raise RefUsageError(
403
+ f"{what} holds {len(value)} Jev declarations; a policy version carries at most "
404
+ f"{MAX_JEV_DECLARATIONS}"
405
+ )
406
+ for i, entry in enumerate(value):
407
+ if not isinstance(entry, dict) or not isinstance(entry.get("name"), str) or not entry["name"]:
408
+ raise RefUsageError(f"{what} declaration #{i} is not an object with a name")
409
+ return value
410
+
411
+
248
412
  def check_race(base: Optional[int], returned: int) -> None:
249
413
  """Raise when a deploy landed on top of somebody else's.
250
414
 
@@ -724,7 +724,17 @@ class AuditFinding:
724
724
 
725
725
  @dataclass
726
726
  class PolicyVersion:
727
- """One published version of a policy. Versions are minted, never edited."""
727
+ """One published version of a policy. Versions are minted, never edited.
728
+
729
+ ``kind`` is what the version carries: ``regex`` (JavaScript only — every
730
+ version published before kinds existed), ``jev`` (Jev checks only, no
731
+ JavaScript) or ``both`` (JavaScript whose verdict its own Jev checks may
732
+ clear). ``semantic`` is the list of Jev declarations for ``jev``/``both``.
733
+ ``authority``/``reviewed_by`` are DERIVED by the server from the kind and
734
+ never sent by a client. ``jev_chars`` is what its Jev checks take of a
735
+ machine's Jev question budget, measured by the server the way the machine
736
+ measures it; ``None`` for ``regex``.
737
+ """
728
738
 
729
739
  id: str
730
740
  version: int
@@ -735,9 +745,18 @@ class PolicyVersion:
735
745
  created_by: Optional[str]
736
746
  disabled: bool
737
747
  archived: bool
748
+ kind: str = "regex"
749
+ semantic: Optional[List[Any]] = None
750
+ semantic_sha256: Optional[str] = None
751
+ authority: Optional[str] = None
752
+ reviewed_by: Optional[List[str]] = None
753
+ jev_chars: Optional[int] = None
738
754
 
739
755
  @classmethod
740
756
  def from_dict(cls, d: Dict[str, Any]) -> "PolicyVersion":
757
+ semantic = d.get("semantic")
758
+ reviewed = d.get("reviewedBy", d.get("reviewed_by"))
759
+ chars = d.get("jevChars", d.get("jev_chars"))
741
760
  return cls(
742
761
  id=str(d.get("id", "")),
743
762
  version=_as_int(d.get("version"), 0),
@@ -748,18 +767,46 @@ class PolicyVersion:
748
767
  created_by=d.get("createdBy", d.get("created_by")),
749
768
  disabled=bool(d.get("disabled", False)),
750
769
  archived=bool(d.get("archived", False)),
770
+ # A server that predates kinds sends none, and everything it has is
771
+ # JavaScript — `regex` is not a guess, it is the only thing it had.
772
+ kind=str(d.get("kind") or "regex"),
773
+ semantic=semantic if isinstance(semantic, list) else None,
774
+ semantic_sha256=d.get("semanticSha256", d.get("semantic_sha256")),
775
+ authority=d.get("authority"),
776
+ reviewed_by=[str(n) for n in reviewed] if isinstance(reviewed, list) else None,
777
+ jev_chars=chars if isinstance(chars, int) and not isinstance(chars, bool) else None,
751
778
  )
752
779
 
780
+ @property
781
+ def jev_names(self) -> List[str]:
782
+ """The names of this version's Jev checks, in declared order."""
783
+ return [
784
+ str(entry["name"])
785
+ for entry in (self.semantic or [])
786
+ if isinstance(entry, dict) and isinstance(entry.get("name"), str)
787
+ ]
788
+
753
789
  def to_dict(self) -> Dict[str, Any]:
754
790
  """The server's own shape. `vars()` would leak Python snake_case into a
755
791
  contract that is camelCase everywhere else, which is a difference a
756
792
  harness discovers at runtime rather than in review."""
757
- return {
793
+ out: Dict[str, Any] = {
758
794
  "id": self.id, "version": self.version, "description": self.description,
759
795
  "sha256": self.sha256, "source": self.source, "createdAt": self.created_at,
760
796
  "createdBy": self.created_by, "disabled": self.disabled,
761
- "archived": self.archived,
797
+ "archived": self.archived, "kind": self.kind,
762
798
  }
799
+ if self.semantic is not None:
800
+ out["semantic"] = self.semantic
801
+ if self.semantic_sha256:
802
+ out["semanticSha256"] = self.semantic_sha256
803
+ if self.authority:
804
+ out["authority"] = self.authority
805
+ if self.reviewed_by is not None:
806
+ out["reviewedBy"] = self.reviewed_by
807
+ if self.jev_chars is not None:
808
+ out["jevChars"] = self.jev_chars
809
+ return out
763
810
 
764
811
 
765
812
  @dataclass
@@ -774,6 +821,9 @@ class PolicyRef:
774
821
  id: str
775
822
  version: int
776
823
  effect: str = "enforce"
824
+ #: None means every agent; a nonempty selector list narrows this
825
+ #: machine's assignment, never the immutable published policy version.
826
+ agent_targets: Optional[List[Dict[str, str]]] = None
777
827
 
778
828
  @classmethod
779
829
  def from_dict(cls, d: Dict[str, Any]) -> "PolicyRef":
@@ -781,14 +831,23 @@ class PolicyRef:
781
831
  id=str(d.get("id", "")),
782
832
  version=_as_int(d.get("version"), 0),
783
833
  effect=str(d.get("effect") or "enforce"),
834
+ agent_targets=[dict(target) for target in d["agentTargets"]]
835
+ if isinstance(d.get("agentTargets"), list) else None,
784
836
  )
785
837
 
786
838
  def to_dict(self) -> Dict[str, Any]:
787
- return {"id": self.id, "version": self.version, "effect": self.effect}
839
+ out: Dict[str, Any] = {"id": self.id, "version": self.version, "effect": self.effect}
840
+ if self.agent_targets is not None:
841
+ out["agentTargets"] = self.agent_targets
842
+ return out
788
843
 
789
844
  @property
790
845
  def label(self) -> str:
791
- return f"{self.id}@{self.version}:{self.effect}"
846
+ scope = "" if not self.agent_targets else " → " + ", ".join(
847
+ f"{t['integration']}/{t['instanceId']}" if t.get("instanceId") else f"all {t['integration']}"
848
+ for t in self.agent_targets
849
+ )
850
+ return f"{self.id}@{self.version}:{self.effect}{scope}"
792
851
 
793
852
 
794
853
  @dataclass
@@ -806,6 +865,9 @@ class Deployment:
806
865
  policies: List[PolicyRef]
807
866
  updated_at: str
808
867
  updated_by: Optional[str]
868
+ #: The Jev mode FailproofAI Cloud sets on this machine (`off|observe|enforce`),
869
+ #: or None when Cloud does not override the machine's own (`local`).
870
+ jev_mode: Optional[str] = None
809
871
 
810
872
  @classmethod
811
873
  def from_dict(cls, d: Dict[str, Any]) -> "Deployment":
@@ -815,14 +877,18 @@ class Deployment:
815
877
  policies=[PolicyRef.from_dict(p) for p in (d.get("policies") or [])],
816
878
  updated_at=str(d.get("updatedAt", d.get("updated_at", "")) or ""),
817
879
  updated_by=d.get("updatedBy", d.get("updated_by")),
880
+ jev_mode=d.get("jevMode", d.get("jev_mode")) or None,
818
881
  )
819
882
 
820
883
  def to_dict(self) -> Dict[str, Any]:
821
- return {
884
+ out: Dict[str, Any] = {
822
885
  "machineId": self.machine_id, "deployment": self.deployment,
823
886
  "policies": [p.to_dict() for p in self.policies],
824
887
  "updatedAt": self.updated_at, "updatedBy": self.updated_by,
825
888
  }
889
+ if self.jev_mode:
890
+ out["jevMode"] = self.jev_mode
891
+ return out
826
892
 
827
893
 
828
894
  @dataclass
@@ -851,6 +917,13 @@ class Machine:
851
917
  deployed: bool
852
918
  policy_count: int
853
919
  event_count: int
920
+ #: What the machine last reported it could not apply — `[{id, version, kind,
921
+ #: message}]` — or None when it has never reported (an empty list means it
922
+ #: reported and all is well).
923
+ policy_errors: Optional[List[Dict[str, Any]]] = None
924
+ policy_errors_at: Optional[Any] = None
925
+ #: The Jev mode FailproofAI Cloud sets on this machine, or None (`local`).
926
+ jev_mode: Optional[str] = None
854
927
 
855
928
  @classmethod
856
929
  def from_dict(cls, d: Dict[str, Any]) -> "Machine":
@@ -858,6 +931,8 @@ class Machine:
858
931
  v = d.get(key)
859
932
  return int(v) if isinstance(v, (int, float)) else None
860
933
 
934
+ errors = d.get("policyErrors", d.get("policy_errors"))
935
+
861
936
  return cls(
862
937
  machine_id=str(d.get("machineId", d.get("machine_id", "")) or ""),
863
938
  label=d.get("label"),
@@ -870,6 +945,9 @@ class Machine:
870
945
  deployed=bool(d.get("deployed", False)),
871
946
  policy_count=_as_int(d.get("policyCount"), 0),
872
947
  event_count=_as_int(d.get("eventCount"), 0),
948
+ policy_errors=[e for e in errors if isinstance(e, dict)] if isinstance(errors, list) else None,
949
+ policy_errors_at=d.get("policyErrorsAt", d.get("policy_errors_at")),
950
+ jev_mode=d.get("jevMode", d.get("jev_mode")) or None,
873
951
  )
874
952
 
875
953
  @property
@@ -892,6 +970,11 @@ class Machine:
892
970
  "appliedAt": self.applied_at, "deployed": self.deployed,
893
971
  "policyCount": self.policy_count, "eventCount": self.event_count,
894
972
  "drifted": self.drifted,
973
+ # Emitted only when the server sent them, so a server that predates
974
+ # them reads exactly as it always did.
975
+ **({"policyErrors": self.policy_errors} if self.policy_errors is not None else {}),
976
+ **({"policyErrorsAt": self.policy_errors_at} if self.policy_errors_at is not None else {}),
977
+ **({"jevMode": self.jev_mode} if self.jev_mode else {}),
895
978
  }
896
979
 
897
980
  @property