failproofai 0.0.10 → 0.0.11-beta.10
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 +9 -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 +51 -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/invite/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/audit/invite/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/audit/invite/route.js +7 -0
- package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/audit/invite/route_client-reference-manifest.js +3 -0
- 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/build-manifest.json +9 -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.map +5 -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 +9 -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]__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]__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]__13h8pzr._.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]__1_mqemn._.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]__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]__044xt9.._.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]__1r1h8v9._.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]__1uatkiv._.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/[root-of-the-server]__1y6gxxb._.js +3 -0
- package/.next/standalone/.next/server/chunks/{_0ebx_lc._.js → _0p53ge1._.js} +2 -2
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_audit_invite_route_actions_0-2n5sy.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_0-tu4ot._.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_0ttxbz7._.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_1bnh1y0._.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_1epycqa._.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_1wpdcgo._.js +3 -0
- 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_1nxcc4v._.js +3 -0
- 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]__01tn1ou._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0808sha._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e4-6d8._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ehe24g._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0f62vu9._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0g253ve._.js +4 -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]__0k65l27._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0vxf0_g._.js +4 -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]__12mcauo._.js +4 -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]__0t5l7a5._.js → [root-of-the-server]__1d8omgc._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__10xgshr._.js → [root-of-the-server]__1dky4g0._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1e-x7j4._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1fax1sl._.js +19 -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]__1pcxxwg._.js +4 -0
- 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]__1uvfwgr._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1w6v_1u._.js +3 -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} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_0il3fl1._.js +3 -0
- 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 +65 -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_0az0sfq._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_1ynf7el._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_0nye1s3.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_1ao30b1.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_0uboya6._.js +6 -0
- 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_0xrgzyz.js +4 -0
- 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 +2 -2
- 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/{dAuQps6jUwCz9X1Q5FFOO → DOSSF5hRUtt3-QZEm-ZIk}/_clientMiddlewareManifest.js +2 -2
- package/.next/standalone/.next/static/chunks/{0pkl..xgo-qox.js → 02e80j0576qfu.js} +1 -1
- package/.next/standalone/.next/static/chunks/{07uz2g0_38qia.js → 03fmihek9n986.js} +1 -1
- package/.next/standalone/.next/static/chunks/0f7d7hnbh4djs.js +1 -0
- package/.next/standalone/.next/static/chunks/0h7auy7hzjyhw.js +1 -0
- package/.next/standalone/.next/static/chunks/0wwt5o04i4zwh.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/13xzda05yw19e.js +1 -0
- package/.next/standalone/.next/static/chunks/{150i0n26fnvso.js → 1__i9af9g78vd.js} +1 -1
- package/.next/standalone/.next/static/chunks/1uxa5lm6yco79.js +1 -0
- package/.next/standalone/.next/static/chunks/20dqelk3xz_ya.css +1 -0
- package/.next/standalone/.next/static/chunks/{0j171xiqge4rv.js → 29lzaddhez98q.js} +1 -1
- package/.next/standalone/.next/static/chunks/29nrs5xs9c4hx.css +2 -0
- package/.next/standalone/.next/static/chunks/{0lt8ko3lw.5yt.js → 2b_e9tyly10lo.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0rnqmir4cd5p9.js → 2h0dkzyy0vocp.js} +1 -1
- package/.next/standalone/.next/static/chunks/2lp3a3a3_4_9o.js +63 -0
- package/.next/standalone/.next/static/chunks/{179yytvmam0ug.js → 2nt_slonrn0rw.js} +1 -1
- package/.next/standalone/.next/static/chunks/2plcgtv_tkv9t.js +1 -0
- package/.next/standalone/.next/static/chunks/33k2epr1iz8_z.js +6 -0
- package/.next/standalone/.next/static/chunks/{0d3shmwh5_nmn.js → 33u59vf_8xpd-.js} +1 -1
- package/.next/standalone/.next/static/chunks/3zkg2s2vzxc3d.js +1 -0
- package/.next/standalone/.next/static/chunks/{turbopack-05z7a19q43zfq.js → turbopack-3lrm4f20fz89b.js} +1 -1
- package/.next/standalone/SECURITY.md +73 -0
- package/.next/standalone/app/actions/get-audit-result.ts +35 -0
- package/.next/standalone/app/api/audit/_state.ts +79 -0
- package/.next/standalone/app/api/audit/invite/route.ts +183 -0
- package/.next/standalone/app/api/audit/run/route.ts +103 -0
- package/.next/standalone/app/api/audit/status/route.ts +24 -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 +397 -0
- package/.next/standalone/app/audit/_components/audit-poster.tsx +326 -0
- package/.next/standalone/app/audit/_components/audit-progress-strip.tsx +98 -0
- package/.next/standalone/app/audit/_components/auth-dialog.tsx +375 -0
- package/.next/standalone/app/audit/_components/come-back-better-section.tsx +333 -0
- package/.next/standalone/app/audit/_components/empty-state.tsx +152 -0
- package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +187 -0
- package/.next/standalone/app/audit/_components/invite-dialog.tsx +227 -0
- package/.next/standalone/app/audit/_components/quirks-section.tsx +75 -0
- package/.next/standalone/app/audit/_components/report-footer.tsx +35 -0
- package/.next/standalone/app/audit/_components/rerun-button.tsx +119 -0
- package/.next/standalone/app/audit/_components/run-progress.tsx +120 -0
- package/.next/standalone/app/audit/_components/share-templates.ts +94 -0
- package/.next/standalone/app/audit/_components/sigil.tsx +36 -0
- package/.next/standalone/app/audit/_components/strengths-section.tsx +45 -0
- package/.next/standalone/app/audit/audit-styles.css +1178 -0
- package/.next/standalone/app/audit/loading.tsx +24 -0
- package/.next/standalone/app/audit/page.tsx +63 -0
- package/.next/standalone/app/components/sessions-list.tsx +77 -80
- package/.next/standalone/app/globals.css +754 -139
- package/.next/standalone/app/layout.tsx +6 -8
- package/.next/standalone/app/policies/hooks-client.tsx +340 -141
- package/.next/standalone/app/project/[name]/page.tsx +31 -37
- package/.next/standalone/app/projects/loading.tsx +30 -8
- package/.next/standalone/app/projects/page.tsx +66 -17
- 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 +119 -65
- package/.next/standalone/components/reach-developers.tsx +39 -11
- package/.next/standalone/lib/atomic-write.ts +67 -0
- package/.next/standalone/lib/auth/api-server-client.ts +306 -0
- package/.next/standalone/lib/auth/auth-store.ts +250 -0
- package/.next/standalone/lib/claude-sessions.ts +181 -0
- package/.next/standalone/lib/client-telemetry.ts +2 -0
- package/.next/standalone/lib/fetch-with-timeout.ts +59 -0
- package/.next/standalone/lib/share-card.ts +144 -0
- package/.next/standalone/lib/telemetry.ts +12 -7
- package/.next/standalone/node_modules/@next/env/package.json +2 -2
- package/.next/standalone/node_modules/next/dist/build/static-paths/app.js +2 -1
- package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
- package/.next/standalone/node_modules/next/dist/build/utils.js +2 -1
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/fetch-server-response.js +2 -2
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/set-cache-busting-search-param.js +8 -2
- package/.next/standalone/node_modules/next/dist/client/dev/debug-channel.js +102 -2
- package/.next/standalone/node_modules/next/dist/client/route-params.js +23 -6
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js +13 -13
- 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 +10 -10
- 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 +21 -14
- package/.next/standalone/node_modules/next/dist/server/app-render/app-render.js +62 -9
- package/.next/standalone/node_modules/next/dist/server/app-render/collect-segment-data.js +16 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/create-component-tree.js +49 -19
- package/.next/standalone/node_modules/next/dist/server/app-render/get-script-nonce-from-header.js +8 -20
- package/.next/standalone/node_modules/next/dist/server/app-render/metadata-insertion/create-server-inserted-metadata.js +8 -7
- package/.next/standalone/node_modules/next/dist/server/app-render/use-flight-response.js +2 -2
- package/.next/standalone/node_modules/next/dist/server/async-storage/work-store.js +2 -1
- package/.next/standalone/node_modules/next/dist/server/base-server.js +13 -5
- 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/dev/static-paths-worker.js +2 -1
- package/.next/standalone/node_modules/next/dist/server/image-optimizer.js +22 -2
- 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/is-rsc-request.js +18 -0
- package/.next/standalone/node_modules/next/dist/server/lib/mock-request.js +30 -5
- package/.next/standalone/node_modules/next/dist/server/lib/patch-fetch.js +5 -1
- package/.next/standalone/node_modules/next/dist/server/lib/patch-set-header.js +7 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-server.js +6 -3
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/resolve-routes.js +18 -4
- package/.next/standalone/node_modules/next/dist/server/lib/server-ipc/utils.js +3 -1
- package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/next-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/request/fallback-params.js +27 -1
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-route/module.js +1 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/route-module.js +11 -1
- package/.next/standalone/node_modules/next/dist/server/server-utils.js +19 -2
- package/.next/standalone/node_modules/next/dist/server/stream-utils/node-web-streams-helper.js +5 -5
- package/.next/standalone/node_modules/next/dist/server/use-cache/use-cache-wrapper.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/web/adapter.js +4 -1
- package/.next/standalone/node_modules/next/dist/server/web/edge-route-module-wrapper.js +2 -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/{server → shared/lib}/htmlescape.js +15 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/routes/app.js +13 -1
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/cache-busting-search-param.js +56 -10
- 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 +26 -18
- package/.next/standalone/proxy.ts +1 -1
- 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 +12 -5
- package/bin/failproofai.mjs +263 -70
- package/dist/cli.mjs +3830 -1617
- package/lib/atomic-write.ts +67 -0
- package/lib/auth/api-server-client.ts +306 -0
- package/lib/auth/auth-store.ts +250 -0
- package/lib/claude-sessions.ts +181 -0
- package/lib/client-telemetry.ts +2 -0
- package/lib/fetch-with-timeout.ts +59 -0
- package/lib/share-card.ts +144 -0
- package/lib/telemetry.ts +12 -7
- package/package.json +26 -18
- package/scripts/install-telemetry.mjs +4 -0
- package/scripts/launch.ts +2 -2
- package/scripts/postinstall.mjs +89 -1
- package/src/audit/archetypes.ts +944 -0
- package/src/audit/cache.ts +151 -0
- package/src/audit/cli-adapters/claude.ts +97 -0
- package/src/audit/cli-adapters/codex.ts +56 -0
- package/src/audit/cli-adapters/copilot.ts +51 -0
- package/src/audit/cli-adapters/cursor.ts +51 -0
- package/src/audit/cli-adapters/gemini.ts +51 -0
- package/src/audit/cli-adapters/index.ts +70 -0
- package/src/audit/cli-adapters/opencode.ts +52 -0
- package/src/audit/cli-adapters/pi.ts +51 -0
- package/src/audit/cli-adapters/shared.ts +85 -0
- package/src/audit/cli.ts +319 -0
- package/src/audit/dashboard-cache.ts +158 -0
- package/src/audit/detectors/find-from-root.ts +27 -0
- package/src/audit/detectors/git-commit-no-verify.ts +22 -0
- package/src/audit/detectors/index.ts +33 -0
- package/src/audit/detectors/prefer-edit-over-read-cat.ts +31 -0
- package/src/audit/detectors/prefer-edit-over-sed-awk.ts +27 -0
- package/src/audit/detectors/prefer-write-over-heredoc.ts +36 -0
- package/src/audit/detectors/redundant-cd-cwd.ts +28 -0
- package/src/audit/detectors/reread-after-edit.ts +58 -0
- package/src/audit/detectors/sleep-polling-loop.ts +34 -0
- package/src/audit/features.ts +314 -0
- package/src/audit/findings.ts +298 -0
- package/src/audit/index.ts +387 -0
- package/src/audit/open-browser.ts +69 -0
- package/src/audit/replay.ts +147 -0
- package/src/audit/report.ts +349 -0
- package/src/audit/scoring.ts +174 -0
- package/src/audit/social-proof.ts +34 -0
- package/src/audit/strengths.ts +138 -0
- package/src/audit/types.ts +216 -0
- package/src/auth/cli.ts +359 -0
- package/src/hooks/builtin-policies.ts +81 -2
- package/src/hooks/custom-hooks-loader.ts +19 -3
- package/src/hooks/first-run-nudge.ts +146 -0
- package/src/hooks/handler.ts +21 -102
- package/src/hooks/hook-telemetry.ts +2 -2
- package/src/hooks/install-prompt.ts +34 -4
- package/src/hooks/manager.ts +72 -5
- package/src/hooks/policy-evaluator.ts +19 -4
- package/src/hooks/policy-registry.ts +21 -1
- package/src/hooks/policy-types.ts +9 -0
- package/src/hooks/tool-name-canonicalize.ts +65 -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]__0d_ob4n._.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/package_json_[json]_cjs_0z7w.hh._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02r.cjq._.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]__0609ezh._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__07_-mkc._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__09z7o2x._.js +0 -19
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_sh2n0._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e9o9ri._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0l6swv1._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0logebz._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0mi5ejy._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0odijkc._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0podumr._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0rkxer-._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0rl2kwi._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0vg0uey._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0x5limi._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ye1w50._.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]__10._f0s._.js +0 -4
- 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/lib_utils_ts_068jk73._.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_0h9llsw._.js +0 -6
- 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_0j79~gv.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/01q52wg_amm60.js +0 -2
- package/.next/standalone/.next/static/chunks/0kqar56yl~41o.js +0 -6
- package/.next/standalone/.next/static/chunks/0ml1.ck_5t36i.js +0 -1
- package/.next/standalone/.next/static/chunks/0w6fzf.07a24u.js +0 -1
- package/.next/standalone/.next/static/chunks/0zig0fh30t6ou.js +0 -1
- package/.next/standalone/.next/static/chunks/12l2t63hkyo2q.js +0 -1
- package/.next/standalone/.next/static/chunks/12pt~2f.c1sha.js +0 -1
- package/.next/standalone/.next/static/chunks/14lii11wmo450.js +0 -4
- package/.next/standalone/.next/static/chunks/17rm86uz2nd5a.css +0 -2
- package/.next/standalone/.next/static/media/4fa387ec64143e14-s.0q3udbd2bu5yp.woff2 +0 -0
- package/.next/standalone/.next/static/media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2 +0 -0
- package/.next/standalone/.next/static/media/bbc41e54d2fcbd21-s.0gw~uztddq1df.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/auth/login.ts +0 -104
- package/src/auth/logout.ts +0 -50
- package/src/auth/token-store.ts +0 -64
- package/src/relay/daemon.ts +0 -362
- package/src/relay/pid.ts +0 -76
- package/src/relay/queue.ts +0 -225
- /package/.next/standalone/.next/server/app/{icon.png → api/audit/invite}/route/build-manifest.json +0 -0
- /package/.next/standalone/.next/server/app/{icon.png → api/audit/invite}/route.js.map +0 -0
- /package/.next/standalone/.next/static/{dAuQps6jUwCz9X1Q5FFOO → DOSSF5hRUtt3-QZEm-ZIk}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{dAuQps6jUwCz9X1Q5FFOO → DOSSF5hRUtt3-QZEm-ZIk}/_ssgManifest.js +0 -0
- /package/.next/standalone/.next/static/chunks/{03~yq9q893hmn.js → 0cz1d0mv5g_q7.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
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers used by every per-CLI adapter.
|
|
3
|
+
*
|
|
4
|
+
* The lib/<cli>-sessions.ts parsers all produce the same `LogEntry[]` shape
|
|
5
|
+
* (defined in lib/log-entries.ts), so the conversion from LogEntry[] to
|
|
6
|
+
* NormalizedToolEvent[] is uniform across CLIs. The only per-CLI difference is
|
|
7
|
+
* the canonicalization function, which we delegate to
|
|
8
|
+
* `src/hooks/tool-name-canonicalize.ts`.
|
|
9
|
+
*/
|
|
10
|
+
import type { LogEntry } from "../../../lib/log-entries";
|
|
11
|
+
import type { IntegrationType } from "../../hooks/types";
|
|
12
|
+
import {
|
|
13
|
+
canonicalizeToolName,
|
|
14
|
+
canonicalizeToolInput,
|
|
15
|
+
} from "../../hooks/tool-name-canonicalize";
|
|
16
|
+
import {
|
|
17
|
+
AUDIT_TOOL_RESULT_MAX_BYTES,
|
|
18
|
+
type NormalizedToolEvent,
|
|
19
|
+
} from "../types";
|
|
20
|
+
|
|
21
|
+
/** Truncate a string to at most `maxBytes` UTF-8 bytes, preserving valid
|
|
22
|
+
* encoding (never splits a multi-byte sequence). `String.prototype.length`
|
|
23
|
+
* counts UTF-16 code units, not bytes — using it to "cap memory" would let
|
|
24
|
+
* through up to 4× the intended byte budget for non-ASCII text. */
|
|
25
|
+
function truncateToUtf8Bytes(s: string, maxBytes: number): string {
|
|
26
|
+
const buf = Buffer.from(s, "utf-8");
|
|
27
|
+
if (buf.byteLength <= maxBytes) return s;
|
|
28
|
+
// Walk back at most 3 bytes to land on a UTF-8 boundary (a leading byte is
|
|
29
|
+
// 0xxxxxxx or 11xxxxxx; continuation bytes are 10xxxxxx).
|
|
30
|
+
let end = maxBytes;
|
|
31
|
+
while (end > 0 && (buf[end] & 0xc0) === 0x80) end--;
|
|
32
|
+
return buf.subarray(0, end).toString("utf-8");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ConvertContext {
|
|
36
|
+
cli: IntegrationType;
|
|
37
|
+
sessionId: string;
|
|
38
|
+
transcriptPath: string;
|
|
39
|
+
/** Cwd resolved by the per-CLI parser. May be empty if the transcript had no
|
|
40
|
+
* session-start record. The audit falls back to the decoded project name. */
|
|
41
|
+
cwd: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Walks the LogEntry[] in timestamp order and yields one NormalizedToolEvent
|
|
45
|
+
* per `tool_use` content block, with the matching `tool_result.content` text
|
|
46
|
+
* attached (truncated). Returns events in chronological order. */
|
|
47
|
+
export function logEntriesToEvents(
|
|
48
|
+
entries: LogEntry[],
|
|
49
|
+
ctx: ConvertContext,
|
|
50
|
+
): NormalizedToolEvent[] {
|
|
51
|
+
const events: NormalizedToolEvent[] = [];
|
|
52
|
+
|
|
53
|
+
for (const entry of entries) {
|
|
54
|
+
if (entry.type !== "assistant") continue;
|
|
55
|
+
for (const block of entry.message.content) {
|
|
56
|
+
if (block.type !== "tool_use") continue;
|
|
57
|
+
const rawName = block.name;
|
|
58
|
+
const canonicalName = canonicalizeToolName(rawName, ctx.cli) ?? rawName;
|
|
59
|
+
const canonicalInput = canonicalizeToolInput(
|
|
60
|
+
canonicalName,
|
|
61
|
+
block.input,
|
|
62
|
+
ctx.cli,
|
|
63
|
+
) as Record<string, unknown>;
|
|
64
|
+
|
|
65
|
+
let toolResultText: string | undefined;
|
|
66
|
+
if (block.result?.content) {
|
|
67
|
+
toolResultText = truncateToUtf8Bytes(block.result.content, AUDIT_TOOL_RESULT_MAX_BYTES);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
events.push({
|
|
71
|
+
cli: ctx.cli,
|
|
72
|
+
sessionId: ctx.sessionId,
|
|
73
|
+
transcriptPath: ctx.transcriptPath,
|
|
74
|
+
cwd: ctx.cwd,
|
|
75
|
+
timestamp: entry.timestamp,
|
|
76
|
+
toolName: canonicalName,
|
|
77
|
+
rawToolName: rawName,
|
|
78
|
+
toolInput: canonicalInput ?? {},
|
|
79
|
+
toolResultText,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return events;
|
|
85
|
+
}
|
package/src/audit/cli.ts
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `failproofai audit` — run a local audit of your agent-CLI history, then open
|
|
3
|
+
* the dashboard to view it.
|
|
4
|
+
*
|
|
5
|
+
* failproofai audit Scan, then launch the dashboard at /audit.
|
|
6
|
+
* failproofai audit --help Show usage.
|
|
7
|
+
*
|
|
8
|
+
* `runAudit()` is a pure local function (no network, no account). We run it,
|
|
9
|
+
* render the same four progress stages the dashboard's RunProgress shows,
|
|
10
|
+
* pre-warm the dashboard cache (~/.failproofai/audit-dashboard.json), then start
|
|
11
|
+
* the bundled dashboard server and open the browser to /audit — which renders
|
|
12
|
+
* instantly from that cache.
|
|
13
|
+
*
|
|
14
|
+
* No arguments yet — a bare `failproofai audit` does a full scan (all CLIs, all
|
|
15
|
+
* history). Flags (--since, --cli, --project, --port, --no-open) are easy
|
|
16
|
+
* follow-ups against `RunAuditOptions`.
|
|
17
|
+
*/
|
|
18
|
+
import { runAudit } from "./index";
|
|
19
|
+
import { writeDashboardCache } from "./dashboard-cache";
|
|
20
|
+
import type { AuditResult, RunAuditOptions } from "./types";
|
|
21
|
+
import { trackHookEvent } from "../hooks/hook-telemetry";
|
|
22
|
+
import { getInstanceId } from "../../lib/telemetry-id";
|
|
23
|
+
import { openWhenReady } from "./open-browser";
|
|
24
|
+
|
|
25
|
+
/** Port the bundled dashboard binds to. Matches `scripts/launch.ts`'s default
|
|
26
|
+
* for `start` mode, which `failproofai` (bare) already uses. */
|
|
27
|
+
const DASHBOARD_PORT = 8020;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Mirror of `app/audit/_components/run-progress.tsx`'s `STAGES`. Kept identical
|
|
31
|
+
* so the CLI and the dashboard's in-progress view tell the same story — the
|
|
32
|
+
* dashboard even renders a mock `$ failproofai audit` terminal, and this is the
|
|
33
|
+
* real thing. `audit-cli.test.ts` guards against drift between the two.
|
|
34
|
+
*/
|
|
35
|
+
export const AUDIT_STAGES: ReadonlyArray<{ label: string; detail: string }> = [
|
|
36
|
+
{ label: "discovering transcripts", detail: "walking ~/.claude, ~/.codex, ~/.cursor, …" },
|
|
37
|
+
{ label: "parsing session logs", detail: "reading JSONL + sqlite session stores" },
|
|
38
|
+
{ label: "running policy checks", detail: "replaying through 30 builtin policies" },
|
|
39
|
+
{ label: "aggregating results", detail: "counting hits, ranking by frequency" },
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
const HELP = `
|
|
43
|
+
failproofai audit — audit your AI agent's behavior, then open the dashboard
|
|
44
|
+
|
|
45
|
+
USAGE
|
|
46
|
+
failproofai audit Scan your agent-CLI session history for risky and
|
|
47
|
+
wasteful patterns, then open the audit dashboard.
|
|
48
|
+
failproofai audit --help Show this help.
|
|
49
|
+
|
|
50
|
+
WHAT IT DOES
|
|
51
|
+
1. Scans past sessions from every installed agent CLI (Claude, Codex, Cursor,
|
|
52
|
+
Copilot, OpenCode, Pi, Gemini) — entirely on your machine.
|
|
53
|
+
2. Starts the local dashboard and opens
|
|
54
|
+
http://localhost:${DASHBOARD_PORT}/audit with your results.
|
|
55
|
+
|
|
56
|
+
Runs fully offline — no account or network required. Press Ctrl+C to stop the
|
|
57
|
+
dashboard server when you're done.
|
|
58
|
+
`.trimStart();
|
|
59
|
+
|
|
60
|
+
// ── ANSI helpers ────────────────────────────────────────────────────────────
|
|
61
|
+
const RESET = "\x1b[0m";
|
|
62
|
+
const DIM = "\x1b[2m";
|
|
63
|
+
const BOLD = "\x1b[1m";
|
|
64
|
+
const PINK = "\x1b[38;5;204m";
|
|
65
|
+
const GREEN = "\x1b[38;5;120m";
|
|
66
|
+
const CYAN = "\x1b[38;5;81m";
|
|
67
|
+
const SPINNER = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
68
|
+
|
|
69
|
+
function colorOn(): boolean {
|
|
70
|
+
if (process.env.NO_COLOR && process.env.NO_COLOR !== "") return false;
|
|
71
|
+
if (process.env.FORCE_COLOR === "0") return false;
|
|
72
|
+
if (process.env.FORCE_COLOR) return true;
|
|
73
|
+
return !!process.stdout.isTTY;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Wrap `s` in an ANSI code when color is enabled, else return it bare. */
|
|
77
|
+
function c(code: string, s: string): string {
|
|
78
|
+
return colorOn() ? `${code}${s}${RESET}` : s;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function num(n: number): string {
|
|
82
|
+
return n.toLocaleString("en-US");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Print an error and exit 1. We exit directly rather than throwing a `CliError`
|
|
87
|
+
* because, in the shipped single-file bundle (`dist/cli.mjs`), the entrypoint's
|
|
88
|
+
* dynamically-imported `CliError` is a different class instance than the one
|
|
89
|
+
* bundled here, so `err instanceof CliError` fails and the message degrades to
|
|
90
|
+
* "Unexpected error" + exit 2. Exiting here keeps the audit command's failures
|
|
91
|
+
* clean in both source and bundled runs.
|
|
92
|
+
*/
|
|
93
|
+
function die(message: string): never {
|
|
94
|
+
process.stderr.write(`Error: ${message}\n`);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ── Progress animation ───────────────────────────────────────────────────────
|
|
99
|
+
|
|
100
|
+
interface Progress {
|
|
101
|
+
/** Mark every stage done and stop the timers. */
|
|
102
|
+
finish(): void;
|
|
103
|
+
/** Stop the timers without marking done (used on error). */
|
|
104
|
+
fail(): void;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Render the four audit stages with a live spinner, redrawing in place. Like the
|
|
109
|
+
* dashboard's RunProgress, the stages are time-driven (runAudit emits no phase
|
|
110
|
+
* events) and the last stage is *held* until `finish()` is called, so it never
|
|
111
|
+
* claims "done" before the real work resolves. TTY-only — the caller picks the
|
|
112
|
+
* plain-text path when stdout isn't a terminal.
|
|
113
|
+
*/
|
|
114
|
+
function startProgress(): Progress {
|
|
115
|
+
const n = AUDIT_STAGES.length;
|
|
116
|
+
let stage = 0;
|
|
117
|
+
let tick = 0;
|
|
118
|
+
let done = false;
|
|
119
|
+
let printed = false;
|
|
120
|
+
|
|
121
|
+
const lineFor = (i: number): string => {
|
|
122
|
+
const s = AUDIT_STAGES[i];
|
|
123
|
+
if (done || i < stage) return ` ${c(GREEN, "✓")} ${c(DIM, s.label)}`;
|
|
124
|
+
if (i === stage) {
|
|
125
|
+
return ` ${c(PINK, SPINNER[tick % SPINNER.length])} ${s.label} ${c(DIM, s.detail)}`;
|
|
126
|
+
}
|
|
127
|
+
return ` ${c(DIM, "○")} ${c(DIM, s.label)}`;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const render = (): void => {
|
|
131
|
+
const lines = Array.from({ length: n }, (_, i) => lineFor(i));
|
|
132
|
+
// Move the cursor back up over the previously-drawn block, then clear and
|
|
133
|
+
// rewrite each line in place.
|
|
134
|
+
if (printed) process.stdout.write(`\x1b[${n}A`);
|
|
135
|
+
process.stdout.write(lines.map((l) => `\x1b[2K${l}`).join("\n") + "\n");
|
|
136
|
+
printed = true;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
render();
|
|
140
|
+
const spinTimer = setInterval(() => {
|
|
141
|
+
tick++;
|
|
142
|
+
render();
|
|
143
|
+
}, 90);
|
|
144
|
+
// Advance through stages on a fixed cadence, holding on the last one until
|
|
145
|
+
// finish() flips `done`.
|
|
146
|
+
const stageTimer = setInterval(() => {
|
|
147
|
+
if (stage < n - 1) {
|
|
148
|
+
stage++;
|
|
149
|
+
render();
|
|
150
|
+
}
|
|
151
|
+
}, 1100);
|
|
152
|
+
|
|
153
|
+
const stop = (): void => {
|
|
154
|
+
clearInterval(spinTimer);
|
|
155
|
+
clearInterval(stageTimer);
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
return {
|
|
159
|
+
finish() {
|
|
160
|
+
stop();
|
|
161
|
+
done = true;
|
|
162
|
+
render();
|
|
163
|
+
},
|
|
164
|
+
fail() {
|
|
165
|
+
stop();
|
|
166
|
+
process.stdout.write("\n");
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** Run the audit, showing animated progress on a TTY or a single line elsewhere. */
|
|
172
|
+
async function runWithProgress(opts: RunAuditOptions): Promise<AuditResult> {
|
|
173
|
+
if (!process.stdout.isTTY) {
|
|
174
|
+
process.stdout.write(" scanning your agent session history — this can take a moment…\n");
|
|
175
|
+
return runAudit(opts);
|
|
176
|
+
}
|
|
177
|
+
const progress = startProgress();
|
|
178
|
+
try {
|
|
179
|
+
const result = await runAudit(opts);
|
|
180
|
+
progress.finish();
|
|
181
|
+
return result;
|
|
182
|
+
} catch (err) {
|
|
183
|
+
progress.fail();
|
|
184
|
+
throw err;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ── Output ───────────────────────────────────────────────────────────────────
|
|
189
|
+
|
|
190
|
+
function printHeader(): void {
|
|
191
|
+
process.stdout.write(`\n ${c(PINK, "🛡 failproofai audit")} ${c(DIM, "· beta")}\n\n`);
|
|
192
|
+
process.stdout.write(` ${c(DIM, "starting audit…")}\n\n`);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* The post-run summary lines (no leading indent, no trailing newlines). Pure so
|
|
197
|
+
* it's unit-testable; `printSummary` handles the indentation + stdout.
|
|
198
|
+
*/
|
|
199
|
+
export function buildSummary(result: AuditResult): string[] {
|
|
200
|
+
const sessions = result.transcripts.scanned;
|
|
201
|
+
const events = result.eventsScanned;
|
|
202
|
+
const projects = result.projectsScanned.length;
|
|
203
|
+
const enabledRows = result.results.filter((r) => r.source === "builtin" && r.enabledInConfig);
|
|
204
|
+
const slippingRows = result.results.filter((r) => !(r.source === "builtin" && r.enabledInConfig));
|
|
205
|
+
|
|
206
|
+
const lines: string[] = [];
|
|
207
|
+
lines.push(
|
|
208
|
+
`${c(GREEN, "✓ audit complete")} ${c(DIM, "·")} ` +
|
|
209
|
+
`${c(BOLD, num(events))} tool call${events === 1 ? "" : "s"} across ` +
|
|
210
|
+
`${num(sessions)} session${sessions === 1 ? "" : "s"}` +
|
|
211
|
+
(projects > 0 ? ` ${c(DIM, "·")} ${num(projects)} project${projects === 1 ? "" : "s"}` : ""),
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
if (result.totals.hits === 0) {
|
|
215
|
+
// Only call it a "clean run" when we actually scanned something — for zero
|
|
216
|
+
// events the caller prints "no agent sessions found yet" guidance instead.
|
|
217
|
+
if (events > 0) lines.push(c(DIM, "clean run — nothing flagged. nice."));
|
|
218
|
+
return lines;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const parts: string[] = [];
|
|
222
|
+
if (slippingRows.length > 0) {
|
|
223
|
+
parts.push(
|
|
224
|
+
`${c(PINK, String(slippingRows.length))} ${slippingRows.length === 1 ? "pattern" : "patterns"} slipping through`,
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
if (enabledRows.length > 0) {
|
|
228
|
+
parts.push(`${c(GREEN, String(enabledRows.length))} already blocked by your policies`);
|
|
229
|
+
}
|
|
230
|
+
if (parts.length > 0) lines.push(parts.join(` ${c(DIM, "·")} `));
|
|
231
|
+
return lines;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function printSummary(result: AuditResult): void {
|
|
235
|
+
process.stdout.write("\n");
|
|
236
|
+
for (const line of buildSummary(result)) process.stdout.write(` ${line}\n`);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// ── Entry point ──────────────────────────────────────────────────────────────
|
|
240
|
+
|
|
241
|
+
export async function runAuditCli(args: string[]): Promise<void> {
|
|
242
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
243
|
+
process.stdout.write(HELP);
|
|
244
|
+
process.exit(0);
|
|
245
|
+
}
|
|
246
|
+
// No arguments supported yet — reject typos rather than silently doing a bare
|
|
247
|
+
// audit, so a future `failproofai audit --since 7d` doesn't quietly no-op.
|
|
248
|
+
const stray = args.find((a) => a !== "--help" && a !== "-h");
|
|
249
|
+
if (stray) {
|
|
250
|
+
die(
|
|
251
|
+
`\`audit\` takes no arguments yet (got: ${stray}).\n` +
|
|
252
|
+
`Run \`failproofai audit\` to scan your history and open the dashboard.`,
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const instanceId = getInstanceId();
|
|
257
|
+
void trackHookEvent(instanceId, "cli_audit_started", { source: "cli" });
|
|
258
|
+
|
|
259
|
+
printHeader();
|
|
260
|
+
|
|
261
|
+
// Full scan: all CLIs, all history, per-transcript cache on.
|
|
262
|
+
const opts: RunAuditOptions = {};
|
|
263
|
+
|
|
264
|
+
let result: AuditResult;
|
|
265
|
+
try {
|
|
266
|
+
result = await runWithProgress(opts);
|
|
267
|
+
} catch (err) {
|
|
268
|
+
void trackHookEvent(instanceId, "cli_audit_failed", {
|
|
269
|
+
source: "cli",
|
|
270
|
+
error_type: err instanceof Error ? err.name : "unknown",
|
|
271
|
+
});
|
|
272
|
+
die(`Audit failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
printSummary(result);
|
|
276
|
+
|
|
277
|
+
void trackHookEvent(instanceId, "cli_audit_completed", {
|
|
278
|
+
source: "cli",
|
|
279
|
+
events_scanned: result.eventsScanned,
|
|
280
|
+
sessions_scanned: result.transcripts.scanned,
|
|
281
|
+
total_hits: result.totals.hits,
|
|
282
|
+
findings: result.results.length,
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// No sessions on disk — guide the user instead of opening an empty dashboard.
|
|
286
|
+
if (result.eventsScanned === 0) {
|
|
287
|
+
process.stdout.write(
|
|
288
|
+
`\n ${c(DIM, "no agent sessions found yet.")}\n` +
|
|
289
|
+
` install hooks with ${c(CYAN, "failproofai policies --install")} ` +
|
|
290
|
+
`${c(DIM, "and come back after using your agent.")}\n\n`,
|
|
291
|
+
);
|
|
292
|
+
process.exit(0);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Pre-warm the dashboard cache — the /audit page reads this file directly, so
|
|
296
|
+
// the page renders our result instantly with no in-browser re-run.
|
|
297
|
+
const persisted = writeDashboardCache(opts, result);
|
|
298
|
+
if (!persisted) {
|
|
299
|
+
process.stdout.write(
|
|
300
|
+
`\n ${c(PINK, "!")} ${c(DIM, "couldn't save the audit cache; the dashboard may show an empty state.")}\n`,
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const url = `http://localhost:${DASHBOARD_PORT}/audit`;
|
|
305
|
+
process.stdout.write(
|
|
306
|
+
`\n ${c(DIM, "starting the dashboard…")}\n` +
|
|
307
|
+
` ${c(PINK, "✦")} ${c(BOLD, "here's your audit")} ${c(DIM, "→")} ${c(CYAN, url)}\n` +
|
|
308
|
+
` ${c(DIM, "(opening in your browser — press Ctrl+C to stop the server)")}\n\n`,
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
// Open the page once the server answers (best-effort, detached), then start
|
|
312
|
+
// the server. `launch("start")` blocks-by-keeping-alive — it spawns the
|
|
313
|
+
// bundled standalone dashboard and the process stays up serving it.
|
|
314
|
+
openWhenReady(DASHBOARD_PORT, "/audit");
|
|
315
|
+
const { launch } = await import("../../scripts/launch");
|
|
316
|
+
launch("start");
|
|
317
|
+
// Intentionally no process.exit(): launch() keeps this process alive running
|
|
318
|
+
// the dashboard until the user stops it.
|
|
319
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whole-result cache for the Next.js dashboard's `/audit` page.
|
|
3
|
+
*
|
|
4
|
+
* Stored at `~/.failproofai/audit-dashboard.json` with mode 0600. Single
|
|
5
|
+
* slot — a new run with different params overwrites the previous entry.
|
|
6
|
+
* Read by `app/actions/get-audit-result.ts` (server action) and written by
|
|
7
|
+
* `app/api/audit/run/route.ts` on successful run completion.
|
|
8
|
+
*
|
|
9
|
+
* Separate from the per-transcript cache at `~/.failproofai/cache/audit/`
|
|
10
|
+
* (see `src/audit/cache.ts`): that one makes re-running fast; this one
|
|
11
|
+
* makes navigating back to /audit instant without re-running.
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { homedir } from "node:os";
|
|
16
|
+
import { writeJsonAtomically } from "../../lib/atomic-write";
|
|
17
|
+
import type { AuditResult, RunAuditOptions } from "./types";
|
|
18
|
+
|
|
19
|
+
const DEFAULT_MAX_AGE_MINUTES = 30;
|
|
20
|
+
|
|
21
|
+
/** Hard expiry: the dashboard cache is rejected on read once it's this old.
|
|
22
|
+
* Matches the per-transcript TTL in `cache.ts` so the whole audit surface
|
|
23
|
+
* has a consistent 7-day freshness window — past that, `/audit` falls
|
|
24
|
+
* through to its empty state and nudges the user to re-audit. */
|
|
25
|
+
const DASHBOARD_CACHE_TTL_MINUTES = 7 * 24 * 60;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Bump whenever the on-disk shape of a cached entry changes in a way the
|
|
29
|
+
* reader can't tolerate (added required field, renamed key, swapped result
|
|
30
|
+
* version). Entries written with a different `schemaVersion` are rejected
|
|
31
|
+
* — better an empty state than rendering against the wrong shape.
|
|
32
|
+
*
|
|
33
|
+
* v2: AuditResult.version bumped 1→2 (added `projectsScanned`,
|
|
34
|
+
* `eventsScanned`, `enabledBuiltinNames`). Renderers defaulted missing
|
|
35
|
+
* fields silently, which masked a stale cache as "0 tool calls scanned"
|
|
36
|
+
* instead of triggering the empty-state recovery. Rejecting v1 entries
|
|
37
|
+
* forces a re-run.
|
|
38
|
+
*/
|
|
39
|
+
export const DASHBOARD_CACHE_SCHEMA_VERSION = 2;
|
|
40
|
+
|
|
41
|
+
export interface DashboardCacheEntry {
|
|
42
|
+
/** Bumped whenever the cache shape changes incompatibly. */
|
|
43
|
+
schemaVersion: number;
|
|
44
|
+
/** ISO timestamp the cache was written at. */
|
|
45
|
+
cachedAt: string;
|
|
46
|
+
/** The exact RunAuditOptions the cached result was produced with. */
|
|
47
|
+
params: RunAuditOptions;
|
|
48
|
+
/** The full `AuditResult` from `runAudit()`. */
|
|
49
|
+
result: AuditResult;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function getCachePath(): string {
|
|
53
|
+
return join(homedir(), ".failproofai", "audit-dashboard.json");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Read the cache file. Returns null on missing/corrupt/unreadable file —
|
|
57
|
+
* callers treat "no cache" as the empty state. */
|
|
58
|
+
export function readDashboardCache(): DashboardCacheEntry | null {
|
|
59
|
+
const cachePath = getCachePath();
|
|
60
|
+
if (!existsSync(cachePath)) return null;
|
|
61
|
+
try {
|
|
62
|
+
const raw = readFileSync(cachePath, "utf-8");
|
|
63
|
+
const entry = JSON.parse(raw) as DashboardCacheEntry;
|
|
64
|
+
// `typeof null === "object"`, so explicit null checks are required for
|
|
65
|
+
// params and result — otherwise a corrupt cache like `{"params": null}`
|
|
66
|
+
// would slip through and crash downstream readers.
|
|
67
|
+
if (
|
|
68
|
+
!entry
|
|
69
|
+
|| typeof entry !== "object"
|
|
70
|
+
|| typeof entry.cachedAt !== "string"
|
|
71
|
+
|| !entry.params
|
|
72
|
+
|| typeof entry.params !== "object"
|
|
73
|
+
|| !entry.result
|
|
74
|
+
|| typeof entry.result !== "object"
|
|
75
|
+
) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
// Reject anything written by an older code version with a different
|
|
79
|
+
// shape. The dashboard treats null as the "no cached result" empty
|
|
80
|
+
// state, which is the safer fallback when we can't trust the bytes.
|
|
81
|
+
if (entry.schemaVersion !== DASHBOARD_CACHE_SCHEMA_VERSION) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
if (isCacheStale(entry.cachedAt, DASHBOARD_CACHE_TTL_MINUTES)) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
return entry;
|
|
88
|
+
} catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Write the cache file atomically via the shared `writeJsonAtomically`
|
|
94
|
+
* helper. Returns `true` on success and `false` if the write threw (disk
|
|
95
|
+
* full, permissions, …) — never throwing into the run path. The temp-file
|
|
96
|
+
* dance protects concurrent readers (e.g. the 1s status poll firing while a
|
|
97
|
+
* fresh run writes a multi-hundred-KB AuditResult) from observing a torn JSON
|
|
98
|
+
* file. The fire-and-forget run route relies on this boolean to surface a
|
|
99
|
+
* persistence failure: the cache is the only channel by which a detached
|
|
100
|
+
* run's result reaches the dashboard, so a silently dropped write would
|
|
101
|
+
* otherwise look like a successful run that serves stale data. */
|
|
102
|
+
export function writeDashboardCache(params: RunAuditOptions, result: AuditResult): boolean {
|
|
103
|
+
try {
|
|
104
|
+
const entry: DashboardCacheEntry = {
|
|
105
|
+
schemaVersion: DASHBOARD_CACHE_SCHEMA_VERSION,
|
|
106
|
+
cachedAt: new Date().toISOString(),
|
|
107
|
+
params,
|
|
108
|
+
result,
|
|
109
|
+
};
|
|
110
|
+
writeJsonAtomically(getCachePath(), entry);
|
|
111
|
+
return true;
|
|
112
|
+
} catch {
|
|
113
|
+
// Best-effort: never throw into the run path. The caller decides how to
|
|
114
|
+
// treat a failed persist (the run route reports it as a run error).
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** True when the cache is older than `maxAgeMinutes` (default 30). The
|
|
120
|
+
* dashboard doesn't auto-refresh on stale cache — staleness only drives
|
|
121
|
+
* the "Re-run" affordance hint. */
|
|
122
|
+
export function isCacheStale(cachedAt: string, maxAgeMinutes: number = DEFAULT_MAX_AGE_MINUTES): boolean {
|
|
123
|
+
const cachedMs = new Date(cachedAt).getTime();
|
|
124
|
+
if (Number.isNaN(cachedMs)) return true;
|
|
125
|
+
const ageMs = Date.now() - cachedMs;
|
|
126
|
+
return ageMs > maxAgeMinutes * 60_000;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Read just the `cachedAt` timestamp from the dashboard cache file,
|
|
131
|
+
* **bypassing** the TTL check. Used by the empty-state path to tell apart
|
|
132
|
+
* "no audit has ever run" from "your last audit aged out". A non-null
|
|
133
|
+
* return whose age exceeds `DASHBOARD_CACHE_TTL_MINUTES` means the cache
|
|
134
|
+
* was rejected by `readDashboardCache()` for being expired (rather than
|
|
135
|
+
* missing or schema-incompatible).
|
|
136
|
+
*/
|
|
137
|
+
export function readDashboardCacheMeta(): { cachedAt: string } | null {
|
|
138
|
+
const cachePath = getCachePath();
|
|
139
|
+
if (!existsSync(cachePath)) return null;
|
|
140
|
+
try {
|
|
141
|
+
const raw = readFileSync(cachePath, "utf-8");
|
|
142
|
+
const entry = JSON.parse(raw) as Partial<DashboardCacheEntry>;
|
|
143
|
+
// Require schema-version match + a parseable ISO timestamp before
|
|
144
|
+
// surfacing the entry as "this user's audit aged out". A
|
|
145
|
+
// schema-incompatible entry is structurally indistinguishable from
|
|
146
|
+
// "no audit has ever run", so it should fall through to the
|
|
147
|
+
// first-run empty copy, not the expired banner.
|
|
148
|
+
if (
|
|
149
|
+
!entry
|
|
150
|
+
|| entry.schemaVersion !== DASHBOARD_CACHE_SCHEMA_VERSION
|
|
151
|
+
|| typeof entry.cachedAt !== "string"
|
|
152
|
+
|| Number.isNaN(new Date(entry.cachedAt).getTime())
|
|
153
|
+
) return null;
|
|
154
|
+
return { cachedAt: entry.cachedAt };
|
|
155
|
+
} catch {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Detector } from "../types";
|
|
2
|
+
|
|
3
|
+
const RISKY_ROOTS = ["/", "/home", "/usr", "/etc", "/var", "/opt", "/Users"];
|
|
4
|
+
|
|
5
|
+
/** Bash `find` invoked against the filesystem root or another high-level
|
|
6
|
+
* directory — tends to exhaust resources and rarely returns useful results. */
|
|
7
|
+
export const findFromRoot: Detector = {
|
|
8
|
+
name: "find-from-root",
|
|
9
|
+
description: "Bash `find` against `/`, `/home`, `/usr`, etc. — scope to cwd instead.",
|
|
10
|
+
category: "Risky",
|
|
11
|
+
severity: "warn",
|
|
12
|
+
displayTitle: "Ran find from /, /home, /usr, etc.",
|
|
13
|
+
impact: "Filesystem-wide finds exhaust resources and rarely return useful results.",
|
|
14
|
+
detect(event) {
|
|
15
|
+
if (event.toolName !== "Bash") return null;
|
|
16
|
+
const command = (event.toolInput as { command?: unknown }).command;
|
|
17
|
+
if (typeof command !== "string") return null;
|
|
18
|
+
const cmd = command.trim();
|
|
19
|
+
// find / OR find /home OR find "/etc" … — first non-flag arg
|
|
20
|
+
const match = /(?:^|[\s;|&])find\s+(?:-\S+\s+)*("[^"]+"|'[^']+'|\S+)/.exec(cmd);
|
|
21
|
+
if (!match) return null;
|
|
22
|
+
const raw = match[1].replace(/^["']|["']$/g, "");
|
|
23
|
+
const stripped = raw.replace(/\/+$/, "") || "/";
|
|
24
|
+
if (!RISKY_ROOTS.includes(stripped)) return null;
|
|
25
|
+
return { example: cmd.slice(0, 160) };
|
|
26
|
+
},
|
|
27
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Detector } from "../types";
|
|
2
|
+
|
|
3
|
+
/** `git commit ... --no-verify` (or short `-n`) — skipping pre-commit hooks. */
|
|
4
|
+
export const gitCommitNoVerify: Detector = {
|
|
5
|
+
name: "git-commit-no-verify",
|
|
6
|
+
description: "git commit invoked with --no-verify / -n, skipping hooks.",
|
|
7
|
+
category: "Risky",
|
|
8
|
+
severity: "warn",
|
|
9
|
+
displayTitle: "Committed with --no-verify",
|
|
10
|
+
impact: "Skips pre-commit hooks that exist to catch broken or unsafe code.",
|
|
11
|
+
detect(event) {
|
|
12
|
+
if (event.toolName !== "Bash") return null;
|
|
13
|
+
const command = (event.toolInput as { command?: unknown }).command;
|
|
14
|
+
if (typeof command !== "string") return null;
|
|
15
|
+
const cmd = command;
|
|
16
|
+
if (!/\bgit\s+commit\b/.test(cmd)) return null;
|
|
17
|
+
if (/\s--no-verify\b/.test(cmd) || /\s-n\b/.test(cmd)) {
|
|
18
|
+
return { example: cmd.replace(/\s+/g, " ").trim().slice(0, 160) };
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
},
|
|
22
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry of audit-only detectors.
|
|
3
|
+
*
|
|
4
|
+
* Detectors are pure functions over a NormalizedToolEvent (plus optional
|
|
5
|
+
* per-session state). They detect "stupid behaviors" not currently covered by
|
|
6
|
+
* the runtime builtin policies, with no real-time enforcement — counting only.
|
|
7
|
+
*
|
|
8
|
+
* Add a new detector by writing a sibling file and registering it here.
|
|
9
|
+
*/
|
|
10
|
+
import type { Detector } from "../types";
|
|
11
|
+
import { redundantCdCwd } from "./redundant-cd-cwd";
|
|
12
|
+
import { preferEditOverReadCat } from "./prefer-edit-over-read-cat";
|
|
13
|
+
import { preferEditOverSedAwk } from "./prefer-edit-over-sed-awk";
|
|
14
|
+
import { preferWriteOverHeredoc } from "./prefer-write-over-heredoc";
|
|
15
|
+
import { sleepPollingLoop } from "./sleep-polling-loop";
|
|
16
|
+
import { findFromRoot } from "./find-from-root";
|
|
17
|
+
import { gitCommitNoVerify } from "./git-commit-no-verify";
|
|
18
|
+
import { rereadAfterEdit } from "./reread-after-edit";
|
|
19
|
+
|
|
20
|
+
export const AUDIT_DETECTORS: Detector[] = [
|
|
21
|
+
redundantCdCwd,
|
|
22
|
+
preferEditOverReadCat,
|
|
23
|
+
preferEditOverSedAwk,
|
|
24
|
+
preferWriteOverHeredoc,
|
|
25
|
+
sleepPollingLoop,
|
|
26
|
+
findFromRoot,
|
|
27
|
+
gitCommitNoVerify,
|
|
28
|
+
rereadAfterEdit,
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
export function getDetectorByName(name: string): Detector | undefined {
|
|
32
|
+
return AUDIT_DETECTORS.find((d) => d.name === name);
|
|
33
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Detector } from "../types";
|
|
2
|
+
|
|
3
|
+
const SOURCE_EXT_RE = /\.(?:ts|tsx|js|jsx|mjs|cjs|py|go|rs|java|kt|swift|rb|php|c|h|cc|cpp|hpp|cs|scala|sh|bash|zsh|json|yaml|yml|toml|md|txt|sql|html|css|scss|sass)$/i;
|
|
4
|
+
|
|
5
|
+
/** `cat | head | tail | less | more` invoked on a single source file with no
|
|
6
|
+
* shell pipeline / redirection. The Read tool is the right answer. .env files
|
|
7
|
+
* are intentionally excluded (covered by `block-env-files`). */
|
|
8
|
+
export const preferEditOverReadCat: Detector = {
|
|
9
|
+
name: "prefer-edit-over-read-cat",
|
|
10
|
+
description: "Bash `cat`/`head`/`tail`/`less`/`more` on a single source file — use Read.",
|
|
11
|
+
category: "Wasteful",
|
|
12
|
+
severity: "info",
|
|
13
|
+
displayTitle: "Used `cat`/`head`/`tail` on a source file",
|
|
14
|
+
impact: "Burns tokens; the Read tool returns content directly without going through Bash output.",
|
|
15
|
+
detect(event) {
|
|
16
|
+
if (event.toolName !== "Bash") return null;
|
|
17
|
+
const command = (event.toolInput as { command?: unknown }).command;
|
|
18
|
+
if (typeof command !== "string") return null;
|
|
19
|
+
const cmd = command.trim();
|
|
20
|
+
// Reject any shell pipeline, redirection, command chaining or substitution.
|
|
21
|
+
if (/[|<>;&`$()]/.test(cmd)) return null;
|
|
22
|
+
const match = /^(cat|head|tail|less|more)\s+(?:-\S+\s+)*(?:"([^"]+)"|'([^']+)'|(\S+))\s*$/.exec(cmd);
|
|
23
|
+
if (!match) return null;
|
|
24
|
+
const path = match[2] ?? match[3] ?? match[4] ?? "";
|
|
25
|
+
if (!path) return null;
|
|
26
|
+
// .env is covered by block-env-files; skip to avoid double-counting.
|
|
27
|
+
if (/(?:^|\/)\.env(?:\..+)?$/.test(path)) return null;
|
|
28
|
+
if (!SOURCE_EXT_RE.test(path)) return null;
|
|
29
|
+
return { example: cmd };
|
|
30
|
+
},
|
|
31
|
+
};
|