failproofai 1.0.0-beta.2 → 1.0.0-beta.21
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 +2 -1
- package/.next/standalone/.next/build-manifest.json +6 -6
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/routes-manifest.json +6 -0
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js +3 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +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 +3 -3
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js +3 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_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.js +3 -2
- package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route.js +4 -3
- package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/status/route.js +1 -1
- package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js +3 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +3 -2
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js +3 -2
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js +3 -2
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js +3 -2
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js +5 -3
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
- 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 -2
- package/.next/standalone/.next/server/app/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +3 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +30 -18
- package/.next/standalone/.next/server/app/policies/page.js +5 -3
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js +4 -2
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +6 -4
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +4 -2
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/settings/page/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/settings/page/build-manifest.json +18 -0
- package/.next/standalone/.next/server/app/settings/page/next-font-manifest.json +6 -0
- package/.next/standalone/.next/server/app/settings/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +53 -0
- package/.next/standalone/.next/server/app/settings/page.js +18 -0
- package/.next/standalone/.next/server/app/settings/page.js.map +5 -0
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app-paths-manifest.json +2 -1
- package/.next/standalone/.next/server/chunks/[externals]__0h9_83k._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[externals]__1nl3dvw._.js → [externals]__0r-zamh._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[externals]__1ifpkx-._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0l4vuqm._.js → [root-of-the-server]__00ni9za._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06hexd0._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__08y94xv._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__094p1f1._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_0xu5z._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ed01_d._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0-dh5jy._.js → [root-of-the-server]__0effm9m._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0g0vcwt._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__18d-9oi._.js → [root-of-the-server]__0ix8gm7._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0h3lfmp._.js → [root-of-the-server]__0ji11a-._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__10oa-v9._.js → [root-of-the-server]__0ojwjxl._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__16le-kd._.js → [root-of-the-server]__0pbp9fe._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q-v9z2._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0vb5fl2._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0sb_5m8._.js → [root-of-the-server]__131ebum._.js} +4 -4
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ibjy5x._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tvn4wf._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__20d06rh._.js +3 -0
- package/.next/standalone/.next/server/chunks/_0lxbzdq._.js +3 -0
- package/.next/standalone/.next/server/chunks/_1zuiiy3._.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_telemetry_ts_0dctyyw._.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +5 -5
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +2 -1
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +2 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[externals]__1aq139v._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0-wfhrp._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__06bp_fg._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__074qmkp._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1apb7k_._.js → [root-of-the-server]__0_1tiya._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__170799-._.js → [root-of-the-server]__0spkm68._.js} +11 -11
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0t281d4._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17itmx-._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__01od0m6._.js → [root-of-the-server]__1n2vcv4._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1qapotl._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1rv-sc9._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1tlvv9a._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1u-wx42._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1v185mo._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0-yi74u._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0rjgfln._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0vo2qyt._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0xej-0e._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_10399ge._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_11_p9y8._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_149k9oy._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1_hwp06._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1ctse6u._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1e19atl._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1mnhi_r._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1ror7k9._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1sdgprl._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0dwo94s.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +2 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.js +4 -0
- package/.next/standalone/.next/server/middleware-build-manifest.js +6 -6
- package/.next/standalone/.next/server/middleware.js +2 -2
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +74 -20
- package/.next/standalone/.next/static/chunks/{03fmihek9n986.js → 06zgzyh3wv1ig.js} +1 -1
- package/.next/standalone/.next/static/chunks/0km-jn9o5xyqs.css +2 -0
- package/.next/standalone/.next/static/chunks/{1hdhteui932bq.js → 0qmo2t50kpb30.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2sbelanzvxvv0.js → 113g8wtal6_c4.js} +22 -22
- package/.next/standalone/.next/static/chunks/16p68cybetr31.js +1 -0
- package/.next/standalone/.next/static/chunks/18wqn0_3mzylf.js +1 -0
- package/.next/standalone/.next/static/chunks/1v1gqvpjk62jm.js +1 -0
- package/.next/standalone/.next/static/chunks/{0fi645si-uiiq.js → 1xq1m8h14tnlj.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3hp8ulqknybil.js → 1y3vwogqb88dx.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3vs4ay36tjds_.js → 1zmh-b0ulrqu7.js} +1 -1
- package/.next/standalone/.next/static/chunks/23kev26by1e4f.js +1 -0
- package/.next/standalone/.next/static/chunks/299lhw60e8gr6.js +1 -0
- package/.next/standalone/.next/static/chunks/{18rvdw5v72364.js → 2adbpdaxp5ygq.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2j94uwkb4s3qr.js → 2kbqcw-6swmav.js} +1 -1
- package/.next/standalone/.next/static/chunks/2n9n5m0963pdg.js +6 -0
- package/.next/standalone/.next/static/chunks/2uvhw57mf9lg_.css +2 -0
- package/.next/standalone/.next/static/chunks/{31feojxhjyjpl.js → 30nrrpwymht5m.js} +1 -1
- package/.next/standalone/.next/static/chunks/31coz11ia5vc4.js +1 -0
- package/.next/standalone/.next/static/chunks/{turbopack-1lsv92x7klwrn.js → turbopack-3diub4ctvn1n0.js} +1 -1
- package/.next/standalone/SECURITY.md +8 -2
- package/.next/standalone/app/actions/get-active-pauses.ts +16 -0
- package/.next/standalone/app/actions/get-hooks-config.ts +2 -2
- package/.next/standalone/app/actions/get-scheduled-audit.ts +70 -0
- package/.next/standalone/app/actions/update-scheduled-audit.ts +44 -0
- package/.next/standalone/app/api/audit/run/route.ts +28 -0
- package/.next/standalone/app/api/audit/status/route.ts +13 -1
- package/.next/standalone/app/api/auth/status/route.ts +1 -1
- package/.next/standalone/app/audit/_components/audit-dashboard.tsx +1 -3
- package/.next/standalone/app/audit/_components/audit-progress-strip.tsx +1 -1
- package/.next/standalone/app/audit/_components/auth-dialog.css +159 -0
- package/.next/standalone/app/audit/_components/auth-dialog.tsx +3 -0
- package/.next/standalone/app/audit/_components/come-back-better-section.tsx +1 -1
- package/.next/standalone/app/audit/_components/empty-state.tsx +0 -1
- package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +1 -1
- package/.next/standalone/app/audit/_components/quirks-section.tsx +0 -1
- package/.next/standalone/app/audit/_components/report-footer.tsx +0 -2
- package/.next/standalone/app/audit/_components/run-progress.tsx +1 -1
- package/.next/standalone/app/audit/_components/strengths-section.tsx +0 -1
- package/.next/standalone/app/audit/audit-styles.css +6 -149
- package/.next/standalone/app/components/pause-notices.tsx +111 -0
- package/.next/standalone/app/components/raw-log-viewer.tsx +1 -1
- package/.next/standalone/app/components/toast.tsx +1 -1
- package/.next/standalone/app/policies/hooks-client.tsx +84 -8
- package/.next/standalone/app/settings/page.tsx +31 -0
- package/.next/standalone/app/settings/settings-client.tsx +487 -0
- package/.next/standalone/components/navbar.tsx +2 -0
- package/.next/standalone/lib/auth/api-server-client.ts +2 -3
- package/.next/standalone/lib/auth/auth-store.ts +4 -5
- package/.next/standalone/lib/codex-sessions.ts +2 -1
- package/.next/standalone/lib/dashboard-host.ts +101 -0
- package/.next/standalone/lib/install-check.ts +22 -7
- package/.next/standalone/lib/pi-sessions.ts +99 -14
- package/.next/standalone/lib/telemetry-enabled.ts +54 -0
- package/.next/standalone/lib/telemetry-id.ts +52 -1
- package/.next/standalone/lib/telemetry.ts +8 -4
- 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 +3 -3
- 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 +4 -4
- package/.next/standalone/package.json +23 -12
- package/.next/standalone/proxy.ts +111 -1
- package/.next/standalone/server.js +1 -1
- package/bin/failproofai-worker.mjs +1 -1
- package/bin/failproofai.mjs +1041 -81
- package/bin/failproofaid-shim.mjs +4 -4
- package/dist/cli.mjs +18513 -10474
- package/dist/worker.mjs +1223 -299
- package/lib/auth/api-server-client.ts +2 -3
- package/lib/auth/auth-store.ts +4 -5
- package/lib/codex-sessions.ts +2 -1
- package/lib/dashboard-host.ts +101 -0
- package/lib/install-check.ts +22 -7
- package/lib/pi-sessions.ts +99 -14
- package/lib/telemetry-enabled.ts +54 -0
- package/lib/telemetry-id.ts +52 -1
- package/lib/telemetry.ts +8 -4
- package/package.json +23 -12
- package/scripts/build-daemon-packages.mjs +247 -0
- package/scripts/daemon-platforms.mjs +42 -0
- package/scripts/dev-hook.mjs +46 -5
- package/scripts/install-telemetry.mjs +8 -1
- package/scripts/launch.ts +25 -3
- package/scripts/parse-script-args.ts +27 -1
- package/scripts/prune-standalone.mjs +26 -0
- package/scripts/publish-aliases.mjs +62 -41
- package/scripts/repro-npm-install.sh +155 -0
- package/scripts/translate-docs/cache.ts +1 -1
- package/scripts/translate-docs/cli.ts +2 -2
- package/scripts/translate-docs/mintlify-nav.ts +1 -1
- package/scripts/translate-docs/readme-translator.ts +163 -4
- package/scripts/validate-mdx.ts +153 -13
- package/src/audit/audit-lock.ts +285 -0
- package/src/audit/audit-schedule.ts +111 -0
- package/src/audit/cache.ts +18 -5
- package/src/audit/cli-adapters/goose.ts +2 -1
- package/src/audit/cli-adapters/hermes.ts +28 -10
- package/src/audit/cli.ts +191 -35
- package/src/audit/dashboard-cache.ts +2 -3
- package/src/audit/report.ts +0 -1
- package/src/hooks/backfill-cli.ts +247 -0
- package/src/hooks/builtin-policies.ts +391 -3
- package/src/hooks/cloud-connection.ts +354 -0
- package/src/hooks/cloud-enrollment-cli.ts +439 -0
- package/src/hooks/cloud-enrollment.ts +284 -0
- package/src/hooks/cloud-introspect.ts +147 -0
- package/src/hooks/cloud-managed-policies.ts +206 -0
- package/src/hooks/collector-config.ts +218 -0
- package/src/hooks/configure-wizard.ts +1211 -233
- package/src/hooks/custom-hooks-loader.ts +243 -37
- package/src/hooks/daemon-client.ts +136 -33
- package/src/hooks/daemon-download.ts +264 -31
- package/src/hooks/daemon-service.ts +1124 -76
- package/src/hooks/first-run-gate.ts +50 -0
- package/src/hooks/flush-cli.ts +180 -0
- package/src/hooks/fp-config.ts +835 -0
- package/src/hooks/fp-home.ts +714 -0
- package/src/hooks/fp-reset.ts +1363 -0
- package/src/hooks/handler.ts +185 -6
- package/src/hooks/harness-cli.ts +386 -0
- package/src/hooks/hook-activity-store.ts +171 -24
- package/src/hooks/hook-logger.ts +2 -2
- package/src/hooks/hook-telemetry.ts +5 -1
- package/src/hooks/hooks-config.ts +4 -3
- package/src/hooks/integrations.ts +0 -1
- package/src/hooks/loader-utils.ts +172 -9
- package/src/hooks/manager.ts +41 -5
- package/src/hooks/migrations.ts +450 -0
- package/src/hooks/onboarding-attempt.ts +195 -0
- package/src/hooks/onboarding-lock.ts +118 -0
- package/src/hooks/policy-types.ts +28 -0
- package/src/hooks/session-pause-cli.ts +159 -0
- package/src/hooks/session-pause.ts +267 -0
- package/src/hooks/setup-state.ts +256 -0
- package/src/hooks/tui.ts +209 -9
- package/src/hooks/uninstall-cli.ts +418 -0
- package/src/hooks/worker-server.ts +134 -15
- package/.next/standalone/.next/server/chunks/[externals]__14odj07._.js +0 -3
- package/.next/standalone/.next/server/chunks/[externals]__1s61mel._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0id_xf7._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0longh-._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__19120tr._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fwl2mz._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1myjm-d._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rhmvod._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[externals]__1_g_b3t._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0114ewg._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02r5bgf._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e8sjqm._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0lkzqax._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0nb0syg._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qucxyj._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0u02miy._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0uno39i._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__14dd6h8._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ath6v_._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1psjybo._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1zqz4v8._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/_1m_p7pi._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_0oy_-36.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1ezd2jf._.js +0 -5
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1tnuifj._.js +0 -5
- package/.next/standalone/.next/static/chunks/0h7auy7hzjyhw.js +0 -1
- package/.next/standalone/.next/static/chunks/0zbxssxh53n-3.js +0 -1
- package/.next/standalone/.next/static/chunks/2mazwb1qmur1p.js +0 -1
- package/.next/standalone/.next/static/chunks/2pujpnfx4pws6.css +0 -2
- package/.next/standalone/.next/static/chunks/33u59vf_8xpd-.js +0 -1
- package/.next/standalone/.next/static/chunks/3i27c3hcriawq.css +0 -1
- package/.next/standalone/.next/static/chunks/3s7myk_co0gbh.js +0 -1
- package/.next/standalone/.next/static/chunks/40k1_v4os4cw6.js +0 -6
- package/.next/standalone/Cargo.lock +0 -428
- package/.next/standalone/Cargo.toml +0 -9
- package/.next/standalone/crates/PROTOCOL.md +0 -122
- package/.next/standalone/crates/failproofaid/Cargo.toml +0 -18
- package/.next/standalone/crates/failproofaid/src/lock.rs +0 -81
- package/.next/standalone/crates/failproofaid/src/main.rs +0 -83
- package/.next/standalone/crates/failproofaid/src/paths.rs +0 -172
- package/.next/standalone/crates/failproofaid/src/server.rs +0 -502
- package/.next/standalone/crates/failproofaid/src/worker.rs +0 -400
- package/.next/standalone/crates/failproofaid/tests/daemon_e2e.rs +0 -241
- package/.next/standalone/crates/fpai-ipc/Cargo.toml +0 -16
- package/.next/standalone/crates/fpai-ipc/src/envelope.rs +0 -175
- package/.next/standalone/crates/fpai-ipc/src/framing.rs +0 -177
- package/.next/standalone/crates/fpai-ipc/src/lib.rs +0 -10
- package/.next/standalone/crates/fpai-ipc/src/peer.rs +0 -80
- package/.next/standalone/docker-hook-sync/Dockerfile +0 -79
- package/.next/standalone/docker-hook-sync/entrypoint.sh +0 -109
- package/.next/standalone/integration-suite/Dockerfile +0 -47
- package/.next/standalone/integration-suite/README.md +0 -129
- package/.next/standalone/integration-suite/canary-policies.mjs +0 -45
- package/.next/standalone/integration-suite/capture-tokens.sh +0 -48
- package/.next/standalone/integration-suite/ci-entrypoint.sh +0 -179
- package/.next/standalone/integration-suite/inject-tokens.sh +0 -44
- package/.next/standalone/integration-suite/install-clis.sh +0 -136
- package/.next/standalone/integration-suite/probe-cli.sh +0 -248
- package/.next/standalone/integration-suite/report.js +0 -120
- package/.next/standalone/integration-suite/run.sh +0 -159
- package/.next/standalone/openclaw-plugin/index.js +0 -223
- package/.next/standalone/openclaw-plugin/openclaw.plugin.json +0 -6
- package/.next/standalone/openclaw-plugin/package.json +0 -12
- package/.next/standalone/osv-scanner.toml +0 -17
- package/.next/standalone/pi-extension/index.ts +0 -524
- package/.next/standalone/pi-extension/package.json +0 -12
- package/.next/standalone/postcss.config.mjs +0 -8
- package/.next/standalone/readme-arch-hq.gif +0 -0
- package/.next/standalone/rust-toolchain.toml +0 -4
- package/src/auth/cli.ts +0 -371
- /package/.next/standalone/.next/static/{NWAjs0tHFyzk97gRGG09r → VjEdIL6W5uBsvEzknXqV9}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{NWAjs0tHFyzk97gRGG09r → VjEdIL6W5uBsvEzknXqV9}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{NWAjs0tHFyzk97gRGG09r → VjEdIL6W5uBsvEzknXqV9}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `failproofai config --connect | --disconnect`, and the connection half of
|
|
3
|
+
* `--status`.
|
|
4
|
+
*/
|
|
5
|
+
import {
|
|
6
|
+
clearCloudCredentials,
|
|
7
|
+
maskToken,
|
|
8
|
+
readCloudCredentials,
|
|
9
|
+
writeCloudCredentials,
|
|
10
|
+
resolveMachineId,
|
|
11
|
+
resolveMachineLabel,
|
|
12
|
+
validateCloudUrl,
|
|
13
|
+
verifyCloudCredentials,
|
|
14
|
+
cloudCredentialPath,
|
|
15
|
+
} from "./cloud-enrollment";
|
|
16
|
+
import {
|
|
17
|
+
daemonRestartCommand,
|
|
18
|
+
daemonServiceStatus,
|
|
19
|
+
daemonStatusCommand,
|
|
20
|
+
daemonVersionSkew,
|
|
21
|
+
} from "./daemon-service";
|
|
22
|
+
import { clearActiveCloudManagedPolicies } from "./cloud-managed-policies";
|
|
23
|
+
import { readVersionFile, readCredentials } from "./fp-config";
|
|
24
|
+
import { version as cliVersion } from "../../package.json";
|
|
25
|
+
import { daemonSocketPresent } from "./daemon-client";
|
|
26
|
+
import {
|
|
27
|
+
cloudBaseFor,
|
|
28
|
+
configuredPaths,
|
|
29
|
+
connectToCloud,
|
|
30
|
+
describeOutcome,
|
|
31
|
+
} from "./cloud-connection";
|
|
32
|
+
import {
|
|
33
|
+
clearIngestCredential,
|
|
34
|
+
hasIngestCredential,
|
|
35
|
+
readIngestCredential,
|
|
36
|
+
validateIngestKey,
|
|
37
|
+
} from "./collector-config";
|
|
38
|
+
import { updateConfig } from "./fp-config";
|
|
39
|
+
import type { introspectKey } from "./cloud-introspect";
|
|
40
|
+
|
|
41
|
+
export interface ConnectOptions {
|
|
42
|
+
url?: string;
|
|
43
|
+
token?: string;
|
|
44
|
+
machineId?: string;
|
|
45
|
+
/** Human-facing display name for this machine. Defaults to the hostname. */
|
|
46
|
+
machineLabel?: string;
|
|
47
|
+
/**
|
|
48
|
+
* The hostname, passed in by the caller (and injected by tests). Used as the
|
|
49
|
+
* default machine *label*, no longer as the machine id — the id now mints or
|
|
50
|
+
* reuses a stable key so two hosts with the same hostname never merge.
|
|
51
|
+
*/
|
|
52
|
+
defaultMachineId?: string;
|
|
53
|
+
/**
|
|
54
|
+
* Send full session transcripts as well as hook decisions.
|
|
55
|
+
*
|
|
56
|
+
* DEFAULTS ON. A transcript carries prompts, file contents and whatever was
|
|
57
|
+
* pasted into a terminal — which is precisely what makes a dashboard worth
|
|
58
|
+
* connecting to, so hiding it behind an opt-in produced the empty-dashboard
|
|
59
|
+
* problem in a different costume. `false` is the explicit opt-out; the
|
|
60
|
+
* disclosure is printed either way.
|
|
61
|
+
*/
|
|
62
|
+
sessions?: boolean;
|
|
63
|
+
environment?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Injected for tests so nothing reaches the network.
|
|
66
|
+
*
|
|
67
|
+
* All THREE must be here, and a new network call added below has to gain its
|
|
68
|
+
* seam in the same commit: `introspect` was added without one, so every test
|
|
69
|
+
* in `cloud-enrollment-cli.test.ts` silently began making a real request to
|
|
70
|
+
* `be.failproof.ai`. It usually failed fast enough to pass, which is the worst
|
|
71
|
+
* available outcome — the suite went intermittently red on network timing
|
|
72
|
+
* rather than on anything a change had broken.
|
|
73
|
+
*/
|
|
74
|
+
verify?: typeof verifyCloudCredentials;
|
|
75
|
+
verifyIngest?: typeof validateIngestKey;
|
|
76
|
+
introspect?: typeof introspectKey;
|
|
77
|
+
daemonStatus?: () => ReturnType<typeof daemonServiceStatus>;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface CommandResult {
|
|
81
|
+
exitCode: number;
|
|
82
|
+
lines: string[];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* How a machine is named in CLI output: the human label, plus enough of the id to
|
|
87
|
+
* tell two machines apart.
|
|
88
|
+
*
|
|
89
|
+
* The full uuid used to be printed in every status line — `Mac.localdomain
|
|
90
|
+
* (dde01f39-afba-40eb-bf1a-815d9f17ac2d)` — which is 36 characters of noise for
|
|
91
|
+
* the one reader who cannot use them, and it made the id look like the machine's
|
|
92
|
+
* name. The id still has to appear: labels default to the hostname and are free to
|
|
93
|
+
* collide, so the label alone cannot identify a machine. Eight hex characters
|
|
94
|
+
* distinguish any realistic fleet while staying readable.
|
|
95
|
+
*
|
|
96
|
+
* `failproofai config --status --verbose` prints the full id for support.
|
|
97
|
+
*/
|
|
98
|
+
export function describeMachine(
|
|
99
|
+
machineId: string,
|
|
100
|
+
machineLabel?: string,
|
|
101
|
+
full = false,
|
|
102
|
+
): string {
|
|
103
|
+
if (!machineLabel || machineLabel === machineId) return machineId;
|
|
104
|
+
return full ? `${machineLabel} (${machineId})` : `${machineLabel} (${machineId.slice(0, 8)})`;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Warn rather than refuse when there is no daemon.
|
|
109
|
+
*
|
|
110
|
+
* Cloud policy is evaluated by failproofaid, so credentials alone pull
|
|
111
|
+
* nothing — but refusing would break baking a machine image where the daemon
|
|
112
|
+
* is installed later, and enrolment is genuinely independent of it. Say so
|
|
113
|
+
* loudly instead of failing.
|
|
114
|
+
*/
|
|
115
|
+
function daemonWarning(status: ReturnType<typeof daemonServiceStatus>): string[] {
|
|
116
|
+
if (status === "running") return [];
|
|
117
|
+
// "I could not tell", NOT "it is not a service". This has its own branch, and it
|
|
118
|
+
// is ahead of the socket check, because on macOS it is the COMMON case rather
|
|
119
|
+
// than an edge one: a LaunchDaemon lives in launchd's system domain, so
|
|
120
|
+
// `daemonServiceStatus()` needs elevation to read it and returns "unknown"
|
|
121
|
+
// whenever `sudo -n` finds no cached credential — which is most of the time, for
|
|
122
|
+
// a normal user running a read-only status command.
|
|
123
|
+
//
|
|
124
|
+
// With no branch of its own it fell through to the socket check below and
|
|
125
|
+
// announced that the daemon was "running outside the service manager", which is
|
|
126
|
+
// flatly false for a correctly installed service, and told the user to install
|
|
127
|
+
// something they already had. Linux never showed it, because `systemctl
|
|
128
|
+
// is-active` needs no privileges — that asymmetry was the whole of the bug.
|
|
129
|
+
if (status === "unknown") {
|
|
130
|
+
const check = daemonStatusCommand();
|
|
131
|
+
return [
|
|
132
|
+
"",
|
|
133
|
+
...(daemonSocketPresent()
|
|
134
|
+
? [" A daemon is running and policy is being pulled."]
|
|
135
|
+
: ["! No daemon is answering, so nothing is being pulled right now."]),
|
|
136
|
+
" Its service state needs elevation to read, so it is not shown above.",
|
|
137
|
+
...(check ? [` Check it with: sudo ${check}`] : []),
|
|
138
|
+
];
|
|
139
|
+
}
|
|
140
|
+
// A daemon started by hand is invisible to the service manager but is
|
|
141
|
+
// running and pulling. Telling someone whose machine is actively enforcing
|
|
142
|
+
// that "nothing will be pulled" is false, and it is exactly the state a
|
|
143
|
+
// developer testing locally is in.
|
|
144
|
+
if (daemonSocketPresent()) {
|
|
145
|
+
return [
|
|
146
|
+
"",
|
|
147
|
+
" A daemon is running outside the service manager, so policy is being pulled.",
|
|
148
|
+
" Install it as a service to survive reboot and logout: failproofai config",
|
|
149
|
+
];
|
|
150
|
+
}
|
|
151
|
+
if (status === "unsupported-platform") {
|
|
152
|
+
return [
|
|
153
|
+
"",
|
|
154
|
+
"! failproofaid does not run on this platform yet, so nothing will be pulled.",
|
|
155
|
+
" The credentials are stored and will work on a supported machine.",
|
|
156
|
+
];
|
|
157
|
+
}
|
|
158
|
+
if (status === "not-installed") {
|
|
159
|
+
// "as a service", not "at all": this reads the service manager, so a daemon
|
|
160
|
+
// someone is running by hand during development is reported as absent. The
|
|
161
|
+
// wording has to be true in both cases.
|
|
162
|
+
return [
|
|
163
|
+
"",
|
|
164
|
+
"! failproofaid is not installed as a service, so nothing will be pulled yet.",
|
|
165
|
+
" Install it with: failproofai config",
|
|
166
|
+
];
|
|
167
|
+
}
|
|
168
|
+
return [
|
|
169
|
+
"",
|
|
170
|
+
"! failproofaid is installed but not running, so nothing will be pulled yet.",
|
|
171
|
+
" Check it with: failproofai config --status",
|
|
172
|
+
];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export async function runConnectCommand(opts: ConnectOptions): Promise<CommandResult> {
|
|
176
|
+
if (!opts.url) return { exitCode: 1, lines: ["--connect needs a URL, e.g. --connect https://be.failproof.ai"] };
|
|
177
|
+
if (!opts.token) {
|
|
178
|
+
return {
|
|
179
|
+
exitCode: 1,
|
|
180
|
+
lines: [
|
|
181
|
+
"--connect needs a machine token: --token <key>",
|
|
182
|
+
"",
|
|
183
|
+
"Create an API key carrying only the `policies:pull` permission for this",
|
|
184
|
+
"machine. Do not use an admin key.",
|
|
185
|
+
],
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Accepts the ingest endpoint too. People paste what the older setup asked
|
|
190
|
+
// for, or what is already in their `ingest.json`, and refusing a URL we can
|
|
191
|
+
// read perfectly well is pedantry.
|
|
192
|
+
const validated = validateCloudUrl(cloudBaseFor(opts.url));
|
|
193
|
+
if (!validated.ok) return { exitCode: 1, lines: [validated.reason] };
|
|
194
|
+
|
|
195
|
+
// The stable key: an explicit --machine-id wins, else the id already enrolled
|
|
196
|
+
// here is reused (idempotent re-connect), else a fresh one is minted. Never
|
|
197
|
+
// the hostname — that is the label, so same-hostname hosts do not merge.
|
|
198
|
+
const machineId = resolveMachineId(opts.machineId);
|
|
199
|
+
const machineLabel = resolveMachineLabel(opts.machineLabel ?? opts.defaultMachineId);
|
|
200
|
+
// Humans read the label; the id is shown in parentheses only when it differs,
|
|
201
|
+
// so an operator who set an explicit --machine-id still sees it.
|
|
202
|
+
const shownAs = describeMachine(machineId, machineLabel);
|
|
203
|
+
|
|
204
|
+
// ONE connection, both capabilities. Each is verified before anything is
|
|
205
|
+
// written and reported on its own, because a key can carry `policies:pull`
|
|
206
|
+
// without `events:add` and the useful message names which one is missing.
|
|
207
|
+
const outcome = await connectToCloud({
|
|
208
|
+
url: validated.url,
|
|
209
|
+
token: opts.token,
|
|
210
|
+
machineId,
|
|
211
|
+
machineLabel,
|
|
212
|
+
sessions: opts.sessions,
|
|
213
|
+
environment: opts.environment,
|
|
214
|
+
verifyPolicy: opts.verify,
|
|
215
|
+
verifyIngest: opts.verifyIngest,
|
|
216
|
+
introspect: opts.introspect,
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
if (!outcome.anyConfigured) {
|
|
220
|
+
return { exitCode: 1, lines: describeOutcome(outcome, shownAs, validated.url) };
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// The exit code tracks the PRIMARY purpose — enrolling this machine for
|
|
224
|
+
// cloud-managed policy. Configuring the dashboard is worth doing and worth
|
|
225
|
+
// reporting, but it must not turn a failed enrolment into a success: a fleet
|
|
226
|
+
// provisioning script running `--connect … && …` has to stop when the machine
|
|
227
|
+
// will not receive policy. The ingest credential still gets written, because
|
|
228
|
+
// it works and discarding it helps nobody.
|
|
229
|
+
const exitCode = outcome.policy.ok ? 0 : 1;
|
|
230
|
+
|
|
231
|
+
const status = (opts.daemonStatus ?? daemonServiceStatus)();
|
|
232
|
+
const paths = configuredPaths(outcome);
|
|
233
|
+
const lines = [
|
|
234
|
+
...describeOutcome(outcome, shownAs, validated.url),
|
|
235
|
+
` Token ${maskToken(opts.token)} stored in ${paths.join(" and ")} (owner-only).`,
|
|
236
|
+
];
|
|
237
|
+
if (outcome.ingest.ok) {
|
|
238
|
+
// Stated on BOTH branches, never only on the surprising one. Connecting
|
|
239
|
+
// sends transcripts by default — prompts, file contents, command output —
|
|
240
|
+
// and a default that carries that much is one the user has to be told
|
|
241
|
+
// about at the moment it takes effect, not left to find in --help.
|
|
242
|
+
lines.push(
|
|
243
|
+
opts.sessions === false
|
|
244
|
+
? " Session transcripts are NOT being sent (--no-transcripts). Decisions only."
|
|
245
|
+
: " Sending policy decisions AND full session transcripts (prompts, file\n" +
|
|
246
|
+
" contents, command output). Use --no-transcripts for decisions only.",
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
lines.push(...daemonWarning(status));
|
|
250
|
+
|
|
251
|
+
return { exitCode, lines };
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Rename this machine without re-enrolling it.
|
|
256
|
+
*
|
|
257
|
+
* `--machine-label` was accepted only alongside `--connect`, so the sole way to
|
|
258
|
+
* change a name was to re-run enrolment with the URL and token again — which reads
|
|
259
|
+
* as a destructive operation for what is a display change, and which nobody with a
|
|
260
|
+
* machine token to hand is going to do casually. The hostname default is a
|
|
261
|
+
* suggestion (`resolveMachineLabel`), so renaming is the expected path, not an
|
|
262
|
+
* exception.
|
|
263
|
+
*
|
|
264
|
+
* The label rides the desired-state request (`&label=`), which is also the check
|
|
265
|
+
* that the credentials still work — so a rename verifies as a side effect. A
|
|
266
|
+
* server that cannot be reached is NOT treated as failure: the label is stored
|
|
267
|
+
* locally first and the daemon sends it on its next poll. Refusing to rename a
|
|
268
|
+
* machine because the network is down would make this useless exactly when someone
|
|
269
|
+
* is trying to label a machine they are debugging.
|
|
270
|
+
*/
|
|
271
|
+
export async function runRenameCommand(
|
|
272
|
+
label: string | undefined,
|
|
273
|
+
deps: { verify?: typeof verifyCloudCredentials } = {},
|
|
274
|
+
): Promise<CommandResult> {
|
|
275
|
+
const trimmed = label?.trim();
|
|
276
|
+
if (!trimmed) {
|
|
277
|
+
return { exitCode: 1, lines: ["--machine-label needs a name, e.g. --machine-label \"Nikita's Mac\""] };
|
|
278
|
+
}
|
|
279
|
+
const creds = readCloudCredentials();
|
|
280
|
+
if (!creds) {
|
|
281
|
+
return {
|
|
282
|
+
exitCode: 1,
|
|
283
|
+
lines: [
|
|
284
|
+
"This machine is not connected to Failproof Cloud, so it has no name to change.",
|
|
285
|
+
"Connect it first: failproofai config --connect <url> --token <key>",
|
|
286
|
+
],
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
if (creds.machineLabel === trimmed) {
|
|
290
|
+
return { exitCode: 0, lines: [`This machine is already named ${describeMachine(creds.machineId, trimmed)}.`] };
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const previous = creds.machineLabel;
|
|
294
|
+
// Stored BEFORE the push, so a rename survives an unreachable server.
|
|
295
|
+
writeCloudCredentials({ ...creds, machineLabel: trimmed });
|
|
296
|
+
|
|
297
|
+
const verify = deps.verify ?? verifyCloudCredentials;
|
|
298
|
+
const result = await verify({ ...creds, machineLabel: trimmed });
|
|
299
|
+
|
|
300
|
+
const lines = [
|
|
301
|
+
previous
|
|
302
|
+
? `Renamed ${previous} to ${describeMachine(creds.machineId, trimmed)}.`
|
|
303
|
+
: `Named this machine ${describeMachine(creds.machineId, trimmed)}.`,
|
|
304
|
+
];
|
|
305
|
+
if (!result.ok) {
|
|
306
|
+
lines.push(
|
|
307
|
+
"",
|
|
308
|
+
`! The new name is stored but ${creds.url} could not be told: ${result.reason}`,
|
|
309
|
+
" The daemon sends it on its next poll, so the dashboard catches up on its own.",
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
// Exit 0 either way: the rename DID happen locally, and reporting failure for a
|
|
313
|
+
// stored change would send the user round again to redo something that is done.
|
|
314
|
+
return { exitCode: 0, lines };
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
export function runDisconnectCommand(): CommandResult {
|
|
318
|
+
const existing = readCloudCredentials();
|
|
319
|
+
const hadIngest = hasIngestCredential();
|
|
320
|
+
const removed = clearCloudCredentials();
|
|
321
|
+
// Disconnect means disconnect. Clearing only the policy credential would
|
|
322
|
+
// leave the machine still shipping activity to a cloud the user believes
|
|
323
|
+
// they have left — the one outcome nobody expects from this command.
|
|
324
|
+
const removedIngest = clearIngestCredential();
|
|
325
|
+
// Stop ENFORCING them too, not merely refreshing them. Clearing the
|
|
326
|
+
// credential ends the daemon's polling; every artifact already on disk stayed
|
|
327
|
+
// referenced by `active.json` and kept being loaded on every tool call — so a
|
|
328
|
+
// machine that had deliberately left its organisation went on being governed
|
|
329
|
+
// by whatever deployment was current when it left, indefinitely, while
|
|
330
|
+
// `--status` reported it as unconnected.
|
|
331
|
+
const stoppedManaged = clearActiveCloudManagedPolicies();
|
|
332
|
+
// Back to OSS. Leaving mode = "cloud" with no credentials would describe a
|
|
333
|
+
// machine that does not exist, and every cloud code path keys off this flag
|
|
334
|
+
// rather than off "is a token lying around" precisely so that a disconnected
|
|
335
|
+
// machine is provably silent instead of silent-by-happenstance.
|
|
336
|
+
updateConfig({ mode: "oss" });
|
|
337
|
+
|
|
338
|
+
if (!removed && !existing && !hadIngest && !stoppedManaged) {
|
|
339
|
+
return { exitCode: 0, lines: ["This machine is not connected to Failproof Cloud."] };
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const lines = [
|
|
343
|
+
"Disconnected from Failproof Cloud.",
|
|
344
|
+
"",
|
|
345
|
+
stoppedManaged
|
|
346
|
+
? " Cloud-managed policies stop being enforced and stop being refreshed.\n" +
|
|
347
|
+
" Local builtin, custom and convention policies are unaffected."
|
|
348
|
+
: " Local builtin, custom and convention policies are unaffected.",
|
|
349
|
+
];
|
|
350
|
+
if (removedIngest) {
|
|
351
|
+
// Named honestly. The collector manager starts once for the daemon's
|
|
352
|
+
// lifetime (`main.rs`) and the uploader caches its bearer key at
|
|
353
|
+
// construction, so nothing already running notices this file disappear —
|
|
354
|
+
// "stop being sent" was true only of the NEXT daemon start. Telling the
|
|
355
|
+
// user the step that makes it true beats a claim that quietly is not.
|
|
356
|
+
lines.push(
|
|
357
|
+
" No new hook activity or transcripts will be queued. A running failproofaid",
|
|
358
|
+
" keeps the key it started with, so restart it to stop the current process",
|
|
359
|
+
` sending: ${daemonRestartCommand() ?? "restart failproofaid"}`,
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
return { exitCode: 0, lines };
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/** The connection half of `--status`. Never prints the token. */
|
|
366
|
+
/**
|
|
367
|
+
* The version line for `--status`.
|
|
368
|
+
*
|
|
369
|
+
* First thing worth knowing in a bug report, and the only place a user can
|
|
370
|
+
* currently find out which daemon they are running without listing a directory.
|
|
371
|
+
*/
|
|
372
|
+
export function versionStatusLines(): string[] {
|
|
373
|
+
const skew = daemonVersionSkew();
|
|
374
|
+
const recorded = readVersionFile();
|
|
375
|
+
const daemon = recorded?.daemon ?? "not installed";
|
|
376
|
+
return [
|
|
377
|
+
`CLI ${cliVersion} · daemon ${daemon}${skew ? " (STALE)" : ""} · layout ${recorded?.layout ?? "-"}`,
|
|
378
|
+
...(skew ? [" Run `failproofai config` to update the daemon."] : []),
|
|
379
|
+
];
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
export function connectionStatusLines(
|
|
383
|
+
daemonStatus = daemonServiceStatus,
|
|
384
|
+
/** Print the full machine id rather than a short prefix. */
|
|
385
|
+
verbose = false,
|
|
386
|
+
): string[] {
|
|
387
|
+
const envUrl = process.env.FAILPROOFAI_CLOUD_URL;
|
|
388
|
+
if (envUrl) {
|
|
389
|
+
// Env wins over the file in the daemon, so reporting the file here would
|
|
390
|
+
// describe a configuration that is not in effect.
|
|
391
|
+
return [
|
|
392
|
+
`Cloud: configured by environment (${envUrl}), which takes precedence over ${cloudCredentialPath()}.`,
|
|
393
|
+
];
|
|
394
|
+
}
|
|
395
|
+
const creds = readCloudCredentials();
|
|
396
|
+
const ingest = readIngestCredential();
|
|
397
|
+
|
|
398
|
+
// Reported as ONE connection with two capabilities. A machine sending
|
|
399
|
+
// activity but pulling no policy, or the reverse, is a state worth seeing at
|
|
400
|
+
// a glance — it is exactly the half-configured case this command exists to
|
|
401
|
+
// catch, and two unrelated lines made it easy to miss.
|
|
402
|
+
if (!creds && !ingest) return ["Cloud: not connected."];
|
|
403
|
+
|
|
404
|
+
// Recorded at connect time from the server's own answer, never guessed from
|
|
405
|
+
// the URL: one deployment hosts many orgs, so the host says nothing about
|
|
406
|
+
// which one this machine's data lands in. Absent against a server with no
|
|
407
|
+
// introspect endpoint, and on credentials written before this was recorded —
|
|
408
|
+
// in both cases the line is simply omitted rather than guessed at.
|
|
409
|
+
const org = readCredentials().org;
|
|
410
|
+
const orgLine = org
|
|
411
|
+
? org.name && org.slug
|
|
412
|
+
? `${org.name} (${org.slug})`
|
|
413
|
+
: (org.name ?? org.slug ?? org.id)
|
|
414
|
+
: undefined;
|
|
415
|
+
|
|
416
|
+
const lines: string[] = [];
|
|
417
|
+
if (creds) {
|
|
418
|
+
// Label first, with a short id to disambiguate; the bare id is the fallback
|
|
419
|
+
// for credentials written before labels existed.
|
|
420
|
+
const shownAs = describeMachine(creds.machineId, creds.machineLabel, verbose);
|
|
421
|
+
lines.push(`Cloud: connected to ${creds.url} as ${shownAs} (token ${maskToken(creds.token)}).`);
|
|
422
|
+
lines.push(` Policy pulling centrally-managed policies.`);
|
|
423
|
+
} else {
|
|
424
|
+
lines.push(`Cloud: connected to ${cloudBaseFor(ingest!.url)} for reporting only.`);
|
|
425
|
+
lines.push(` Policy NOT pulling — this machine enforces only its local policies.`);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
if (orgLine) lines.push(` Org ${orgLine}`);
|
|
429
|
+
|
|
430
|
+
if (ingest) {
|
|
431
|
+
lines.push(` Dashboard sending hook activity to ${ingest.url}.`);
|
|
432
|
+
} else {
|
|
433
|
+
lines.push(` Dashboard NOT sending — nothing from this machine appears in the dashboard.`);
|
|
434
|
+
lines.push(` Re-run: failproofai config --connect ${creds!.url} --token <key>`);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
lines.push(...daemonWarning(daemonStatus()).map((l) => (l === "" ? "" : ` ${l.trim()}`)));
|
|
438
|
+
return lines;
|
|
439
|
+
}
|