failproofai 1.0.2-beta.2 → 1.0.2-beta.4
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 +6 -6
- 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/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.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/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.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 +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +13 -13
- 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 +2 -3
- 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 +4 -5
- 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 +2 -2
- 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 +3 -4
- 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 +4 -4
- 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 +4 -4
- 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/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.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 +14 -14
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
- 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.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 +2 -2
- 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.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.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.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 +4 -4
- 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]__0e32-7c._.js → [externals]__1qzqcio._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_usx0j._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_zk340._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0clqfab._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0oy4kxb._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0zf034w._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0igxt32._.js → [root-of-the-server]__1p8poxd._.js} +2 -2
- package/.next/standalone/.next/server/chunks/_0lxbzdq._.js +3 -0
- package/.next/standalone/.next/server/chunks/_1ek68ln._.js +6 -5
- package/.next/standalone/.next/server/chunks/_1lbh81u._.js +3 -0
- package/.next/standalone/.next/server/chunks/_1zuiiy3._.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +2 -2
- package/.next/standalone/.next/server/chunks/{node_modules_posthog-node_dist_entrypoints_index_node_mjs_04op_ou._.js → node_modules_posthog-node_dist_entrypoints_index_node_mjs_09d5c79._.js} +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +2 -2
- package/.next/standalone/.next/server/chunks/{node_modules_posthog-node_dist_entrypoints_index_node_mjs_0dr20uz._.js → node_modules_posthog-node_dist_entrypoints_index_node_mjs_1d2g73o._.js} +1 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_hooks_fp-home_ts_09kv0bn._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013jr2b._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02npjtd._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__07gm3zl._.js +4 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0da85px._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ftmoxc._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0oa1lav._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p-5p8u._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s740oi._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__14muoc4._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{src_hooks_08o7bqo._.js → [root-of-the-server]__15r6r7w._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1p2otjt._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1tag8_-._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_1oggjel._.js → _0ovx4lz._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1dkh76z._.js +23 -0
- package/.next/standalone/.next/server/chunks/ssr/_1u8-lu2._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +1 -1
- 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 +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_13n822a._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +2 -2
- package/.next/standalone/.next/server/middleware-build-manifest.js +6 -6
- package/.next/standalone/.next/server/middleware.js +1 -1
- 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 +19 -19
- package/.next/standalone/.next/static/chunks/{1yw71gn8vqco1.js → 00_t-xvc59tkb.js} +2 -2
- package/.next/standalone/.next/static/chunks/{3jjmdqqzem21x.js → 07j2u70_3qsx8.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2fzxl7n717pbc.js → 0d_re32wscs0b.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0ykd_go4oahan.js → 0ds64uculrze8.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0nnbtp0w4sxrr.js → 0k_yvjc1yz0pq.js} +1 -1
- package/.next/standalone/.next/static/chunks/0lshnlpy1m6bc.js +1 -0
- package/.next/standalone/.next/static/chunks/{1da5a_a-3btas.js → 1o0ahew9568ls.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1za08zjcctyil.js → 1oz0svxwt9574.js} +2 -2
- package/.next/standalone/.next/static/chunks/{29eh4k77otcw6.js → 1q76jk_1_wgjq.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2axi5ehjbld9h.js → 2817_8e94ah9z.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1nzy5jc_vf9e0.js → 2dbi_x0c8n8fi.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1fac8krph-zgp.js → 354-n7p7labpn.js} +1 -1
- package/.next/standalone/.next/static/chunks/turbopack-17utl_jw0wj11.js +1 -0
- package/.next/standalone/SECURITY.md +18 -3
- package/.next/standalone/fp-cloud-cli/CHANGELOG.md +7 -0
- package/.next/standalone/fp-cloud-cli/uv.lock +6 -6
- package/.next/standalone/node_modules/@next/env/package.json +1 -1
- package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
- package/.next/standalone/node_modules/next/dist/client/components/segment-cache/cache.js +23 -34
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js +1 -1
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo.runtime.prod.js +1 -1
- package/.next/standalone/node_modules/next/dist/compiled/next-server/pages-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/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/start-server.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 +10 -10
- package/.next/standalone/package.json +19 -19
- package/.next/standalone/sdk/python/CHANGELOG.md +7 -0
- package/.next/standalone/sdk/python/uv.lock +23 -23
- package/.next/standalone/server.js +1 -1
- package/bin/failproofai.mjs +131 -55
- package/dist/cli.mjs +12940 -12627
- package/dist/worker.mjs +11 -1
- package/package.json +19 -19
- package/src/audit/cache.ts +34 -29
- package/src/audit/replay.ts +15 -91
- package/src/hooks/configure-wizard.ts +16 -48
- package/src/hooks/handler.ts +8 -1
- package/src/hooks/manager.ts +24 -2
- package/src/hooks/pack-cli.ts +572 -43
- package/src/hooks/pack-manifest.ts +28 -0
- package/src/hooks/pack-store.ts +20 -28
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__01eqny5._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0neqlu-._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t9oqnn._.js +0 -3
- package/.next/standalone/.next/server/chunks/_0bs-v8p._.js +0 -3
- package/.next/standalone/.next/server/chunks/_0tovk6q._.js +0 -3
- package/.next/standalone/.next/server/chunks/_0trp3yc._.js +0 -3
- package/.next/standalone/.next/server/chunks/_185gyk9._.js +0 -3
- package/.next/standalone/.next/server/chunks/src_hooks_0xbw3bu._.js +0 -12
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__090sxxw._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__192nhvh._.js +0 -5
- package/.next/standalone/.next/server/chunks/ssr/_0wb8osu._.js +0 -23
- package/.next/standalone/.next/static/chunks/140ip21rqmelt.js +0 -1
- package/.next/standalone/.next/static/chunks/turbopack-2vqpa-dts1gy4.js +0 -1
- /package/.next/standalone/.next/static/{A7czO1PZdTcNzLGa_H1sm → 0iNzkTsP6rh14Rj5WL17o}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{A7czO1PZdTcNzLGa_H1sm → 0iNzkTsP6rh14Rj5WL17o}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{A7czO1PZdTcNzLGa_H1sm → 0iNzkTsP6rh14Rj5WL17o}/_ssgManifest.js +0 -0
package/dist/worker.mjs
CHANGED
|
@@ -2559,7 +2559,7 @@ var init_builtin_policies = __esm(() => {
|
|
|
2559
2559
|
});
|
|
2560
2560
|
|
|
2561
2561
|
// package.json
|
|
2562
|
-
var version = "1.0.2-beta.
|
|
2562
|
+
var version = "1.0.2-beta.4";
|
|
2563
2563
|
var init_package = () => {};
|
|
2564
2564
|
|
|
2565
2565
|
// src/posthog-key.ts
|
|
@@ -8972,7 +8972,15 @@ function parsePack(root, value) {
|
|
|
8972
8972
|
}
|
|
8973
8973
|
enabled = raw.enabled.filter((n) => names.has(n));
|
|
8974
8974
|
}
|
|
8975
|
+
let clis = null;
|
|
8976
|
+
if (raw.clis !== undefined) {
|
|
8977
|
+
if (!Array.isArray(raw.clis) || raw.clis.some((c) => typeof c !== "string")) {
|
|
8978
|
+
throw new Error(`pack ${raw.id} clis is not an array of agent names`);
|
|
8979
|
+
}
|
|
8980
|
+
clis = raw.clis;
|
|
8981
|
+
}
|
|
8975
8982
|
return {
|
|
8983
|
+
clis,
|
|
8976
8984
|
id: identity.id,
|
|
8977
8985
|
version: identity.version,
|
|
8978
8986
|
source: raw.source,
|
|
@@ -9435,6 +9443,8 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
|
|
|
9435
9443
|
continue;
|
|
9436
9444
|
if (!cloudManaged && activePause)
|
|
9437
9445
|
continue;
|
|
9446
|
+
if (pack?.clis && !pack.clis.includes(cli))
|
|
9447
|
+
continue;
|
|
9438
9448
|
if (pack?.enabled && !pack.enabled.includes(hook.name))
|
|
9439
9449
|
continue;
|
|
9440
9450
|
if (pack && enabledBuiltinNames.has(hook.name))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "failproofai",
|
|
3
|
-
"version": "1.0.2-beta.
|
|
3
|
+
"version": "1.0.2-beta.4",
|
|
4
4
|
"description": "Observability and enforcement for AI agent harnesses. 39 built-in policies hooked into 12 of them — Claude Code, Codex, Cursor, Hermes, OpenClaw and more — blocking the tool call before it runs. Local dashboard included, no account needed.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"failproofai": "./dist/cli.mjs",
|
|
@@ -80,33 +80,33 @@
|
|
|
80
80
|
"access": "public"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
|
-
"@anthropic-ai/sdk": "^0.
|
|
83
|
+
"@anthropic-ai/sdk": "^0.120.0",
|
|
84
84
|
"@mdx-js/mdx": "^3.1.1",
|
|
85
85
|
"@tailwindcss/postcss": "^4.3.1",
|
|
86
|
-
"@tanstack/react-virtual": "^3.14.
|
|
86
|
+
"@tanstack/react-virtual": "^3.14.10",
|
|
87
87
|
"@testing-library/jest-dom": "^7.0.0",
|
|
88
88
|
"@testing-library/react": "^16.3.2",
|
|
89
|
-
"@testing-library/user-event": "^14.6.
|
|
89
|
+
"@testing-library/user-event": "^14.6.5",
|
|
90
90
|
"@types/node": "26.2.0",
|
|
91
91
|
"@types/react": "19.2.18",
|
|
92
92
|
"@types/react-dom": "^19.2.3",
|
|
93
|
-
"@vitejs/plugin-react": "^6.0
|
|
93
|
+
"@vitejs/plugin-react": "^6.1.0",
|
|
94
94
|
"clsx": "^2.1.1",
|
|
95
|
-
"eslint": "^10.
|
|
96
|
-
"eslint-config-next": "^16.2
|
|
95
|
+
"eslint": "^10.9.0",
|
|
96
|
+
"eslint-config-next": "^16.3.2",
|
|
97
97
|
"jsdom": "^30.0.1",
|
|
98
|
-
"lucide-react": "^1.
|
|
99
|
-
"next": "^16.2
|
|
98
|
+
"lucide-react": "^1.33.0",
|
|
99
|
+
"next": "^16.3.2",
|
|
100
100
|
"react": "^19.2.4",
|
|
101
101
|
"react-dom": "^19.2.4",
|
|
102
102
|
"tailwind-merge": "^3.4.0",
|
|
103
103
|
"tailwindcss": "^4.3.1",
|
|
104
104
|
"typescript": "6.0.3",
|
|
105
|
-
"vitest": "^4.1.
|
|
105
|
+
"vitest": "^4.1.11"
|
|
106
106
|
},
|
|
107
107
|
"dependencies": {
|
|
108
108
|
"html-to-image": "^1.11.13",
|
|
109
|
-
"posthog-node": "^5.
|
|
109
|
+
"posthog-node": "^5.50.0",
|
|
110
110
|
"sql.js": "^1.14.1",
|
|
111
111
|
"yaml": "^2.9.0"
|
|
112
112
|
},
|
|
@@ -120,15 +120,15 @@
|
|
|
120
120
|
"sharp": "0.35.0"
|
|
121
121
|
},
|
|
122
122
|
"optionalDependencies": {
|
|
123
|
-
"@failproofai/failproofaid-linux-x64": "1.0.2-beta.
|
|
124
|
-
"@failproofai/failproofaid-linux-arm64": "1.0.2-beta.
|
|
125
|
-
"@failproofai/failproofaid-darwin-x64": "1.0.2-beta.
|
|
126
|
-
"@failproofai/failproofaid-darwin-arm64": "1.0.2-beta.
|
|
123
|
+
"@failproofai/failproofaid-linux-x64": "1.0.2-beta.4",
|
|
124
|
+
"@failproofai/failproofaid-linux-arm64": "1.0.2-beta.4",
|
|
125
|
+
"@failproofai/failproofaid-darwin-x64": "1.0.2-beta.4",
|
|
126
|
+
"@failproofai/failproofaid-darwin-arm64": "1.0.2-beta.4"
|
|
127
127
|
},
|
|
128
128
|
"failproofaidBinaries": {
|
|
129
|
-
"linux-x64": "
|
|
130
|
-
"linux-arm64": "
|
|
131
|
-
"darwin-x64": "
|
|
132
|
-
"darwin-arm64": "
|
|
129
|
+
"linux-x64": "08bc00a7f8d7c80bf898471ce59c57f4e96c1420080009cc933b2ddeb4f23750",
|
|
130
|
+
"linux-arm64": "1167d809628cff04c38efbc0eaa83ca26ab8de2878bed0ef59ca43054173eea7",
|
|
131
|
+
"darwin-x64": "6ed32db21af6869c4475e753e524ad8e128436674209ad778421b240a4bd5c53",
|
|
132
|
+
"darwin-arm64": "3843de034c9d6b11f77c1f423e6201ad6a77b7eff3b3d4460ba324c5aeb62021"
|
|
133
133
|
}
|
|
134
134
|
}
|
package/src/audit/cache.ts
CHANGED
|
@@ -13,7 +13,6 @@ import { createHash } from "node:crypto";
|
|
|
13
13
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync } from "node:fs";
|
|
14
14
|
import { join } from "node:path";
|
|
15
15
|
import { BUILTIN_POLICIES } from "../hooks/builtin-policies";
|
|
16
|
-
import { readInstalledPacks } from "../hooks/pack-manifest";
|
|
17
16
|
import { AUDIT_DETECTORS } from "./detectors";
|
|
18
17
|
import type { TranscriptAuditResult } from "./types";
|
|
19
18
|
import { auditCacheDir } from "../hooks/fp-home";
|
|
@@ -22,23 +21,27 @@ let cachedEngineVersion: string | null = null;
|
|
|
22
21
|
let cachedDetectorVersion: string | null = null;
|
|
23
22
|
|
|
24
23
|
/**
|
|
25
|
-
* Hash of every builtin policy's name
|
|
26
|
-
*
|
|
27
|
-
* caches.
|
|
24
|
+
* Hash of every builtin policy's name and function body. Changes when policy
|
|
25
|
+
* code changes, invalidating downstream caches.
|
|
28
26
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
27
|
+
* Nothing else is in it, and specifically not installed packs. The audit
|
|
28
|
+
* evaluates the implementations compiled into this build and only those —
|
|
29
|
+
* `replay.ts` iterates `BUILTIN_POLICIES` and never reads the installed packs —
|
|
30
|
+
* so a pack cannot move an audit result, and keying on one meant every install
|
|
31
|
+
* or removal cold-rescanned the entire history to reproduce the answers it
|
|
32
|
+
* already had. The key it replaced folded packs in by `id|version|sha256`; the
|
|
33
|
+
* rationale was that packs "change what a machine would have caught", which is
|
|
34
|
+
* true of enforcement and was never true of this replay.
|
|
36
35
|
*
|
|
37
|
-
* **A machine with no packs
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
36
|
+
* **A machine with no packs hashes byte-identically to the old key**, because
|
|
37
|
+
* that one contributed nothing for an empty pack set — not an empty line, not a
|
|
38
|
+
* separator. So this change costs a rescan only to machines that had a pack
|
|
39
|
+
* installed, and costs it exactly once.
|
|
40
|
+
*
|
|
41
|
+
* It is deliberately NOT the source text of anything loaded at runtime: the
|
|
42
|
+
* loader rewrites a per-load temporary filename into every import specifier, so
|
|
43
|
+
* hashing loaded source would change on every single run and cold-rescan the
|
|
44
|
+
* whole history each time.
|
|
42
45
|
*/
|
|
43
46
|
function getEngineVersion(): string {
|
|
44
47
|
if (cachedEngineVersion) return cachedEngineVersion;
|
|
@@ -46,19 +49,21 @@ function getEngineVersion(): string {
|
|
|
46
49
|
.map((p) => `${p.name}|${p.fn.toString()}`)
|
|
47
50
|
.sort()
|
|
48
51
|
.join("\n");
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
// Packs are NOT in this key, and that is the whole point of the audit's design
|
|
53
|
+
// rather than an omission.
|
|
54
|
+
//
|
|
55
|
+
// `replay.ts` evaluates `BUILTIN_POLICIES` and nothing else — it never reads
|
|
56
|
+
// `readInstalledPacks()`, and third-party pack policies are never replayed. So
|
|
57
|
+
// an installed pack cannot change an audit result, and folding its identity in
|
|
58
|
+
// here invalidated every cached transcript on a change that provably produces
|
|
59
|
+
// the same answers: a full rescan of thousands of transcripts to arrive back
|
|
60
|
+
// where it started. That was survivable while packs were rare; policies ARE
|
|
61
|
+
// packs now, so installing or removing one is routine.
|
|
62
|
+
//
|
|
63
|
+
// If audit is ever extended to evaluate what a pack would actually have
|
|
64
|
+
// caught, this key has to carry pack identity again — and that change belongs
|
|
65
|
+
// in the same commit as the one that makes it true.
|
|
66
|
+
cachedEngineVersion = createHash("sha1").update(builtinBlob).digest("hex").slice(0, 16);
|
|
62
67
|
return cachedEngineVersion;
|
|
63
68
|
}
|
|
64
69
|
|
package/src/audit/replay.ts
CHANGED
|
@@ -13,19 +13,13 @@
|
|
|
13
13
|
* execSync against live git, so they never fire on PreToolUse/PostToolUse
|
|
14
14
|
* replay — no explicit skip needed.
|
|
15
15
|
*/
|
|
16
|
-
import { resolve } from "node:path";
|
|
17
|
-
import { existsSync } from "node:fs";
|
|
18
16
|
import type { EvaluationResult } from "../hooks/policy-evaluator";
|
|
19
17
|
import { evaluatePolicies } from "../hooks/policy-evaluator";
|
|
20
18
|
import { BUILTIN_POLICIES, registerBuiltinPolicies } from "../hooks/builtin-policies";
|
|
21
|
-
import { PACK_ENTRY_ASSET, bundledPackDir } from "../hooks/pack-store";
|
|
22
|
-
import { loadCustomHooks } from "../hooks/custom-hooks-loader";
|
|
23
|
-
import { clearCustomHooks } from "../hooks/custom-hooks-registry";
|
|
24
19
|
import {
|
|
25
20
|
clearPolicies,
|
|
26
21
|
getAllPolicies,
|
|
27
22
|
normalizePolicyName,
|
|
28
|
-
registerPolicy,
|
|
29
23
|
setAllPolicies,
|
|
30
24
|
} from "../hooks/policy-registry";
|
|
31
25
|
import type { RegisteredPolicy } from "../hooks/policy-types";
|
|
@@ -46,10 +40,20 @@ let initialized = false;
|
|
|
46
40
|
* (e.g. the Next.js dashboard) doesn't wipe any prior policy registrations. */
|
|
47
41
|
let savedSnapshot: RegisteredPolicy[] | null = null;
|
|
48
42
|
|
|
49
|
-
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
43
|
+
/**
|
|
44
|
+
* Register every builtin policy (regardless of user config) so the replay shows
|
|
45
|
+
* what *could* be caught, not just what is currently enabled. Called once per
|
|
46
|
+
* `runAudit` invocation. Snapshots the existing registry so `restoreReplay()`
|
|
47
|
+
* can put it back.
|
|
48
|
+
*
|
|
49
|
+
* The implementations compiled into this build, and ONLY those. The audit used
|
|
50
|
+
* to prefer a vendored `policy-pack/` copy where one existed, which was
|
|
51
|
+
* meaningful while the package shipped that directory; it no longer ships it, so
|
|
52
|
+
* that branch could not fire in any published build and existed only to be
|
|
53
|
+
* misread as "the audit scores against installed packs". It does not, and must
|
|
54
|
+
* not: an audit is a fixed yardstick, and one that changed shape with whatever
|
|
55
|
+
* pack a machine happened to have could not be compared against its own history.
|
|
56
|
+
*/
|
|
53
57
|
export async function initReplay(): Promise<void> {
|
|
54
58
|
if (initialized) return;
|
|
55
59
|
savedSnapshot = getAllPolicies();
|
|
@@ -57,90 +61,10 @@ export async function initReplay(): Promise<void> {
|
|
|
57
61
|
const enabled = BUILTIN_POLICIES
|
|
58
62
|
.map((p) => p.name)
|
|
59
63
|
.filter((n) => !SKIP_POLICIES.has(normalizePolicyName(n)));
|
|
60
|
-
|
|
64
|
+
registerBuiltinPolicies(enabled);
|
|
61
65
|
initialized = true;
|
|
62
66
|
}
|
|
63
67
|
|
|
64
|
-
/**
|
|
65
|
-
* Register the audit's policies from the pack that ships inside the package,
|
|
66
|
-
* rather than from implementations compiled into this build.
|
|
67
|
-
*
|
|
68
|
-
* The audit scores by RUNNING the policies — three of its four penalty buckets
|
|
69
|
-
* are replay hits — so the day the builtins stop being compiled in, this is
|
|
70
|
-
* what keeps `failproofai audit` reporting the same findings and the same score
|
|
71
|
-
* for the same transcripts. The pack carries the identical functions:
|
|
72
|
-
* `builtin-pack-conformance.test.ts` replays a corpus through both and asserts
|
|
73
|
-
* the verdicts do not diverge.
|
|
74
|
-
*
|
|
75
|
-
* Two things it must get right, or the audit quietly changes:
|
|
76
|
-
*
|
|
77
|
-
* - The pack cannot carry `block-failproofai-commands`, because `alwaysOn` is
|
|
78
|
-
* refused by the pack loader by design — a downloaded file that no local
|
|
79
|
-
* command can switch off. It is registered from the compiled side, so the
|
|
80
|
-
* replayed set is the same 39 either way.
|
|
81
|
-
* - The skip list still applies. `warn-repeated-tool-calls` writes a per-session
|
|
82
|
-
* sidecar into the user's real transcript directory on every evaluation.
|
|
83
|
-
*
|
|
84
|
-
* Returns false when there is no vendored pack to read — a source checkout that
|
|
85
|
-
* has not run `build:pack`, or a tarball packed without it — and the caller
|
|
86
|
-
* falls back to the compiled implementations. An audit that silently scored on
|
|
87
|
-
* fewer policies would be worse than either.
|
|
88
|
-
*/
|
|
89
|
-
async function registerFromVendoredPack(enabled: string[]): Promise<boolean> {
|
|
90
|
-
const dir = bundledPackDir();
|
|
91
|
-
if (!dir) return false;
|
|
92
|
-
const entry = resolve(dir, PACK_ENTRY_ASSET);
|
|
93
|
-
if (!existsSync(entry)) return false;
|
|
94
|
-
|
|
95
|
-
const wanted = new Set(enabled);
|
|
96
|
-
let hooks;
|
|
97
|
-
try {
|
|
98
|
-
clearCustomHooks();
|
|
99
|
-
hooks = await loadCustomHooks(entry, { strict: true });
|
|
100
|
-
} catch {
|
|
101
|
-
return false;
|
|
102
|
-
} finally {
|
|
103
|
-
clearCustomHooks();
|
|
104
|
-
}
|
|
105
|
-
if (hooks.length === 0) return false;
|
|
106
|
-
const fromPack = new Map(hooks.map((hook) => [hook.name, hook]));
|
|
107
|
-
|
|
108
|
-
// Registered in CATALOG ORDER, taking the pack's function where it has one and
|
|
109
|
-
// the compiled one for the guard the pack may not carry.
|
|
110
|
-
//
|
|
111
|
-
// Order is not cosmetic here. `getPoliciesForEvent` sorts by priority only and
|
|
112
|
-
// V8's sort is stable, so registration order decides EVALUATION order, and
|
|
113
|
-
// `evaluatePolicies` stops at the first deny — which means the order decides
|
|
114
|
-
// which policy is CREDITED for a hit. Appending the always-on guard after the
|
|
115
|
-
// pack instead of at its catalog position moved it from index 11 to last, and
|
|
116
|
-
// re-attributed 3 events in a 23,477-event corpus: 456 -> 453 for the guard,
|
|
117
|
-
// with the denies it used to shadow surfacing as block-force-push and
|
|
118
|
-
// block-gh-pipeline. The audit's per-policy counts are what a user reads, so
|
|
119
|
-
// that is a changed audit, not a changed internal.
|
|
120
|
-
let registered = 0;
|
|
121
|
-
for (const policy of BUILTIN_POLICIES) {
|
|
122
|
-
if (!wanted.has(policy.name)) continue;
|
|
123
|
-
const packHook = fromPack.get(policy.name);
|
|
124
|
-
if (policy.alwaysOn || !packHook) {
|
|
125
|
-
registerPolicy(policy.name, policy.description, policy.fn, policy.match, 0, policy.params);
|
|
126
|
-
continue;
|
|
127
|
-
}
|
|
128
|
-
registerPolicy(
|
|
129
|
-
packHook.name,
|
|
130
|
-
packHook.description ?? policy.description,
|
|
131
|
-
packHook.fn,
|
|
132
|
-
packHook.match ?? policy.match,
|
|
133
|
-
0,
|
|
134
|
-
policy.params,
|
|
135
|
-
);
|
|
136
|
-
registered += 1;
|
|
137
|
-
}
|
|
138
|
-
// Nothing came from the pack: it loaded but carried none of the names the
|
|
139
|
-
// audit replays. Falling back is more honest than scoring on the compiled set
|
|
140
|
-
// while claiming the pack lane ran.
|
|
141
|
-
return registered > 0;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
68
|
/** Restore the registry to whatever was there before `initReplay()`. Safe to
|
|
145
69
|
* call when not initialized (no-op). Always paired with `initReplay()` in a
|
|
146
70
|
* try/finally inside `runAudit()`. */
|
|
@@ -32,7 +32,6 @@ import { dirname, resolve, sep } from "node:path";
|
|
|
32
32
|
|
|
33
33
|
import {
|
|
34
34
|
selectOne,
|
|
35
|
-
multiSelect,
|
|
36
35
|
promptText,
|
|
37
36
|
intro,
|
|
38
37
|
outro,
|
|
@@ -223,7 +222,6 @@ export function buildAgentChoices(scope: HookScope, cwd: string): MultiChoice<In
|
|
|
223
222
|
});
|
|
224
223
|
}
|
|
225
224
|
|
|
226
|
-
const ALL_CLIS = "__all_clis__";
|
|
227
225
|
|
|
228
226
|
const DIM_NOTE = "(auto-loaded)";
|
|
229
227
|
|
|
@@ -938,54 +936,24 @@ export async function runConfigureWizard(io: WizardIO = {}): Promise<WizardResul
|
|
|
938
936
|
// An "Everything available" row protects every supported CLI (detected +
|
|
939
937
|
// set-up-ahead); when ticked it wins over the individual boxes.
|
|
940
938
|
//
|
|
941
|
-
//
|
|
942
|
-
// cannot make for you: which agents on this machine should be guarded. The
|
|
943
|
-
// detected ones are pre-ticked, so the common answer is a single keypress.
|
|
939
|
+
// Every supported agent, detected or not — setup asks nothing about this.
|
|
944
940
|
//
|
|
945
|
-
//
|
|
946
|
-
//
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
// under project scope is what crashed the apply on Hermes.
|
|
957
|
-
hint: `protect all ${clisSupportingScope(primaryScope).length} CLIs configurable here`,
|
|
958
|
-
// A selector, not a harness. Counting it gave "13 harnesses" for
|
|
959
|
-
// the 12 supported CLIs, and listed "Everything available" among them.
|
|
960
|
-
summaryExclude: true,
|
|
961
|
-
},
|
|
962
|
-
...buildAgentChoices(primaryScope, cwd),
|
|
963
|
-
],
|
|
964
|
-
minSelected: 1,
|
|
965
|
-
summaryNoun: "harnesses",
|
|
966
|
-
hint: "detected CLIs are pre-selected · space toggles · ctrl+a all · ↵ confirm",
|
|
967
|
-
stdin,
|
|
968
|
-
stdout,
|
|
969
|
-
});
|
|
970
|
-
if (picked === null) return cancel();
|
|
971
|
-
clisSel = picked;
|
|
972
|
-
}
|
|
973
|
-
// Filter to what the chosen scopes support in BOTH branches: "Everything
|
|
974
|
-
// available" must not expand to CLIs that cannot take any selected scope,
|
|
975
|
-
// and a locked row can't be ticked but belt-and-braces keeps the invariant
|
|
976
|
-
// local to the one place `clis` is built.
|
|
941
|
+
// It used to be the one question left, on the reasoning that which agents to
|
|
942
|
+
// guard is a real choice. It stopped being one when this package stopped
|
|
943
|
+
// shipping policies: hooks alone enforce nothing, so wiring them everywhere
|
|
944
|
+
// costs a config entry and changes no behaviour until a pack arrives. What it
|
|
945
|
+
// buys is that an agent installed NEXT WEEK is guarded from its first tool
|
|
946
|
+
// call, instead of running unguarded until somebody remembers to re-run setup
|
|
947
|
+
// — and nobody remembers, because nothing tells them to.
|
|
948
|
+
//
|
|
949
|
+
// ALL twelve, not the detected ones, for exactly that reason. The cost is
|
|
950
|
+
// honest and worth naming: hook config appears under `~/.cursor/`,
|
|
951
|
+
// `~/.factory/` and the rest for agents that may never be installed.
|
|
977
952
|
//
|
|
978
|
-
//
|
|
979
|
-
//
|
|
980
|
-
//
|
|
981
|
-
|
|
982
|
-
// skips what a given scope cannot take.
|
|
983
|
-
const supported = new Set(scopes.flatMap((s) => clisSupportingScope(s)));
|
|
984
|
-
const clis: IntegrationType[] = (
|
|
985
|
-
clisSel.includes(ALL_CLIS)
|
|
986
|
-
? [...INTEGRATION_TYPES]
|
|
987
|
-
: (clisSel.filter((v) => v !== ALL_CLIS) as IntegrationType[])
|
|
988
|
-
).filter((id) => supported.has(id));
|
|
953
|
+
// Which policies run, and on which of these agents, is chosen at
|
|
954
|
+
// `failproofai policies add` — where the user is looking at a real list
|
|
955
|
+
// instead of answering in the abstract.
|
|
956
|
+
const clis: IntegrationType[] = [...clisSupportingScope(primaryScope)];
|
|
989
957
|
|
|
990
958
|
// 4 — Connect this machine? Last, because by this point the user has decided
|
|
991
959
|
// what to protect, so "would you like to see it in a dashboard?" follows
|
package/src/hooks/handler.ts
CHANGED
|
@@ -425,9 +425,16 @@ export async function evaluateHookEvent(
|
|
|
425
425
|
if (!cloudManaged && policyId && disabledCustomPolicies.has(policyId)) continue;
|
|
426
426
|
// Same rule for a session pause — it suspends local policy, never cloud.
|
|
427
427
|
if (!cloudManaged && activePause) continue;
|
|
428
|
+
// A pack narrowed to particular agents does not fire on the others.
|
|
429
|
+
// Setup wires hooks into every supported CLI — hooks alone enforce
|
|
430
|
+
// nothing — so the choice of which agents a pack guards is made when the
|
|
431
|
+
// pack is installed, and this is where it takes effect. `clis: null`
|
|
432
|
+
// means every agent, which is what an install with no narrowing writes
|
|
433
|
+
// and what every pack installed before this field existed reads as.
|
|
434
|
+
if (pack?.clis && !pack.clis.includes(cli)) continue;
|
|
428
435
|
// A pack's artifact registers everything it contains; the user may have
|
|
429
436
|
// taken only some of it. `enabled: null` means the whole pack, which is
|
|
430
|
-
// what `
|
|
437
|
+
// what `policies add` writes when no selection was made.
|
|
431
438
|
if (pack?.enabled && !pack.enabled.includes(hook.name)) continue;
|
|
432
439
|
// A pack policy whose name is an ENABLED BUILTIN is the same guard
|
|
433
440
|
// twice. The two register under different keys — `failproofai/block-sudo`
|
package/src/hooks/manager.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { execSync } from "node:child_process";
|
|
|
9
9
|
import { existsSync } from "node:fs";
|
|
10
10
|
import { resolve, basename } from "node:path";
|
|
11
11
|
import { platform, arch, release, hostname } from "node:os";
|
|
12
|
-
import {
|
|
12
|
+
import { INTEGRATION_TYPES,
|
|
13
13
|
HOOK_SCOPES,
|
|
14
14
|
type HookScope,
|
|
15
15
|
type IntegrationType,
|
|
@@ -256,8 +256,30 @@ function deduplicateScopes(scopes: readonly HookScope[], cwd?: string): HookScop
|
|
|
256
256
|
});
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
+
/**
|
|
260
|
+
* Is ANY agent CLI wired to call failproofai at this scope?
|
|
261
|
+
*
|
|
262
|
+
* Asked Claude Code and only Claude Code, which made it wrong for every machine
|
|
263
|
+
* guarded through one of the other eleven. A user with hooks in `~/.codex/` was
|
|
264
|
+
* told nothing was installed — quietly, while this only tinted a subtitle, and
|
|
265
|
+
* loudly once the listing started warning that every policy shown was inert.
|
|
266
|
+
* Reported from a real machine set up for codex.
|
|
267
|
+
*
|
|
268
|
+
* Any one integration answering yes is enough: the question is whether
|
|
269
|
+
* enforcement can reach this machine at all, not whether a particular agent is
|
|
270
|
+
* covered. Which agents specifically is a different question, and the per-CLI
|
|
271
|
+
* rows of the listing already answer it.
|
|
272
|
+
*/
|
|
259
273
|
export function hooksInstalledInSettings(scope: HookScope, cwd?: string): boolean {
|
|
260
|
-
return
|
|
274
|
+
return INTEGRATION_TYPES.some((id) => {
|
|
275
|
+
try {
|
|
276
|
+
return getIntegration(id).hooksInstalledInSettings(scope, cwd);
|
|
277
|
+
} catch {
|
|
278
|
+
// An integration whose settings file is unreadable is not evidence that
|
|
279
|
+
// nothing is installed — keep asking the rest.
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
});
|
|
261
283
|
}
|
|
262
284
|
|
|
263
285
|
export interface InstallHooksOptions {
|