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.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +23 -23
- package/.next/standalone/.next/prerender-manifest.json +4 -4
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js +2 -2
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js +3 -3
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/api/audit/invite/route.js +5 -6
- package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route.js +24 -24
- package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/status/route.js +2 -2
- package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js +4 -5
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +6 -7
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js +6 -7
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js +5 -6
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +2 -2
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js +4 -4
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +3 -3
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +2 -2
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
- package/.next/standalone/.next/server/app/policies/page.js +7 -7
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js +7 -7
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +8 -8
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +3 -3
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/settings/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/settings/page.js +10 -10
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/{[externals]__0qkp92tjfvw8r._.js → [externals]__0vt9i6fqinjne._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[externals]__1x24dzcbbq6-g._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__02vous7mpi2xm._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__03i5o4a840guz._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0__a_je8fsn65._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_hsnj_a2mvl_._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1izwqj_ij_9x_._.js → [root-of-the-server]__0f_4g-vazrvxv._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0l-oi4gdtmlo5._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0swiyzbmvja2d._.js → [root-of-the-server]__0t9ufnv5hi2hq._.js} +5 -5
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wg9dk8x8bnau._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__12kq3x-h7t7i1._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1a5zkndjwlc13._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1r7kbfkiw2xmu._.js → [root-of-the-server]__1aaw59g-5uty7._.js} +12 -12
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1hqpg6vgmfexv._.js +3 -0
- package/.next/standalone/.next/server/chunks/_09dz7xva4ce_2._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0hf5q4xzyg40j._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0tovk6q0miud6._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0trp3ycqv17cl._.js +1 -1
- package/.next/standalone/.next/server/chunks/_19011-u44143j._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1ek68lnh2daur._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1vslkoe35wok6._.js +1 -1
- package/.next/standalone/.next/server/chunks/{_1ixl-kxq_ctsa._.js → _1y590mjzpkbos._.js} +2 -2
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4vkpxxu7._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_hooks_0_em82s16zfym._.js +5 -0
- package/.next/standalone/.next/server/chunks/src_hooks_builtin-policies_ts_1yq5ybgx1v98e._.js +3 -0
- package/.next/standalone/.next/server/chunks/src_hooks_custom-hooks-loader_ts_0lnb3n3h94wnn._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_hooks_daemon-client_ts_0il_yu1zc0291._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_hooks_fp-home_ts_09kv0bn_4twyh._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01j58mdcdw0vn._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0588st-tpiuia._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__08ch3staq3ejw._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_a8z2ldp2v3n._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0vcyntk4snf0f._.js → [root-of-the-server]__0b78b0j8iyv6l._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0bigvy9xmv2ka._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ffu2-38y03ic._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0g8b0kyorya-t._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h86bl2qf0k_o._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1_xbg2kx30wp-._.js → [root-of-the-server]__0naevg4bcoh54._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0pia5h3p8re4c._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__075uro8t92s0_._.js → [root-of-the-server]__0pwj2h2efe5f-._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0zn1d4blhd3bu._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1-ey9fgesfbc0._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__15usvs-ms-0hf._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__16gb3_92zvk5x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17r4zrwanhp6r._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1avi2kypusyb_._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1lnfv02ucky7m._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1mc9-zlnh656_._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1r7drlqli-ado._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1s2-ck3k3rsoo._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1l1qgu5mfapkh._.js → [root-of-the-server]__1vx7o8ukefudh._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0eoura3_9gjb-._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0pedwblqdoh58._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_128ebxr83nk6g._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1_ozgifqv1ssi._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_1gb0ifpkowwub._.js → _1a3tubds7s7ow._.js} +10 -9
- package/.next/standalone/.next/server/chunks/ssr/_1djqs9i27e4kg._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo5_vm5f.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9snixb5fd-._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47q0xq5w._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x33jqb6._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpcz0uxur._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_settings_02tf1h47jmhhd._.js +1 -1
- 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
- package/.next/standalone/.next/server/chunks/ssr/package_json_[json]_cjs_013tntikdft59._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_06kzv9ddabn3_._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_0agdmptetetdt._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_0mdwgjisv4fub._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1cv9_c4l1tzrm._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_daemon-client_ts_0k41_i7jg6ndv._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_pack-cli_ts_0t7me658zqmh_._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +23 -23
- package/.next/standalone/.next/server/middleware.js +2 -2
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/preview-props.json +3 -3
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +23 -23
- package/.next/standalone/.next/static/chunks/{0frxv4_m-m2u5.js → 063al_q720fkj.js} +1 -1
- package/.next/standalone/.next/static/chunks/0_zfad4co-t2z.js +1 -0
- package/.next/standalone/.next/static/chunks/0jutamwqz8pg5.js +1 -0
- package/.next/standalone/.next/static/chunks/114hbolvrv94e.js +1 -0
- package/.next/standalone/.next/static/chunks/{37stoe-_yd852.js → 18433qz-8njv3.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1kwj8uqxuv85t.js → 1b32-afqacaen.js} +1 -1
- package/.next/standalone/.next/static/chunks/{44a7k2_62qc-9.js → 1p-hsi58i-6h0.js} +2 -2
- package/.next/standalone/.next/static/chunks/{302llgh97ce6w.js → 2-tf6_7u623kd.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1_c0dc7zqj1n7.js → 24w3x2da9sk49.js} +1 -1
- package/.next/standalone/.next/static/chunks/2tjfp9dirxnku.js +1 -0
- package/.next/standalone/.next/static/chunks/{16z6_d7sp61jm.js → 3-pku9qwv1yfu.js} +1 -1
- package/.next/standalone/.next/static/chunks/{15rm15u5a6dua.js → 42e8zab314654.js} +1 -1
- package/.next/standalone/fp-cloud-cli/CHANGELOG.md +41 -0
- package/.next/standalone/fp-cloud-cli/README.md +42 -1
- package/.next/standalone/fp-cloud-cli/fp_cli/client.py +117 -12
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/fleet_cmds.py +285 -19
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/policies_cmds.py +84 -18
- package/.next/standalone/fp-cloud-cli/fp_cli/enforcement.py +170 -6
- package/.next/standalone/fp-cloud-cli/fp_cli/models.py +89 -6
- package/.next/standalone/fp-cloud-cli/fp_cli/output.py +259 -21
- package/.next/standalone/fp-cloud-cli/fp_cli/policy_check.py +8 -5
- package/.next/standalone/fp-cloud-cli/skill/SKILL.md +2 -2
- package/.next/standalone/fp-cloud-cli/skill/references/commands.md +17 -9
- package/.next/standalone/fp-cloud-cli/tests/test_cloud_jev.py +692 -0
- package/.next/standalone/fp-cloud-cli/tests/test_enforcement_logic.py +46 -0
- package/.next/standalone/fp-cloud-cli/tests/test_output.py +23 -0
- package/.next/standalone/fp-cloud-cli/uv.lock +6 -6
- package/.next/standalone/hermes-plugin/README.md +6 -4
- package/.next/standalone/hermes-plugin/__init__.py +16 -0
- package/.next/standalone/hermes-plugin/client.py +5 -1
- package/.next/standalone/hermes-plugin/plugin.yaml +1 -1
- package/.next/standalone/node_modules/@next/env/package.json +1 -1
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/context.js +72 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/diag.js +84 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/metrics.js +50 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/propagation.js +80 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/trace.js +70 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/baggage/context-helpers.js +52 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/baggage/internal/baggage-impl.js +44 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/baggage/internal/symbol.js +12 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/baggage/utils.js +41 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/context/NoopContextManager.js +27 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/context/context.js +52 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/context-api.js +16 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag/ComponentLogger.js +47 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag/consoleLogger.js +73 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag/internal/logLevelLogger.js +34 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag/types.js +33 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag-api.js +20 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/index.js +71 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/internal/global-utils.js +60 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/internal/semver.js +111 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/metrics/Metric.js +18 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/metrics/NoopMeter.js +118 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/metrics/NoopMeterProvider.js +20 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/metrics-api.js +17 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/propagation/NoopTextMapPropagator.js +23 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/propagation/TextMapPropagator.js +36 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/propagation-api.js +17 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/NonRecordingSpan.js +58 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/NoopTracer.js +68 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/NoopTracerProvider.js +21 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/ProxyTracer.js +46 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/ProxyTracerProvider.js +46 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/SamplingResult.js +33 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/context-utils.js +71 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/internal/tracestate-impl.js +94 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/internal/tracestate-validators.js +35 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/internal/utils.js +16 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/invalid-span-constants.js +25 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/span_kind.js +38 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/spancontext-utils.js +66 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/status.js +29 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/trace_flags.js +18 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace-api.js +17 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/version.js +10 -0
- package/.next/standalone/node_modules/@opentelemetry/api/package.json +96 -0
- package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js +2 -2
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo.runtime.prod.js +2 -2
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-route-turbo.runtime.prod.js +1 -1
- package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +3 -3
- package/.next/standalone/node_modules/next/dist/server/app-render/async-local-storage.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/config.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-turbopack.js +2 -2
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-webpack.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/app-info-log.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/generate-agent-files.js +3 -3
- package/.next/standalone/node_modules/next/dist/server/lib/router-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/trace/tracer.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/typescript/rules/config.js +2 -2
- package/.next/standalone/node_modules/next/dist/server/use-cache/use-cache-wrapper.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/anonymous-meta.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/events/swc-load-failure.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/events/version.js +2 -2
- package/.next/standalone/node_modules/next/package.json +11 -11
- package/.next/standalone/package.json +11 -11
- package/.next/standalone/sdk/python/CHANGELOG.md +7 -0
- package/.next/standalone/sdk/python/failproofai_sdk/_version.py +1 -1
- package/.next/standalone/sdk/python/pyproject.toml +19 -0
- package/.next/standalone/sdk/python/uv.lock +520 -301
- package/.next/standalone/sdk/typescript/CHANGELOG.md +13 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package-lock.json +4 -13
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package.json +2 -1
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package-lock.json +4 -13
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package.json +3 -0
- package/.next/standalone/sdk/typescript/package-lock.json +178 -162
- package/.next/standalone/sdk/typescript/package.json +1 -1
- package/.next/standalone/sdk/typescript/src/version.ts +1 -1
- package/.next/standalone/server.js +1 -1
- package/bin/failproofai.mjs +17 -1
- package/dist/cli.mjs +2866 -1124
- package/dist/worker.mjs +1450 -145
- package/hermes-plugin/README.md +6 -4
- package/hermes-plugin/__init__.py +16 -0
- package/hermes-plugin/client.py +5 -1
- package/hermes-plugin/plugin.yaml +1 -1
- package/package.json +11 -11
- package/src/hooks/agent-roster.ts +172 -0
- package/src/hooks/agent-targets.ts +60 -0
- package/src/hooks/cloud-connection.ts +97 -27
- package/src/hooks/cloud-enrollment-cli.ts +7 -4
- package/src/hooks/cloud-managed-policies.ts +380 -20
- package/src/hooks/cloud-policy-errors.ts +481 -0
- package/src/hooks/config-status.ts +1 -1
- package/src/hooks/custom-hooks-loader.ts +26 -3
- package/src/hooks/daemon-client.ts +9 -4
- package/src/hooks/daemon-service.ts +2 -1
- package/src/hooks/effective-reviewers.ts +22 -1
- package/src/hooks/fp-home.ts +6 -0
- package/src/hooks/handler.ts +235 -18
- package/src/hooks/health-probe.ts +15 -0
- package/src/hooks/integrations.ts +18 -11
- package/src/hooks/jev-cli.ts +197 -0
- package/src/hooks/jev-cloud-connection.ts +92 -0
- package/src/hooks/manager.ts +122 -16
- package/src/hooks/pack-failclosed.ts +2 -0
- package/src/hooks/pack-manifest.ts +8 -1
- package/src/hooks/policy-evaluator.ts +5 -1
- package/src/hooks/policy-registry.ts +3 -2
- package/src/hooks/policy-reviewability.ts +21 -5
- package/src/hooks/semantic/cloud-jev-health.ts +227 -0
- package/src/hooks/semantic/cloud-jev.ts +677 -0
- package/src/hooks/semantic/jev-client.ts +18 -1
- package/src/hooks/semantic/jev-config.ts +173 -3
- package/src/hooks/semantic/jev-review.ts +129 -10
- package/src/hooks/semantic/pack-policies.ts +2 -1
- package/src/hooks/semantic/types.ts +8 -0
- package/src/hooks/session-pause-cli.ts +1 -1
- package/src/hooks/worker-server.ts +5 -1
- package/.next/standalone/.next/server/chunks/[externals]__0hjaw70fchx66._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__07l68zv0hqdiu._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0car70pylmvor._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0u3i025_setk_._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__10a2f6s636yc7._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qt5u58xrcuk6._.js +0 -3
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_077n_4ip5__fu._.js +0 -3
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_0mqvvxcn6v0op._.js +0 -3
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_0pb7ds5g0vzgn._.js +0 -3
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_1gasm5xkeqmm3._.js +0 -3
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_1q1heqmkhh8l4._.js +0 -3
- package/.next/standalone/.next/server/chunks/src_hooks_1aveq0uhs2t1b._.js +0 -5
- package/.next/standalone/.next/server/chunks/src_hooks_1eem5a7cyqlb2._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0888k4s6spfmh._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_bflu046ep5j._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_lbstb5x2t15._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0fdwgktjfhedo._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s4deza787asx._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__18qe-hu0gwqm4._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1_p_9xe520fex._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1fmhm8_s9i4re._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1g76awtnmimd1._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1pczevlpk5lxh._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0dc-of_bn0cim._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_effective-reviewers_ts_1h4wtvo55j16x._.js +0 -5
- package/.next/standalone/.next/static/chunks/0m-tv1y6ghhtk.js +0 -1
- package/.next/standalone/.next/static/chunks/0ol2gj4ntfn56.js +0 -1
- package/.next/standalone/.next/static/chunks/3hj5_7i3nw4zj.js +0 -1
- package/.next/standalone/.next/static/chunks/3iyoapeoq_hup.js +0 -1
- /package/.next/standalone/.next/static/{kEFP3ybXwZdriNEQmWwlH → xq8UgF5yFxty1VWxY2hyn}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{kEFP3ybXwZdriNEQmWwlH → xq8UgF5yFxty1VWxY2hyn}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{kEFP3ybXwZdriNEQmWwlH → xq8UgF5yFxty1VWxY2hyn}/_ssgManifest.js +0 -0
package/src/hooks/jev-cli.ts
CHANGED
|
@@ -108,6 +108,8 @@ import {
|
|
|
108
108
|
inspectJevConfig,
|
|
109
109
|
jevCloudBaseUrl,
|
|
110
110
|
jevConfigPath,
|
|
111
|
+
loadJevConfigForCloudMode,
|
|
112
|
+
TRANSCRIPTS_DISABLED_PROBLEM,
|
|
111
113
|
providerForUrl,
|
|
112
114
|
providerHostConflict,
|
|
113
115
|
readJevConfigFileForUpdate,
|
|
@@ -144,6 +146,7 @@ import {
|
|
|
144
146
|
type ReviewableCoverage,
|
|
145
147
|
} from "./policy-reviewability";
|
|
146
148
|
import { jevStats, type JevStats } from "./semantic/jev-stats";
|
|
149
|
+
import { listActiveCloudManagedPolicies, readCloudJevState, type CloudJevState } from "./cloud-managed-policies";
|
|
147
150
|
import { readCredentials, readJevCloudCredential, type JevCloudCredential } from "./fp-config";
|
|
148
151
|
import type { JevRequest } from "./semantic/types";
|
|
149
152
|
import { TOKEN_ON_ARGV, optsFor, paint, screenKit, stack, wrap, type RenderOpts } from "./tui";
|
|
@@ -1418,7 +1421,201 @@ function safeCoverage(): ReviewableCoverage | null {
|
|
|
1418
1421
|
}
|
|
1419
1422
|
}
|
|
1420
1423
|
|
|
1424
|
+
// ── status: FailproofAI Cloud ────────────────────────────────────────────────
|
|
1425
|
+
//
|
|
1426
|
+
// FailproofAI Cloud can SET this machine's Jev mode (`active.json` `jevMode`).
|
|
1427
|
+
// With `observe`/`enforce` the Jev checks Cloud deployed here run ON Cloud —
|
|
1428
|
+
// nothing of them is on this machine (CONTRACT C10) — every gated tool call
|
|
1429
|
+
// goes there on the Cloud Jev credential, and `jev.json` is not used. With
|
|
1430
|
+
// `off`, Jev is off whatever `jev.json` says. So `status` answers from Cloud
|
|
1431
|
+
// first; without a Cloud mode the local answer stands.
|
|
1432
|
+
//
|
|
1433
|
+
// What it can show about Cloud's checks is only what the machine knows: the
|
|
1434
|
+
// mode, and the `reviewedBy` names of the deployment's `both` policies — the
|
|
1435
|
+
// Cloud checks that may clear their regex half. Never a check's contents: the
|
|
1436
|
+
// machine does not have them.
|
|
1437
|
+
|
|
1438
|
+
/** Label for everything Cloud decided here. Customer-facing: never "AgentEye". */
|
|
1439
|
+
const MODE_SET_BY_CLOUD = "mode set by FailproofAI Cloud";
|
|
1440
|
+
|
|
1441
|
+
/** The one sentence the contract fixes for `jev status` under a Cloud mode (C10.5). */
|
|
1442
|
+
export function jevRunsOnCloudLine(mode: string): string {
|
|
1443
|
+
return `Jev checks run on FailproofAI Cloud (mode: ${mode})`;
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
function safeCloudJev(): CloudJevState {
|
|
1447
|
+
try {
|
|
1448
|
+
return readCloudJevState();
|
|
1449
|
+
} catch {
|
|
1450
|
+
return { jevMode: null, deployment: null, errors: [] };
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
/** A `both` policy's Cloud reviewers, as the deployment names them. */
|
|
1455
|
+
interface CloudReviewers {
|
|
1456
|
+
policy: string;
|
|
1457
|
+
version: number;
|
|
1458
|
+
effect: "enforce" | "observe";
|
|
1459
|
+
reviewedBy: string[];
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
/** Every Cloud JS policy that names Cloud checks in `reviewedBy` — a `both` policy. Never throws. */
|
|
1463
|
+
function cloudReviewers(): CloudReviewers[] {
|
|
1464
|
+
try {
|
|
1465
|
+
// Every assignment, agent-scoped ones included: this describes the machine.
|
|
1466
|
+
return listActiveCloudManagedPolicies()
|
|
1467
|
+
.filter((p) => p.authority === "reviewable" && (p.reviewedBy?.length ?? 0) > 0)
|
|
1468
|
+
.map((p) => ({ policy: p.id, version: p.version, effect: p.effect, reviewedBy: [...(p.reviewedBy ?? [])] }));
|
|
1469
|
+
} catch {
|
|
1470
|
+
return [];
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
/** What to do about a Cloud mode this machine cannot act on. */
|
|
1475
|
+
function cloudProblemAdvice(problem: string): string[] {
|
|
1476
|
+
if (problem === TRANSCRIPTS_DISABLED_PROBLEM) {
|
|
1477
|
+
return [
|
|
1478
|
+
"Jev does not run here: this machine was connected for decisions only (--no-transcripts), and a Jev call sends each checked tool call and the recent prompt to FailproofAI Cloud.",
|
|
1479
|
+
"To use FailproofAI Cloud's Jev checks, reconnect without --no-transcripts (failproofai config --token <key>).",
|
|
1480
|
+
];
|
|
1481
|
+
}
|
|
1482
|
+
// Over plain http the credential is fine; enforce is what http refuses.
|
|
1483
|
+
// Asking for another key there sent people after the wrong fix.
|
|
1484
|
+
if (/plain http/.test(problem)) {
|
|
1485
|
+
return [
|
|
1486
|
+
"Jev does not run here: FailproofAI Cloud set enforce, and this machine is connected over plain http, where Jev runs only in observe mode.",
|
|
1487
|
+
"Reconnect to an https FailproofAI Cloud URL (failproofai config --token <key> --url https://…), or set the machine's Jev mode to observe from FailproofAI Cloud.",
|
|
1488
|
+
];
|
|
1489
|
+
}
|
|
1490
|
+
return [
|
|
1491
|
+
`Jev cannot run here: ${problem}.`,
|
|
1492
|
+
"Connect with a key that carries jev:evaluate (failproofai config --token <key>). A local jev.json is not used while FailproofAI Cloud sets the mode.",
|
|
1493
|
+
];
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1421
1496
|
async function status(argv: string[], opts: RenderOpts): Promise<JevCliResult> {
|
|
1497
|
+
const cloud = safeCloudJev();
|
|
1498
|
+
if (cloud.jevMode === null && cloud.errors.length === 0) return localStatus(argv, opts);
|
|
1499
|
+
const parsed = parseFlags(argv, new Set(["--json"]));
|
|
1500
|
+
if (typeof parsed === "string" || parsed.positionals.length > 0) return localStatus(argv, opts);
|
|
1501
|
+
const asJson = parsed.bools.has("--json");
|
|
1502
|
+
|
|
1503
|
+
if (cloud.jevMode === null) {
|
|
1504
|
+
// A mode this build cannot read is no mode: jev.json decides. Said beside it.
|
|
1505
|
+
const local = await localStatus(argv, opts);
|
|
1506
|
+
if (asJson && local.json !== undefined) {
|
|
1507
|
+
const body = JSON.parse(local.json) as Record<string, unknown>;
|
|
1508
|
+
body.cloud = { jevMode: null, modeSetBy: null, errors: cloud.errors };
|
|
1509
|
+
return { ...local, json: JSON.stringify(body, null, 2) };
|
|
1510
|
+
}
|
|
1511
|
+
return { ...local, lines: [...local.lines, ...jevWarn(cloud.errors.map((e) => `${e.id}: ${e.message}`), opts)] };
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
const mode = cloud.jevMode;
|
|
1515
|
+
const resolved = loadJevConfigForCloudMode(mode);
|
|
1516
|
+
const reviewers = cloudReviewers();
|
|
1517
|
+
let stats: JevStats | null = null;
|
|
1518
|
+
try {
|
|
1519
|
+
stats = await jevStats();
|
|
1520
|
+
} catch {
|
|
1521
|
+
stats = null;
|
|
1522
|
+
}
|
|
1523
|
+
const cfg = resolved.config;
|
|
1524
|
+
const coverage = cfg ? safeCoverage() : null;
|
|
1525
|
+
const route = cfg ? jevRoute(cfg) : null;
|
|
1526
|
+
const running = cfg !== null;
|
|
1527
|
+
|
|
1528
|
+
if (asJson) {
|
|
1529
|
+
const body: Record<string, unknown> = {
|
|
1530
|
+
path: jevConfigPath(),
|
|
1531
|
+
status: running ? "ok" : mode === "off" ? "off" : "unconfigured",
|
|
1532
|
+
mode,
|
|
1533
|
+
modeSetBy: "FailproofAI Cloud",
|
|
1534
|
+
...(mode !== "off" ? { runsOn: "FailproofAI Cloud" } : {}),
|
|
1535
|
+
...(cfg && route
|
|
1536
|
+
? {
|
|
1537
|
+
provider: cfg.provider,
|
|
1538
|
+
providerLabel: providerLabel(cfg.provider),
|
|
1539
|
+
endpoint: shownEndpoint(cfg.provider, route.endpoint),
|
|
1540
|
+
model: route.model,
|
|
1541
|
+
modelIsDefault: route.modelIsDefault,
|
|
1542
|
+
timeoutMs: cfg.timeoutMs,
|
|
1543
|
+
}
|
|
1544
|
+
: {}),
|
|
1545
|
+
...(resolved.problem ? { problem: resolved.problem } : {}),
|
|
1546
|
+
cloud: { jevMode: mode, modeSetBy: "FailproofAI Cloud", reviewers, errors: cloud.errors },
|
|
1547
|
+
...(coverage
|
|
1548
|
+
? {
|
|
1549
|
+
reviewablePolicies: {
|
|
1550
|
+
enabled: coverage.enabled,
|
|
1551
|
+
reviewable: coverage.reviewable,
|
|
1552
|
+
customPolicyFiles: coverage.customFiles,
|
|
1553
|
+
// The checks THIS machine's packs give; Cloud's are asked on Cloud.
|
|
1554
|
+
jevChecks: coverage.jevChecks,
|
|
1555
|
+
// "No checks installed" is not a problem here: FailproofAI Cloud's
|
|
1556
|
+
// checks are asked whatever this machine has installed.
|
|
1557
|
+
problem: coverage.jevChecks === 0 ? null : reviewableProblem(coverage),
|
|
1558
|
+
},
|
|
1559
|
+
}
|
|
1560
|
+
: {}),
|
|
1561
|
+
stats,
|
|
1562
|
+
};
|
|
1563
|
+
return ok([], JSON.stringify(body, null, 2));
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
const head =
|
|
1567
|
+
mode === "off"
|
|
1568
|
+
? jevHeader("Jev status", `off — ${MODE_SET_BY_CLOUD}`, opts)
|
|
1569
|
+
: running
|
|
1570
|
+
? jevHeader("Jev status", `on · ${mode} — ${jevRunsOnCloudLine(mode)}`, opts)
|
|
1571
|
+
: jevHeader("Jev status", `off — FailproofAI Cloud set ${mode}, and this machine cannot run it`, opts);
|
|
1572
|
+
const reviewerRows = reviewers.map((r): [string, string] => [
|
|
1573
|
+
`${r.policy} v${r.version}`,
|
|
1574
|
+
`${r.reviewedBy.join(", ")}${r.effect === "observe" ? " (not asked while observed)" : ""}`,
|
|
1575
|
+
]);
|
|
1576
|
+
return ok(
|
|
1577
|
+
stack(
|
|
1578
|
+
head,
|
|
1579
|
+
mode === "off"
|
|
1580
|
+
? jevNote(
|
|
1581
|
+
`FailproofAI Cloud switched Jev off on this machine. That overrides ${jevConfigPath()} for as long as this machine is connected.`,
|
|
1582
|
+
opts,
|
|
1583
|
+
)
|
|
1584
|
+
: jevNote(
|
|
1585
|
+
`${jevRunsOnCloudLine(mode)}. Every checked tool call goes to FailproofAI Cloud, which asks the Jev checks it ` +
|
|
1586
|
+
"deployed to this machine and this machine's installed packs' checks in one request; nothing of Cloud's checks is " +
|
|
1587
|
+
`installed here. ${jevConfigPath()} is not used while FailproofAI Cloud sets the mode. In enforce, Jev's own deny ` +
|
|
1588
|
+
"checks block calls as well as clearing the regex policies they review. Jev-only Cloud policies are not on this machine, so they are " +
|
|
1589
|
+
"not listed here; fp fleet show and the dashboard list them.",
|
|
1590
|
+
opts,
|
|
1591
|
+
),
|
|
1592
|
+
cfg && route
|
|
1593
|
+
? jevRows(
|
|
1594
|
+
[
|
|
1595
|
+
["runs on", "FailproofAI Cloud"],
|
|
1596
|
+
["endpoint", shownEndpoint(cfg.provider, route.endpoint)],
|
|
1597
|
+
["model", route.modelIsDefault ? `${route.model} (provider default)` : route.model],
|
|
1598
|
+
["mode", `${modeLine(mode)} (${MODE_SET_BY_CLOUD})`],
|
|
1599
|
+
["timeout", `${cfg.timeoutMs} ms`],
|
|
1600
|
+
],
|
|
1601
|
+
opts,
|
|
1602
|
+
)
|
|
1603
|
+
: jevRows([["mode", mode === "off" ? `${modeLine("off")} (${MODE_SET_BY_CLOUD})` : `${mode} (${MODE_SET_BY_CLOUD}) — not running`]], opts),
|
|
1604
|
+
resolved.problem ? jevWarn(cloudProblemAdvice(resolved.problem), opts) : null,
|
|
1605
|
+
reviewerRows.length > 0
|
|
1606
|
+
? stack(
|
|
1607
|
+
[screenKit(opts).head("Cloud reviewers", "FailproofAI Cloud policies reviewed by their Cloud Jev checks")],
|
|
1608
|
+
jevRows(reviewerRows, opts),
|
|
1609
|
+
)
|
|
1610
|
+
: [],
|
|
1611
|
+
cloud.errors.length > 0 ? jevWarn(cloud.errors.map((e) => `${e.id}: ${e.message}`), opts) : null,
|
|
1612
|
+
coverage ? jevNote(reviewableSummary(coverage), opts) : null,
|
|
1613
|
+
jevStatsLines(stats, opts),
|
|
1614
|
+
),
|
|
1615
|
+
);
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
async function localStatus(argv: string[], opts: RenderOpts): Promise<JevCliResult> {
|
|
1422
1619
|
const parsed = parseFlags(argv, new Set(["--json"]));
|
|
1423
1620
|
if (typeof parsed === "string") return fail([parsed, "", ...JEV_USAGE]);
|
|
1424
1621
|
if (parsed.positionals.length > 0) return fail([STRAY_ARGUMENT, "", ...JEV_USAGE]);
|
|
@@ -86,8 +86,100 @@ export type CloudJevConfigWrite =
|
|
|
86
86
|
/** Set when the kept file leaves Jev off here: refused, or switched off. */
|
|
87
87
|
jevOff?: { why: "refused"; problem: string; fix?: string } | { why: "off" };
|
|
88
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* The Cloud's own `jev.json` (provider `failproofai`, as `config` writes it)
|
|
91
|
+
* named another FailproofAI Cloud origin, and was pointed at this one: same
|
|
92
|
+
* mode, same everything else. A BYOK file is never touched.
|
|
93
|
+
*/
|
|
94
|
+
| { status: "repointed"; path: string; from: string; baseUrl: string; mode: string }
|
|
89
95
|
| { status: "error"; path: string; problem: string };
|
|
90
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Create `jev.json` for the Cloud provider unless one exists. Never throws and
|
|
99
|
+
* never replaces a file — except the Cloud's own file pointing at another
|
|
100
|
+
* FailproofAI Cloud origin, which is re-pointed here (`repointCloudJevConfig`):
|
|
101
|
+
* a reconnect on a new URL (http → https) otherwise left Jev off, refused for
|
|
102
|
+
* naming an origin the key was not issued for.
|
|
103
|
+
*/
|
|
104
|
+
export function writeCloudJevConfig(cloudBase: string): CloudJevConfigWrite {
|
|
105
|
+
const first = writeCloudJevConfigIfAbsent(cloudBase);
|
|
106
|
+
if (first.status === "kept" && first.provider === JEV_CLOUD_PROVIDER && first.otherOrigin) {
|
|
107
|
+
return repointCloudJevConfig(cloudBase, first);
|
|
108
|
+
}
|
|
109
|
+
return first;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Point the Cloud's `jev.json` at `cloudBase`, keeping every other field. The
|
|
114
|
+
* file is moved aside first and judged there (as `removeCloudJevConfig` does),
|
|
115
|
+
* so a BYOK file renamed into place meanwhile is never the one rewritten, and
|
|
116
|
+
* the new file is linked in no-clobber.
|
|
117
|
+
*/
|
|
118
|
+
function repointCloudJevConfig(cloudBase: string, found: Extract<CloudJevConfigWrite, { status: "kept" }>): CloudJevConfigWrite {
|
|
119
|
+
const path = jevConfigPath();
|
|
120
|
+
let baseUrl: string;
|
|
121
|
+
try {
|
|
122
|
+
baseUrl = jevCloudBaseUrl(cloudBase);
|
|
123
|
+
} catch {
|
|
124
|
+
return found;
|
|
125
|
+
}
|
|
126
|
+
let st: Stats;
|
|
127
|
+
try {
|
|
128
|
+
st = lstatSync(path);
|
|
129
|
+
} catch {
|
|
130
|
+
return found;
|
|
131
|
+
}
|
|
132
|
+
if (!st.isFile()) return found;
|
|
133
|
+
const aside = `${path}.${process.pid}.${randomBytes(6).toString("hex")}.repointing`;
|
|
134
|
+
try {
|
|
135
|
+
renameSync(path, aside);
|
|
136
|
+
} catch {
|
|
137
|
+
return found;
|
|
138
|
+
}
|
|
139
|
+
let raw: Record<string, unknown> | null = null;
|
|
140
|
+
try {
|
|
141
|
+
const parsed: unknown = JSON.parse(readFileSync(aside, "utf8"));
|
|
142
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) raw = parsed as Record<string, unknown>;
|
|
143
|
+
} catch {
|
|
144
|
+
raw = null;
|
|
145
|
+
}
|
|
146
|
+
if (!raw || raw.provider !== JEV_CLOUD_PROVIDER) {
|
|
147
|
+
// Not the Cloud's after all: back exactly as it was.
|
|
148
|
+
putBack(aside, path, st.mode & 0o777);
|
|
149
|
+
return found;
|
|
150
|
+
}
|
|
151
|
+
const body = `${JSON.stringify({ ...raw, baseUrl }, null, 2)}\n`;
|
|
152
|
+
const tmp = `${path}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
|
|
153
|
+
try {
|
|
154
|
+
writeFileSync(tmp, body, { mode: 0o600, flag: "wx" });
|
|
155
|
+
chmodSync(tmp, 0o600);
|
|
156
|
+
linkSync(tmp, path);
|
|
157
|
+
} catch {
|
|
158
|
+
// Something landed at the path meanwhile, or the write failed: the old
|
|
159
|
+
// file goes back (never over the new one) and nothing was re-pointed.
|
|
160
|
+
putBack(aside, path, st.mode & 0o777);
|
|
161
|
+
return found;
|
|
162
|
+
} finally {
|
|
163
|
+
try {
|
|
164
|
+
rmSync(tmp, { force: true });
|
|
165
|
+
} catch {
|
|
166
|
+
// A stray temp file holds no key.
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
unlinkSync(aside);
|
|
171
|
+
} catch {
|
|
172
|
+
// The aside copy is the old URL only; harmless if it lingers.
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
status: "repointed",
|
|
176
|
+
path,
|
|
177
|
+
from: found.otherOrigin ?? "",
|
|
178
|
+
baseUrl,
|
|
179
|
+
mode: typeof raw.mode === "string" ? raw.mode : DEFAULT_JEV_MODE,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
91
183
|
/**
|
|
92
184
|
* Create `jev.json` for the Cloud provider unless one exists. Never throws and
|
|
93
185
|
* never replaces a file.
|
package/src/hooks/manager.ts
CHANGED
|
@@ -32,7 +32,9 @@ import { getInstanceId, hashToId } from "../../lib/telemetry-id";
|
|
|
32
32
|
import { CliError } from "../cli-error";
|
|
33
33
|
import { hookLogWarn } from "./hook-logger";
|
|
34
34
|
import { customPoliciesDir } from "./fp-home";
|
|
35
|
-
import {
|
|
35
|
+
import { listActiveCloudManagedPolicies, readCloudJevState, type CloudJevMode } from "./cloud-managed-policies";
|
|
36
|
+
import { readCloudLoadChecked, readCloudPolicyErrors } from "./cloud-policy-errors";
|
|
37
|
+
import { readRosterLabels } from "./agent-roster";
|
|
36
38
|
import { CORE_SOURCE, addPack, setPackPolicyEnabled } from "./pack-store";
|
|
37
39
|
import type { ResolvedPack } from "./pack-manifest";
|
|
38
40
|
import { hasInstalledRegexPacks, readInstalledPacks } from "./pack-manifest";
|
|
@@ -363,7 +365,7 @@ export function notEnforcingReason(cwd?: string): NotEnforcingReason | null {
|
|
|
363
365
|
|
|
364
366
|
// Cloud-managed policies, pushed from a deployment.
|
|
365
367
|
try {
|
|
366
|
-
for (const artifact of
|
|
368
|
+
for (const artifact of listActiveCloudManagedPolicies()) {
|
|
367
369
|
if (artifact.effect === "observe") observing = true;
|
|
368
370
|
else return null;
|
|
369
371
|
}
|
|
@@ -409,7 +411,7 @@ export function enforcingPolicyCount(cwd?: string): { count: number; custom: boo
|
|
|
409
411
|
// An unreadable manifest counts nothing, as it enforces nothing.
|
|
410
412
|
}
|
|
411
413
|
try {
|
|
412
|
-
for (const artifact of
|
|
414
|
+
for (const artifact of listActiveCloudManagedPolicies()) {
|
|
413
415
|
if (artifact.effect !== "observe") count++;
|
|
414
416
|
}
|
|
415
417
|
} catch {
|
|
@@ -1245,7 +1247,14 @@ export interface PoliciesScreen {
|
|
|
1245
1247
|
attention: { failed: boolean; text: string; fix?: string } | null;
|
|
1246
1248
|
custom: PoliciesScreenRow[];
|
|
1247
1249
|
convention: Array<{ scope: string; rows: PoliciesScreenRow[] }>;
|
|
1248
|
-
cloud: {
|
|
1250
|
+
cloud: {
|
|
1251
|
+
deployment: number | null;
|
|
1252
|
+
rows: PoliciesScreenRow[];
|
|
1253
|
+
/** FailproofAI Cloud's Jev mode for this machine, when the deployment sets one. */
|
|
1254
|
+
jevMode?: CloudJevMode | null;
|
|
1255
|
+
/** Problems reading the deployment, each one line. */
|
|
1256
|
+
problems?: string[];
|
|
1257
|
+
} | null;
|
|
1249
1258
|
/**
|
|
1250
1259
|
* Builtins this build enforces itself because no pack is installed: the
|
|
1251
1260
|
* migration shim (`handler.ts` registers `enabledPolicies` when
|
|
@@ -1376,7 +1385,19 @@ export function renderPoliciesScreen(
|
|
|
1376
1385
|
}
|
|
1377
1386
|
if (screen.custom.length > 0) plain("Custom policies", undefined, screen.custom);
|
|
1378
1387
|
for (const { scope, rows } of screen.convention) plain("Convention policies", scope, rows);
|
|
1379
|
-
if (screen.cloud)
|
|
1388
|
+
if (screen.cloud) {
|
|
1389
|
+
const { deployment, rows, jevMode, problems } = screen.cloud;
|
|
1390
|
+
plain("Cloud-managed", deployment !== null ? `deployment ${deployment}` : undefined, rows);
|
|
1391
|
+
if (jevMode === "off") {
|
|
1392
|
+
out.push(`${INDENT}Jev mode: off, set by FailproofAI Cloud (overrides jev.json).`);
|
|
1393
|
+
} else if (jevMode) {
|
|
1394
|
+
out.push(`${INDENT}Jev mode: ${jevMode}, set by FailproofAI Cloud. Jev checks run on FailproofAI Cloud; nothing of them is installed here.`);
|
|
1395
|
+
// Jev-only Cloud policies never reach the machine (N6): say so, or an
|
|
1396
|
+
// empty section reads as "Cloud deployed nothing".
|
|
1397
|
+
out.push(`${INDENT}Jev-only Cloud policies are not listed here; see them with ${kit.cmd("fp fleet show")} or on the dashboard.`);
|
|
1398
|
+
}
|
|
1399
|
+
for (const problem of problems ?? []) out.push(kit.caution(problem));
|
|
1400
|
+
}
|
|
1380
1401
|
|
|
1381
1402
|
if (folded > 0) out.push("", `See all ${total} with ${kit.cmd("failproofai policies --all")}`);
|
|
1382
1403
|
return out;
|
|
@@ -1591,20 +1612,105 @@ export async function listHooks(cwd?: string, { all = false }: { all?: boolean }
|
|
|
1591
1612
|
// pushed to a fleet were the ones invisible to the person running the
|
|
1592
1613
|
// command on it. Read-only: they belong to the deployment, which the heading
|
|
1593
1614
|
// says, and `--uninstall <name>` cannot switch one off.
|
|
1615
|
+
//
|
|
1616
|
+
// Each policy's KIND is shown — `regex` (JS) or `both` (JS whose verdict
|
|
1617
|
+
// its own Jev checks may clear) — with the Jev check names a `both` policy
|
|
1618
|
+
// is reviewed by. Those checks, and every `jev` policy, run on FailproofAI
|
|
1619
|
+
// Cloud (CONTRACT C10): nothing of them is on this machine, so no Jev-only
|
|
1620
|
+
// policy is listed here, and the machine cannot count them.
|
|
1594
1621
|
let cloud: PoliciesScreen["cloud"] = null;
|
|
1595
1622
|
try {
|
|
1596
|
-
|
|
1597
|
-
|
|
1623
|
+
// Every assignment, agent-scoped ones included (B4): this lists the
|
|
1624
|
+
// machine's deployment, not what one hook would load.
|
|
1625
|
+
let active: ReturnType<typeof listActiveCloudManagedPolicies> = [];
|
|
1626
|
+
let jsProblem: string | null = null;
|
|
1627
|
+
try {
|
|
1628
|
+
active = listActiveCloudManagedPolicies();
|
|
1629
|
+
} catch (err) {
|
|
1630
|
+
// The Jev mode is read independently below; a machine Cloud set one on
|
|
1631
|
+
// still gets its section, with this said.
|
|
1632
|
+
jsProblem = err instanceof Error ? err.message : String(err);
|
|
1633
|
+
}
|
|
1634
|
+
let jev: ReturnType<typeof readCloudJevState> = { jevMode: null, deployment: null, errors: [] };
|
|
1635
|
+
try {
|
|
1636
|
+
jev = readCloudJevState();
|
|
1637
|
+
} catch {
|
|
1638
|
+
// Never throws by contract; guarded anyway, for the same reason as above.
|
|
1639
|
+
}
|
|
1640
|
+
// A Cloud JS policy that did not load (B5): the hook path records it in
|
|
1641
|
+
// errors.json for the deployment in force, so the row says "not loaded"
|
|
1642
|
+
// rather than ● on.
|
|
1643
|
+
const loadErrors = new Map<string, string>();
|
|
1644
|
+
try {
|
|
1645
|
+
for (const e of readCloudPolicyErrors() ?? []) {
|
|
1646
|
+
if (e.kind !== "regex" && e.kind !== "both") continue;
|
|
1647
|
+
const artifact = active.find((a) => a.id === e.id);
|
|
1648
|
+
if (artifact && (e.version === null || e.version === artifact.version)) loadErrors.set(e.id, e.message);
|
|
1649
|
+
}
|
|
1650
|
+
} catch {
|
|
1651
|
+
// No report: every row reads as the deployment says.
|
|
1652
|
+
}
|
|
1653
|
+
// Only the hook path imports Cloud JavaScript (N4): a policy no hook has
|
|
1654
|
+
// load-checked under this deployment is not yet known to load, so it is
|
|
1655
|
+
// not drawn as ● on.
|
|
1656
|
+
let loadChecked: Set<string> | null = null;
|
|
1657
|
+
try {
|
|
1658
|
+
const record = readCloudLoadChecked();
|
|
1659
|
+
loadChecked = new Set(record && record.deployment === active[0]?.deployment ? record.checked : []);
|
|
1660
|
+
} catch {
|
|
1661
|
+
loadChecked = new Set();
|
|
1662
|
+
}
|
|
1663
|
+
const labels = active.some((a) => a.agentTargets?.some((tg) => tg.instanceId)) ? readRosterLabels() : new Map<string, string>();
|
|
1664
|
+
const targetText = (targets: NonNullable<(typeof active)[number]["agentTargets"]>): string =>
|
|
1665
|
+
`for ${targets
|
|
1666
|
+
.map((tg) => (tg.instanceId ? `${tg.integration} / ${labels.get(tg.instanceId) ?? tg.instanceId}` : tg.integration))
|
|
1667
|
+
.join(", ")}`;
|
|
1668
|
+
if (active.length > 0 || jev.jevMode !== null) {
|
|
1598
1669
|
cloud = {
|
|
1599
|
-
deployment: active[0].deployment,
|
|
1600
|
-
rows: active.map((artifact) =>
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1670
|
+
deployment: active[0]?.deployment ?? jev.deployment ?? null,
|
|
1671
|
+
rows: active.map((artifact) => {
|
|
1672
|
+
// Only a `both` policy carries a server-derived reviewer list (C1).
|
|
1673
|
+
const both = artifact.authority === "reviewable" && (artifact.reviewedBy?.length ?? 0) > 0;
|
|
1674
|
+
const checks = both ? (artifact.reviewedBy ?? []).join(", ") : "";
|
|
1675
|
+
const tags = [
|
|
1676
|
+
// `observe` is evaluated and then has its verdict discarded, so the
|
|
1677
|
+
// row says so rather than reading as plain enforcement.
|
|
1678
|
+
...(artifact.effect === "observe" ? ["observe"] : []),
|
|
1679
|
+
// A plain JS policy stays the plain row it always was.
|
|
1680
|
+
...(both ? ["both"] : []),
|
|
1681
|
+
// An observe `both` has its Jev half withheld by Cloud (C9.3).
|
|
1682
|
+
...(both ? [artifact.effect === "observe" ? `${checks} (not asked while observed)` : `Jev checks: ${checks}`] : []),
|
|
1683
|
+
...(artifact.agentTargets?.length ? [targetText(artifact.agentTargets)] : []),
|
|
1684
|
+
];
|
|
1685
|
+
const failed = loadErrors.get(artifact.id);
|
|
1686
|
+
if (failed !== undefined) {
|
|
1687
|
+
return {
|
|
1688
|
+
state: "failed" as const,
|
|
1689
|
+
name: artifact.id,
|
|
1690
|
+
description: `v${artifact.version}`,
|
|
1691
|
+
tag: [...tags, `not loaded: ${failed}`].join(" · "),
|
|
1692
|
+
};
|
|
1693
|
+
}
|
|
1694
|
+
if (!loadChecked?.has(`${artifact.id}@${artifact.version}`)) {
|
|
1695
|
+
return {
|
|
1696
|
+
state: "off" as const,
|
|
1697
|
+
name: artifact.id,
|
|
1698
|
+
description: `v${artifact.version}`,
|
|
1699
|
+
tag: [...tags, "not loaded yet: it loads at the next agent tool call"].join(" · "),
|
|
1700
|
+
};
|
|
1701
|
+
}
|
|
1702
|
+
return {
|
|
1703
|
+
state: "on" as const,
|
|
1704
|
+
name: artifact.id,
|
|
1705
|
+
description: `v${artifact.version}`,
|
|
1706
|
+
...(tags.length > 0 ? { tag: tags.join(" · ") } : {}),
|
|
1707
|
+
};
|
|
1708
|
+
}),
|
|
1709
|
+
jevMode: jev.jevMode,
|
|
1710
|
+
problems: [
|
|
1711
|
+
...(jsProblem !== null ? [`The Cloud JavaScript policies could not be read, so none of them is enforcing: ${jsProblem}`] : []),
|
|
1712
|
+
...jev.errors.map((e) => `${e.id}${e.version === null ? "" : ` v${e.version}`}: ${e.message}`),
|
|
1713
|
+
],
|
|
1608
1714
|
};
|
|
1609
1715
|
}
|
|
1610
1716
|
} catch {
|
|
@@ -54,6 +54,8 @@ export interface MissingGuard {
|
|
|
54
54
|
*/
|
|
55
55
|
export const PERMANENT_LOAD_FAILURES: ReadonlySet<string> = new Set([
|
|
56
56
|
"module_not_found",
|
|
57
|
+
// A data file the policy reads at load is as missing on the next call.
|
|
58
|
+
"file_not_found",
|
|
57
59
|
"syntax_error",
|
|
58
60
|
"runtime_error",
|
|
59
61
|
"path_missing",
|
|
@@ -738,8 +738,15 @@ export function semanticQuestions(
|
|
|
738
738
|
* Per ENTRY, not per pack: one malformed question set must not take the rest of
|
|
739
739
|
* a publisher's semantic policies with it, for the same reason one malformed
|
|
740
740
|
* pack does not take the other packs with it.
|
|
741
|
+
*
|
|
742
|
+
* Exported for one reader outside this file: the shared FailproofAI Cloud
|
|
743
|
+
* fixtures test (`cloud-jev-policies.test.ts`). A Cloud Jev declaration is
|
|
744
|
+
* exactly a manifest semantic entry, and Cloud's publish validation mirrors
|
|
745
|
+
* this parser — so the test pins that both accept and refuse the same
|
|
746
|
+
* declarations, and measure their questions alike. The machine itself never
|
|
747
|
+
* parses a Cloud declaration: those checks run on FailproofAI Cloud (C10).
|
|
741
748
|
*/
|
|
742
|
-
function parsePackSemantic(packId: string, value: unknown, warnings: string[]): SemanticManifestEntry[] {
|
|
749
|
+
export function parsePackSemantic(packId: string, value: unknown, warnings: string[]): SemanticManifestEntry[] {
|
|
743
750
|
if (value === undefined) return [];
|
|
744
751
|
if (!Array.isArray(value)) {
|
|
745
752
|
warnings.push(`pack ${packId} semantic is not an array, so none of it was loaded`);
|
|
@@ -250,7 +250,11 @@ export async function evaluatePolicies(
|
|
|
250
250
|
twoTier: {
|
|
251
251
|
activity: combined.activity,
|
|
252
252
|
decidedByJev: combined.decidedByJev,
|
|
253
|
-
|
|
253
|
+
// The deciding check's origin — and, in observe mode, the origin of the
|
|
254
|
+
// check that WOULD have decided (B12), so that row names its policy too.
|
|
255
|
+
...((combined.decidedByJev || combined.observeVerdict) && review.kind === "answered" && review.origin
|
|
256
|
+
? { jevOrigin: review.origin }
|
|
257
|
+
: {}),
|
|
254
258
|
...(combined.observeVerdict ? { observeVerdict: combined.observeVerdict } : {}),
|
|
255
259
|
},
|
|
256
260
|
};
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import type { HookEventType } from "./types";
|
|
9
9
|
import type { PolicyFunction, PolicyMatcher, PolicyParamsSchema, RegisteredPolicy } from "./policy-types";
|
|
10
10
|
import { effectiveReviewerNames, forgetEffectiveReviewerNames } from "./effective-reviewers";
|
|
11
|
+
import type { AgentIdentity } from "./agent-targets";
|
|
11
12
|
import { resolvePolicyAuthority, type AuthorityDeclaration } from "./policy-authority";
|
|
12
13
|
|
|
13
14
|
const REGISTRY_KEY = "__FAILPROOFAI_POLICY_REGISTRY__";
|
|
@@ -126,14 +127,14 @@ export function getPoliciesForEvent(
|
|
|
126
127
|
}
|
|
127
128
|
|
|
128
129
|
/** `cli`: the agent this pass registers for, which scopes the Jev reviewer set. */
|
|
129
|
-
export function clearPolicies(cli?: string): void {
|
|
130
|
+
export function clearPolicies(cli?: string, agent: AgentIdentity | null = null): void {
|
|
130
131
|
const g = globalThis as GlobalWithRegistry;
|
|
131
132
|
g[REGISTRY_KEY] = [];
|
|
132
133
|
setIndexCache(null);
|
|
133
134
|
// The reviewer set describes the policies that are about to be registered, so
|
|
134
135
|
// it is rebuilt with them. Dropping it here is also what keeps one read per
|
|
135
136
|
// evaluation instead of one per policy.
|
|
136
|
-
forgetEffectiveReviewerNames(cli);
|
|
137
|
+
forgetEffectiveReviewerNames(cli, agent);
|
|
137
138
|
}
|
|
138
139
|
|
|
139
140
|
/**
|
|
@@ -55,7 +55,12 @@
|
|
|
55
55
|
* - **A session pause.** It suspends local policy for minutes, and a warning
|
|
56
56
|
* about a policy set that is coming back shortly would be noise.
|
|
57
57
|
*/
|
|
58
|
-
import {
|
|
58
|
+
import {
|
|
59
|
+
cloudAuthorityDeclaration,
|
|
60
|
+
cloudReviewerNames,
|
|
61
|
+
readActiveCloudManagedPolicies,
|
|
62
|
+
readCloudJevMode,
|
|
63
|
+
} from "./cloud-managed-policies";
|
|
59
64
|
import { jevPacks } from "./effective-reviewers";
|
|
60
65
|
import { resolve } from "node:path";
|
|
61
66
|
import { discoverPolicyFiles } from "./custom-hooks-loader";
|
|
@@ -202,9 +207,15 @@ export function surveyReviewableCoverage(cwd?: string): ReviewableCoverage {
|
|
|
202
207
|
}
|
|
203
208
|
|
|
204
209
|
try {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
210
|
+
// Exactly as `handler.ts` registers them: a `both` policy is reviewable
|
|
211
|
+
// only while FailproofAI Cloud's Jev mode asks, and then only by its own
|
|
212
|
+
// Cloud checks (`cloud:<id>/<name>`), which this machine cannot list but
|
|
213
|
+
// Cloud answers for. No mode, `off`, or an `observe` assignment: hard.
|
|
214
|
+
const mode = readCloudJevMode();
|
|
215
|
+
const assignments = readActiveCloudManagedPolicies();
|
|
216
|
+
const cloudReviewers = cloudReviewerNames(assignments, mode);
|
|
217
|
+
if (cloudReviewers.length > 0) reviewers = new Set([...(reviewers ?? []), ...cloudReviewers]);
|
|
218
|
+
for (const assignment of assignments) records.push(cloudAuthorityDeclaration(assignment, mode));
|
|
208
219
|
} catch {
|
|
209
220
|
// Same fail-open as the handler's own read of this file.
|
|
210
221
|
}
|
|
@@ -225,7 +236,12 @@ export function surveyReviewableCoverage(cwd?: string): ReviewableCoverage {
|
|
|
225
236
|
customFiles = 0;
|
|
226
237
|
}
|
|
227
238
|
|
|
228
|
-
return {
|
|
239
|
+
return {
|
|
240
|
+
...countReviewable(records, reviewers),
|
|
241
|
+
customFiles,
|
|
242
|
+
// The checks THIS machine asks; a Cloud policy's checks are FailproofAI Cloud's.
|
|
243
|
+
jevChecks: reviewers ? [...reviewers].filter((name) => !name.startsWith("cloud:")).length : 0,
|
|
244
|
+
};
|
|
229
245
|
}
|
|
230
246
|
|
|
231
247
|
/**
|