failproofai 1.0.7 → 1.0.8
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 +3 -3
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- 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 +4 -4
- 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 +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- 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 +4 -4
- 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 +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- 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 +8 -7
- 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.nft.json +1 -1
- 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.nft.json +1 -1
- 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.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js +9 -7
- 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 +15 -15
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +6 -6
- 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/server-reference-manifest.json +14 -14
- package/.next/standalone/.next/server/app/policies/page.js +11 -10
- 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/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js +8 -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/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 +6 -6
- 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/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +7 -6
- 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/server-reference-manifest.json +52 -8
- package/.next/standalone/.next/server/app/settings/page.js +12 -7
- 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]__1msfs-h._.js → [externals]__19_pzeq._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[externals]__1_bftcl._.js → [externals]__20kzpkf._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ttrwnd._.js +22 -0
- package/.next/standalone/.next/server/chunks/_09dz7xv._.js +21 -21
- package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0trp3yc._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1ek68ln._.js +16 -16
- package/.next/standalone/.next/server/chunks/{_1c3k-8x._.js → _1q5i8mb._.js} +2 -2
- package/.next/standalone/.next/server/chunks/lib_16xa545._.js +3 -0
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_hooks_1aveq0u._.js +5 -0
- package/.next/standalone/.next/server/chunks/src_hooks_1eem5a7._.js +3 -0
- package/.next/standalone/.next/server/chunks/src_hooks_custom-hooks-loader_ts_0lnb3n3._.js +4 -2
- package/.next/standalone/.next/server/chunks/ssr/[externals]__0ohnuzs._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01bmjsj._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__04usis8._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__02npjtd._.js → [root-of-the-server]__056wjo4._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__059yza8._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__06pflha._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0eip4_k._.js +22 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0p-5p8u._.js → [root-of-the-server]__0n0xg95._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qcb0mg._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__013jr2b._.js → [root-of-the-server]__0rwtwpm._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0yrsbd_._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0da85px._.js → [root-of-the-server]__11mayhe._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__12e7nhs._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__13d-wb6._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__13t1zkw._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__15578wp._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__19evfi8._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1dinjii._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1m_svbe._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0cxe_2_._.js → [root-of-the-server]__1mf3zp6._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0ftmoxc._.js → [root-of-the-server]__1pprgri._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1p2otjt._.js → [root-of-the-server]__1q4p5b8._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1qiz0e4._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{_166t73i._.js → _0-vcssj._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_042cgl1._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0bqoto4._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0uyu3jf._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_13kfn90._.js +23 -0
- package/.next/standalone/.next/server/chunks/ssr/{_1es2j7i._.js → _1gb0ifp._.js} +5 -5
- package/.next/standalone/.next/server/chunks/ssr/{_1_qswah._.js → _1q46vxx._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +13 -13
- package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9sni._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_settings_02tf1h4._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_0drixxt._.js → node_modules_next_dist_0w6mzq5._.js} +4 -4
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_18_d8l1._.js +151 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_0-q0umm._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_06kzv9d._.js +12 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_0g194sy._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1cv9_c4._.js +4 -2
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1kx9e0d._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_effective-reviewers_ts_1h4wtvo._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-home_ts_0je3xkv._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_pack-cli_ts_0t7me65._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_semantic_pack-policies_ts_0gh_bu_._.js +3 -0
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- 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/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +67 -23
- package/.next/standalone/.next/static/chunks/06dnzbolj00mc.js +6 -0
- package/.next/standalone/.next/static/chunks/0bhidk90e-07f.css +2 -0
- package/.next/standalone/.next/static/chunks/{2mdh397ghgnvv.js → 0m-9d6yn9hx4j.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0__8a7m868fvf.js → 0wbjy0zo-m7is.js} +1 -1
- package/.next/standalone/.next/static/chunks/16f3fa-lx38hk.js +1 -0
- package/.next/standalone/.next/static/chunks/{0o6qlkgubtoex.js → 21uv-uusw329x.js} +1 -1
- package/.next/standalone/.next/static/chunks/2g2tki08kdhie.js +1 -0
- package/.next/standalone/.next/static/chunks/2qdpj67x6ifk_.js +69 -0
- package/.next/standalone/.next/static/chunks/2qv4hshejedtx.css +1 -0
- package/.next/standalone/.next/static/chunks/3-nbtkhg9y-1j.js +1 -0
- package/.next/standalone/.next/static/chunks/355km0ihuqo1p.js +1 -0
- package/.next/standalone/.next/static/chunks/{13i7-9is-vhys.js → 3c3qbmosdjl6w.js} +1 -1
- package/.next/standalone/PROBE-FOLLOWUP.md +186 -0
- package/.next/standalone/app/actions/get-jev-config.ts +604 -0
- package/.next/standalone/app/actions/pack-actions.ts +12 -0
- package/.next/standalone/app/actions/update-jev-config.ts +569 -0
- package/.next/standalone/app/components/jev-notices.tsx +96 -0
- package/.next/standalone/app/policies/hooks-client.tsx +14 -3
- package/.next/standalone/app/settings/jev-panel.tsx +630 -0
- package/.next/standalone/app/settings/page.tsx +20 -1
- package/.next/standalone/app/settings/settings-client.tsx +27 -1
- package/.next/standalone/app/settings/settings.css +79 -0
- package/.next/standalone/fp-cloud-cli/CHANGELOG.md +22 -4
- package/.next/standalone/fp-cloud-cli/fp_cli/client.py +14 -1
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/keys_cmds.py +17 -3
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/policies_cmds.py +3 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/permissions.py +22 -0
- package/.next/standalone/fp-cloud-cli/fp_cli/policy_check.py +169 -0
- package/.next/standalone/fp-cloud-cli/skill/references/commands.md +1 -1
- package/.next/standalone/fp-cloud-cli/tests/test_keys_queries.py +65 -0
- package/.next/standalone/fp-cloud-cli/tests/test_policy_check.py +61 -0
- package/.next/standalone/package.json +10 -10
- package/.next/standalone/sdk/python/CHANGELOG.md +7 -0
- package/.next/standalone/sdk/python/failproofai_sdk/_version.py +1 -1
- package/.next/standalone/sdk/typescript/CHANGELOG.md +18 -1
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package-lock.json +0 -274
- package/.next/standalone/sdk/typescript/scripts/release.mjs +30 -0
- package/.next/standalone/server.js +1 -1
- package/README.md +3 -2
- package/bin/failproofai.mjs +148 -4
- package/dist/cli.mjs +18599 -9478
- package/dist/index.js +19 -1
- package/dist/worker.mjs +10500 -3773
- package/package.json +10 -10
- package/pi-extension/index.ts +11 -0
- package/scripts/build-policy-pack.mjs +53 -2
- package/src/audit/features.ts +3 -2
- package/src/hooks/builtin-policies.ts +195 -8
- package/src/hooks/cloud-connection.ts +190 -1
- package/src/hooks/cloud-enrollment-cli.ts +57 -8
- package/src/hooks/cloud-introspect.ts +6 -0
- package/src/hooks/cloud-managed-policies.ts +22 -0
- package/src/hooks/configure-wizard.ts +26 -6
- package/src/hooks/custom-hooks-loader.ts +98 -10
- package/src/hooks/custom-hooks-registry.ts +45 -1
- package/src/hooks/effective-reviewers.ts +243 -0
- package/src/hooks/first-run-gate.ts +5 -0
- package/src/hooks/flush-cli.ts +35 -8
- package/src/hooks/fp-config.ts +266 -1
- package/src/hooks/fp-home.ts +23 -0
- package/src/hooks/fp-reset.ts +22 -4
- package/src/hooks/handler.ts +303 -7
- package/src/hooks/hook-activity-store.ts +118 -6
- package/src/hooks/hook-telemetry.ts +41 -0
- package/src/hooks/jev-activity.ts +385 -0
- package/src/hooks/jev-cli.ts +2172 -0
- package/src/hooks/jev-cloud-connection.ts +392 -0
- package/src/hooks/loader-utils.ts +6 -0
- package/src/hooks/manager.ts +45 -7
- package/src/hooks/pack-cli.ts +568 -37
- package/src/hooks/pack-failclosed.ts +3 -0
- package/src/hooks/pack-manifest.ts +489 -7
- package/src/hooks/pack-store.ts +194 -11
- package/src/hooks/policy-authority.ts +386 -0
- package/src/hooks/policy-catalog.ts +206 -0
- package/src/hooks/policy-evaluator.ts +963 -796
- package/src/hooks/policy-registry.ts +27 -1
- package/src/hooks/policy-reviewability.ts +258 -0
- package/src/hooks/policy-types.ts +128 -0
- package/src/hooks/semantic/combine.ts +581 -0
- package/src/hooks/semantic/compile.ts +176 -0
- package/src/hooks/semantic/decide.ts +513 -0
- package/src/hooks/semantic/envelope.ts +1255 -0
- package/src/hooks/semantic/evaluator.ts +556 -0
- package/src/hooks/semantic/facts.ts +387 -0
- package/src/hooks/semantic/intent.ts +1190 -0
- package/src/hooks/semantic/jev-client.ts +1155 -0
- package/src/hooks/semantic/jev-config.ts +1142 -0
- package/src/hooks/semantic/jev-review.ts +389 -0
- package/src/hooks/semantic/jev-stats.ts +289 -0
- package/src/hooks/semantic/jev-throttle.ts +427 -0
- package/src/hooks/semantic/pack-policies.ts +294 -0
- package/src/hooks/semantic/policies.ts +597 -0
- package/src/hooks/semantic/precondition-names.ts +60 -0
- package/src/hooks/semantic/preconditions.ts +58 -0
- package/src/hooks/semantic/redact.ts +2937 -0
- package/src/hooks/semantic/session-root.ts +116 -0
- package/src/hooks/semantic/types.ts +162 -0
- package/src/hooks/semver-precedence.ts +128 -0
- package/src/hooks/tui.ts +4 -0
- package/src/hooks/types.ts +1 -1
- package/src/hooks/worker-server.ts +121 -27
- package/src/index.ts +6 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cuho4x._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1_r2rbg._.js +0 -24
- package/.next/standalone/.next/server/chunks/src_hooks_0iu54mz._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0-_ki57._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0bd3mje._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0cg-bgc._.js +0 -5
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0cpu_mj._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0u3w0ll._.js +0 -22
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17d_ffl._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__19d9tgz._.js +0 -5
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ctpynv._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1jiwfsj._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1phc187._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_06imw3p._.js +0 -5
- package/.next/standalone/.next/server/chunks/ssr/_0h_douw._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_1-i_gzc._.js +0 -23
- package/.next/standalone/.next/server/chunks/ssr/_1u8-lu2._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +0 -3
- package/.next/standalone/.next/static/chunks/094xgi4owxaqf.js +0 -1
- package/.next/standalone/.next/static/chunks/1rz20_pz828f3.js +0 -6
- package/.next/standalone/.next/static/chunks/2k9f4tyv04809.css +0 -1
- package/.next/standalone/.next/static/chunks/2klitrtzpaoe0.js +0 -1
- package/.next/standalone/.next/static/chunks/2rshywgeqsyzk.css +0 -2
- package/.next/standalone/.next/static/chunks/3pzx4chkhko9k.js +0 -1
- package/.next/standalone/.next/static/chunks/3rh5o7e16irrm.js +0 -69
- package/.next/standalone/.next/static/chunks/43ufqrz8qo3h-.js +0 -1
- /package/.next/standalone/.next/static/{PgeWCHmyVbjRznv2VO7KF → 5yKM8NoTOpUI0MoQl8eo5}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{PgeWCHmyVbjRznv2VO7KF → 5yKM8NoTOpUI0MoQl8eo5}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{PgeWCHmyVbjRznv2VO7KF → 5yKM8NoTOpUI0MoQl8eo5}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which semantic policy set this machine runs: a pack's, or the compiled-in one.
|
|
3
|
+
*
|
|
4
|
+
* ## The replacement rule
|
|
5
|
+
*
|
|
6
|
+
* A FailproofAI pack that declares at least ONE `semantic` entry replaces
|
|
7
|
+
* `SEMANTIC_POLICIES` wholesale. It mirrors the rule already in force for the
|
|
8
|
+
* regex builtins — installing a pack stops the compiled builtins registering —
|
|
9
|
+
* and it exists for the same reason: one source of truth, so a name collision
|
|
10
|
+
* between a pack's `destructive-deletion` and the builtin of that name cannot
|
|
11
|
+
* arise, and `reviewedBy: ["destructive-deletion"]` in a pack manifest cannot
|
|
12
|
+
* silently mean the builtin's question set instead of the pack's.
|
|
13
|
+
*
|
|
14
|
+
* Anyone else's checks are ADDED to the compiled-in set instead. Their names
|
|
15
|
+
* cannot collide with it (a third party's claim to a builtin name is void:
|
|
16
|
+
* `isReservedClaim`),
|
|
17
|
+
* and replacing it would drop deny-mode checks like `credential-exfiltration`
|
|
18
|
+
* that add denies the regex tier does not have — weaker, not noisier.
|
|
19
|
+
*
|
|
20
|
+
* Two packs that both declare entries CONCATENATE; a name declared by two packs
|
|
21
|
+
* keeps the first and drops the later one, because the answer map is keyed by
|
|
22
|
+
* policy name and the second would overwrite the first's questions in the
|
|
23
|
+
* compiled request.
|
|
24
|
+
*
|
|
25
|
+
* ## Where the manifest ends and this begins
|
|
26
|
+
*
|
|
27
|
+
* `pack-manifest.ts` validates the shape — names, modes, probe ids, caps it can
|
|
28
|
+
* check by counting — because it runs on every hook event and may not touch a
|
|
29
|
+
* semantic module. Everything that needs the semantic side is here: binding a
|
|
30
|
+
* precondition NAME to its predicate, and the request budget, which is a
|
|
31
|
+
* character count and not a probe count.
|
|
32
|
+
*
|
|
33
|
+
* ## Dropping, not failing
|
|
34
|
+
*
|
|
35
|
+
* Every failure here drops ONE policy and records why. A semantic policy is what
|
|
36
|
+
* CLEARS a reviewable regex verdict, so losing one leaves the regex deny
|
|
37
|
+
* standing: noisier, never weaker. Dropping the whole set would be the same
|
|
38
|
+
* direction but much louder, and failing the pack would deny every event its
|
|
39
|
+
* regex policies cover — a machine locked out over a typo in the half of the
|
|
40
|
+
* system whose job is to let more real work through.
|
|
41
|
+
*/
|
|
42
|
+
import { contestedSemanticNames, isFirstPartyPack, isReservedClaim, jevPacks, replacesBuiltinChecks } from "../effective-reviewers";
|
|
43
|
+
import { hookLogWarn } from "../hook-logger";
|
|
44
|
+
import {
|
|
45
|
+
packSemantic,
|
|
46
|
+
readInstalledPacks,
|
|
47
|
+
semanticQuestions,
|
|
48
|
+
type ResolvedPack,
|
|
49
|
+
type SemanticManifestEntry,
|
|
50
|
+
} from "../pack-manifest";
|
|
51
|
+
import { MAX_REQUEST_CHARS, userAskedQuestion } from "./compile";
|
|
52
|
+
import { MAX_STATE_CHARS } from "./envelope";
|
|
53
|
+
import { INJECTION_PROBE, SCOPE_PROBE, SEMANTIC_POLICIES, TASK_PROBES } from "./policies";
|
|
54
|
+
import { preconditionFor } from "./preconditions";
|
|
55
|
+
import { isPackPreconditionName } from "./precondition-names";
|
|
56
|
+
import type { NoulQuestion, SemanticPolicy } from "./types";
|
|
57
|
+
|
|
58
|
+
/** The question object `compile.ts` builds for one probe. Shared so the measurement matches. */
|
|
59
|
+
function noulOf(probe: { instructions: string; criteria?: { true: string; false: string } }): NoulQuestion {
|
|
60
|
+
return { type: "noul", instructions: probe.instructions, ...(probe.criteria ? { criteria: { ...probe.criteria } } : {}) };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* What the questions a call does NOT get to choose already cost: the injection
|
|
65
|
+
* probe, the v0 scope probe and the v1 task probes, whichever set is larger.
|
|
66
|
+
*
|
|
67
|
+
* Reserved out of the budget below because they are in every request that asks
|
|
68
|
+
* anything, so a pack budget that ignored them would be over by their size on
|
|
69
|
+
* every call.
|
|
70
|
+
*/
|
|
71
|
+
const GLOBAL_QUESTION_CHARS = Math.max(
|
|
72
|
+
JSON.stringify({ [INJECTION_PROBE.id]: noulOf(INJECTION_PROBE), [SCOPE_PROBE.id]: noulOf(SCOPE_PROBE) }).length,
|
|
73
|
+
JSON.stringify(
|
|
74
|
+
Object.fromEntries([INJECTION_PROBE, ...TASK_PROBES].map((p) => [p.id, noulOf(p)])),
|
|
75
|
+
).length,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* How many characters of questions every installed pack may contribute,
|
|
80
|
+
* together.
|
|
81
|
+
*
|
|
82
|
+
* DERIVED, not chosen. `prepareSemantic` checks one number — the serialized
|
|
83
|
+
* request against `MAX_REQUEST_CHARS` — and the state side of that is already
|
|
84
|
+
* spent to the last character by `buildEnvelope` (`MAX_STATE_CHARS`), so what is
|
|
85
|
+
* left for questions is the difference, minus the globals above. A pack set that
|
|
86
|
+
* fits this fits at FULL state size, which is the only size worth budgeting for:
|
|
87
|
+
* the state is a function of the caps and not of what the agent sent, so a
|
|
88
|
+
* request that only fits on small inputs is a request that intermittently
|
|
89
|
+
* doesn't.
|
|
90
|
+
*
|
|
91
|
+
* Deriving it is the point. The count caps it replaced (24 policies, 80 probes)
|
|
92
|
+
* were set without reference to the envelope and permitted a question set 23,032
|
|
93
|
+
* characters past what a request can carry — at which point `PreparedCall
|
|
94
|
+
* .oversized` stops meaning "our own question set overran" and starts meaning
|
|
95
|
+
* "somebody installed a big pack", and the flag that was supposed to be
|
|
96
|
+
* unreachable from ordinary work becomes routine.
|
|
97
|
+
*
|
|
98
|
+
* The real sixteen use `BUILTIN_QUESTION_CHARS` of it, so this is not a
|
|
99
|
+
* constraint on the set we ship. A stranger's pack is added to them, so what it
|
|
100
|
+
* may ask for is what they leave.
|
|
101
|
+
*/
|
|
102
|
+
export const MAX_PACK_QUESTION_CHARS = MAX_REQUEST_CHARS - MAX_STATE_CHARS - GLOBAL_QUESTION_CHARS;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* The compiled cost of one entry's questions, measured the way
|
|
106
|
+
* `prepareSemantic` measures the request: the serialized question map.
|
|
107
|
+
*
|
|
108
|
+
* `user_asked` is counted for an overridable policy even though the shipped
|
|
109
|
+
* path is intent v1, which does not ask it. A budget is worst-case over the
|
|
110
|
+
* modes a machine can run, and the alternative — a set that fits under v1 and
|
|
111
|
+
* overruns the moment anything asks in v0 — is a size cliff that depends on a
|
|
112
|
+
* flag rather than on the pack.
|
|
113
|
+
*/
|
|
114
|
+
export function questionChars(entry: SemanticManifestEntry): number {
|
|
115
|
+
const questions: Record<string, NoulQuestion> = {};
|
|
116
|
+
for (const probe of semanticQuestions(entry)) questions[`${entry.name}.${probe.id}`] = noulOf(probe);
|
|
117
|
+
if (entry.userCanOverride) {
|
|
118
|
+
// It reads `title` and nothing else (`actionPhrase` in `compile.ts`), so a
|
|
119
|
+
// stub is the honest argument here — building a whole `SemanticPolicy` to
|
|
120
|
+
// measure one string would invite it to drift from the real conversion.
|
|
121
|
+
questions[`${entry.name}.user_asked`] = userAskedQuestion({ title: entry.title } as SemanticPolicy);
|
|
122
|
+
}
|
|
123
|
+
return JSON.stringify(questions).length;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** What the compiled-in set spends of that budget when third-party checks join it. */
|
|
127
|
+
export const BUILTIN_QUESTION_CHARS = SEMANTIC_POLICIES.reduce((n, p) => n + questionChars(p as SemanticManifestEntry), 0);
|
|
128
|
+
|
|
129
|
+
export interface ResolvedSemanticPolicies {
|
|
130
|
+
policies: ReadonlyArray<SemanticPolicy>;
|
|
131
|
+
/** True when a pack supplied any of the set. */
|
|
132
|
+
fromPack: boolean;
|
|
133
|
+
/** One line per dropped policy. Diagnostics; nothing here changes a verdict. */
|
|
134
|
+
errors: string[];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Turn one validated manifest entry into a policy the compiler can use. */
|
|
138
|
+
function toSemanticPolicy(entry: SemanticManifestEntry, pack: { id: string; version?: string }): SemanticPolicy {
|
|
139
|
+
// An unknown precondition name DROPS the policy (the caller catches this),
|
|
140
|
+
// rather than compiling it with no gate at all. Ungating would be the wider
|
|
141
|
+
// direction, not the weaker one, but it is not what the author asked for: a
|
|
142
|
+
// question written for the one case its gate selects would then be put to Jev
|
|
143
|
+
// on every call, and nothing would say so. Unreachable through
|
|
144
|
+
// `parsePackSemanticPolicy`, which refuses the name; reachable if the two
|
|
145
|
+
// precondition files ever drift, which is what this is here for.
|
|
146
|
+
const name = entry.precondition;
|
|
147
|
+
if (name !== undefined && !isPackPreconditionName(name)) {
|
|
148
|
+
throw new Error(`precondition ${JSON.stringify(name)} is not a name this build has`);
|
|
149
|
+
}
|
|
150
|
+
const precondition = name === undefined ? null : preconditionFor(name);
|
|
151
|
+
return {
|
|
152
|
+
name: entry.name,
|
|
153
|
+
title: entry.title,
|
|
154
|
+
appliesTo: entry.appliesTo,
|
|
155
|
+
mode: entry.mode,
|
|
156
|
+
userCanOverride: entry.userCanOverride,
|
|
157
|
+
probes: entry.probes,
|
|
158
|
+
...(entry.exempt ? { exempt: entry.exempt } : {}),
|
|
159
|
+
// Absent, never `() => true`: `selectPolicies` treats an absent precondition
|
|
160
|
+
// as "ask", so `precondition: "always"` and an omitted field have to compile
|
|
161
|
+
// to the identical policy.
|
|
162
|
+
...(precondition ? { precondition } : {}),
|
|
163
|
+
guidance: entry.guidance,
|
|
164
|
+
origin: { packId: pack.id, ...(pack.version ? { packVersion: pack.version } : {}) },
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* The semantic set these packs declare, or the compiled-in set when none of them
|
|
170
|
+
* declares any.
|
|
171
|
+
*
|
|
172
|
+
* Pure: it takes the packs rather than reading them, so the caller that already
|
|
173
|
+
* has them does not read `installed.json` a second time and a test does not need
|
|
174
|
+
* a filesystem.
|
|
175
|
+
*/
|
|
176
|
+
export function semanticPoliciesFromPacks(
|
|
177
|
+
packs: ReadonlyArray<Pick<ResolvedPack, "id" | "semantic"> & { source?: string; version?: string }>,
|
|
178
|
+
): ResolvedSemanticPolicies {
|
|
179
|
+
const declared = packs.filter((p) => packSemantic(p).length > 0);
|
|
180
|
+
if (declared.length === 0) return { policies: SEMANTIC_POLICIES, fromPack: false, errors: [] };
|
|
181
|
+
|
|
182
|
+
// FailproofAI's own checks replace the compiled-in set; anyone else's join it
|
|
183
|
+
// (`replacesBuiltinChecks`, which the reviewer set applies too). First-party
|
|
184
|
+
// packs spend the budget first, so install order cannot starve them.
|
|
185
|
+
const replace = replacesBuiltinChecks(declared);
|
|
186
|
+
const ordered = [...declared.filter((p) => isFirstPartyPack(p)), ...declared.filter((p) => !isFirstPartyPack(p))];
|
|
187
|
+
const policies: SemanticPolicy[] = replace ? [] : [...SEMANTIC_POLICIES];
|
|
188
|
+
const errors: string[] = [];
|
|
189
|
+
const seen = new Set<string>(policies.map((p) => p.name));
|
|
190
|
+
// A name two packs declare DIFFERENTLY is asked for nobody. Keeping the first
|
|
191
|
+
// was the escalation: the question that decides another pack's policies came
|
|
192
|
+
// from whichever pack was listed first, so installing a permissive
|
|
193
|
+
// `production-infra-change` beside a real one cleared every policy reviewable
|
|
194
|
+
// by that name. Computed by `effectiveReviewerNames`'s own function, because
|
|
195
|
+
// the name it refuses in the reviewer set and the question refused here have to
|
|
196
|
+
// be the same name — a check in the set with nobody's question, or a question
|
|
197
|
+
// nobody may name, are both worse than neither.
|
|
198
|
+
const contested = contestedSemanticNames(declared);
|
|
199
|
+
let spent = replace ? 0 : BUILTIN_QUESTION_CHARS;
|
|
200
|
+
for (const pack of ordered) {
|
|
201
|
+
for (const entry of packSemantic(pack)) {
|
|
202
|
+
if (isReservedClaim(pack, entry.name)) {
|
|
203
|
+
errors.push(
|
|
204
|
+
`pack ${pack.id} declares semantic policy ${entry.name}, a name reserved for FailproofAI's own Jev checks, ` +
|
|
205
|
+
`so that pack's version of it is never asked`,
|
|
206
|
+
);
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
const claimants = contested.get(entry.name);
|
|
210
|
+
if (claimants) {
|
|
211
|
+
// Once per name: every claimant reaches here with the same message.
|
|
212
|
+
const message =
|
|
213
|
+
`packs ${claimants.join(" and ")} declare different semantic policies named ${entry.name}, so it is asked ` +
|
|
214
|
+
`for neither of them and no policy can be cleared by that name`;
|
|
215
|
+
if (!errors.includes(message)) errors.push(message);
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (seen.has(entry.name)) {
|
|
219
|
+
// Same name, same declaration — a fork or a re-publish of one pack, where
|
|
220
|
+
// the question is identical either way. Kept once, said once.
|
|
221
|
+
errors.push(`pack ${pack.id} declares semantic policy ${entry.name}, which another pack already declared`);
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
const cost = questionChars(entry);
|
|
225
|
+
if (spent + cost > MAX_PACK_QUESTION_CHARS) {
|
|
226
|
+
errors.push(
|
|
227
|
+
`pack ${pack.id} semantic policy ${entry.name} was dropped: its questions need ${cost} characters and ` +
|
|
228
|
+
`only ${Math.max(0, MAX_PACK_QUESTION_CHARS - spent)} of the ${MAX_PACK_QUESTION_CHARS}-character ` +
|
|
229
|
+
`question budget one Jev request has are left`,
|
|
230
|
+
);
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
try {
|
|
234
|
+
policies.push(toSemanticPolicy(entry, pack));
|
|
235
|
+
} catch (err) {
|
|
236
|
+
errors.push(`pack ${pack.id} semantic policy ${entry.name}: ${err instanceof Error ? err.message : String(err)}`);
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
seen.add(entry.name);
|
|
240
|
+
spent += cost;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Every entry a declaring pack shipped was unusable. The compiled-in set is
|
|
245
|
+
// the honest answer — it is what the machine ran yesterday — and it is also
|
|
246
|
+
// the safe one: what a pack's regex half names in `reviewedBy` will not match
|
|
247
|
+
// it, so those policies stay hard rather than being cleared by questions
|
|
248
|
+
// nobody validated.
|
|
249
|
+
if (policies.length === (replace ? 0 : SEMANTIC_POLICIES.length)) return { policies: SEMANTIC_POLICIES, fromPack: false, errors };
|
|
250
|
+
return { policies, fromPack: true, errors };
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const warned = new Set<string>();
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* The live set, read from the installed packs.
|
|
257
|
+
*
|
|
258
|
+
* Called from `prepareSemantic`, so only on a machine that has a Jev config and
|
|
259
|
+
* is preparing a request. It re-reads the manifest rather than caching: the
|
|
260
|
+
* daemon's warm worker lives for hours, a pack can be installed or upgraded
|
|
261
|
+
* under it, and `readInstalledPacks` re-verifies each artifact digest for
|
|
262
|
+
* exactly that reason. The read costs one digest per pack against a call that is
|
|
263
|
+
* about to spend up to three seconds on the network.
|
|
264
|
+
*
|
|
265
|
+
* Never throws. An unreadable manifest yields the compiled-in set, which is the
|
|
266
|
+
* same fail-open posture every other reader of that file takes, and here it also
|
|
267
|
+
* fails in the safe direction: the set a pack's `reviewedBy` names is not the
|
|
268
|
+
* builtin set, so nothing gets cleared by a policy nobody could read.
|
|
269
|
+
*/
|
|
270
|
+
export function resolveSemanticPolicies(cli?: string): ReadonlyArray<SemanticPolicy> {
|
|
271
|
+
let packs: ReadonlyArray<ResolvedPack> = [];
|
|
272
|
+
let manifestErrors: string[] = [];
|
|
273
|
+
try {
|
|
274
|
+
const read = readInstalledPacks();
|
|
275
|
+
packs = read.packs;
|
|
276
|
+
manifestErrors = read.warnings ?? [];
|
|
277
|
+
} catch {
|
|
278
|
+
return SEMANTIC_POLICIES;
|
|
279
|
+
}
|
|
280
|
+
const resolved = semanticPoliciesFromPacks(jevPacks(packs, cli));
|
|
281
|
+
// Once per process per message, like `warnAuthority`: this runs on every gate
|
|
282
|
+
// event, and in the warm worker that is every tool call of every session.
|
|
283
|
+
for (const message of [...manifestErrors, ...resolved.errors]) {
|
|
284
|
+
if (warned.has(message)) continue;
|
|
285
|
+
warned.add(message);
|
|
286
|
+
hookLogWarn(message);
|
|
287
|
+
}
|
|
288
|
+
return resolved.policies;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/** Forget which warnings were already said. Tests only. */
|
|
292
|
+
export function _resetSemanticWarningsForTest(): void {
|
|
293
|
+
warned.clear();
|
|
294
|
+
}
|