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
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cloud-policies/errors.json` — what this machine could not load from its
|
|
3
|
+
* FailproofAI Cloud deployment, for the daemon to report on its next poll
|
|
4
|
+
* (`policyErrors`, CONTRACT C4–C6).
|
|
5
|
+
*
|
|
6
|
+
* Nothing here changes a verdict. Cloud policies are read fail-open: a JS
|
|
7
|
+
* policy that fails to import costs that one policy on this machine and
|
|
8
|
+
* nothing else, which is the right trade on the hook path and the wrong thing
|
|
9
|
+
* to keep quiet about. Before this file the only trace was a line in the local
|
|
10
|
+
* hook log, so a fleet page read "applied" for a deployment that was not. The
|
|
11
|
+
* same goes for FailproofAI Cloud's Jev (CONTRACT C10): a Jev mode this machine
|
|
12
|
+
* cannot act on, and an installed pack's check Cloud dropped for the question
|
|
13
|
+
* budget, are said here rather than only in a local log.
|
|
14
|
+
*
|
|
15
|
+
* ## One writer per file
|
|
16
|
+
*
|
|
17
|
+
* The CLI writes `errors.json`; the daemon keeps its own reconcile errors in
|
|
18
|
+
* `daemon-errors.json` and merges the two onto the wire. Neither writes the
|
|
19
|
+
* other's file, so there is no read-modify-write race between processes.
|
|
20
|
+
*
|
|
21
|
+
* ## Written on change, atomically
|
|
22
|
+
*
|
|
23
|
+
* Computed on every hook evaluation of a Cloud-managed machine, so the write
|
|
24
|
+
* has to be almost always a no-op: the new content is compared with what is on
|
|
25
|
+
* disk (and with what this process last wrote, to skip even that read in the
|
|
26
|
+
* warm worker) and written only when it differs — tmp file + rename, owner-only,
|
|
27
|
+
* so the daemon never reads half a file.
|
|
28
|
+
*
|
|
29
|
+
* A machine that never had a problem never gets the file at all: an empty list
|
|
30
|
+
* is written only to REPLACE a non-empty one, which is what clears the report
|
|
31
|
+
* on the server. That keeps the poll parameter absent on a healthy fleet.
|
|
32
|
+
*/
|
|
33
|
+
import { randomUUID } from "node:crypto";
|
|
34
|
+
import { chmodSync, existsSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
35
|
+
import { homedir } from "node:os";
|
|
36
|
+
import { resolve } from "node:path";
|
|
37
|
+
import {
|
|
38
|
+
CLOUD_POLICY_ERRORS_FILE,
|
|
39
|
+
JEV_BUDGET_FILE,
|
|
40
|
+
cloudManagedPolicyRoot,
|
|
41
|
+
type CloudJevState,
|
|
42
|
+
type CloudManagedPolicyArtifact,
|
|
43
|
+
type CloudPolicyError,
|
|
44
|
+
type CloudPolicyErrorKind,
|
|
45
|
+
} from "./cloud-managed-policies";
|
|
46
|
+
import type { PolicyLoadFailure } from "./custom-hooks-loader";
|
|
47
|
+
import { packsRoot } from "./pack-manifest";
|
|
48
|
+
|
|
49
|
+
export type { CloudPolicyError, CloudPolicyErrorKind } from "./cloud-managed-policies";
|
|
50
|
+
|
|
51
|
+
/** The message the contract fixes for "Cloud set a Jev mode and this machine has no Cloud Jev credential". */
|
|
52
|
+
export const JEV_UNCONFIGURED = "jev_unconfigured";
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The message the contract fixes for "Cloud set a Jev mode on a machine
|
|
56
|
+
* connected for decisions only" (`--no-transcripts`), which never runs Jev
|
|
57
|
+
* (CONTRACT C10.2).
|
|
58
|
+
*/
|
|
59
|
+
export const TRANSCRIPTS_DISABLED = "transcripts_disabled";
|
|
60
|
+
|
|
61
|
+
/** How an installed pack's check FailproofAI Cloud dropped for the question budget is reported (C10.5). */
|
|
62
|
+
export const JEV_BUDGET = "jev_budget";
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* How an installed pack's check is reported when FailproofAI Cloud dropped it
|
|
66
|
+
* because one of the org's Cloud checks has the same name (Cloud wins the name,
|
|
67
|
+
* D-S-2). It is not a budget problem, and its remedy differs.
|
|
68
|
+
*/
|
|
69
|
+
export const JEV_NAME_CLASH = "jev_name_clash";
|
|
70
|
+
|
|
71
|
+
/** Is `e` one of the pack-check drops `jev-budget.json` records? */
|
|
72
|
+
export function isPackDropEntry(e: Pick<CloudPolicyError, "id" | "message">): boolean {
|
|
73
|
+
return e.id.startsWith("pack:") && (e.message.startsWith(JEV_BUDGET) || e.message.startsWith(JEV_NAME_CLASH));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* A message with no local path in it (CONTRACT C9.5): the home directory
|
|
78
|
+
* becomes `~`, and any other absolute path becomes its last segment.
|
|
79
|
+
*
|
|
80
|
+
* The report leaves the machine, and a path names the user — the home-relative
|
|
81
|
+
* artifact path in a missing-artifact message, a loader's temp path in an
|
|
82
|
+
* import error, the `chmod 600 <path>` hint of a refused `jev.json`. The daemon
|
|
83
|
+
* applies the same rule again on the way out (`redact_local_paths` in
|
|
84
|
+
* `cloud_client.rs`, whose tests pin the same cases), so a report never carries
|
|
85
|
+
* a username whichever side wrote it. The full text stays in the local hook
|
|
86
|
+
* log, where it is useful and goes nowhere.
|
|
87
|
+
*
|
|
88
|
+
* A path starts at a `/` that begins the text or follows whitespace, a quote,
|
|
89
|
+
* an opening bracket, `=`, `,` or `:` — but not a URL's `//host` after `:`,
|
|
90
|
+
* and never a `/` following any other character, so a URL (`https://host/path`)
|
|
91
|
+
* and a relative path (`a/b`) are left alone while `file:///tmp/x` and
|
|
92
|
+
* `open:/etc/x` are not — and runs to the next whitespace, quote, closing
|
|
93
|
+
* bracket, `,` or `;`.
|
|
94
|
+
*/
|
|
95
|
+
export function redactLocalPaths(message: string, home: string | null = safeHomedir()): string {
|
|
96
|
+
let text = message;
|
|
97
|
+
const base = home?.replace(/\/+$/, "") ?? "";
|
|
98
|
+
if (base.length > 1) {
|
|
99
|
+
let out = "";
|
|
100
|
+
let rest = text;
|
|
101
|
+
for (let at = rest.indexOf(base); at >= 0; at = rest.indexOf(base)) {
|
|
102
|
+
const next = rest.charAt(at + base.length);
|
|
103
|
+
// `/home/al` must not match inside `/home/alice`.
|
|
104
|
+
const whole = next === "" || next === "/" || next === ":" || PATH_END.test(next);
|
|
105
|
+
out += rest.slice(0, at) + (whole ? "~" : base);
|
|
106
|
+
rest = rest.slice(at + base.length);
|
|
107
|
+
}
|
|
108
|
+
text = out + rest;
|
|
109
|
+
}
|
|
110
|
+
// `:(?!\/\/(?!\/))`: a `:` not followed by a URL's `//host` — `scheme://host`
|
|
111
|
+
// stays, while `file:///path` and `x:/path` are paths.
|
|
112
|
+
return text.replace(/(^|[\s"'`(\[<{=,]|:(?!\/\/(?!\/)))(\/[^\s"'`)\]>},;]*)/g, (_m, lead: string, path: string) => {
|
|
113
|
+
const last = path.replace(/\/+$/, "").split("/").pop() ?? "";
|
|
114
|
+
return lead + (last === "" ? "/" : last);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const PATH_END = /[\s"'`)\]>},;]/;
|
|
119
|
+
|
|
120
|
+
function safeHomedir(): string | null {
|
|
121
|
+
try {
|
|
122
|
+
return homedir();
|
|
123
|
+
} catch {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function cloudPolicyErrorsPath(): string {
|
|
129
|
+
return resolve(cloudManagedPolicyRoot(), CLOUD_POLICY_ERRORS_FILE);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const KINDS: ReadonlySet<string> = new Set<CloudPolicyErrorKind>(["regex", "jev", "both", "daemon"]);
|
|
133
|
+
|
|
134
|
+
/** The file as the CLI last wrote it, or null when absent or unreadable. */
|
|
135
|
+
export function readCloudPolicyErrors(): CloudPolicyError[] | null {
|
|
136
|
+
try {
|
|
137
|
+
const raw = JSON.parse(readFileSync(cloudPolicyErrorsPath(), "utf8")) as { errors?: unknown };
|
|
138
|
+
if (!Array.isArray(raw.errors)) return null;
|
|
139
|
+
return raw.errors.filter(
|
|
140
|
+
(e): e is CloudPolicyError =>
|
|
141
|
+
!!e &&
|
|
142
|
+
typeof e === "object" &&
|
|
143
|
+
typeof (e as CloudPolicyError).id === "string" &&
|
|
144
|
+
typeof (e as CloudPolicyError).message === "string" &&
|
|
145
|
+
KINDS.has((e as CloudPolicyError).kind) &&
|
|
146
|
+
((e as CloudPolicyError).version === null || Number.isSafeInteger((e as CloudPolicyError).version)),
|
|
147
|
+
);
|
|
148
|
+
} catch {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Text this process last wrote, so the warm worker's steady state reads nothing. */
|
|
154
|
+
let lastWritten: { path: string; text: string } | null = null;
|
|
155
|
+
|
|
156
|
+
/** Tests only. */
|
|
157
|
+
export function _resetCloudPolicyErrorsCacheForTest(): void {
|
|
158
|
+
lastWritten = null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function serialize(errors: ReadonlyArray<CloudPolicyError>): string {
|
|
162
|
+
// Field order fixed, so equal lists are equal text. Redacted here as well as
|
|
163
|
+
// in `collectCloudPolicyErrors`: this is the one way into the file.
|
|
164
|
+
const list = errors.map((e) => ({ id: e.id, version: e.version, kind: e.kind, message: redactLocalPaths(e.message) }));
|
|
165
|
+
return `${JSON.stringify({ errors: list }, null, 2)}\n`;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Replace `errors.json` with `errors` when that changes it. Never throws.
|
|
170
|
+
*
|
|
171
|
+
* - `"skipped"`: nothing to report and no file to clear, or no deployment here
|
|
172
|
+
* (no `active.json` — a disconnected or never-managed machine gets no file).
|
|
173
|
+
* - `"unchanged"`: the file already says exactly this.
|
|
174
|
+
* - `"written"`: it did not, and now does.
|
|
175
|
+
* - `"failed"`: the write itself failed (logged nowhere: the next event retries).
|
|
176
|
+
*/
|
|
177
|
+
export function writeCloudPolicyErrors(errors: ReadonlyArray<CloudPolicyError>): "written" | "unchanged" | "skipped" | "failed" {
|
|
178
|
+
try {
|
|
179
|
+
const root = cloudManagedPolicyRoot();
|
|
180
|
+
if (!existsSync(resolve(root, "active.json"))) return "skipped";
|
|
181
|
+
const path = cloudPolicyErrorsPath();
|
|
182
|
+
const text = serialize(errors);
|
|
183
|
+
if (lastWritten && lastWritten.path === path && lastWritten.text === text && existsSync(path)) return "unchanged";
|
|
184
|
+
let current: string | null = null;
|
|
185
|
+
try {
|
|
186
|
+
current = readFileSync(path, "utf8");
|
|
187
|
+
} catch {
|
|
188
|
+
current = null;
|
|
189
|
+
}
|
|
190
|
+
if (current === text) {
|
|
191
|
+
lastWritten = { path, text };
|
|
192
|
+
return "unchanged";
|
|
193
|
+
}
|
|
194
|
+
if (current === null && errors.length === 0) return "skipped";
|
|
195
|
+
writeAtomic(path, text);
|
|
196
|
+
lastWritten = { path, text };
|
|
197
|
+
return "written";
|
|
198
|
+
} catch {
|
|
199
|
+
// A report that cannot be written must not cost a hook its answer.
|
|
200
|
+
return "failed";
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ── Which Cloud JS policies a hook has load-checked (N4) ────────────────────
|
|
205
|
+
//
|
|
206
|
+
// `failproofai policies` must not draw a Cloud policy as ● on before any hook
|
|
207
|
+
// has imported it: only the hook path loads Cloud JavaScript, and only the hook
|
|
208
|
+
// path writes `errors.json`, so right after a deployment a broken policy has
|
|
209
|
+
// no error yet. The hook path records here which `id@version`s of which
|
|
210
|
+
// deployment it has load-checked (loaded, or failed into `errors.json`); the
|
|
211
|
+
// listing shows the rest as not loaded yet. Union across hooks, since an
|
|
212
|
+
// agent-scoped policy is only ever loaded by its own agent's hooks.
|
|
213
|
+
|
|
214
|
+
export const CLOUD_LOAD_CHECKED_FILE = "load-checked.json";
|
|
215
|
+
|
|
216
|
+
export interface CloudLoadChecked {
|
|
217
|
+
deployment: number;
|
|
218
|
+
checked: string[];
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export function cloudLoadCheckedPath(): string {
|
|
222
|
+
return resolve(cloudManagedPolicyRoot(), CLOUD_LOAD_CHECKED_FILE);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** The record, or null when absent or unreadable. */
|
|
226
|
+
export function readCloudLoadChecked(): CloudLoadChecked | null {
|
|
227
|
+
try {
|
|
228
|
+
const raw = JSON.parse(readFileSync(cloudLoadCheckedPath(), "utf8")) as Record<string, unknown>;
|
|
229
|
+
if (!Number.isSafeInteger(raw.deployment) || !Array.isArray(raw.checked)) return null;
|
|
230
|
+
return { deployment: raw.deployment as number, checked: raw.checked.filter((c): c is string => typeof c === "string") };
|
|
231
|
+
} catch {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** Add `policies` to the record for `deployment` (a new deployment starts afresh). Never throws; writes only on change. */
|
|
237
|
+
export function recordCloudLoadChecked(deployment: number, policies: ReadonlyArray<{ id: string; version: number }>): void {
|
|
238
|
+
try {
|
|
239
|
+
if (!existsSync(resolve(cloudManagedPolicyRoot(), "active.json"))) return;
|
|
240
|
+
const path = cloudLoadCheckedPath();
|
|
241
|
+
const prior = readCloudLoadChecked();
|
|
242
|
+
const base = prior && prior.deployment === deployment ? prior.checked : [];
|
|
243
|
+
const next = [...new Set([...base, ...policies.map((p) => `${p.id}@${p.version}`)])].sort();
|
|
244
|
+
if (prior && prior.deployment === deployment && next.length === base.length) return;
|
|
245
|
+
const text = `${JSON.stringify({ deployment, checked: next }, null, 2)}\n`;
|
|
246
|
+
writeAtomic(path, text);
|
|
247
|
+
} catch {
|
|
248
|
+
// A record that cannot be written costs only the listing's accuracy.
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export interface CloudPolicyErrorInputs {
|
|
253
|
+
/** `readActiveCloudManagedPolicies` threw: the whole JS half is not enforcing. */
|
|
254
|
+
manifestError?: string | null;
|
|
255
|
+
/** What the JS reader returned. */
|
|
256
|
+
jsPolicies: ReadonlyArray<CloudManagedPolicyArtifact>;
|
|
257
|
+
/** Import failures by Cloud policy id (`LoadAllResult.cloudFailures`). */
|
|
258
|
+
jsFailures?: ReadonlyMap<string, PolicyLoadFailure>;
|
|
259
|
+
/** Cloud's Jev state (its own problems — an unreadable mode — are in `errors`). */
|
|
260
|
+
jev: Pick<CloudJevState, "errors">;
|
|
261
|
+
/**
|
|
262
|
+
* Why Cloud's `observe`/`enforce` mode cannot run here: `transcripts_disabled`,
|
|
263
|
+
* `jev_unconfigured`, or `jev_unconfigured: <detail>`
|
|
264
|
+
* (`loadJevConfigForCloudMode`). Null when it runs, or Cloud's mode does not ask.
|
|
265
|
+
*/
|
|
266
|
+
jevProblem?: string | null;
|
|
267
|
+
/** Installed packs' checks FailproofAI Cloud dropped for the budget ({@link readJevBudgetDrops}). */
|
|
268
|
+
budgetDrops?: ReadonlyArray<CloudPolicyError>;
|
|
269
|
+
/** FailproofAI Cloud Jev rate-limited or unavailable here (`semantic/cloud-jev-health.ts`). */
|
|
270
|
+
health?: ReadonlyArray<CloudPolicyError>;
|
|
271
|
+
/** Schema-3 deployment, but the running hook could not identify its agent. */
|
|
272
|
+
agentScopeUnresolved?: boolean;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* A Cloud JS assignment's kind, as far as this machine can tell: `both` when
|
|
277
|
+
* the server derived a reviewer list for it (only a `both` policy gets one,
|
|
278
|
+
* CONTRACT C1), else `regex`.
|
|
279
|
+
*/
|
|
280
|
+
function kindOf(policy: Pick<CloudManagedPolicyArtifact, "authority" | "reviewedBy">): CloudPolicyErrorKind {
|
|
281
|
+
return policy.authority === "reviewable" && (policy.reviewedBy?.length ?? 0) > 0 ? "both" : "regex";
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Everything wrong with this machine's Cloud deployment, as `errors.json`
|
|
286
|
+
* entries: deduplicated, in a stable order. Pure.
|
|
287
|
+
*
|
|
288
|
+
* What is NOT here any more (CONTRACT C10): Jev artifact and declaration
|
|
289
|
+
* failures and a `reviewedBy` naming a missing check — the machine holds no
|
|
290
|
+
* Cloud Jev check to fail, and cannot tell which names Cloud has. A `both`
|
|
291
|
+
* policy on a machine whose Cloud mode does not ask simply stays hard; the
|
|
292
|
+
* server knows the mode it set.
|
|
293
|
+
*/
|
|
294
|
+
export function collectCloudPolicyErrors(input: CloudPolicyErrorInputs): CloudPolicyError[] {
|
|
295
|
+
const out: CloudPolicyError[] = [];
|
|
296
|
+
if (input.manifestError) {
|
|
297
|
+
out.push({ id: "active.json", version: null, kind: "daemon", message: `Cloud policies could not be loaded: ${input.manifestError}` });
|
|
298
|
+
}
|
|
299
|
+
if (input.agentScopeUnresolved) {
|
|
300
|
+
out.push({
|
|
301
|
+
id: "agentScope", version: null, kind: "daemon",
|
|
302
|
+
message: "agent_scope_unresolved: this hook's agent profile is unknown; targeted Cloud policies did not match",
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
for (const policy of input.jsPolicies) {
|
|
306
|
+
const failure = input.jsFailures?.get(policy.id);
|
|
307
|
+
if (failure) {
|
|
308
|
+
out.push({ id: policy.id, version: policy.version, kind: kindOf(policy), message: `policy did not load (${failure.type}): ${failure.reason}` });
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
out.push(...input.jev.errors);
|
|
312
|
+
out.push(...(input.budgetDrops ?? []));
|
|
313
|
+
if (input.jevProblem) {
|
|
314
|
+
out.push({ id: "jevMode", version: null, kind: "daemon", message: input.jevProblem });
|
|
315
|
+
}
|
|
316
|
+
out.push(...(input.health ?? []));
|
|
317
|
+
|
|
318
|
+
const seen = new Set<string>();
|
|
319
|
+
return out
|
|
320
|
+
.map((e) => ({ ...e, message: redactLocalPaths(e.message) }))
|
|
321
|
+
.filter((e) => {
|
|
322
|
+
const key = `${e.id}\u0000${e.version}\u0000${e.kind}\u0000${e.message}`;
|
|
323
|
+
if (seen.has(key)) return false;
|
|
324
|
+
seen.add(key);
|
|
325
|
+
return true;
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// ── Installed packs' checks FailproofAI Cloud dropped for the budget ─────────
|
|
330
|
+
//
|
|
331
|
+
// FailproofAI Cloud puts its own checks first in the one question budget and
|
|
332
|
+
// drops whole installed-pack question groups, last first, when the two do not
|
|
333
|
+
// fit together (CONTRACT C10.4 step 5); its reply names them (`droppedLocal`).
|
|
334
|
+
// Which groups a call carries depends on the tool, so a report of only the
|
|
335
|
+
// latest reply's drops would flap from call to call. So the drops are kept,
|
|
336
|
+
// as a union, in `jev-budget.json` for the machine, deployment and Jev mode
|
|
337
|
+
// they happened under — a new deployment or mode starts afresh, which is how
|
|
338
|
+
// a drop that no longer happens stops being reported — and `errors.json`
|
|
339
|
+
// carries them as `{id: "pack:<packId>", kind: "daemon", message: "jev_budget:
|
|
340
|
+
// dropped <name>"}`. A check dropped because an org Cloud check has its name
|
|
341
|
+
// is recorded the same way, as `jev_name_clash: <name> (the FailproofAI Cloud
|
|
342
|
+
// check is used)`. A drop of a pack no longer installed is not reported, here
|
|
343
|
+
// or by the daemon's poll, which also drops the report once the deployment it
|
|
344
|
+
// was recorded under is no longer the active one.
|
|
345
|
+
|
|
346
|
+
/** What a set of budget drops is keyed by: they are true of this deployment only. */
|
|
347
|
+
export interface JevBudgetKey {
|
|
348
|
+
machineId: string;
|
|
349
|
+
deployment: number | null;
|
|
350
|
+
jevMode: "observe" | "enforce";
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/** One dropped pack check; `clash` when Cloud dropped it for a same-named Cloud check. */
|
|
354
|
+
export interface JevPackDrop {
|
|
355
|
+
packId: string;
|
|
356
|
+
name: string;
|
|
357
|
+
clash?: true;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
interface JevBudgetRecord extends JevBudgetKey {
|
|
361
|
+
dropped: JevPackDrop[];
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
export function jevBudgetPath(): string {
|
|
365
|
+
return resolve(cloudManagedPolicyRoot(), JEV_BUDGET_FILE);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function readJevBudgetRecord(): JevBudgetRecord | null {
|
|
369
|
+
try {
|
|
370
|
+
const raw = JSON.parse(readFileSync(jevBudgetPath(), "utf8")) as Partial<JevBudgetRecord>;
|
|
371
|
+
if (
|
|
372
|
+
typeof raw.machineId !== "string" ||
|
|
373
|
+
!(raw.deployment === null || Number.isSafeInteger(raw.deployment)) ||
|
|
374
|
+
(raw.jevMode !== "observe" && raw.jevMode !== "enforce") ||
|
|
375
|
+
!Array.isArray(raw.dropped)
|
|
376
|
+
) {
|
|
377
|
+
return null;
|
|
378
|
+
}
|
|
379
|
+
const dropped = raw.dropped
|
|
380
|
+
.filter((d): d is JevPackDrop => !!d && typeof d.packId === "string" && typeof d.name === "string")
|
|
381
|
+
.map((d) => ({ packId: d.packId, name: d.name, ...(d.clash === true ? { clash: true as const } : {}) }));
|
|
382
|
+
return { machineId: raw.machineId, deployment: raw.deployment as number | null, jevMode: raw.jevMode, dropped };
|
|
383
|
+
} catch {
|
|
384
|
+
return null;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
const sameKey = (a: JevBudgetKey, b: JevBudgetKey): boolean =>
|
|
389
|
+
a.machineId === b.machineId && a.deployment === b.deployment && a.jevMode === b.jevMode;
|
|
390
|
+
|
|
391
|
+
const dropKey = (d: JevPackDrop): string => `${d.packId}\u0000${d.name}\u0000${d.clash === true}`;
|
|
392
|
+
|
|
393
|
+
function budgetEntries(dropped: ReadonlyArray<JevPackDrop>): CloudPolicyError[] {
|
|
394
|
+
return [...dropped]
|
|
395
|
+
.sort((a, b) => (dropKey(a) < dropKey(b) ? -1 : dropKey(a) > dropKey(b) ? 1 : 0))
|
|
396
|
+
.map((d) => ({
|
|
397
|
+
id: `pack:${d.packId}`,
|
|
398
|
+
version: null,
|
|
399
|
+
kind: "daemon" as const,
|
|
400
|
+
message: d.clash ? `${JEV_NAME_CLASH}: ${d.name} (the FailproofAI Cloud check is used)` : `${JEV_BUDGET}: dropped ${d.name}`,
|
|
401
|
+
}));
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* The ids of the installed packs, read straight off `installed.json` (no
|
|
406
|
+
* artifact is verified: only the ids are wanted). An empty set when no pack is
|
|
407
|
+
* installed; null when the file exists and cannot be read, which filters
|
|
408
|
+
* nothing ("cannot tell" is not "not installed"). Never throws.
|
|
409
|
+
*/
|
|
410
|
+
export function installedPackIds(): ReadonlySet<string> | null {
|
|
411
|
+
try {
|
|
412
|
+
const path = resolve(packsRoot(), "installed.json");
|
|
413
|
+
if (!existsSync(path)) return new Set();
|
|
414
|
+
const raw = JSON.parse(readFileSync(path, "utf8")) as { packs?: unknown };
|
|
415
|
+
if (!Array.isArray(raw.packs)) return null;
|
|
416
|
+
return new Set(
|
|
417
|
+
raw.packs.map((p) => (p && typeof p === "object" ? (p as { id?: unknown }).id : null)).filter((id): id is string => typeof id === "string"),
|
|
418
|
+
);
|
|
419
|
+
} catch {
|
|
420
|
+
return null;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* The drops recorded for exactly this machine, deployment and mode, as
|
|
426
|
+
* `errors.json` entries — none for any other key, and none of a pack that is
|
|
427
|
+
* no longer installed (`installed`, when known). Never throws.
|
|
428
|
+
*/
|
|
429
|
+
export function readJevBudgetDrops(key: JevBudgetKey, installed: ReadonlySet<string> | null = null): CloudPolicyError[] {
|
|
430
|
+
const record = readJevBudgetRecord();
|
|
431
|
+
if (!record || !sameKey(record, key)) return [];
|
|
432
|
+
return budgetEntries(installed ? record.dropped.filter((d) => installed.has(d.packId)) : record.dropped);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Add the pack checks FailproofAI Cloud just dropped to the record for `key`
|
|
437
|
+
* (starting afresh when the key changed), and to `errors.json` at once, so the
|
|
438
|
+
* report does not wait for the next hook. Both writes are atomic, owner-only,
|
|
439
|
+
* and happen only when something changed. Never throws: a report must not
|
|
440
|
+
* cost a hook its answer.
|
|
441
|
+
*/
|
|
442
|
+
export function recordJevBudgetDrops(key: JevBudgetKey, drops: ReadonlyArray<JevPackDrop>): void {
|
|
443
|
+
try {
|
|
444
|
+
if (drops.length === 0 || !existsSync(resolve(cloudManagedPolicyRoot(), "active.json"))) return;
|
|
445
|
+
const current = readJevBudgetRecord();
|
|
446
|
+
const base = current && sameKey(current, key) ? current.dropped : [];
|
|
447
|
+
const seen = new Set(base.map(dropKey));
|
|
448
|
+
const added: JevPackDrop[] = [];
|
|
449
|
+
for (const d of drops) {
|
|
450
|
+
const id = dropKey(d);
|
|
451
|
+
if (seen.has(id)) continue;
|
|
452
|
+
seen.add(id);
|
|
453
|
+
added.push({ packId: d.packId, name: d.name, ...(d.clash === true ? { clash: true as const } : {}) });
|
|
454
|
+
}
|
|
455
|
+
if (current && sameKey(current, key) && added.length === 0) return;
|
|
456
|
+
const record: JevBudgetRecord = { ...key, dropped: [...base, ...added] };
|
|
457
|
+
writeAtomic(jevBudgetPath(), `${JSON.stringify(record, null, 2)}\n`);
|
|
458
|
+
// Merged into the report as it stands: every other entry kept, the pack
|
|
459
|
+
// budget drops replaced by this deployment's.
|
|
460
|
+
const report = (readCloudPolicyErrors() ?? []).filter((e) => !isPackDropEntry(e));
|
|
461
|
+
writeCloudPolicyErrors([...report, ...budgetEntries(record.dropped)]);
|
|
462
|
+
} catch {
|
|
463
|
+
// The next event records it again.
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
function writeAtomic(path: string, text: string): void {
|
|
468
|
+
const tmp = `${path}.tmp-${process.pid}-${randomUUID()}`;
|
|
469
|
+
try {
|
|
470
|
+
writeFileSync(tmp, text, { mode: 0o600, flag: "wx" });
|
|
471
|
+
chmodSync(tmp, 0o600);
|
|
472
|
+
renameSync(tmp, path);
|
|
473
|
+
} catch (err) {
|
|
474
|
+
try {
|
|
475
|
+
rmSync(tmp, { force: true });
|
|
476
|
+
} catch {
|
|
477
|
+
// Nothing useful to do.
|
|
478
|
+
}
|
|
479
|
+
throw err;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
@@ -578,7 +578,7 @@ export function renderStatusScreen(facts: StatusFacts, opts: ScreenKitOpts & { c
|
|
|
578
578
|
`${pauseClockTime(pause.expiresAt, opts.clock)}${pause.cwd ? `${kit.sep}${pause.cwd}` : ""}`,
|
|
579
579
|
]),
|
|
580
580
|
// An enforcement fact, not fine print: a pause suspends local policy only.
|
|
581
|
-
...(facts.pauses.length > 0 ? [["", "Cloud-managed policies keep enforcing."] as [string, string]] : []),
|
|
581
|
+
...(facts.pauses.length > 0 ? [["", "Cloud-managed policies, and FailproofAI Cloud's Jev checks, keep enforcing."] as [string, string]] : []),
|
|
582
582
|
];
|
|
583
583
|
|
|
584
584
|
const cloudRows: Array<[string, string]> =
|
|
@@ -176,7 +176,7 @@ async function importWithDeadline(fileUrl: string): Promise<void> {
|
|
|
176
176
|
* Does NOT clear the registry — caller is responsible for that.
|
|
177
177
|
*/
|
|
178
178
|
export interface PolicyLoadFailure {
|
|
179
|
-
type: "module_not_found" | "syntax_error" | "load_timeout" | "runtime_error" | "path_missing";
|
|
179
|
+
type: "module_not_found" | "file_not_found" | "syntax_error" | "load_timeout" | "runtime_error" | "path_missing";
|
|
180
180
|
reason: string;
|
|
181
181
|
}
|
|
182
182
|
|
|
@@ -250,8 +250,13 @@ async function loadSingleFile(
|
|
|
250
250
|
return null;
|
|
251
251
|
} catch (err) {
|
|
252
252
|
const msg = err instanceof Error ? err.message : String(err);
|
|
253
|
-
|
|
253
|
+
// An import that names no module, apart from a file the policy itself
|
|
254
|
+
// reads at load (a `readFileSync` of its data): both are ENOENT underneath,
|
|
255
|
+
// but "module not found" sent people looking for a missing package (B13).
|
|
256
|
+
const errorType = /Cannot find module|MODULE_NOT_FOUND|Cannot find package/i.test(msg)
|
|
254
257
|
? "module_not_found"
|
|
258
|
+
: /ENOENT/i.test(msg)
|
|
259
|
+
? "file_not_found"
|
|
255
260
|
: /SyntaxError|Unexpected token/i.test(msg)
|
|
256
261
|
? "syntax_error"
|
|
257
262
|
: /timed out loading module/i.test(msg)
|
|
@@ -334,6 +339,13 @@ export interface LoadAllResult {
|
|
|
334
339
|
* Only present for a path more than one pack resolved to.
|
|
335
340
|
*/
|
|
336
341
|
packAliases: Map<string, string[]>;
|
|
342
|
+
/**
|
|
343
|
+
* Import failures of FailproofAI Cloud JS policies, keyed by Cloud policy id
|
|
344
|
+
* (every id behind a shared artifact). Fail-open like the rest of the Cloud
|
|
345
|
+
* read — nothing denies over them — but reported to Cloud in `errors.json`,
|
|
346
|
+
* so a deployment that is not actually enforcing says so.
|
|
347
|
+
*/
|
|
348
|
+
cloudFailures?: Map<string, PolicyLoadFailure>;
|
|
337
349
|
}
|
|
338
350
|
|
|
339
351
|
export function customPolicyId(file: string, name: string): string {
|
|
@@ -456,8 +468,12 @@ export async function loadAllCustomHooks(
|
|
|
456
468
|
// codebase exists to remove. It is also announced, so an operator can give the
|
|
457
469
|
// two policies distinguishable source instead of living with the merge.
|
|
458
470
|
const cloudManagedByPath = new Map<string, CloudManagedPolicyArtifact>();
|
|
471
|
+
/** Every Cloud policy id behind each artifact path, for `cloudFailures`. */
|
|
472
|
+
const cloudIdsByPath = new Map<string, string[]>();
|
|
473
|
+
const cloudFailures = new Map<string, PolicyLoadFailure>();
|
|
459
474
|
for (const policy of opts?.cloudManagedPolicies ?? []) {
|
|
460
475
|
const key = resolve(policy.path);
|
|
476
|
+
cloudIdsByPath.set(key, [...(cloudIdsByPath.get(key) ?? []), policy.id]);
|
|
461
477
|
const existing = cloudManagedByPath.get(key);
|
|
462
478
|
if (!existing) {
|
|
463
479
|
cloudManagedByPath.set(key, policy);
|
|
@@ -660,6 +676,9 @@ export async function loadAllCustomHooks(
|
|
|
660
676
|
if (failure && pack) {
|
|
661
677
|
for (const id of packIdsByPath.get(absPath) ?? [pack.id]) packFailures.set(id, failure);
|
|
662
678
|
}
|
|
679
|
+
if (failure && cloudManaged) {
|
|
680
|
+
for (const id of cloudIdsByPath.get(absPath) ?? [cloudManaged.id]) cloudFailures.set(id, failure);
|
|
681
|
+
}
|
|
663
682
|
for (const hook of getCustomHooks().slice(hooksBefore)) {
|
|
664
683
|
const tagged = hook as CustomHook & {
|
|
665
684
|
__policyId?: string;
|
|
@@ -680,6 +699,10 @@ export async function loadAllCustomHooks(
|
|
|
680
699
|
}
|
|
681
700
|
} else {
|
|
682
701
|
hookLogWarn(`custom policy path not found: ${absPath}`);
|
|
702
|
+
if (cloudManaged) {
|
|
703
|
+
const missing = { type: "path_missing", reason: `path missing: ${absPath}` } as const;
|
|
704
|
+
for (const id of cloudIdsByPath.get(absPath) ?? [cloudManaged.id]) cloudFailures.set(id, missing);
|
|
705
|
+
}
|
|
683
706
|
if (pack) {
|
|
684
707
|
const missing = { type: "path_missing", reason: `path missing: ${absPath}` } as const;
|
|
685
708
|
for (const id of packIdsByPath.get(absPath) ?? [pack.id]) packFailures.set(id, missing);
|
|
@@ -830,5 +853,5 @@ export async function loadAllCustomHooks(
|
|
|
830
853
|
const winner = packByPath.get(path);
|
|
831
854
|
if (winner && ids.length > 1) packAliases.set(winner.id, ids);
|
|
832
855
|
}
|
|
833
|
-
return { hooks: allHooks, conventionSources, packFailures, packAliases };
|
|
856
|
+
return { hooks: allHooks, conventionSources, packFailures, packAliases, cloudFailures };
|
|
834
857
|
}
|
|
@@ -16,7 +16,7 @@ import { existsSync } from "node:fs";
|
|
|
16
16
|
import { daemonSocket as daemonSocketPath } from "./fp-home";
|
|
17
17
|
import { readConfig } from "./fp-config";
|
|
18
18
|
|
|
19
|
-
const PROTOCOL_VERSION =
|
|
19
|
+
const PROTOCOL_VERSION = 2;
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Reaching the daemon and getting an answer out of it are two different
|
|
@@ -56,6 +56,8 @@ export interface DaemonHookRequest {
|
|
|
56
56
|
* hazard.
|
|
57
57
|
*/
|
|
58
58
|
cwd?: string;
|
|
59
|
+
/** Settings path of the originating agent profile, not the daemon's. */
|
|
60
|
+
agentSettingsPath?: string;
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
export interface DaemonHookResponse {
|
|
@@ -98,6 +100,7 @@ export interface DaemonPolicyEvaluationRequest {
|
|
|
98
100
|
event: string;
|
|
99
101
|
payload: Record<string, unknown>;
|
|
100
102
|
cwd?: string;
|
|
103
|
+
agentSettingsPath?: string;
|
|
101
104
|
}
|
|
102
105
|
|
|
103
106
|
export type DaemonPolicyEvaluationAttempt =
|
|
@@ -304,6 +307,7 @@ export async function attemptDaemonHook(
|
|
|
304
307
|
cli: req.cli,
|
|
305
308
|
stdin: req.stdin,
|
|
306
309
|
cwd: req.cwd,
|
|
310
|
+
agentSettingsPath: req.agentSettingsPath,
|
|
307
311
|
},
|
|
308
312
|
opts,
|
|
309
313
|
);
|
|
@@ -338,9 +342,9 @@ function isStringArray(value: unknown): value is string[] {
|
|
|
338
342
|
|
|
339
343
|
/**
|
|
340
344
|
* Attempts the structured request used by native in-process integrations.
|
|
341
|
-
* A matching protocol version is not sufficient:
|
|
342
|
-
* `hook` but
|
|
343
|
-
*
|
|
345
|
+
* A matching protocol version is not sufficient: a broken or partial daemon
|
|
346
|
+
* may speak `hook` but not `policyEvaluation`, so only a complete, well-shaped
|
|
347
|
+
* `policyResult` proves this capability exists.
|
|
344
348
|
*/
|
|
345
349
|
export async function attemptDaemonPolicyEvaluation(
|
|
346
350
|
req: DaemonPolicyEvaluationRequest,
|
|
@@ -354,6 +358,7 @@ export async function attemptDaemonPolicyEvaluation(
|
|
|
354
358
|
event: req.event,
|
|
355
359
|
payload: req.payload,
|
|
356
360
|
cwd: req.cwd,
|
|
361
|
+
agentSettingsPath: req.agentSettingsPath,
|
|
357
362
|
},
|
|
358
363
|
opts,
|
|
359
364
|
);
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* `configure-wizard.ts` calls the functions here directly, the same
|
|
8
8
|
* relationship it already has with `manager.ts`'s `installHooks()`.
|
|
9
9
|
*/
|
|
10
|
+
import { HEALTH_PROBE_SOURCE } from "./health-probe";
|
|
10
11
|
import {
|
|
11
12
|
existsSync,
|
|
12
13
|
mkdirSync,
|
|
@@ -1030,7 +1031,7 @@ export async function probeDaemon(): Promise<DaemonProbe> {
|
|
|
1030
1031
|
cli: "claude",
|
|
1031
1032
|
stdin: JSON.stringify({
|
|
1032
1033
|
hook_event_name: "SessionStart",
|
|
1033
|
-
source:
|
|
1034
|
+
source: HEALTH_PROBE_SOURCE,
|
|
1034
1035
|
}),
|
|
1035
1036
|
},
|
|
1036
1037
|
{ responseTimeoutMs: DAEMON_PROBE_TIMEOUT_MS },
|