failproofai 0.0.11-beta.2 → 0.0.11-beta.3
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/app-path-routes-manifest.json +8 -1
- package/.next/standalone/.next/build-manifest.json +10 -10
- package/.next/standalone/.next/prerender-manifest.json +3 -32
- package/.next/standalone/.next/required-server-files.json +2 -1
- package/.next/standalone/.next/routes-manifest.json +45 -3
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +7 -7
- 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 +6 -6
- 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 +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- 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 +7 -7
- package/.next/standalone/.next/server/app/_not-found/page/next-font-manifest.json +2 -6
- 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 +12 -13
- 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 +16 -16
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +16 -16
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
- 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/_not-found.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/audit/run/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/audit/run/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/audit/run/route.js +8 -0
- package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/audit/run/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/audit/status/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/audit/status/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/audit/status/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/audit/status/route.js +6 -0
- package/.next/standalone/.next/server/app/api/audit/status/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/audit/status/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/auth/login-request/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/auth/login-request/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/auth/login-request/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js +6 -0
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/auth/login-request/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/auth/login-verify/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/auth/login-verify/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/auth/login-verify/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +7 -0
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/auth/login-verify/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/auth/logout/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/auth/logout/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/auth/logout/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/auth/logout/route.js +7 -0
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/auth/logout/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/auth/reminder/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/auth/reminder/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/auth/reminder/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js +7 -0
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/auth/reminder/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/auth/status/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/auth/status/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/auth/status/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/auth/status/route.js +7 -0
- package/.next/standalone/.next/server/app/api/auth/status/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/auth/status/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +3 -3
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/audit/page/build-manifest.json +18 -0
- package/.next/standalone/.next/server/app/audit/page/next-font-manifest.json +6 -0
- package/.next/standalone/.next/server/app/audit/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +29 -0
- package/.next/standalone/.next/server/app/audit/page.js +17 -0
- package/.next/standalone/.next/server/app/audit/page.js.map +5 -0
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +16 -17
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +16 -17
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -3
- package/.next/standalone/.next/server/app/page/build-manifest.json +7 -7
- package/.next/standalone/.next/server/app/page/next-font-manifest.json +2 -6
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +14 -15
- 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 +7 -7
- package/.next/standalone/.next/server/app/policies/page/next-font-manifest.json +2 -6
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/policies/page.js +16 -16
- 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 +7 -7
- package/.next/standalone/.next/server/app/project/[name]/page/next-font-manifest.json +2 -6
- 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 +16 -17
- 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 +7 -7
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/next-font-manifest.json +2 -6
- 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 +19 -20
- 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 +7 -7
- package/.next/standalone/.next/server/app/projects/page/next-font-manifest.json +2 -6
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +15 -16
- 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-paths-manifest.json +8 -1
- package/.next/standalone/.next/server/chunks/[externals]__14odj07._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[externals]__0z0j--b._.js → [externals]__1nl3dvw._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[externals]__0-p9.k~._.js → [externals]__1s61mel._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[externals]_node_os_06ur78j._.js → [externals]_node_os_0by37l-._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__07tgnzi._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0kjo7d_._.js → [root-of-the-server]__0_0xu5z._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cag8qd._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0z-180.._.js → [root-of-the-server]__0cycwg6._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__08px0ym._.js → [root-of-the-server]__0f7mikp._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0oeun7z._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q-v9z2._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rv7m0k._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0g48iv.._.js → [root-of-the-server]__0sb_5m8._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0j8-xkl._.js → [root-of-the-server]__0xuaoik._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__12pit4m._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__13h8pzr._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__13ra2jq._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0d_ob4n._.js → [root-of-the-server]__1_mqemn._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1b9z5-i._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0vlhtkc._.js → [root-of-the-server]__1hgv_75._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ixjiy8._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0wu7fr7._.js → [root-of-the-server]__1jm9fw6._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1legmza._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0fwb7ao._.js → [root-of-the-server]__1m2_4t0._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0yfq1yr._.js → [root-of-the-server]__1mhmdzs._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0zso~62._.js → [root-of-the-server]__1ou2ehh._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qxztj-._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rhmvod._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0.~nmr9._.js → [root-of-the-server]__1w9zl9-._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{_0ebx_lc._.js → _0p53ge1._.js} +2 -2
- package/.next/standalone/.next/server/chunks/_1-1804f._.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_audit_run_route_actions_1qgp9io.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_audit_status_route_actions_1f7pjof.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_auth_login-request_route_actions_1c49co0.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_auth_login-verify_route_actions_1r3slzk.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_auth_logout_route_actions_0regwyr.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_auth_reminder_route_actions_1kjgxf8.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_auth_status_route_actions_1aho9zu.js +3 -0
- package/.next/standalone/.next/server/chunks/{_next-internal_server_app_api_download_[project]_[session]_route_actions_0wb00i-.js → _next-internal_server_app_api_download_[project]_[session]_route_actions_1is7vs7.js} +1 -1
- package/.next/standalone/.next/server/chunks/{lib_logger_ts_047tt9f._.js → lib_logger_ts_07e65t5._.js} +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +23 -0
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +3 -0
- package/.next/standalone/.next/server/chunks/{package_json_[json]_cjs_0z7w.hh._.js → package_json_[json]_cjs_1nxcc4v._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[externals]__12dv.x0._.js → [externals]__1_g_b3t._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[externals]_node_async_hooks_0v0ln8c._.js → [externals]_node_async_hooks_1gjz99j._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__00jkjmt._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013du6r._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0989_dx._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e85wxv._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0gfxvb1._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h12me5._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0l13qf2._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0ts150~._.js → [root-of-the-server]__0ywoypf._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1-scthx._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__100hdar._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11rtg6s._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__14dd6h8._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1cd25c7._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0t5l7a5._.js → [root-of-the-server]__1d8omgc._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0tcyn68._.js → [root-of-the-server]__1dky4g0._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__098zro9._.js → [root-of-the-server]__1fax1sl._.js} +4 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1hlrq6y._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ihxdo5._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1mt35_w._.js +221 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0-wn51s._.js → [root-of-the-server]__1pcxxwg._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1usf8v2._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1vvfde2._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__212nf49._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{_03d7qyt._.js → _05whahf._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_11_p9y8._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{_0xb8ngh._.js → _1kje4fm._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_0zx~s__._.js → _1p0-leb._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{app_04qfs8z._.js → app_087bt9w._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{app_0uosk1e._.js → app_1fvisnp._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{app_13f0ohr._.js → app_209u41o._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +43 -0
- package/.next/standalone/.next/server/chunks/ssr/app_audit_loading_tsx_1j1kc6j._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{app_error_tsx_11t4ysq._.js → app_error_tsx_1zds1ns._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{app_global-error_tsx_0m9qisk._.js → app_global-error_tsx_113y3za._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +8 -0
- package/.next/standalone/.next/server/chunks/ssr/{app_project_[name]_error_tsx_0.9-fod._.js → app_project_[name]_error_tsx_1v02_5n._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{app_project_[name]_loading_tsx_03g9xy0._.js → app_project_[name]_loading_tsx_05-l4uf._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{app_project_[name]_session_[sessionId]_error_tsx_0ler-mr._.js → app_project_[name]_session_[sessionId]_error_tsx_0-lj3nd._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{app_project_[name]_session_[sessionId]_loading_tsx_0c0e3yx._.js → app_project_[name]_session_[sessionId]_loading_tsx_0l4aixs._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_projects_loading_tsx_20-3u8b._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{lib_codex-projects_ts_0eosib~._.js → lib_codex-projects_ts_0pqlw37._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{lib_copilot-projects_ts_0r8xkn8._.js → lib_copilot-projects_ts_19wl7tp._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{lib_cursor-projects_ts_0qt1scg._.js → lib_cursor-projects_ts_18-iwyk._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{lib_gemini-projects_ts_0sl~yqr._.js → lib_gemini-projects_ts_1c7bgx-._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{lib_opencode-projects_ts_0op9gyp._.js → lib_opencode-projects_ts_15bjxkm._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{lib_pi-projects_ts_103tsh1._.js → lib_pi-projects_ts_1wikofb._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{lib_utils_ts_068jk73._.js → lib_utils_ts_0az0sfq._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_1ynf7el._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_html2canvas_dist_html2canvas_esm_05gja40.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_html2canvas_dist_html2canvas_esm_1n-0xws.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_0rd0oc-._.js → node_modules_next_1a1kch7._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_0h9llsw._.js → node_modules_next_dist_0uboya6._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_11dij6w._.js → node_modules_next_dist_1d_onnt._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_client_components_0inhx6q._.js → node_modules_next_dist_client_components_0wpq8j3._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_client_components_builtin_forbidden_0ghu-f7.js → node_modules_next_dist_client_components_builtin_forbidden_0symwr9.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_client_components_builtin_unauthorized_0cjv-23.js → node_modules_next_dist_client_components_builtin_unauthorized_0l_sp0x.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0-uvagv.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_03c7gi5.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_09p-8om.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0v-kfiu.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_esm_build_templates_app-page_0j79~gv.js → node_modules_next_dist_esm_build_templates_app-page_0xrgzyz.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_1806lsc.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_1j6dd-e.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_1sa65r-.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1ezd2jf._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1tnuifj._.js +5 -0
- package/.next/standalone/.next/server/functions-config-manifest.json +3 -0
- package/.next/standalone/.next/server/instrumentation.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +10 -10
- package/.next/standalone/.next/server/middleware.js +2 -2
- package/.next/standalone/.next/server/next-font-manifest.js +1 -1
- package/.next/standalone/.next/server/next-font-manifest.json +2 -21
- 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 +27 -9
- package/.next/standalone/.next/static/chunks/{07uz2g0_38qia.js → 03fmihek9n986.js} +1 -1
- package/.next/standalone/.next/static/chunks/09ueq8s1as8xs.css +2 -0
- package/.next/standalone/.next/static/chunks/0ehe4dh0grngk.js +41 -0
- package/.next/standalone/.next/static/chunks/{0bke.~atnsbeb.js → 0gdm-xaez4l7t.js} +1 -1
- package/.next/standalone/.next/static/chunks/{11w14gnqzprir.js → 0kdglk0vtzymo.js} +1 -1
- package/.next/standalone/.next/static/chunks/0qassxjx1ef04.js +1 -0
- package/.next/standalone/.next/static/chunks/0zbxssxh53n-3.js +1 -0
- package/.next/standalone/.next/static/chunks/13f1kmjea-0md.js +2 -0
- package/.next/standalone/.next/static/chunks/1btx2c49fk9xt.css +1 -0
- package/.next/standalone/.next/static/chunks/1fmco3pvq_twz.js +1 -0
- package/.next/standalone/.next/static/chunks/2b1fzuhuk-42n.js +1 -0
- package/.next/standalone/.next/static/chunks/{0bv1oyxspkpkb.js → 2dtip-mvmihiu.js} +1 -1
- package/.next/standalone/.next/static/chunks/2srzafd1_ha5y.js +1 -0
- package/.next/standalone/.next/static/chunks/{0d3shmwh5_nmn.js → 33u59vf_8xpd-.js} +1 -1
- package/.next/standalone/.next/static/chunks/3gti1qdk5epqn.js +1 -0
- package/.next/standalone/.next/static/chunks/{0dvhi-prcsh3~.js → 3krzy-lhwfrmz.js} +1 -1
- package/.next/standalone/.next/static/chunks/{17mubwtqwijpu.js → 3w8d8k_dca5rp.js} +1 -1
- package/.next/standalone/.next/static/chunks/43lnq0c1rnflb.js +6 -0
- package/.next/standalone/.next/static/chunks/{turbopack-0nh.aopesgj~5.js → turbopack-00qy7zfa7m--m.js} +1 -1
- package/.next/standalone/SECURITY.md +73 -0
- package/.next/standalone/app/actions/get-audit-result.ts +24 -0
- package/.next/standalone/app/api/audit/_state.ts +72 -0
- package/.next/standalone/app/api/audit/run/route.ts +89 -0
- package/.next/standalone/app/api/audit/status/route.ts +23 -0
- package/.next/standalone/app/api/auth/login-request/route.ts +91 -0
- package/.next/standalone/app/api/auth/login-verify/route.ts +98 -0
- package/.next/standalone/app/api/auth/logout/route.ts +48 -0
- package/.next/standalone/app/api/auth/reminder/route.ts +213 -0
- package/.next/standalone/app/api/auth/status/route.ts +42 -0
- package/.next/standalone/app/audit/_components/audit-dashboard.tsx +364 -0
- package/.next/standalone/app/audit/_components/auth-dialog.tsx +401 -0
- package/.next/standalone/app/audit/_components/empty-state.tsx +146 -0
- package/.next/standalone/app/audit/_components/findings-section.tsx +135 -0
- package/.next/standalone/app/audit/_components/identity-section.tsx +126 -0
- package/.next/standalone/app/audit/_components/policies-section.tsx +194 -0
- package/.next/standalone/app/audit/_components/report-footer.tsx +35 -0
- package/.next/standalone/app/audit/_components/rerun-button.tsx +81 -0
- package/.next/standalone/app/audit/_components/return-section.tsx +428 -0
- package/.next/standalone/app/audit/_components/run-progress.tsx +120 -0
- package/.next/standalone/app/audit/_components/score-section.tsx +179 -0
- package/.next/standalone/app/audit/_components/share-dock.tsx +265 -0
- package/.next/standalone/app/audit/_components/share-templates.ts +67 -0
- package/.next/standalone/app/audit/_components/show-off-cta.tsx +135 -0
- package/.next/standalone/app/audit/_components/sigil.tsx +93 -0
- package/.next/standalone/app/audit/_components/strengths-section.tsx +57 -0
- package/.next/standalone/app/audit/audit-styles.css +2066 -0
- package/.next/standalone/app/audit/loading.tsx +24 -0
- package/.next/standalone/app/audit/page.tsx +53 -0
- package/.next/standalone/app/globals.css +570 -137
- package/.next/standalone/app/layout.tsx +16 -9
- package/.next/standalone/app/policies/hooks-client.tsx +223 -129
- package/.next/standalone/app/project/[name]/page.tsx +89 -39
- package/.next/standalone/app/projects/loading.tsx +30 -8
- package/.next/standalone/app/projects/page.tsx +76 -18
- package/.next/standalone/assets/audit/Audit Report.html +22 -0
- package/.next/standalone/assets/audit/Show Off Your Agent.html +22 -0
- package/.next/standalone/assets/audit/archetypes.jsx +277 -0
- package/.next/standalone/assets/audit/assets/fonts/bitcount-prop-single.woff2 +0 -0
- package/.next/standalone/assets/audit/audit.jsx +825 -0
- package/.next/standalone/assets/audit/poster-styles.css +424 -0
- package/.next/standalone/assets/audit/poster.jsx +247 -0
- package/.next/standalone/assets/audit/screenshots/poster-optimist.png +0 -0
- package/.next/standalone/assets/audit/screenshots/poster-scrolled.png +0 -0
- package/.next/standalone/assets/audit/styles.css +1225 -0
- package/.next/standalone/assets/audit/tweaks-panel.jsx +425 -0
- package/.next/standalone/assets/logos/company/icon.svg +1 -0
- package/.next/standalone/assets/logos/company/logo.svg +1 -0
- package/.next/standalone/components/navbar.tsx +154 -65
- package/.next/standalone/components/reach-developers.tsx +37 -9
- package/.next/standalone/lib/atomic-write.ts +67 -0
- package/.next/standalone/lib/auth/api-server-client.ts +281 -0
- package/.next/standalone/lib/auth/auth-store.ts +250 -0
- package/.next/standalone/lib/client-telemetry.ts +2 -0
- package/.next/standalone/lib/fetch-with-timeout.ts +42 -0
- package/.next/standalone/lib/share-card.ts +120 -0
- package/.next/standalone/lib/telemetry.ts +12 -7
- 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/dev/debug-channel.js +102 -2
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js +11 -11
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo.runtime.prod.js +13 -13
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-route-turbo.runtime.prod.js +2 -2
- 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/app-render/action-handler.js +18 -8
- package/.next/standalone/node_modules/next/dist/server/config-schema.js +1 -0
- 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/encode-cache-tag.js +45 -0
- package/.next/standalone/node_modules/next/dist/server/lib/implicit-tags.js +6 -3
- package/.next/standalone/node_modules/next/dist/server/lib/patch-fetch.js +5 -1
- package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/web/spec-extension/revalidate.js +4 -3
- package/.next/standalone/node_modules/next/dist/server/web/spec-extension/unstable-cache.js +6 -2
- package/.next/standalone/node_modules/next/dist/shared/lib/errors/canary-only-config-error.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 +15 -15
- package/.next/standalone/node_modules/react/cjs/react.development.js +1 -1
- package/.next/standalone/node_modules/react/cjs/react.production.js +1 -1
- package/.next/standalone/node_modules/react/package.json +1 -1
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.js +1 -1
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.node.production.js +1 -1
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.browser.production.js +3 -3
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.edge.production.js +3 -3
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.node.production.js +3 -3
- package/.next/standalone/node_modules/react-dom/cjs/react-dom.production.js +1 -1
- package/.next/standalone/node_modules/react-dom/package.json +2 -2
- package/.next/standalone/osv-scanner.toml +17 -0
- package/.next/standalone/package.json +8 -3
- package/.next/standalone/public/audit/fonts/bitcount-prop-single.woff2 +0 -0
- package/.next/standalone/public/icon.svg +1 -0
- package/.next/standalone/public/logo.svg +1 -0
- package/.next/standalone/server.js +1 -1
- package/.next/standalone/templates/bitcount-font/README.md +42 -0
- package/.next/standalone/templates/bitcount-font/bitcount-prop-single.woff2 +0 -0
- package/.next/standalone/templates/bitcount-font/bitcount.css +49 -0
- package/.next/standalone/templates/bitcount-font/fonts.ts.example +23 -0
- package/README.md +2 -1
- package/bin/failproofai.mjs +165 -144
- package/dist/cli.mjs +607 -1858
- package/lib/atomic-write.ts +67 -0
- package/lib/auth/api-server-client.ts +281 -0
- package/lib/auth/auth-store.ts +250 -0
- package/lib/client-telemetry.ts +2 -0
- package/lib/fetch-with-timeout.ts +42 -0
- package/lib/share-card.ts +120 -0
- package/lib/telemetry.ts +12 -7
- package/package.json +8 -3
- package/scripts/install-telemetry.mjs +4 -0
- package/src/audit/archetypes.ts +924 -0
- package/src/audit/cache.ts +21 -2
- package/src/audit/dashboard-cache.ts +111 -0
- package/src/audit/features.ts +268 -0
- package/src/audit/findings.ts +298 -0
- package/src/audit/index.ts +39 -21
- package/src/audit/replay.ts +29 -3
- package/src/audit/scoring.ts +174 -0
- package/src/audit/strengths.ts +138 -0
- package/src/audit/types.ts +24 -1
- package/src/auth/cli.ts +359 -0
- package/src/hooks/builtin-policies.ts +2 -1
- package/src/hooks/hook-telemetry.ts +2 -2
- package/src/hooks/policy-registry.ts +20 -0
- package/src/posthog-key.ts +9 -0
- package/.next/standalone/.next/server/app/icon.png/route/app-paths-manifest.json +0 -3
- package/.next/standalone/.next/server/app/icon.png/route.js +0 -7
- package/.next/standalone/.next/server/app/icon.png/route.js.nft.json +0 -1
- package/.next/standalone/.next/server/app/icon.png.body +0 -0
- package/.next/standalone/.next/server/app/icon.png.meta +0 -1
- package/.next/standalone/.next/server/chunks/[externals]_next_dist_0sqmaqd._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06.arfm._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0__i0h0._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fe7_q_._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fw.e.h._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0pxn0e1._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xv0jh2._.js +0 -3
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_icon_png_route_actions_12.gv.r.js +0 -3
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0bdfoky.js +0 -3
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_05pz9._._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01as125._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0370~qj._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__09v.ljl._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0agrcb8._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0b7hkr~._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ehh6vp._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0g8l0tu._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0j4l6hl._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0k5n2kz._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0lp08ll._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n0yaqw._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0o21f.o._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0t8juvy._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0uylufv._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ymlddl._.js +0 -223
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0~03grs._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/app_0cdqd9w._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_0xerkr6._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_0q-m0y-._.js +0 -8
- package/.next/standalone/.next/server/chunks/ssr/app_projects_loading_tsx_13veom4._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_0ttbz1~._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_06u0kr8._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0a_7sdg.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0ef3uwk.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0pbja1x.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0r6o0i2.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_11y81~_.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_12or2kf.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_0mebn66._.js +0 -3
- package/.next/standalone/.next/static/chunks/07kpqoo7kuckx.js +0 -6
- package/.next/standalone/.next/static/chunks/0azb~vy9ds_uy.js +0 -1
- package/.next/standalone/.next/static/chunks/0f5p9plm.aqlp.css +0 -2
- package/.next/standalone/.next/static/chunks/0ffvlbgzgnlw7.js +0 -2
- package/.next/standalone/.next/static/chunks/0spktq7xqab9h.js +0 -1
- package/.next/standalone/.next/static/chunks/118q3uljozd5z.js +0 -4
- package/.next/standalone/.next/static/chunks/12pt~2f.c1sha.js +0 -1
- package/.next/standalone/.next/static/media/4fa387ec64143e14-s.0.qu-9752pffj.woff2 +0 -0
- package/.next/standalone/.next/static/media/5ce348bf30bf5439-s.0ee55_hj9qcer.woff2 +0 -0
- package/.next/standalone/.next/static/media/6306c77e7c8268e4-s.0mao5jbfbduzp.woff2 +0 -0
- package/.next/standalone/.next/static/media/797e433ab948586e-s.p.09zddjkbdep5a.woff2 +0 -0
- package/.next/standalone/.next/static/media/7d817b4c03b0c5f1-s.0uzt.a6d44yda.woff2 +0 -0
- package/.next/standalone/.next/static/media/bbc41e54d2fcbd21-s.0mvwgmnhv29no.woff2 +0 -0
- package/.next/standalone/.next/static/media/icon.0a.gigb3_x5pd.png +0 -0
- package/.next/standalone/app/icon.png +0 -0
- package/src/audit/telemetry.ts +0 -113
- /package/.next/standalone/.next/server/app/{icon.png → api/audit/run}/route/build-manifest.json +0 -0
- /package/.next/standalone/.next/server/app/{icon.png → api/audit/run}/route.js.map +0 -0
- /package/.next/standalone/.next/static/chunks/{03~yq9q893hmn.js → 0cz1d0mv5g_q7.js} +0 -0
- /package/.next/standalone/.next/static/chunks/{0a40sy4tk8ioe.js → 0wwt5o04i4zwh.js} +0 -0
- /package/.next/standalone/.next/static/chunks/{0n1n67imq.udf.js → 1__i9af9g78vd.js} +0 -0
- /package/.next/standalone/.next/static/chunks/{0w6fzf.07a24u.js → 2so39wg7mjbi7.js} +0 -0
- /package/.next/standalone/.next/static/chunks/{0xbo5nl6w4lka.js → 2wbuxnsvux4di.js} +0 -0
- /package/.next/standalone/.next/static/chunks/{0_s0luks5tay-.js → 35fgpd_feci6x.js} +0 -0
- /package/.next/standalone/.next/static/chunks/{15fklyav5py5m.js → 3xpjn3cdgm-7m.js} +0 -0
- /package/.next/standalone/.next/static/chunks/{17.b3suj8zjjj.js → 4448_qq7bd963.js} +0 -0
- /package/.next/standalone/.next/static/{tGVQM5SE3NvbVu0gbAJm7 → wU3ot-EKa5ApKoh785wp8}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{tGVQM5SE3NvbVu0gbAJm7 → wU3ot-EKa5ApKoh785wp8}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{tGVQM5SE3NvbVu0gbAJm7 → wU3ot-EKa5ApKoh785wp8}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the FindingsSection cards from a live AuditResult.
|
|
3
|
+
*
|
|
4
|
+
* Each card has four blocks (per reference design):
|
|
5
|
+
* - what happened (prose summary, hand-written per policy)
|
|
6
|
+
* - what this costs (severity / radius framing)
|
|
7
|
+
* - evidence (real examples from the AuditResult)
|
|
8
|
+
* - the fix (policy slug + install command — only when not enabled)
|
|
9
|
+
*
|
|
10
|
+
* The body / cost copy is hand-curated per policy/detector when we have
|
|
11
|
+
* good copy for it; otherwise we fall back to the policy's authored
|
|
12
|
+
* `displayTitle` + `impact` strings.
|
|
13
|
+
*/
|
|
14
|
+
import type { AuditCount, AuditResult } from "./types";
|
|
15
|
+
|
|
16
|
+
/** Plain-text body so this module stays JSX-free and can be imported
|
|
17
|
+
* server-side. The React layer renders these as paragraphs. */
|
|
18
|
+
export interface FindingCopy {
|
|
19
|
+
body: string;
|
|
20
|
+
cost: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Audit-detector → builtin-policy mapping.
|
|
25
|
+
*
|
|
26
|
+
* Each audit-only detector is paired with the closest real-time policy
|
|
27
|
+
* that catches the same class of behavior. The detector still does the
|
|
28
|
+
* specific pattern-matching; the "fix" prescribed in the report is the
|
|
29
|
+
* builtin policy. Removes the "audit-only — no real-time policy yet"
|
|
30
|
+
* framing so every finding looks like it has a failproofai fix.
|
|
31
|
+
*
|
|
32
|
+
* Mappings authored against the policy catalog in src/hooks/builtin-policies.ts.
|
|
33
|
+
* The first entry is the primary fix (shown in the "$ install" block);
|
|
34
|
+
* additional entries are listed alongside as "also covered by".
|
|
35
|
+
*/
|
|
36
|
+
const DETECTOR_TO_POLICY: Record<string, { primary: string; also?: string }> = {
|
|
37
|
+
// wasteful shell: repetitive cd && cmd burns tokens — same class as
|
|
38
|
+
// 3+ identical tool calls
|
|
39
|
+
"redundant-cd-cwd": { primary: "warn-repeated-tool-calls" },
|
|
40
|
+
// wrong tool choice: bash cat/head/tail on source files crosses the
|
|
41
|
+
// same file-read surface block-read-outside-cwd gates; the repetition
|
|
42
|
+
// is what warn-repeated-tool-calls would have caught
|
|
43
|
+
"prefer-edit-over-read-cat":{ primary: "block-read-outside-cwd", also: "warn-repeated-tool-calls" },
|
|
44
|
+
// wrong tool choice: sed -i / awk > file route a write through the
|
|
45
|
+
// shell — same class as the repeated-mis-use pattern
|
|
46
|
+
"prefer-edit-over-sed-awk": { primary: "warn-repeated-tool-calls" },
|
|
47
|
+
// bash file bypass: heredoc / echo > file is the layer that bypasses
|
|
48
|
+
// the Write tool — both .env and secret-key writes route through it
|
|
49
|
+
"prefer-write-over-heredoc":{ primary: "block-env-files", also: "block-secrets-write" },
|
|
50
|
+
// wasted execution: long sleeps + while-sleep loops are the same
|
|
51
|
+
// shape as backgrounded processes that never get cleaned up
|
|
52
|
+
"sleep-polling-loop": { primary: "warn-background-process" },
|
|
53
|
+
// risky filesystem: find /, /home, /usr is exactly the class of
|
|
54
|
+
// out-of-cwd reads that block-read-outside-cwd gates
|
|
55
|
+
"find-from-root": { primary: "block-read-outside-cwd" },
|
|
56
|
+
// hook bypass: --no-verify is a dangerous-commit-flag pattern; the
|
|
57
|
+
// bypass means CI / hooks never ran — both warn-git-amend's "rewriting
|
|
58
|
+
// history" class and the require-ci-green stop-gate cover this
|
|
59
|
+
"git-commit-no-verify": { primary: "warn-git-amend", also: "require-ci-green-before-stop" },
|
|
60
|
+
// wasteful reads: read after edit/write is identical-tool-call
|
|
61
|
+
// overhead — same redundant-invocation class
|
|
62
|
+
"reread-after-edit": { primary: "warn-repeated-tool-calls" },
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const FINDING_COPY: Record<string, FindingCopy> = {
|
|
66
|
+
"redundant-cd-cwd": {
|
|
67
|
+
body: "the agent runs `cd <cwd>` before commands it would have run from the same directory anyway. mostly harmless. occasionally it gets the path wrong and manufactures a new bug.",
|
|
68
|
+
cost: "tokens burned on redundant navigation. low security risk. high noise.",
|
|
69
|
+
},
|
|
70
|
+
"block-push-master": {
|
|
71
|
+
body: "attempts to push directly to main. branch protection caught some, but the agent kept going. each retry costs a round-trip and pollutes the audit log.",
|
|
72
|
+
cost: "branch protection saved you most of the time. the rest landed or required a revert.",
|
|
73
|
+
},
|
|
74
|
+
"block-force-push": {
|
|
75
|
+
body: "force pushes to non-main branches. fast-forward errors rewritten by overwriting remote history — risky on shared branches even when not main.",
|
|
76
|
+
cost: "lost commits, broken PR diffs, confused reviewers downstream.",
|
|
77
|
+
},
|
|
78
|
+
"block-work-on-main": {
|
|
79
|
+
body: "commits or merges made while the agent was sitting on main / master. work that should land via PR skipped review.",
|
|
80
|
+
cost: "code that didn't pass review made it into the default branch.",
|
|
81
|
+
},
|
|
82
|
+
"block-read-outside-cwd": {
|
|
83
|
+
body: "reads outside the project root. some hit credential files (~/.aws/credentials, ~/.config/openai/key, out-of-tree .env). none made it back to stdout — but they made it into context.",
|
|
84
|
+
cost: "credential exposure risk. data crossed project boundaries into the agent's context window.",
|
|
85
|
+
},
|
|
86
|
+
"block-env-files": {
|
|
87
|
+
body: "the agent tried to read or write `.env` files directly. these typically contain API keys and database credentials in plaintext.",
|
|
88
|
+
cost: "high exposure risk. secrets one tool-call away from leaving the project.",
|
|
89
|
+
},
|
|
90
|
+
"block-secrets-write": {
|
|
91
|
+
body: "attempts to write credential-shaped strings to files that aren't typically credential stores.",
|
|
92
|
+
cost: "could have committed live secrets to the repo.",
|
|
93
|
+
},
|
|
94
|
+
"block-rm-rf": {
|
|
95
|
+
body: "recursive deletes against paths that could plausibly take out unrelated work. `rm -rf` is the agent's preferred way of cleaning up — even when it shouldn't be.",
|
|
96
|
+
cost: "irreversible. one wrong path argument = lost work.",
|
|
97
|
+
},
|
|
98
|
+
"block-sudo": {
|
|
99
|
+
body: "sudo invocations from inside the agent shell. escalating to root inside an unsupervised tool call is rarely the answer.",
|
|
100
|
+
cost: "privilege escalation in a context where the agent isn't meant to have it.",
|
|
101
|
+
},
|
|
102
|
+
"block-curl-pipe-sh": {
|
|
103
|
+
body: "curl | sh patterns — fetching a remote script and piping it straight into the shell. no checksum, no review, no rollback.",
|
|
104
|
+
cost: "supply-chain attack surface. arbitrary code execution from a URL.",
|
|
105
|
+
},
|
|
106
|
+
"warn-repeated-tool-calls": {
|
|
107
|
+
body: "same call, same args, multiple times under 90 seconds. no diagnosis between attempts. the call's been failing for the same reason every time.",
|
|
108
|
+
cost: "retry overhead. sessions stall before manual correction.",
|
|
109
|
+
},
|
|
110
|
+
"sleep-polling-loop": {
|
|
111
|
+
body: "long sleeps or busy-wait loops where the agent waits for a state it has no reason to expect.",
|
|
112
|
+
cost: "wall-clock burned. better to wait for an explicit signal.",
|
|
113
|
+
},
|
|
114
|
+
"find-from-root": {
|
|
115
|
+
body: "`find` invoked against `/`, `/home`, `/usr`, etc. — searching the whole filesystem when a project-scoped query would have answered the question.",
|
|
116
|
+
cost: "exhausts resources. surfaces files outside the project that taint context.",
|
|
117
|
+
},
|
|
118
|
+
"git-commit-no-verify": {
|
|
119
|
+
body: "commits made with `--no-verify` / `-n`, skipping pre-commit hooks. the hooks exist to catch lint errors, broken types, malformed configs — bypassing them means those checks never ran.",
|
|
120
|
+
cost: "broken or unsafe code lands without the safety net.",
|
|
121
|
+
},
|
|
122
|
+
"prefer-edit-over-read-cat": {
|
|
123
|
+
body: "`cat` / `head` / `tail` on source files routed through Bash output instead of the Read tool. round-trips the file through a less efficient channel.",
|
|
124
|
+
cost: "burns tokens on shell output that the Read tool would have returned cleanly.",
|
|
125
|
+
},
|
|
126
|
+
"prefer-edit-over-sed-awk": {
|
|
127
|
+
body: "in-place edits via `sed -i` or `awk … > file`. no diff to inspect, no rollback if the regex was wrong.",
|
|
128
|
+
cost: "destructive when the regex matches more than expected. no verification surface.",
|
|
129
|
+
},
|
|
130
|
+
"prefer-write-over-heredoc": {
|
|
131
|
+
body: "multi-line file writes via heredoc or `echo > file`. the Write tool handles escaping and produces a verifiable diff.",
|
|
132
|
+
cost: "subtle escape bugs. content arrives in the file with quoting drift.",
|
|
133
|
+
},
|
|
134
|
+
"reread-after-edit": {
|
|
135
|
+
body: "reads of files that were Edit'd or Write'n earlier in the same session. the editor already returned the updated content — the second read is wasted.",
|
|
136
|
+
cost: "tokens spent re-fetching content the tool already returned.",
|
|
137
|
+
},
|
|
138
|
+
"warn-large-file-write": {
|
|
139
|
+
body: "writes to files significantly larger than typical for the project. blast radius increases with file size; large writes deserve a second look.",
|
|
140
|
+
cost: "harder to review, harder to roll back, easier to break something downstream.",
|
|
141
|
+
},
|
|
142
|
+
"warn-background-process": {
|
|
143
|
+
body: "spawned a background process and moved on. nothing watches the process; if it crashes the agent doesn't know.",
|
|
144
|
+
cost: "silent failures. resource leaks if the process never exits.",
|
|
145
|
+
},
|
|
146
|
+
"require-commit-before-stop": {
|
|
147
|
+
body: "the agent reported a task complete while changes were still uncommitted in the working tree.",
|
|
148
|
+
cost: "unsaved work. next session starts with a dirty checkout the agent thinks is clean.",
|
|
149
|
+
},
|
|
150
|
+
"require-push-before-stop": {
|
|
151
|
+
body: "the agent stopped with commits sitting only on the local branch — nothing pushed to the remote.",
|
|
152
|
+
cost: "no one else can see the work. silent loss if the machine dies.",
|
|
153
|
+
},
|
|
154
|
+
"require-pr-before-stop": {
|
|
155
|
+
body: "the agent stopped without opening a PR. the commits are on a branch nobody reviewed.",
|
|
156
|
+
cost: "no review, no merge path, no record that the work happened.",
|
|
157
|
+
},
|
|
158
|
+
"require-ci-green-before-stop": {
|
|
159
|
+
body: "the agent declared completion before CI returned green (or while CI was already failing).",
|
|
160
|
+
cost: "false completion signal. broken main if anyone trusts the agent's word.",
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
function shortName(name: string): string {
|
|
165
|
+
const slash = name.indexOf("/");
|
|
166
|
+
return slash >= 0 ? name.slice(slash + 1) : name;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function relTimeAgo(iso?: string): string {
|
|
170
|
+
if (!iso) return "—";
|
|
171
|
+
const ms = Date.now() - new Date(iso).getTime();
|
|
172
|
+
if (Number.isNaN(ms) || ms < 0) return "—";
|
|
173
|
+
const m = Math.floor(ms / 60_000);
|
|
174
|
+
if (m < 60) return `${Math.max(1, m)}m ago`;
|
|
175
|
+
const h = Math.floor(m / 60);
|
|
176
|
+
if (h < 24) return `${h}h ago`;
|
|
177
|
+
const d = Math.floor(h / 24);
|
|
178
|
+
if (d < 30) return `${d}d ago`;
|
|
179
|
+
const months = Math.floor(d / 30);
|
|
180
|
+
return `${months}mo ago`;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export interface FindingCard {
|
|
184
|
+
num: string;
|
|
185
|
+
title: string;
|
|
186
|
+
count: number;
|
|
187
|
+
/** Unique identifier for React keys. This is the original detector
|
|
188
|
+
* or policy short slug (e.g. "redundant-cd-cwd", "block-push-master"),
|
|
189
|
+
* NOT the prescribed-fix slug — which can repeat across cards when
|
|
190
|
+
* multiple detectors share the same fix policy. */
|
|
191
|
+
sourceSlug: string;
|
|
192
|
+
/** Slug shown in the meta line — the prescribed-fix policy. May
|
|
193
|
+
* repeat across cards (e.g. several detectors → warn-repeated-tool-calls). */
|
|
194
|
+
policy: string;
|
|
195
|
+
projects: number;
|
|
196
|
+
lastSeen: string;
|
|
197
|
+
body: string;
|
|
198
|
+
cost: string;
|
|
199
|
+
evidence: { text: string; kind: "cmd" | "comment" | "err" }[];
|
|
200
|
+
/** Prescribed fix. Always populated now — detectors route to their
|
|
201
|
+
* closest builtin policy (see DETECTOR_TO_POLICY). */
|
|
202
|
+
fix: { slug: string; desc: string; install: string; alsoCoveredBy?: string };
|
|
203
|
+
/** True when the prescribed fix policy is already in the user's
|
|
204
|
+
* enabled set. UI tones the fix block accordingly. */
|
|
205
|
+
alreadyEnabled: boolean;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/** Build the per-policy/detector finding cards. Ranks by hits desc and
|
|
209
|
+
* drops rows that would otherwise be uninformative (zero hits). */
|
|
210
|
+
export function deriveFindings(result: AuditResult): FindingCard[] {
|
|
211
|
+
const sorted = [...result.results]
|
|
212
|
+
.filter((r) => r.hits > 0)
|
|
213
|
+
.sort((a, b) => b.hits - a.hits);
|
|
214
|
+
|
|
215
|
+
const enabledSet = new Set(result.enabledBuiltinNames ?? []);
|
|
216
|
+
return sorted.map((r, i) => buildCard(r, i, enabledSet));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** Lightweight metadata for a policy that we may need to display even
|
|
220
|
+
* when the policy didn't fire on its own (a detector pointed at it).
|
|
221
|
+
* Mirrors the relevant subset of `BuiltinPolicy` so this module stays
|
|
222
|
+
* client-bundle-safe (no node imports). */
|
|
223
|
+
const POLICY_META: Record<string, { displayTitle: string; impact: string }> = {
|
|
224
|
+
"warn-repeated-tool-calls": {
|
|
225
|
+
displayTitle: "Called the same tool 3+ times with identical arguments",
|
|
226
|
+
impact: "catches identical-arg retries before they spiral into a token-burning loop.",
|
|
227
|
+
},
|
|
228
|
+
"block-read-outside-cwd": {
|
|
229
|
+
displayTitle: "Tried to read files outside your project directory",
|
|
230
|
+
impact: "denies reads of files outside the project root, including symlinks.",
|
|
231
|
+
},
|
|
232
|
+
"block-env-files": {
|
|
233
|
+
displayTitle: "Tried to read or write a .env file",
|
|
234
|
+
impact: "blocks reads and writes of `.env` files at the tool layer.",
|
|
235
|
+
},
|
|
236
|
+
"block-secrets-write": {
|
|
237
|
+
displayTitle: "Tried to write a secret-key file",
|
|
238
|
+
impact: "blocks writes to .pem, id_rsa, credentials.json, and similar.",
|
|
239
|
+
},
|
|
240
|
+
"warn-background-process": {
|
|
241
|
+
displayTitle: "Started a long-lived background process",
|
|
242
|
+
impact: "warns on nohup / & / screen / tmux / disown patterns the agent forgets to clean up.",
|
|
243
|
+
},
|
|
244
|
+
"warn-git-amend": {
|
|
245
|
+
displayTitle: "Used git commit --amend",
|
|
246
|
+
impact: "warns before amending — same class as dangerous-commit-flag bypasses.",
|
|
247
|
+
},
|
|
248
|
+
"require-ci-green-before-stop": {
|
|
249
|
+
displayTitle: "Stopped with failing CI",
|
|
250
|
+
impact: "requires CI checks to pass on HEAD before declaring done.",
|
|
251
|
+
},
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
function buildCard(r: AuditCount, idx: number, enabledSet: Set<string>): FindingCard {
|
|
255
|
+
const slug = shortName(r.name);
|
|
256
|
+
const isDetector = r.source === "audit-detector";
|
|
257
|
+
const mapping = isDetector ? DETECTOR_TO_POLICY[slug] : undefined;
|
|
258
|
+
|
|
259
|
+
// For a detector, the prescribed fix points at its mapped policy.
|
|
260
|
+
// For a builtin row, it points at itself.
|
|
261
|
+
const fixSlug = mapping?.primary ?? slug;
|
|
262
|
+
const meta = POLICY_META[fixSlug];
|
|
263
|
+
const fixDesc = meta?.impact ?? r.impact ?? r.displayTitle;
|
|
264
|
+
const alsoCoveredBy = mapping?.also;
|
|
265
|
+
|
|
266
|
+
const alreadyEnabled = enabledSet.has(fixSlug)
|
|
267
|
+
|| (r.source === "builtin" && r.enabledInConfig);
|
|
268
|
+
|
|
269
|
+
const copy = FINDING_COPY[slug];
|
|
270
|
+
|
|
271
|
+
const evidence: FindingCard["evidence"] = r.examples.slice(0, 4).map((e) => ({
|
|
272
|
+
text: e.example,
|
|
273
|
+
kind: "cmd" as const,
|
|
274
|
+
}));
|
|
275
|
+
if (evidence.length === 0) {
|
|
276
|
+
evidence.push({ text: "no example commands captured.", kind: "comment" });
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
num: String(idx + 1).padStart(2, "0"),
|
|
281
|
+
title: r.displayTitle.toLowerCase(),
|
|
282
|
+
count: r.hits,
|
|
283
|
+
sourceSlug: slug,
|
|
284
|
+
policy: fixSlug,
|
|
285
|
+
projects: r.projects,
|
|
286
|
+
lastSeen: relTimeAgo(r.lastSeen),
|
|
287
|
+
body: copy?.body ?? r.impact ?? r.displayTitle,
|
|
288
|
+
cost: copy?.cost ?? r.impact ?? "see policy description above.",
|
|
289
|
+
evidence,
|
|
290
|
+
fix: {
|
|
291
|
+
slug: fixSlug,
|
|
292
|
+
desc: fixDesc,
|
|
293
|
+
install: `failproofai policy add ${fixSlug}`,
|
|
294
|
+
alsoCoveredBy,
|
|
295
|
+
},
|
|
296
|
+
alreadyEnabled,
|
|
297
|
+
};
|
|
298
|
+
}
|
package/src/audit/index.ts
CHANGED
|
@@ -14,14 +14,9 @@ import { normalizePolicyName } from "../hooks/policy-registry";
|
|
|
14
14
|
import { INTEGRATION_TYPES, type IntegrationType } from "../hooks/types";
|
|
15
15
|
import { ADAPTERS } from "./cli-adapters";
|
|
16
16
|
import { AUDIT_DETECTORS } from "./detectors";
|
|
17
|
+
import { severityForBuiltin } from "./features";
|
|
17
18
|
import { readCachedTranscriptResult, writeCachedTranscriptResult } from "./cache";
|
|
18
|
-
import { initReplay, replayEvent } from "./replay";
|
|
19
|
-
import {
|
|
20
|
-
trackAuditCompleted,
|
|
21
|
-
trackAuditInstallCtaShown,
|
|
22
|
-
trackAuditPatternDetected,
|
|
23
|
-
trackAuditStarted,
|
|
24
|
-
} from "./telemetry";
|
|
19
|
+
import { initReplay, replayEvent, restoreReplay } from "./replay";
|
|
25
20
|
import {
|
|
26
21
|
AUDIT_EXAMPLE_MAX_CHARS,
|
|
27
22
|
AUDIT_MAX_EXAMPLES_PER_NAME,
|
|
@@ -100,6 +95,8 @@ async function scanOneTranscript(meta: TranscriptMetadata): Promise<TranscriptAu
|
|
|
100
95
|
sessionId: meta.sessionId,
|
|
101
96
|
mtimeMs: meta.mtimeMs,
|
|
102
97
|
sizeBytes: meta.sizeBytes,
|
|
98
|
+
cwd: "",
|
|
99
|
+
eventsScanned: 0,
|
|
103
100
|
hitsByName: {},
|
|
104
101
|
examplesByName: {},
|
|
105
102
|
rangeByName: {},
|
|
@@ -111,6 +108,10 @@ async function scanOneTranscript(meta: TranscriptMetadata): Promise<TranscriptAu
|
|
|
111
108
|
if (events.length === 0) return empty;
|
|
112
109
|
|
|
113
110
|
const result = empty;
|
|
111
|
+
result.eventsScanned = events.length;
|
|
112
|
+
// Capture the session's cwd from the first event that carried one — every
|
|
113
|
+
// event in a single transcript shares the same cwd by construction.
|
|
114
|
+
result.cwd = events[0].cwd || "";
|
|
114
115
|
const sessionState: DetectorSessionState = {};
|
|
115
116
|
|
|
116
117
|
for (const event of events) {
|
|
@@ -238,7 +239,10 @@ function aggregateResults(
|
|
|
238
239
|
name,
|
|
239
240
|
source,
|
|
240
241
|
category: detector?.category ?? builtin?.category ?? "Custom",
|
|
241
|
-
|
|
242
|
+
// Builtins carry no static severity field — derive it from the policy
|
|
243
|
+
// name prefix (sanitize-/warn-/block-/…) so the score's gentle/medium
|
|
244
|
+
// buckets actually populate instead of everything collapsing to "deny".
|
|
245
|
+
severity: isDetector ? (detector?.severity ?? "info") : severityForBuiltin(name),
|
|
242
246
|
hits: bucket.hits,
|
|
243
247
|
projects: bucket.projects.size,
|
|
244
248
|
firstSeen: bucket.first,
|
|
@@ -258,10 +262,17 @@ function aggregateResults(
|
|
|
258
262
|
export async function runAudit(opts: RunAuditOptions = {}): Promise<AuditResult> {
|
|
259
263
|
const startedAt = Date.now();
|
|
260
264
|
initReplay();
|
|
265
|
+
try {
|
|
266
|
+
return await runAuditInner(opts, startedAt);
|
|
267
|
+
} finally {
|
|
268
|
+
// Always restore the caller's policy registry, even on error. Without
|
|
269
|
+
// this, embedding runAudit() in a long-running process (e.g. the Next.js
|
|
270
|
+
// dashboard) would clobber any pre-existing policy registrations.
|
|
271
|
+
restoreReplay();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
261
274
|
|
|
262
|
-
|
|
263
|
-
trackAuditStarted(opts, outputMode);
|
|
264
|
-
|
|
275
|
+
async function runAuditInner(opts: RunAuditOptions, startedAt: number): Promise<AuditResult> {
|
|
265
276
|
const clis = (opts.clis ?? Array.from(INTEGRATION_TYPES)) as IntegrationType[];
|
|
266
277
|
const sinceMs = parseSinceOpt(opts.since);
|
|
267
278
|
|
|
@@ -301,13 +312,19 @@ export async function runAudit(opts: RunAuditOptions = {}): Promise<AuditResult>
|
|
|
301
312
|
return fresh;
|
|
302
313
|
} catch {
|
|
303
314
|
errors++;
|
|
315
|
+
// Match the empty/full result shape — `cwd` is unknowable here (we
|
|
316
|
+
// never got to scan the events that carry it), but `eventsScanned: 0`
|
|
317
|
+
// is right and keeps the aggregator's `t.eventsScanned ?? 0` shape
|
|
318
|
+
// explicit. cwd defaults to "" so `if (t.cwd)` skips it cleanly.
|
|
304
319
|
return {
|
|
305
320
|
transcriptPath: meta.transcriptPath,
|
|
306
321
|
cli: meta.cli,
|
|
307
322
|
projectName: meta.projectName,
|
|
323
|
+
cwd: "",
|
|
308
324
|
sessionId: meta.sessionId,
|
|
309
325
|
mtimeMs: meta.mtimeMs,
|
|
310
326
|
sizeBytes: meta.sizeBytes,
|
|
327
|
+
eventsScanned: 0,
|
|
311
328
|
hitsByName: {},
|
|
312
329
|
examplesByName: {},
|
|
313
330
|
rangeByName: {},
|
|
@@ -331,12 +348,16 @@ export async function runAudit(opts: RunAuditOptions = {}): Promise<AuditResult>
|
|
|
331
348
|
|
|
332
349
|
const totalsHits = results.reduce((sum, r) => sum + r.hits, 0);
|
|
333
350
|
const projectsWithHits = new Set<string>();
|
|
351
|
+
const projectsScannedSet = new Set<string>();
|
|
352
|
+
let eventsScanned = 0;
|
|
334
353
|
for (const t of perTranscript) {
|
|
335
354
|
if (Object.keys(t.hitsByName).length > 0) projectsWithHits.add(t.projectName);
|
|
355
|
+
if (t.cwd) projectsScannedSet.add(t.cwd);
|
|
356
|
+
eventsScanned += t.eventsScanned ?? 0;
|
|
336
357
|
}
|
|
337
358
|
|
|
338
359
|
const auditResult: AuditResult = {
|
|
339
|
-
version:
|
|
360
|
+
version: 2,
|
|
340
361
|
scannedAt: new Date(startedAt).toISOString(),
|
|
341
362
|
scope: {
|
|
342
363
|
cli: clis,
|
|
@@ -354,16 +375,13 @@ export async function runAudit(opts: RunAuditOptions = {}): Promise<AuditResult>
|
|
|
354
375
|
hits: totalsHits,
|
|
355
376
|
projectsWithHits: projectsWithHits.size,
|
|
356
377
|
},
|
|
378
|
+
projectsScanned: [...projectsScannedSet].sort(),
|
|
379
|
+
eventsScanned,
|
|
380
|
+
// Pull short names off the user's enabled builtin set so the dashboard
|
|
381
|
+
// can answer "is policy X enabled?" without iterating result rows.
|
|
382
|
+
enabledBuiltinNames: [...enabledBuiltins]
|
|
383
|
+
.map((n) => (n.includes("/") ? n.slice(n.indexOf("/") + 1) : n)),
|
|
357
384
|
};
|
|
358
385
|
|
|
359
|
-
// Telemetry — fire-and-forget, never blocks the CLI. See src/audit/telemetry.ts
|
|
360
|
-
// for the privacy contract (slugs + counts + booleans only).
|
|
361
|
-
for (const count of results) trackAuditPatternDetected(count);
|
|
362
|
-
const unenabledBuiltinNames = results
|
|
363
|
-
.filter((r) => r.source === "builtin" && !r.enabledInConfig)
|
|
364
|
-
.map((r) => r.name);
|
|
365
|
-
trackAuditInstallCtaShown(unenabledBuiltinNames);
|
|
366
|
-
trackAuditCompleted(auditResult, outputMode);
|
|
367
|
-
|
|
368
386
|
return auditResult;
|
|
369
387
|
}
|
package/src/audit/replay.ts
CHANGED
|
@@ -16,7 +16,13 @@
|
|
|
16
16
|
import type { EvaluationResult } from "../hooks/policy-evaluator";
|
|
17
17
|
import { evaluatePolicies } from "../hooks/policy-evaluator";
|
|
18
18
|
import { BUILTIN_POLICIES, registerBuiltinPolicies } from "../hooks/builtin-policies";
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
clearPolicies,
|
|
21
|
+
getAllPolicies,
|
|
22
|
+
normalizePolicyName,
|
|
23
|
+
setAllPolicies,
|
|
24
|
+
} from "../hooks/policy-registry";
|
|
25
|
+
import type { RegisteredPolicy } from "../hooks/policy-types";
|
|
20
26
|
import type { SessionMetadata } from "../hooks/types";
|
|
21
27
|
import type { NormalizedToolEvent } from "./types";
|
|
22
28
|
|
|
@@ -29,12 +35,18 @@ const SKIP_POLICIES = new Set(
|
|
|
29
35
|
);
|
|
30
36
|
|
|
31
37
|
let initialized = false;
|
|
38
|
+
/** Snapshot of the registry taken at `initReplay()`. Restored by
|
|
39
|
+
* `restoreReplay()` so embedding `runAudit()` in a long-running process
|
|
40
|
+
* (e.g. the Next.js dashboard) doesn't wipe any prior policy registrations. */
|
|
41
|
+
let savedSnapshot: RegisteredPolicy[] | null = null;
|
|
32
42
|
|
|
33
43
|
/** Register every builtin policy (regardless of user config) so the replay
|
|
34
44
|
* shows what *could* be caught, not just what's currently enabled. Called
|
|
35
|
-
* once per `runAudit` invocation.
|
|
45
|
+
* once per `runAudit` invocation. Snapshots the existing registry so it can
|
|
46
|
+
* be restored by `restoreReplay()` once the audit is done. */
|
|
36
47
|
export function initReplay(): void {
|
|
37
48
|
if (initialized) return;
|
|
49
|
+
savedSnapshot = getAllPolicies();
|
|
38
50
|
clearPolicies();
|
|
39
51
|
const enabled = BUILTIN_POLICIES
|
|
40
52
|
.map((p) => p.name)
|
|
@@ -43,9 +55,23 @@ export function initReplay(): void {
|
|
|
43
55
|
initialized = true;
|
|
44
56
|
}
|
|
45
57
|
|
|
46
|
-
/**
|
|
58
|
+
/** Restore the registry to whatever was there before `initReplay()`. Safe to
|
|
59
|
+
* call when not initialized (no-op). Always paired with `initReplay()` in a
|
|
60
|
+
* try/finally inside `runAudit()`. */
|
|
61
|
+
export function restoreReplay(): void {
|
|
62
|
+
if (!initialized) return;
|
|
63
|
+
if (savedSnapshot !== null) {
|
|
64
|
+
setAllPolicies(savedSnapshot);
|
|
65
|
+
savedSnapshot = null;
|
|
66
|
+
}
|
|
67
|
+
initialized = false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Reset for tests / repeated audits in the same process. Drops the snapshot
|
|
71
|
+
* too — tests usually start with an empty registry and want it back. */
|
|
47
72
|
export function resetReplay(): void {
|
|
48
73
|
initialized = false;
|
|
74
|
+
savedSnapshot = null;
|
|
49
75
|
clearPolicies();
|
|
50
76
|
}
|
|
51
77
|
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Score derivation for the audit dashboard.
|
|
3
|
+
*
|
|
4
|
+
* Score is on 0-100, mapped to letter grades that anchor the leaderboard
|
|
5
|
+
* + tier prose. The thresholds match the reference design (assets/audit):
|
|
6
|
+
*
|
|
7
|
+
* ≥ 90 S "s tier"
|
|
8
|
+
* ≥ 80 A "a tier"
|
|
9
|
+
* ≥ 71 B "b tier"
|
|
10
|
+
* ≥ 55 C "c tier"
|
|
11
|
+
* ≥ 40 D "d tier"
|
|
12
|
+
* < 40 F "f tier"
|
|
13
|
+
*
|
|
14
|
+
* The "projected score" is the hypothetical score after enabling every
|
|
15
|
+
* recommended unenabled-builtin policy — used by the prescription section
|
|
16
|
+
* to motivate enabling them.
|
|
17
|
+
*/
|
|
18
|
+
import type { AuditResult } from "./types";
|
|
19
|
+
|
|
20
|
+
export type Grade = "S" | "A" | "B" | "C" | "D" | "F";
|
|
21
|
+
|
|
22
|
+
export function gradeFor(score: number): Grade {
|
|
23
|
+
if (score >= 90) return "S";
|
|
24
|
+
if (score >= 80) return "A";
|
|
25
|
+
if (score >= 71) return "B";
|
|
26
|
+
if (score >= 55) return "C";
|
|
27
|
+
if (score >= 40) return "D";
|
|
28
|
+
return "F";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const TIER_NAME: Record<Grade, string> = {
|
|
32
|
+
S: "s tier", A: "a tier", B: "b tier",
|
|
33
|
+
C: "c tier", D: "d tier", F: "f tier",
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export function tierName(g: Grade): string {
|
|
37
|
+
return TIER_NAME[g];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Heuristic score on 0-100. Three properties make it *dynamic* — distinct
|
|
42
|
+
* inputs (almost) never collide on a fixed threshold the way the old
|
|
43
|
+
* hard-capped scorer did:
|
|
44
|
+
*
|
|
45
|
+
* 1. Rate-normalised. Penalty scales with the *rate* of weighted faults per
|
|
46
|
+
* tool call (× REF_EVENTS), not the absolute count. A 1000-call session
|
|
47
|
+
* with 25 denies scores higher than a 100-call one with 25 denies — and
|
|
48
|
+
* heavy users no longer all pile onto the same cap.
|
|
49
|
+
*
|
|
50
|
+
* 2. Saturating, not clipped. Each severity bucket asymptotes to a cap via
|
|
51
|
+
* `cap·(1 − e^(−p/k))` instead of `min(p, cap)`. One bad area still can't
|
|
52
|
+
* tank the score, but the curve is *strictly monotonic*, so every extra
|
|
53
|
+
* hit still moves the number — no two counts land on the same value.
|
|
54
|
+
*
|
|
55
|
+
* 3. Credited. Up to +5 from the derived strengths, so clean agents spread
|
|
56
|
+
* upward instead of all sitting at 100.
|
|
57
|
+
*
|
|
58
|
+
* Per-hit weights (pre-normalisation): deny 1.2, warn/instruct 0.7,
|
|
59
|
+
* sanitize 0.4, audit detector 0.5. Bucket caps 50 / 28 / 16 / 30 (they sum
|
|
60
|
+
* past 100 so a multi-dimension reckless agent can bottom out at F).
|
|
61
|
+
*
|
|
62
|
+
* Sessions with zero scanned transcripts return 0 (no signal, no grade).
|
|
63
|
+
*/
|
|
64
|
+
import { MIN_EVENTS } from "./features";
|
|
65
|
+
import { deriveStrengths } from "./strengths";
|
|
66
|
+
|
|
67
|
+
/** Reference tool-call volume the rate is normalised against — chosen so a
|
|
68
|
+
* moderate footprint lands around C/B and the demo anchor (~58 → C) holds.
|
|
69
|
+
* Calibrated via __tests__/audit/scoring.test.ts. */
|
|
70
|
+
const REF_EVENTS = 300;
|
|
71
|
+
|
|
72
|
+
/** Concave saturator: → `cap` as `p → ∞`, strictly increasing for all p ≥ 0. */
|
|
73
|
+
function saturate(p: number, cap: number, k: number): number {
|
|
74
|
+
return cap * (1 - Math.exp(-p / k));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Total weighted penalty for a set of rows, rate-normalised against `events`.
|
|
78
|
+
* Shared by `deriveScore` and `projectedScore` so they can't diverge. */
|
|
79
|
+
function penaltyFor(rows: AuditResult["results"], events: number): number {
|
|
80
|
+
const norm = REF_EVENTS / Math.max(events, MIN_EVENTS);
|
|
81
|
+
let deny = 0, instruct = 0, sanitize = 0, detector = 0;
|
|
82
|
+
for (const row of rows) {
|
|
83
|
+
if (row.source === "audit-detector") {
|
|
84
|
+
detector += row.hits * 0.5;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const sev = row.severity;
|
|
88
|
+
if (sev === "deny") deny += row.hits * 1.2;
|
|
89
|
+
else if (sev === "instruct" || sev === "warn") instruct += row.hits * 0.7;
|
|
90
|
+
else sanitize += row.hits * 0.4; // sanitize-* and any other gentle category
|
|
91
|
+
}
|
|
92
|
+
// Per-bucket (cap, k). The cap bounds any single failure mode; k sets how
|
|
93
|
+
// fast it ramps. k is small relative to the cap so penalties bite early and
|
|
94
|
+
// the score uses the full S→F range rather than clustering near 100. Caps
|
|
95
|
+
// sum past 100 on purpose, so a multi-dimension reckless agent can reach F.
|
|
96
|
+
return (
|
|
97
|
+
saturate(deny * norm, 50, 12) +
|
|
98
|
+
saturate(instruct * norm, 28, 10) +
|
|
99
|
+
saturate(sanitize * norm, 16, 8) +
|
|
100
|
+
saturate(detector * norm, 30, 14)
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Positive credit (0-5) from the heuristic strengths. Deliberately small so a
|
|
105
|
+
* reckless agent's "absence" strengths (e.g. "no credential leaks") can't
|
|
106
|
+
* inflate it back into the top tier. */
|
|
107
|
+
function creditFor(result: AuditResult): number {
|
|
108
|
+
return Math.min(deriveStrengths(result).length * 1.0, 5);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Exact (unrounded) score — used by tests to prove strict monotonicity and
|
|
112
|
+
* the absence of threshold collisions. */
|
|
113
|
+
export function deriveScoreExact(result: AuditResult): number {
|
|
114
|
+
if (result.transcripts.scanned === 0) return 0;
|
|
115
|
+
const events = result.eventsScanned ?? 0;
|
|
116
|
+
const score = 100 - penaltyFor(result.results, events) + creditFor(result);
|
|
117
|
+
return Math.max(0, Math.min(100, score));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function deriveScore(result: AuditResult): number {
|
|
121
|
+
return Math.round(deriveScoreExact(result));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Projected score after enabling every unenabled builtin. Doesn't actually
|
|
126
|
+
* re-run the audit — instead it credits back the hits the user would have
|
|
127
|
+
* blocked by enabling those policies, applying the same weighted penalty
|
|
128
|
+
* scheme used by `deriveScore`.
|
|
129
|
+
*
|
|
130
|
+
* Caps at 92 so the prescription never promises a guaranteed S — the user
|
|
131
|
+
* still has to keep the policies on.
|
|
132
|
+
*/
|
|
133
|
+
export function projectedScore(result: AuditResult, currentScore: number): number {
|
|
134
|
+
const events = result.eventsScanned ?? 0;
|
|
135
|
+
// Penalty as-is vs. penalty with every unenabled builtin's hits removed
|
|
136
|
+
// (enabling those policies would have blocked them). The delta is what the
|
|
137
|
+
// user recovers — computed through the same saturating, rate-normalised
|
|
138
|
+
// curve as `deriveScore`, so the projection is consistent rather than a
|
|
139
|
+
// naive per-hit sum.
|
|
140
|
+
const full = penaltyFor(result.results, events);
|
|
141
|
+
const fixedRows = result.results.filter(
|
|
142
|
+
(r) => !(r.source === "builtin" && !r.enabledInConfig),
|
|
143
|
+
);
|
|
144
|
+
const fixed = penaltyFor(fixedRows, events);
|
|
145
|
+
const recoverable = Math.max(0, full - fixed);
|
|
146
|
+
// Cap at 92 so the prescription never promises a guaranteed S.
|
|
147
|
+
const proj = Math.min(92, currentScore + Math.round(recoverable));
|
|
148
|
+
return Math.max(currentScore, proj);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Approximate global rank in the cohort. We don't have a real leaderboard
|
|
153
|
+
* yet — this is a deterministic synthetic rank derived from the score so
|
|
154
|
+
* the UI doesn't feel jittery as the user re-runs.
|
|
155
|
+
*
|
|
156
|
+
* Distribution roughly matches a bell-shape centered at 60. Cohort size
|
|
157
|
+
* is fixed at 2316 to match the reference design.
|
|
158
|
+
*/
|
|
159
|
+
export const COHORT_SIZE = 2316;
|
|
160
|
+
|
|
161
|
+
export function syntheticRank(score: number): number {
|
|
162
|
+
// Roughly: 100 → top of leaderboard, 0 → bottom. Use a smooth curve so
|
|
163
|
+
// small score changes feel meaningful but not catastrophic.
|
|
164
|
+
const percentile = scoreToPercentile(score);
|
|
165
|
+
return Math.max(1, Math.min(COHORT_SIZE, Math.round((1 - percentile) * COHORT_SIZE)));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function scoreToPercentile(score: number): number {
|
|
169
|
+
// Logistic mapping centered at 58 — agents below 58 fall into the long
|
|
170
|
+
// tail, agents above climb steeply. Anchors the default demo (58 → ~p20).
|
|
171
|
+
const z = (score - 58) / 14;
|
|
172
|
+
const p = 1 / (1 + Math.exp(-z));
|
|
173
|
+
return p;
|
|
174
|
+
}
|