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
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import { execSync } from 'child_process';
|
|
3
3
|
import { readFileSync, writeFileSync, mkdirSync, rmSync, cpSync } from 'fs';
|
|
4
4
|
import { join, dirname } from 'path';
|
|
5
|
-
import { fileURLToPath } from 'url';
|
|
5
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
6
|
+
import { daemonOptionalDependencies } from './daemon-platforms.mjs';
|
|
6
7
|
|
|
7
8
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
9
|
const rootPkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'));
|
|
@@ -11,7 +12,7 @@ const DRY_RUN = process.argv.includes('--dry-run');
|
|
|
11
12
|
const distTagIdx = process.argv.indexOf('--dist-tag');
|
|
12
13
|
const DIST_TAG = distTagIdx !== -1 ? process.argv[distTagIdx + 1] : (VERSION.includes('-') ? 'beta' : 'latest');
|
|
13
14
|
|
|
14
|
-
const ALIASES = [
|
|
15
|
+
export const ALIASES = [
|
|
15
16
|
// Formatting variants — no "ai", or hyphen/underscore separators
|
|
16
17
|
'failproof',
|
|
17
18
|
'failproof-ai',
|
|
@@ -31,57 +32,77 @@ const ALIASES = [
|
|
|
31
32
|
'faliproofai',
|
|
32
33
|
];
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
/**
|
|
36
|
+
* The manifest one alias stub publishes.
|
|
37
|
+
*
|
|
38
|
+
* The four `@failproofai/failproofaid-<platform>` pins are the same ones the
|
|
39
|
+
* root package carries. They arrive transitively through the `failproofai`
|
|
40
|
+
* dependency anyway, but naming them here means someone who installs a typo'd
|
|
41
|
+
* name gets the daemon binary for exactly the reason the root package does,
|
|
42
|
+
* rather than by accident of resolution — and a test can assert it.
|
|
43
|
+
*/
|
|
44
|
+
export function aliasManifest(name, version = VERSION, pkg = rootPkg) {
|
|
45
|
+
return {
|
|
42
46
|
name,
|
|
43
|
-
version
|
|
47
|
+
version,
|
|
44
48
|
description: `Alias for failproofai — installs if you typed '${name}' instead of 'failproofai'`,
|
|
45
49
|
bin: { [name]: './bin/proxy.js' },
|
|
46
50
|
files: ['bin/'],
|
|
47
|
-
dependencies: { failproofai:
|
|
51
|
+
dependencies: { failproofai: version },
|
|
52
|
+
optionalDependencies: daemonOptionalDependencies(version),
|
|
48
53
|
publishConfig: { access: 'public' },
|
|
49
|
-
repository:
|
|
50
|
-
homepage:
|
|
51
|
-
bugs:
|
|
52
|
-
license:
|
|
54
|
+
repository: pkg.repository,
|
|
55
|
+
homepage: pkg.homepage,
|
|
56
|
+
bugs: pkg.bugs,
|
|
57
|
+
license: pkg.license,
|
|
53
58
|
};
|
|
59
|
+
}
|
|
54
60
|
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
export function main() {
|
|
62
|
+
const warnings = [];
|
|
57
63
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
64
|
+
for (const name of ALIASES) {
|
|
65
|
+
const tmpDir = join('/tmp', `npm-alias-${name}-${Date.now()}`);
|
|
66
|
+
const binDir = join(tmpDir, 'bin');
|
|
67
|
+
mkdirSync(binDir, { recursive: true });
|
|
68
|
+
|
|
69
|
+
const pkg = aliasManifest(name);
|
|
65
70
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
71
|
+
writeFileSync(join(tmpDir, 'package.json'), JSON.stringify(pkg, null, 2) + '\n');
|
|
72
|
+
cpSync(join(__dirname, 'alias-proxy.js'), join(binDir, 'proxy.js'));
|
|
73
|
+
|
|
74
|
+
if (DRY_RUN) {
|
|
75
|
+
console.log(`[dry-run] Would publish ${name}@${VERSION} (tag: ${DIST_TAG})`);
|
|
76
|
+
console.log(JSON.stringify(pkg, null, 2));
|
|
77
|
+
console.log('---');
|
|
78
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
console.log(`Publishing ${name}@${VERSION}...`);
|
|
83
|
+
try {
|
|
84
|
+
execSync(`npm publish --tag ${DIST_TAG}`, { cwd: tmpDir, stdio: 'pipe' });
|
|
85
|
+
console.log(`Done: ${name}`);
|
|
86
|
+
} catch (err) {
|
|
87
|
+
const output = (err.stdout?.toString() ?? '') + (err.stderr?.toString() ?? '');
|
|
88
|
+
if (output.includes('too similar')) {
|
|
89
|
+
warnings.push(`${name}: blocked by npm similarity check — request via npm support`);
|
|
90
|
+
} else if (output.includes('cannot publish over')) {
|
|
91
|
+
console.log(`[skip] ${name}: already published at ${VERSION}`);
|
|
92
|
+
} else {
|
|
93
|
+
warnings.push(`${name}: ${output.trim().split('\n').find(l => l.includes('npm error')) ?? 'unknown error'}`);
|
|
94
|
+
}
|
|
78
95
|
}
|
|
96
|
+
|
|
97
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
79
98
|
}
|
|
80
99
|
|
|
81
|
-
|
|
100
|
+
if (warnings.length > 0) {
|
|
101
|
+
console.log('\n::warning::Some alias packages were not published:');
|
|
102
|
+
for (const w of warnings) console.log(` - ${w}`);
|
|
103
|
+
}
|
|
82
104
|
}
|
|
83
105
|
|
|
84
|
-
if (
|
|
85
|
-
|
|
86
|
-
for (const w of warnings) console.log(` - ${w}`);
|
|
106
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
107
|
+
main();
|
|
87
108
|
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
3
|
+
# Reproduce a REAL user install, in the shape that actually breaks.
|
|
4
|
+
#
|
|
5
|
+
# sudo npm i -g failproofai (global prefix owned by root)
|
|
6
|
+
# then run the CLI as a NORMAL user
|
|
7
|
+
#
|
|
8
|
+
# That split is the whole point. A single-user laptop where npm's prefix is
|
|
9
|
+
# owned by the person running the hooks hides an entire class of bug — it is
|
|
10
|
+
# how the root-owned policy-shim fail-open shipped: every hook run by a non-root
|
|
11
|
+
# user hit EACCES, the policy never loaded, and the hook exited 0 ALLOWING the
|
|
12
|
+
# call, while builtins kept firing so the machine looked protected.
|
|
13
|
+
#
|
|
14
|
+
# systemd is real here (jrei/systemd-ubuntu), so `failproofai config` installs
|
|
15
|
+
# and starts the actual service rather than skipping that half.
|
|
16
|
+
#
|
|
17
|
+
# Usage:
|
|
18
|
+
# scripts/repro-npm-install.sh # build, pack, drop into a shell
|
|
19
|
+
# scripts/repro-npm-install.sh --published # install the last RELEASE instead
|
|
20
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
21
|
+
set -uo pipefail
|
|
22
|
+
|
|
23
|
+
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
24
|
+
cd "$REPO"
|
|
25
|
+
|
|
26
|
+
IMAGE=jrei/systemd-ubuntu:24.04
|
|
27
|
+
NAME=fpai-repro
|
|
28
|
+
USER_IN_BOX=dev
|
|
29
|
+
PUBLISHED=0
|
|
30
|
+
[ "${1:-}" = "--published" ] && PUBLISHED=1
|
|
31
|
+
|
|
32
|
+
VERSION=$(node -p "require('$REPO/package.json').version")
|
|
33
|
+
say() { printf '\n\033[1m── %s\033[0m\n' "$1"; }
|
|
34
|
+
|
|
35
|
+
# ── 1. Build what a tarball would carry ──────────────────────────────────────
|
|
36
|
+
if [ "$PUBLISHED" -eq 0 ]; then
|
|
37
|
+
say "Building dist + daemon"
|
|
38
|
+
[ -f dist/cli.mjs ] || bun run build
|
|
39
|
+
[ -f target/release/failproofaid ] || cargo build --release --bin failproofaid
|
|
40
|
+
|
|
41
|
+
# `dist/cli.mjs` INLINES the version at build time. `npm pack --ignore-scripts`
|
|
42
|
+
# skips the `prepare` script that would rebuild it, so bumping package.json
|
|
43
|
+
# without rebuilding packs a bundle that reports the OLD version — and you
|
|
44
|
+
# spend an afternoon testing code you did not write. A real publish never hits
|
|
45
|
+
# this (publish.yml builds, and `prepare` runs on a normal pack); this is a
|
|
46
|
+
# trap of the fast path only, which is exactly why it is checked here.
|
|
47
|
+
if ! grep -q "$VERSION" dist/cli.mjs 2>/dev/null; then
|
|
48
|
+
say "dist is stale (built for $(grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+-beta\.[0-9]\+' dist/cli.mjs | head -1)) — rebuilding"
|
|
49
|
+
bun run build
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
say "Packing $VERSION"
|
|
53
|
+
rm -f failproofai-*.tgz
|
|
54
|
+
npm pack --ignore-scripts >/dev/null 2>&1
|
|
55
|
+
TARBALL="$REPO/failproofai-$VERSION.tgz"
|
|
56
|
+
[ -f "$TARBALL" ] || { echo "pack failed"; exit 1; }
|
|
57
|
+
ls -la "$TARBALL" | awk '{printf " %s bytes %s\n", $5, $9}'
|
|
58
|
+
|
|
59
|
+
# Belt and braces: assert what is actually IN the tarball, not what we meant
|
|
60
|
+
# to put there.
|
|
61
|
+
PACKED=$(tar -xzOf "$TARBALL" package/dist/cli.mjs 2>/dev/null \
|
|
62
|
+
| grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+-beta\.[0-9]\+' | head -1)
|
|
63
|
+
if [ "$PACKED" != "$VERSION" ]; then
|
|
64
|
+
echo " REFUSING: tarball reports '$PACKED' but package.json says '$VERSION'"
|
|
65
|
+
exit 1
|
|
66
|
+
fi
|
|
67
|
+
echo " bundled version verified: $PACKED"
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# ── 2. A container with a real init ──────────────────────────────────────────
|
|
71
|
+
say "Starting $IMAGE (real systemd)"
|
|
72
|
+
docker rm -f "$NAME" >/dev/null 2>&1
|
|
73
|
+
# --cgroupns=host + the two tmpfs mounts are REQUIRED on a cgroup v2 host
|
|
74
|
+
# (anything modern). Without them systemd cannot set up its own hierarchy and
|
|
75
|
+
# the container exits 255 immediately, with an empty `docker logs` — which is
|
|
76
|
+
# a genuinely awful thing to debug, hence the comment.
|
|
77
|
+
docker run -d --name "$NAME" --privileged --cgroupns=host \
|
|
78
|
+
--network=host \
|
|
79
|
+
-v /sys/fs/cgroup:/sys/fs/cgroup:rw --tmpfs /run --tmpfs /run/lock \
|
|
80
|
+
${TARBALL:+-v "$TARBALL":/pkg.tgz:ro} \
|
|
81
|
+
-v "$REPO/target/release/failproofaid":/opt/failproofaid:ro \
|
|
82
|
+
"$IMAGE" >/dev/null
|
|
83
|
+
# Wait for systemd to finish booting, or `systemctl` answers nothing useful.
|
|
84
|
+
until docker exec "$NAME" systemctl is-system-running 2>/dev/null | grep -qE 'running|degraded'; do
|
|
85
|
+
if ! docker ps --filter "name=$NAME" --format '{{.Names}}' | grep -q "$NAME"; then
|
|
86
|
+
echo " container died during boot — cgroup v2 flags wrong for this host?"
|
|
87
|
+
docker logs "$NAME" 2>&1 | tail -5
|
|
88
|
+
exit 1
|
|
89
|
+
fi
|
|
90
|
+
sleep 1
|
|
91
|
+
done
|
|
92
|
+
echo " systemd: $(docker exec "$NAME" systemctl is-system-running 2>/dev/null)"
|
|
93
|
+
|
|
94
|
+
# ── 3. Node, and a NON-ROOT user to run as ───────────────────────────────────
|
|
95
|
+
say "Installing Node + creating an unprivileged user"
|
|
96
|
+
docker exec "$NAME" bash -lc '
|
|
97
|
+
apt-get update -qq >/dev/null 2>&1
|
|
98
|
+
apt-get install -y -qq curl ca-certificates sudo >/dev/null 2>&1
|
|
99
|
+
curl -fsSL https://deb.nodesource.com/setup_22.x -o /tmp/n.sh 2>/dev/null && bash /tmp/n.sh >/dev/null 2>&1
|
|
100
|
+
apt-get install -y -qq nodejs >/dev/null 2>&1
|
|
101
|
+
node --version
|
|
102
|
+
' 2>&1 | sed 's/^/ node /'
|
|
103
|
+
|
|
104
|
+
docker exec "$NAME" bash -lc "
|
|
105
|
+
id $USER_IN_BOX >/dev/null 2>&1 || useradd -m -s /bin/bash $USER_IN_BOX
|
|
106
|
+
# Passwordless sudo: the daemon install needs root, and we are testing the
|
|
107
|
+
# INSTALL, not whether a human can type a password.
|
|
108
|
+
echo '$USER_IN_BOX ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/$USER_IN_BOX
|
|
109
|
+
chmod 440 /etc/sudoers.d/$USER_IN_BOX
|
|
110
|
+
"
|
|
111
|
+
|
|
112
|
+
# ── 4. Install globally AS ROOT — the shape that exposes ownership bugs ──────
|
|
113
|
+
say "npm install -g (as root)"
|
|
114
|
+
if [ "$PUBLISHED" -eq 1 ]; then
|
|
115
|
+
docker exec "$NAME" bash -lc "npm install -g failproofai@$VERSION 2>&1 | tail -4"
|
|
116
|
+
else
|
|
117
|
+
docker exec "$NAME" bash -lc "npm install -g /pkg.tgz 2>&1 | tail -4"
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
say "Who owns the global install?"
|
|
121
|
+
docker exec "$NAME" bash -lc '
|
|
122
|
+
P=$(npm root -g)/failproofai
|
|
123
|
+
stat -c " %U:%G %a %n" "$P" 2>/dev/null
|
|
124
|
+
stat -c " %U:%G %a %n" "$P/dist" 2>/dev/null
|
|
125
|
+
'
|
|
126
|
+
|
|
127
|
+
# ── 5. Hand over, running as the unprivileged user ───────────────────────────
|
|
128
|
+
say "Ready"
|
|
129
|
+
cat <<EOF
|
|
130
|
+
|
|
131
|
+
The box is up as container "$NAME". Everything below runs as the
|
|
132
|
+
UNPRIVILEGED user, against a root-owned global install — the real shape.
|
|
133
|
+
|
|
134
|
+
Shell in:
|
|
135
|
+
docker exec -it -u $USER_IN_BOX $NAME bash -l
|
|
136
|
+
|
|
137
|
+
Then, inside:
|
|
138
|
+
failproofai --version
|
|
139
|
+
failproofai config # real systemd service install
|
|
140
|
+
systemctl status failproofaid@$USER_IN_BOX
|
|
141
|
+
|
|
142
|
+
The daemon binary is mounted at /opt/failproofaid. There is no GitHub
|
|
143
|
+
release for $VERSION, so point the CLI at it rather than letting it try
|
|
144
|
+
to download one:
|
|
145
|
+
export FAILPROOFAI_DAEMON_BINARY=/opt/failproofaid
|
|
146
|
+
|
|
147
|
+
Fire a hook exactly as an agent CLI would:
|
|
148
|
+
printf '{"session_id":"s","cwd":"'"\$PWD"'","hook_event_name":"PreToolUse",
|
|
149
|
+
"tool_name":"Bash","tool_input":{"command":"sudo rm -rf /"}}' \\
|
|
150
|
+
| failproofai --hook PreToolUse --cli claude
|
|
151
|
+
|
|
152
|
+
Tear down:
|
|
153
|
+
docker rm -f $NAME
|
|
154
|
+
|
|
155
|
+
EOF
|
|
@@ -2,7 +2,7 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
-
import type {
|
|
5
|
+
import type { TranslationCache } from "./types";
|
|
6
6
|
|
|
7
7
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
8
|
const CACHE_FILE = join(__dirname, ".translation-cache.json");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { parseArgs } from "node:util";
|
|
3
|
-
import { existsSync,
|
|
3
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
import { dirname, join, relative } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import {
|
|
@@ -297,7 +297,7 @@ async function main() {
|
|
|
297
297
|
|
|
298
298
|
// Translate uncached pages with concurrency limit
|
|
299
299
|
if (uncachedTasks.length > 0) {
|
|
300
|
-
|
|
300
|
+
await runWithConcurrency(
|
|
301
301
|
uncachedTasks.map(({ page, relPath, lang }) => async () => {
|
|
302
302
|
try {
|
|
303
303
|
const result = await translateMdxPage(page, lang, {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { getLanguageByCode, NAV_TRANSLATIONS
|
|
4
|
+
import { getLanguageByCode, NAV_TRANSLATIONS } from "./config";
|
|
5
5
|
|
|
6
6
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
7
|
const DOCS_JSON_PATH = join(__dirname, "..", "..", "docs", "docs.json");
|
|
@@ -17,6 +17,158 @@ const ROOT_DIR = join(__dirname, "..", "..");
|
|
|
17
17
|
const README_PATH = join(ROOT_DIR, "README.md");
|
|
18
18
|
const I18N_DIR = join(ROOT_DIR, "docs", "i18n");
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Prefix that walks from `docs/i18n/` back to the repo root. Keep in sync with
|
|
22
|
+
* I18N_DIR — the disclaimer and language selector already hard-code the same
|
|
23
|
+
* two levels in their `../../README.md` links.
|
|
24
|
+
*/
|
|
25
|
+
const TO_REPO_ROOT = "../../";
|
|
26
|
+
|
|
27
|
+
/** Raw-content base for repo files that must resolve off-GitHub too. */
|
|
28
|
+
const RAW_BASE = "https://raw.githubusercontent.com/FailproofAI/failproofai/main/";
|
|
29
|
+
|
|
30
|
+
const ASSET_RE = /\.(?:png|jpe?g|gif|svg|webp|ico|mp4|webm)$/i;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Re-point the root README's repo-root-relative paths so they still resolve
|
|
34
|
+
* from `docs/i18n/README.<lang>.md`, two directories deeper.
|
|
35
|
+
*
|
|
36
|
+
* The root README lives AT the repo root, so it writes `readme-arch-hq.gif` and
|
|
37
|
+
* `assets/logos/claude.svg` — correct there. The translator is prompt-forbidden
|
|
38
|
+
* from touching paths ("Preserve all URLs and paths", translator.ts), and
|
|
39
|
+
* rightly so, but that means every translated copy inherited those paths
|
|
40
|
+
* verbatim into a directory two levels down, where they resolve against
|
|
41
|
+
* `docs/i18n/`. Both consumers 404'd: GitHub asked for
|
|
42
|
+
* `docs/i18n/assets/logos/claude.svg` and Mintlify (which also serves these
|
|
43
|
+
* pages, unlisted, at `/i18n/README.<lang>`) asked S3 for `exosphere/i18n/...`.
|
|
44
|
+
* Every logo and the architecture GIF were broken in all 14 languages.
|
|
45
|
+
*
|
|
46
|
+
* The two ref kinds get different treatment because they resolve in different
|
|
47
|
+
* places:
|
|
48
|
+
* - IMAGES become absolute raw.githubusercontent URLs. A `../../` relative
|
|
49
|
+
* path would fix GitHub but not Mintlify, whose copy of the page has no
|
|
50
|
+
* `assets/` tree above it to walk into — an absolute URL is the only form
|
|
51
|
+
* that renders on BOTH surfaces.
|
|
52
|
+
* - DOCUMENT links (`./LICENSE`, `./CONTRIBUTING.md`, the translations row's
|
|
53
|
+
* `./docs/i18n/README.*.md`) get the `../../` prefix instead. GitHub is the
|
|
54
|
+
* only surface where a link to a repo file resolves at all, and a raw URL
|
|
55
|
+
* there would serve unrendered plaintext.
|
|
56
|
+
*
|
|
57
|
+
* Left alone: absolute URLs, anchors, `mailto:`, protocol-relative `//`,
|
|
58
|
+
* site-absolute `/`, anything already starting with `../`, and everything
|
|
59
|
+
* inside a fenced code block (where a path is literal sample text, not a ref).
|
|
60
|
+
*/
|
|
61
|
+
export function rebaseReadmePaths(content: string): string {
|
|
62
|
+
// Recomputed before each pass. `String.replace` reports offsets into the
|
|
63
|
+
// string it is scanning, so one map is valid for a whole pass — but a pass
|
|
64
|
+
// that rewrites a path AHEAD of a fence lengthens the text and shifts that
|
|
65
|
+
// fence, leaving offsets from the previous string pointing short. The next
|
|
66
|
+
// pass would then read a literal `<img src=…>` inside a fence as ordinary
|
|
67
|
+
// markup and rewrite the sample path this guard exists to protect.
|
|
68
|
+
let fenceRanges = findFenceRanges(content);
|
|
69
|
+
const insideFence = (offset: number): boolean =>
|
|
70
|
+
fenceRanges.some(([start, end]) => offset >= start && offset < end);
|
|
71
|
+
|
|
72
|
+
const rebase = (path: string): string | null => {
|
|
73
|
+
if (path === "" || /^[a-z][a-z0-9+.-]*:/i.test(path)) return null; // scheme
|
|
74
|
+
if (path.startsWith("#") || path.startsWith("/")) return null; // anchor, site-absolute
|
|
75
|
+
if (path.startsWith("../")) return null; // already rebased
|
|
76
|
+
const bare = path.replace(/^\.\//, "");
|
|
77
|
+
if (bare === "" || bare.startsWith("../")) return null;
|
|
78
|
+
return ASSET_RE.test(bare.split(/[?#]/)[0])
|
|
79
|
+
? `${RAW_BASE}${bare}`
|
|
80
|
+
: `${TO_REPO_ROOT}${bare}`;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// Markdown links and images: `](path)` / `](path "title")`.
|
|
84
|
+
let out = content.replace(
|
|
85
|
+
/(\]\()([^)\s]+)/g,
|
|
86
|
+
(match, prefix: string, path: string, offset: number) => {
|
|
87
|
+
if (insideFence(offset)) return match;
|
|
88
|
+
const next = rebase(path);
|
|
89
|
+
return next === null ? match : `${prefix}${next}`;
|
|
90
|
+
},
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
// HTML/JSX attributes: the README's logo table is a raw <table> of <img>.
|
|
94
|
+
fenceRanges = findFenceRanges(out);
|
|
95
|
+
out = out.replace(
|
|
96
|
+
/((?:src|href)=(["']))(.*?)\2/g,
|
|
97
|
+
(match, prefix: string, quote: string, path: string, offset: number) => {
|
|
98
|
+
if (insideFence(offset)) return match;
|
|
99
|
+
const next = rebase(path);
|
|
100
|
+
return next === null ? match : `${prefix}${next}${quote}`;
|
|
101
|
+
},
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
// `srcset` needs its own pass: each logo cell is a <picture> whose dark-mode
|
|
105
|
+
// <source srcset="assets/logos/*-dark.svg"> sits beside the <img src>. Miss
|
|
106
|
+
// it and half the table stays broken for dark-theme readers only — the half
|
|
107
|
+
// least likely to be noticed in review.
|
|
108
|
+
fenceRanges = findFenceRanges(out);
|
|
109
|
+
out = out.replace(
|
|
110
|
+
/(srcset=(["']))(.*?)\2/g,
|
|
111
|
+
(match, prefix: string, quote: string, value: string, offset: number) => {
|
|
112
|
+
if (insideFence(offset)) return match;
|
|
113
|
+
return `${prefix}${rebaseSrcset(value)}${quote}`;
|
|
114
|
+
},
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
return out;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Rebase every candidate in a `srcset` value, preserving each one's optional
|
|
121
|
+
* density/width descriptor (`logo.svg 2x`, `wide.png 800w`) and the original
|
|
122
|
+
* comma spacing.
|
|
123
|
+
*/
|
|
124
|
+
function rebaseSrcset(value: string): string {
|
|
125
|
+
return value
|
|
126
|
+
.split(",")
|
|
127
|
+
.map((candidate) => {
|
|
128
|
+
const [, lead, url, descriptor] =
|
|
129
|
+
/^(\s*)(\S+)(.*)$/.exec(candidate) ?? [];
|
|
130
|
+
if (url === undefined) return candidate; // whitespace-only candidate
|
|
131
|
+
const next = rebase(url);
|
|
132
|
+
return `${lead}${next ?? url}${descriptor}`;
|
|
133
|
+
})
|
|
134
|
+
.join(",");
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Byte ranges covered by fenced code blocks, per CommonMark: a fence opens with
|
|
140
|
+
* ≥3 backticks or tildes and closes only on a later line using the SAME
|
|
141
|
+
* character at ≥ the same length.
|
|
142
|
+
*
|
|
143
|
+
* Follows the scanner in `mdx-translator.convertHtmlComments`, with one
|
|
144
|
+
* correction: a CLOSING fence may carry only trailing whitespace, never an info
|
|
145
|
+
* string. Accepting ```` ```ts ```` as a close would end the block at the first
|
|
146
|
+
* *nested* opener inside it and leave the real code that follows looking like
|
|
147
|
+
* prose — whose sample paths this function exists to protect.
|
|
148
|
+
*/
|
|
149
|
+
function findFenceRanges(content: string): Array<[number, number]> {
|
|
150
|
+
const ranges: Array<[number, number]> = [];
|
|
151
|
+
const fenceRe = /^[ \t]*(`{3,}|~{3,})([^\n]*)$/gm;
|
|
152
|
+
let match: RegExpExecArray | null;
|
|
153
|
+
let open: { char: string; length: number; start: number } | null = null;
|
|
154
|
+
while ((match = fenceRe.exec(content)) !== null) {
|
|
155
|
+
const [, marker, rest] = match;
|
|
156
|
+
if (!open) {
|
|
157
|
+
open = { char: marker[0], length: marker.length, start: match.index };
|
|
158
|
+
} else if (
|
|
159
|
+
marker[0] === open.char &&
|
|
160
|
+
marker.length >= open.length &&
|
|
161
|
+
rest.trim() === ""
|
|
162
|
+
) {
|
|
163
|
+
const lineEnd = content.indexOf("\n", fenceRe.lastIndex);
|
|
164
|
+
ranges.push([open.start, lineEnd === -1 ? content.length : lineEnd]);
|
|
165
|
+
open = null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (open) ranges.push([open.start, content.length]);
|
|
169
|
+
return ranges;
|
|
170
|
+
}
|
|
171
|
+
|
|
20
172
|
function buildLanguageSelector(currentLang: string): string {
|
|
21
173
|
const flags: Record<string, string> = {
|
|
22
174
|
en: "\ud83c\uddfa\ud83c\uddf8",
|
|
@@ -117,10 +269,17 @@ export async function translateReadme(
|
|
|
117
269
|
// Same MDX sanitizers as translateMdxPage — the README emits JSX (the
|
|
118
270
|
// logo table), so strip stray attribute quotes, drop any unmatched
|
|
119
271
|
// trailing code fence (which would swallow the RTL `</div>`), and
|
|
120
|
-
// convert HTML comments to MDX — then
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
|
|
272
|
+
// convert HTML comments to MDX — then re-point the root README's
|
|
273
|
+
// repo-root-relative paths for this file's depth, and wrap in
|
|
274
|
+
// disclaimer + selector + RTL div.
|
|
275
|
+
//
|
|
276
|
+
// The rebase runs on the model output ONLY, never on the wrapper: the
|
|
277
|
+
// disclaimer's `../../README.md` and the selector's sibling
|
|
278
|
+
// `README.<lang>.md` links are already written for `docs/i18n/`.
|
|
279
|
+
const cleaned = rebaseReadmePaths(
|
|
280
|
+
convertHtmlComments(
|
|
281
|
+
stripStrayTrailingFence(sanitizeJsxAttributes(raw)),
|
|
282
|
+
),
|
|
124
283
|
);
|
|
125
284
|
return `${disclaimer}\n\n${langSelector}\n\n---\n${rtlOpen}\n${cleaned}\n${rtlClose}`;
|
|
126
285
|
},
|