failproofai 1.0.7-beta.0 → 1.0.7-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +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/_not-found/__PAGE__.segment.rsc +14 -14
- 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.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
- 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.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
- 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/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +7 -7
- package/.next/standalone/.next/server/app/settings/page.js +2 -2
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0l3yhx4._.js +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0trp3yc._.js +1 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_hooks_18qtd42._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__04usis8._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__056wjo4._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1p28m0u._.js → [root-of-the-server]__0l44ual._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n0xg95._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0rwtwpm._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s_yomn._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11mayhe._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1pprgri._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1q4p5b8._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_042cgl1._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0bqoto4._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_0cf1olg._.js → _1mel6y1._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_135-c3y._.js → _1v-jvrv._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9sni._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_settings_02tf1h4._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_15t8kqj._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1fm2w5z._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1j0zy3v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- 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 +22 -22
- package/.next/standalone/.next/static/chunks/043j99m8ykg__.css +2 -0
- package/.next/standalone/.next/static/chunks/{0289oapk24zql.js → 0fqd7m_u81mi5.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2tqszh84mp_2l.js → 129ag2bw93bdh.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0pyy9m5cm8zku.js → 1qd741hzlmjbo.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3vwnzfx9q80yl.js → 2_pltstd8-xgs.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3vp7c3knkh8mr.js → 2c8j9l6j_b1ci.js} +1 -1
- package/.next/standalone/.next/static/chunks/3-k569wzcli8q.js +1 -0
- package/.next/standalone/.next/static/chunks/{3cdkxrukvlvul.js → 3brze37td_wnc.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3dnd-_29uiaj3.js → 3otmypm6j_xfo.js} +2 -2
- package/.next/standalone/.next/static/chunks/{00i9thnpht4l1.js → 3ugmd_7dyn0id.js} +1 -1
- package/.next/standalone/.next/static/chunks/3yxro_r2_o9ad.js +69 -0
- package/.next/standalone/PROBE-FOLLOWUP.md +186 -0
- package/.next/standalone/app/actions/get-jev-config.ts +38 -23
- package/.next/standalone/app/actions/update-jev-config.ts +1 -1
- package/.next/standalone/app/settings/jev-panel.tsx +33 -29
- package/.next/standalone/package.json +10 -10
- package/.next/standalone/sdk/python/skill/SKILL.md +60 -14
- package/.next/standalone/sdk/python/skill/agents/openai.yaml +2 -1
- package/.next/standalone/sdk/python/skill/references/evaluator.md +255 -0
- package/.next/standalone/sdk/python/skill/references/events.md +17 -8
- package/.next/standalone/sdk/python/skill/references/frameworks.md +3 -0
- package/.next/standalone/sdk/python/skill/references/install.md +3 -0
- package/.next/standalone/sdk/python/skill/references/integration.md +6 -2
- package/.next/standalone/sdk/python/skill/references/typescript.md +568 -0
- package/.next/standalone/sdk/typescript/CHANGELOG.md +119 -0
- package/.next/standalone/sdk/typescript/LICENSE +42 -0
- package/.next/standalone/sdk/typescript/README.md +552 -0
- package/.next/standalone/sdk/typescript/eslint.config.mjs +59 -0
- package/.next/standalone/sdk/typescript/examples/research-agent.ts +197 -0
- package/.next/standalone/sdk/typescript/integration/ai.test.ts +920 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/agent.ts +337 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/package-lock.json +281 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/package.json +13 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/surfaces.ts +605 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/tsconfig.surfaces.json +4 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/agent.ts +342 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package-lock.json +168 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package.json +13 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/surfaces.ts +628 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/tsconfig.surfaces.json +4 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/agent.ts +346 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/package-lock.json +156 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/package.json +13 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/surfaces.ts +651 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/tsconfig.surfaces.json +4 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/agent.ts +350 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/package-lock.json +153 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/package.json +13 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/surfaces.ts +651 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/tsconfig.surfaces.json +4 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-0.3/agent.ts +623 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-0.3/package-lock.json +463 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-0.3/package.json +15 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-0.3/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/agent-v1.ts +99 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/agent.ts +623 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/package-lock.json +336 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/package.json +15 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/agent.ts +96 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/package-lock.json +579 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/package.json +15 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/vendor/lc-weather-provider/index.cjs +53 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/vendor/lc-weather-provider/index.mjs +55 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/vendor/lc-weather-provider/package.json +18 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/agent.ts +659 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/package-lock.json +635 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/package.json +15 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.12/agent.ts +659 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.12/package-lock.json +553 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.12/package.json +15 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.12/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/agent.ts +877 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/mcp-server.mjs +66 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package-lock.json +6417 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package.json +15 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/agent.ts +872 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/mcp-server.mjs +66 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package-lock.json +2540 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package.json +15 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/actions.ts +18 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/api/ai/route.ts +42 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/api/edge/route.ts +29 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/api/langgraph/route.ts +21 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/api/llamaindex/route.ts +11 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/api/mastra/route.ts +19 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/api/status/route.ts +7 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/layout.tsx +9 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/page.tsx +15 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/instrumentation.ts +15 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/lib/ai.ts +61 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/lib/langgraph.ts +68 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/lib/llamaindex.ts +98 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/lib/mastra.ts +90 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/next.config.ts +52 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package-lock.json +4343 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package.json +28 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/agent.ts +51 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/deno-npm.ts +76 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/package-lock.json +484 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/package.json +15 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/types/agent.ts +79 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/types/package-lock.json +740 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/types/package.json +11 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/vanilla/agent.ts +197 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/vanilla/package-lock.json +70 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/vanilla/package.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/vanilla/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/global-setup.ts +29 -0
- package/.next/standalone/sdk/typescript/integration/harness.ts +451 -0
- package/.next/standalone/sdk/typescript/integration/langchain.test.ts +682 -0
- package/.next/standalone/sdk/typescript/integration/llamaindex.test.ts +709 -0
- package/.next/standalone/sdk/typescript/integration/mastra-coverage.test.ts +386 -0
- package/.next/standalone/sdk/typescript/integration/mastra.test.ts +311 -0
- package/.next/standalone/sdk/typescript/integration/nextjs.test.ts +341 -0
- package/.next/standalone/sdk/typescript/integration/runtime-parity.ts +180 -0
- package/.next/standalone/sdk/typescript/integration/runtimes.bun.test.ts +15 -0
- package/.next/standalone/sdk/typescript/integration/runtimes.core.test.ts +113 -0
- package/.next/standalone/sdk/typescript/integration/runtimes.deno.test.ts +19 -0
- package/.next/standalone/sdk/typescript/integration/types.test.ts +141 -0
- package/.next/standalone/sdk/typescript/integration/vanilla.test.ts +255 -0
- package/.next/standalone/sdk/typescript/package-lock.json +2640 -0
- package/.next/standalone/sdk/typescript/package.json +401 -0
- package/.next/standalone/sdk/typescript/scripts/finalize-build.mjs +123 -0
- package/.next/standalone/sdk/typescript/scripts/release.mjs +177 -0
- package/.next/standalone/sdk/typescript/src/clock.ts +58 -0
- package/.next/standalone/sdk/typescript/src/context.ts +214 -0
- package/.next/standalone/sdk/typescript/src/edge/adapter.ts +18 -0
- package/.next/standalone/sdk/typescript/src/edge/ai.ts +116 -0
- package/.next/standalone/sdk/typescript/src/edge/index.ts +238 -0
- package/.next/standalone/sdk/typescript/src/edge/langchain.ts +18 -0
- package/.next/standalone/sdk/typescript/src/edge/llamaindex.ts +12 -0
- package/.next/standalone/sdk/typescript/src/edge/mastra.ts +17 -0
- package/.next/standalone/sdk/typescript/src/edge/notice.ts +33 -0
- package/.next/standalone/sdk/typescript/src/environment.ts +75 -0
- package/.next/standalone/sdk/typescript/src/evaluator/authoring.ts +480 -0
- package/.next/standalone/sdk/typescript/src/evaluator/cli.ts +96 -0
- package/.next/standalone/sdk/typescript/src/evaluator/client.ts +421 -0
- package/.next/standalone/sdk/typescript/src/evaluator/expression.ts +1292 -0
- package/.next/standalone/sdk/typescript/src/evaluator/index.ts +144 -0
- package/.next/standalone/sdk/typescript/src/evaluator/protocol.ts +747 -0
- package/.next/standalone/sdk/typescript/src/evaluator/runtime.ts +930 -0
- package/.next/standalone/sdk/typescript/src/evaluator/sandbox-worker.ts +171 -0
- package/.next/standalone/sdk/typescript/src/evaluator/source-limits.ts +27 -0
- package/.next/standalone/sdk/typescript/src/evaluator/source.ts +509 -0
- package/.next/standalone/sdk/typescript/src/events.ts +879 -0
- package/.next/standalone/sdk/typescript/src/exit.ts +117 -0
- package/.next/standalone/sdk/typescript/src/index.ts +186 -0
- package/.next/standalone/sdk/typescript/src/integrations/ai.ts +1566 -0
- package/.next/standalone/sdk/typescript/src/integrations/compat.ts +322 -0
- package/.next/standalone/sdk/typescript/src/integrations/core.ts +1321 -0
- package/.next/standalone/sdk/typescript/src/integrations/index.ts +355 -0
- package/.next/standalone/sdk/typescript/src/integrations/langchain.ts +2340 -0
- package/.next/standalone/sdk/typescript/src/integrations/llamaindex.ts +2111 -0
- package/.next/standalone/sdk/typescript/src/integrations/mastra.ts +1802 -0
- package/.next/standalone/sdk/typescript/src/logger.ts +98 -0
- package/.next/standalone/sdk/typescript/src/next.ts +115 -0
- package/.next/standalone/sdk/typescript/src/node-require.ts +446 -0
- package/.next/standalone/sdk/typescript/src/redact.ts +305 -0
- package/.next/standalone/sdk/typescript/src/resolver.ts +120 -0
- package/.next/standalone/sdk/typescript/src/runtime.ts +29 -0
- package/.next/standalone/sdk/typescript/src/schema.ts +410 -0
- package/.next/standalone/sdk/typescript/src/scopes.ts +701 -0
- package/.next/standalone/sdk/typescript/src/shared.ts +33 -0
- package/.next/standalone/sdk/typescript/src/version.ts +5 -0
- package/.next/standalone/sdk/typescript/src/writer.ts +934 -0
- package/.next/standalone/sdk/typescript/test/adapters.test.ts +397 -0
- package/.next/standalone/sdk/typescript/test/ai.test.ts +1076 -0
- package/.next/standalone/sdk/typescript/test/copies.test.ts +204 -0
- package/.next/standalone/sdk/typescript/test/edge.test.ts +183 -0
- package/.next/standalone/sdk/typescript/test/evaluator-client.test.ts +234 -0
- package/.next/standalone/sdk/typescript/test/evaluator-protocol.test.ts +225 -0
- package/.next/standalone/sdk/typescript/test/events.test.ts +193 -0
- package/.next/standalone/sdk/typescript/test/expression.test.ts +181 -0
- package/.next/standalone/sdk/typescript/test/global-setup.ts +26 -0
- package/.next/standalone/sdk/typescript/test/helpers.ts +130 -0
- package/.next/standalone/sdk/typescript/test/integrations.test.ts +369 -0
- package/.next/standalone/sdk/typescript/test/langchain-copies.test.ts +204 -0
- package/.next/standalone/sdk/typescript/test/langchain.test.ts +999 -0
- package/.next/standalone/sdk/typescript/test/llamaindex.test.ts +1760 -0
- package/.next/standalone/sdk/typescript/test/mastra-coverage.test.ts +501 -0
- package/.next/standalone/sdk/typescript/test/mastra-lifecycle.test.ts +479 -0
- package/.next/standalone/sdk/typescript/test/mastra.test.ts +285 -0
- package/.next/standalone/sdk/typescript/test/next.test.ts +109 -0
- package/.next/standalone/sdk/typescript/test/packaging.test.ts +312 -0
- package/.next/standalone/sdk/typescript/test/redaction.test.ts +171 -0
- package/.next/standalone/sdk/typescript/test/runtimes.test.ts +101 -0
- package/.next/standalone/sdk/typescript/test/sandbox.test.ts +189 -0
- package/.next/standalone/sdk/typescript/test/scopes.test.ts +271 -0
- package/.next/standalone/sdk/typescript/test/setup.ts +19 -0
- package/.next/standalone/sdk/typescript/test/skill-snippets.test.ts +73 -0
- package/.next/standalone/sdk/typescript/test/spool-contract.test.ts +124 -0
- package/.next/standalone/sdk/typescript/test/tracker-bounds.test.ts +191 -0
- package/.next/standalone/sdk/typescript/test/wire-format.test.ts +214 -0
- package/.next/standalone/sdk/typescript/test/writer.test.ts +407 -0
- package/.next/standalone/sdk/typescript/tsconfig.build.json +15 -0
- package/.next/standalone/sdk/typescript/tsconfig.cjs.json +19 -0
- package/.next/standalone/sdk/typescript/tsconfig.json +28 -0
- package/.next/standalone/sdk/typescript/vitest.config.ts +33 -0
- package/.next/standalone/sdk/typescript/vitest.integration.config.ts +23 -0
- package/.next/standalone/server.js +1 -1
- package/README.md +2 -2
- package/dist/cli.mjs +225 -30
- package/dist/worker.mjs +120 -14
- package/package.json +10 -10
- package/scripts/build-policy-pack.mjs +14 -0
- package/src/audit/features.ts +3 -2
- package/src/hooks/builtin-policies.ts +156 -5
- package/src/hooks/jev-cli.ts +57 -1
- package/src/hooks/manager.ts +1 -1
- package/src/hooks/pack-cli.ts +191 -24
- package/src/hooks/pack-store.ts +1 -1
- package/src/hooks/policy-catalog.ts +148 -9
- package/src/hooks/types.ts +1 -1
- package/.next/standalone/.next/static/chunks/15heikmy3yjzc.js +0 -1
- package/.next/standalone/.next/static/chunks/285spx855h_3r.css +0 -2
- package/.next/standalone/.next/static/chunks/2plg9qae1yejv.js +0 -69
- /package/.next/standalone/.next/static/{qbVI48kgBOf9CTOKcFIk2 → gbEOjBgZAxF2UIUwZVHNu}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{qbVI48kgBOf9CTOKcFIk2 → gbEOjBgZAxF2UIUwZVHNu}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{qbVI48kgBOf9CTOKcFIk2 → gbEOjBgZAxF2UIUwZVHNu}/_ssgManifest.js +0 -0
package/src/hooks/pack-cli.ts
CHANGED
|
@@ -44,9 +44,9 @@ import {
|
|
|
44
44
|
import type { PolicyEffect } from "./cloud-managed-policies";
|
|
45
45
|
import { loadCustomHooks } from "./custom-hooks-loader";
|
|
46
46
|
import { getSemanticRegistrations } from "./custom-hooks-registry";
|
|
47
|
-
import { authorityFieldsOf, authorityProblem } from "./policy-authority";
|
|
48
|
-
import type { SemanticPolicyDeclaration } from "./policy-types";
|
|
49
|
-
import type { MultiChoice, TTYIn, TTYOut } from "./tui";
|
|
47
|
+
import { authorityFieldsOf, authorityProblem, resolvePolicyAuthority } from "./policy-authority";
|
|
48
|
+
import type { PolicyCatalogEntry, SemanticPolicyDeclaration } from "./policy-types";
|
|
49
|
+
import type { MultiChoice, RenderOpts, TTYIn, TTYOut } from "./tui";
|
|
50
50
|
import {
|
|
51
51
|
chip,
|
|
52
52
|
emptyState,
|
|
@@ -342,10 +342,10 @@ async function build(rest: string[]): Promise<PackCliResult> {
|
|
|
342
342
|
// Refused rather than bundled: see the note above. A relative specifier is the
|
|
343
343
|
// only kind that would be rewritten by the loader and left outside the digest.
|
|
344
344
|
const source = readFileSync(entryPath, "utf8");
|
|
345
|
-
const localImport =
|
|
345
|
+
const localImport = firstRelativeSpecifier(source);
|
|
346
346
|
if (localImport) {
|
|
347
347
|
return fail([
|
|
348
|
-
`${entryPath} imports ${localImport
|
|
348
|
+
`${entryPath} imports ${localImport}, and only the entry file is digest-pinned.`,
|
|
349
349
|
"Bundle it to a single file first (esbuild, bun build, rollup), then build the pack from that.",
|
|
350
350
|
]);
|
|
351
351
|
}
|
|
@@ -469,7 +469,7 @@ async function build(rest: string[]): Promise<PackCliResult> {
|
|
|
469
469
|
// out was not cosmetic: `registerPolicy` takes a pack policy's schema from the
|
|
470
470
|
// MANIFEST by name, so a pack published without it evaluates every one of its
|
|
471
471
|
// policies with `ctx.params = {}` — which discards the user's own configured
|
|
472
|
-
// values too, not just the defaults. Of the
|
|
472
|
+
// values too, not just the defaults. Of the 39 builtins, 20 carry a schema:
|
|
473
473
|
// `prefer-package-manager` would have been inert, and `block-sudo`'s
|
|
474
474
|
// `allowPatterns`, `block-rm-rf`'s and `block-read-outside-cwd`'s `allowPaths`
|
|
475
475
|
// would all have stopped working — every one of them failing silently
|
|
@@ -1878,6 +1878,44 @@ const PUBLISH_VALUE_FLAGS = new Set([
|
|
|
1878
1878
|
"--repo", "--version", "--id", "--tag", "--notes", "--out", "--effect", "--entry", "--init",
|
|
1879
1879
|
"--commit", "--min-cli-version",
|
|
1880
1880
|
]);
|
|
1881
|
+
/**
|
|
1882
|
+
* The first relative specifier an entry imports, or null.
|
|
1883
|
+
*
|
|
1884
|
+
* Two callers read this and they must agree, because between them they are the
|
|
1885
|
+
* only two outcomes: `publish` bundles a multi-file entry into the one artifact
|
|
1886
|
+
* a pack has to be, and `build` REFUSES one, since only the entry file is
|
|
1887
|
+
* digest-pinned. A shape that neither recognises gets bundled by neither and
|
|
1888
|
+
* refused by neither, and the author sees whatever the loader's rewrite makes of
|
|
1889
|
+
* it — which is an esbuild parse error naming a token, not a file.
|
|
1890
|
+
*
|
|
1891
|
+
* Both sites previously used `[^;\n]*` between `import` and `from`, which cannot
|
|
1892
|
+
* cross a newline and requires a `from` clause to exist. So both missed:
|
|
1893
|
+
*
|
|
1894
|
+
* import "./policies/regex" // side-effect only: there is no `from`
|
|
1895
|
+
* import {
|
|
1896
|
+
* aLongList,
|
|
1897
|
+
* } from "./shared" // the `from` is on another line
|
|
1898
|
+
*
|
|
1899
|
+
* and a pack entry written either way — the natural way to write one whose
|
|
1900
|
+
* halves register at module scope — failed to publish with `Expected "from" but
|
|
1901
|
+
* found "{"`. Now `[^;]*?` spans newlines and stops at a statement end, and the
|
|
1902
|
+
* bare form is matched on its own. Over-reaching to a later `from` is harmless:
|
|
1903
|
+
* the answer is only ever used as "is there a relative import, and name one".
|
|
1904
|
+
*/
|
|
1905
|
+
export function firstRelativeSpecifier(source: string): string | null {
|
|
1906
|
+
const patterns = [
|
|
1907
|
+
/(?:^|\n)\s*(?:import|export)\b[^;]*?\bfrom\s*["'](\.[^"']*)["']/,
|
|
1908
|
+
/(?:^|\n)\s*import\s*["'](\.[^"']*)["']/,
|
|
1909
|
+
/\bimport\s*\(\s*["'](\.[^"']*)["']\s*\)/,
|
|
1910
|
+
/\brequire\s*\(\s*["'](\.[^"']*)["']\s*\)/,
|
|
1911
|
+
];
|
|
1912
|
+
for (const re of patterns) {
|
|
1913
|
+
const m = re.exec(source);
|
|
1914
|
+
if (m) return m[1];
|
|
1915
|
+
}
|
|
1916
|
+
return null;
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1881
1919
|
function publishEntryArg(rest: string[]): string | undefined {
|
|
1882
1920
|
const consumed = new Set<number>();
|
|
1883
1921
|
for (let i = 0; i < rest.length; i += 1) {
|
|
@@ -2255,10 +2293,7 @@ async function publish(rest: string[]): Promise<PackCliResult> {
|
|
|
2255
2293
|
// a bundler for a step this tool already performs for its own pack.
|
|
2256
2294
|
let entryToBuild = entry;
|
|
2257
2295
|
const needsBundle =
|
|
2258
|
-
discovered.length > 1 ||
|
|
2259
|
-
/(?:^|\n)\s*(?:import|export)[^;\n]*from\s+["']\.[^"']*["']/.test(
|
|
2260
|
-
readFileSync(entry, "utf8"),
|
|
2261
|
-
);
|
|
2296
|
+
discovered.length > 1 || firstRelativeSpecifier(readFileSync(entry, "utf8")) !== null;
|
|
2262
2297
|
if (needsBundle) {
|
|
2263
2298
|
const sources = discovered.length > 1 ? discovered : [entry];
|
|
2264
2299
|
const bundled = bundleEntry(sources, outDirEarly);
|
|
@@ -2658,7 +2693,7 @@ async function add(rest: string[]): Promise<PackCliResult> {
|
|
|
2658
2693
|
];
|
|
2659
2694
|
const skipped = result.available.filter((n) => !result.enabled.includes(n));
|
|
2660
2695
|
|
|
2661
|
-
// Say WHY this set is on. Without it, "10 of
|
|
2696
|
+
// Say WHY this set is on. Without it, "10 of 39 enabled" reads like
|
|
2662
2697
|
// something went wrong rather than like the pack's own recommendation.
|
|
2663
2698
|
const why = {
|
|
2664
2699
|
defaults: "the pack's defaults",
|
|
@@ -2952,6 +2987,147 @@ function relativeAge(iso: string): string {
|
|
|
2952
2987
|
return `${value} ${label}${value === 1 ? "" : "s"} ago`;
|
|
2953
2988
|
}
|
|
2954
2989
|
|
|
2990
|
+
/**
|
|
2991
|
+
* Which of a pack's OWN regex policies each of its Jev checks can clear, keyed
|
|
2992
|
+
* by check name and empty for a check nothing names.
|
|
2993
|
+
*
|
|
2994
|
+
* INVERTED out of the same manifest's `reviewedBy` rather than declared beside
|
|
2995
|
+
* the checks. A semantic entry says nothing about the policies that name it, so
|
|
2996
|
+
* the only other way to show this column is a second list kept by hand — which
|
|
2997
|
+
* is wrong the first time a publisher adds a reviewer to one policy, and wrong
|
|
2998
|
+
* in the direction that overstates what Jev may clear.
|
|
2999
|
+
*
|
|
3000
|
+
* Judged with `resolvePolicyAuthority` against the pack's OWN check names,
|
|
3001
|
+
* because that is the rule the installing machine applies: a pack declaring
|
|
3002
|
+
* semantic entries replaces the compiled-in set (`effectiveReviewerNames`), so
|
|
3003
|
+
* its `reviewedBy` may name only its own checks, and a declaration that names
|
|
3004
|
+
* anything else — or one sitting under `authority: "hard"`, which a manifest may
|
|
3005
|
+
* carry because the two fields are parsed independently — registers HARD. A
|
|
3006
|
+
* policy in either state can never be cleared, so naming it under a check would
|
|
3007
|
+
* promise a clear that cannot happen.
|
|
3008
|
+
*/
|
|
3009
|
+
function reviewersByCheck(
|
|
3010
|
+
policies: ReadonlyArray<PolicyCatalogEntry>,
|
|
3011
|
+
semantic: ReadonlyArray<SemanticManifestEntry>,
|
|
3012
|
+
): Map<string, string[]> {
|
|
3013
|
+
const ownChecks = new Set(semantic.map((s) => s.name));
|
|
3014
|
+
const byCheck = new Map<string, string[]>(semantic.map((s) => [s.name, []]));
|
|
3015
|
+
for (const policy of policies) {
|
|
3016
|
+
const { authority, reviewedBy } = resolvePolicyAuthority(policy, ownChecks);
|
|
3017
|
+
if (authority !== "reviewable") continue;
|
|
3018
|
+
for (const check of reviewedBy ?? []) byCheck.get(check)?.push(policy.name);
|
|
3019
|
+
}
|
|
3020
|
+
return byCheck;
|
|
3021
|
+
}
|
|
3022
|
+
|
|
3023
|
+
/** Reviewers named in full. Past this the cell names two and counts the rest. */
|
|
3024
|
+
const REVIEWERS_LISTED = 3;
|
|
3025
|
+
|
|
3026
|
+
/**
|
|
3027
|
+
* A check's reviewers as one cell.
|
|
3028
|
+
*
|
|
3029
|
+
* The question a reader brings to this column is "can this check clear anything
|
|
3030
|
+
* of mine", which two names and a count answer as well as ten do — and ten
|
|
3031
|
+
* names in a cell push the column past the terminal, where `table` cuts one of
|
|
3032
|
+
* them mid-word and the row stops being readable at all.
|
|
3033
|
+
*/
|
|
3034
|
+
function reviewersCell(names: ReadonlyArray<string>): string {
|
|
3035
|
+
if (names.length <= REVIEWERS_LISTED) return names.join(", ");
|
|
3036
|
+
return `${names.slice(0, 2).join(", ")}, +${names.length - 2}`;
|
|
3037
|
+
}
|
|
3038
|
+
|
|
3039
|
+
/**
|
|
3040
|
+
* Why a check that no policy names is in the pack at all — and the two answers
|
|
3041
|
+
* are different facts, so the row has to tell them apart.
|
|
3042
|
+
*
|
|
3043
|
+
* A `deny` check with no reviewer is a concern the pack's regex half does not
|
|
3044
|
+
* cover: it can only ever ADD a deny, never clear one, and that is a gap in the
|
|
3045
|
+
* regex tier rather than a mistake in the manifest. An `instruct` check can
|
|
3046
|
+
* never answer deny, so every conjunction naming it has one reachable outcome —
|
|
3047
|
+
* a clear — which is why nothing names it and why nothing should (the
|
|
3048
|
+
* `block-work-on-main` entry in CHANGELOG 1.0.7-beta.1 is that bug, shipped).
|
|
3049
|
+
*/
|
|
3050
|
+
function unreviewedCell(mode: SemanticManifestEntry["mode"], policies: number): string {
|
|
3051
|
+
if (mode === "instruct") return "instruct-only — it can never deny";
|
|
3052
|
+
// "the 38" borrows the count from the heading above, where it has just been
|
|
3053
|
+
// read. The other two spellings exist because that sentence has no grammatical
|
|
3054
|
+
// form at one or zero — and a pack of Jev checks alone, with no regex half at
|
|
3055
|
+
// all, is a legitimate thing to publish.
|
|
3056
|
+
if (policies === 0) return "this pack has no policies to clear";
|
|
3057
|
+
if (policies === 1) return "the one policy here does not cover this";
|
|
3058
|
+
return `nothing in the ${policies} covers this`;
|
|
3059
|
+
}
|
|
3060
|
+
|
|
3061
|
+
/**
|
|
3062
|
+
* A pack's Jev checks as a section of rows — the shape the category sections
|
|
3063
|
+
* use, deliberately NOT their columns.
|
|
3064
|
+
*
|
|
3065
|
+
* It replaces a prose paragraph that listed sixteen names comma-separated above
|
|
3066
|
+
* a screen where everything else was a scannable row. The rows are not policy
|
|
3067
|
+
* rows and must not read as ones: there is no on/off chip, because nothing
|
|
3068
|
+
* toggles a check, `--policy` cannot name one, and none of them appears in
|
|
3069
|
+
* `failproofai policies`. What the columns carry instead is the pair of facts
|
|
3070
|
+
* that decide what a check does on a real machine — its mode, and which of this
|
|
3071
|
+
* pack's own policies it can clear.
|
|
3072
|
+
*
|
|
3073
|
+
* Null when the pack declares none, so a pack with no semantic half prints no
|
|
3074
|
+
* section rather than an empty one.
|
|
3075
|
+
*/
|
|
3076
|
+
export function jevChecksSection(
|
|
3077
|
+
pack: {
|
|
3078
|
+
policies: ReadonlyArray<PolicyCatalogEntry>;
|
|
3079
|
+
semantic: ReadonlyArray<SemanticManifestEntry>;
|
|
3080
|
+
},
|
|
3081
|
+
opts?: RenderOpts,
|
|
3082
|
+
): string[] | null {
|
|
3083
|
+
if (pack.semantic.length === 0) return null;
|
|
3084
|
+
const reviewers = reviewersByCheck(pack.policies, pack.semantic);
|
|
3085
|
+
const rows = pack.semantic.map((check) => {
|
|
3086
|
+
const named = reviewers.get(check.name) ?? [];
|
|
3087
|
+
// `reviews` and `—` lead the same cell rather than sitting in a column of
|
|
3088
|
+
// their own. A fourth column would pad every `—` out to the width of
|
|
3089
|
+
// `reviews`, which costs nine characters of the only column allowed to
|
|
3090
|
+
// shrink — enough to ellipsize the reason on an 80-column terminal, where
|
|
3091
|
+
// this way everything fits whole.
|
|
3092
|
+
return [
|
|
3093
|
+
check.mode,
|
|
3094
|
+
check.name,
|
|
3095
|
+
named.length > 0
|
|
3096
|
+
? `reviews ${reviewersCell(named)}`
|
|
3097
|
+
: `— ${unreviewedCell(check.mode, pack.policies.length)}`,
|
|
3098
|
+
];
|
|
3099
|
+
});
|
|
3100
|
+
return [
|
|
3101
|
+
// The count is on the heading rather than in a row, the way every other
|
|
3102
|
+
// section on this screen carries its own total.
|
|
3103
|
+
...rule(
|
|
3104
|
+
`Jev checks — ${pack.semantic.length} · not selectable · only where Jev is configured`,
|
|
3105
|
+
opts,
|
|
3106
|
+
),
|
|
3107
|
+
// The reviewers column is the only one allowed to shrink: a mode or a check
|
|
3108
|
+
// name cut in half is a fact nobody can act on, while a cut reviewer list is
|
|
3109
|
+
// one that was already abbreviated.
|
|
3110
|
+
...table({ head: ["", "", ""], rows, protect: [0, 1] }, opts),
|
|
3111
|
+
"",
|
|
3112
|
+
...note(
|
|
3113
|
+
"Nothing toggles them: `--policy` cannot name one, `failproofai policies` never lists them, " +
|
|
3114
|
+
"and a pack's checks replace the ones this build ships with.",
|
|
3115
|
+
opts,
|
|
3116
|
+
),
|
|
3117
|
+
...note(
|
|
3118
|
+
// A pack of Jev checks alone has no regex half for the column to be about,
|
|
3119
|
+
// so the sentence says what IS true of it rather than "its own 0 policies".
|
|
3120
|
+
pack.policies.length === 0
|
|
3121
|
+
? "This pack ships no regex policies, so none of these checks clears anything here: a deny " +
|
|
3122
|
+
"check can only ADD a deny, and an instruct check only ever warns."
|
|
3123
|
+
: `\`reviews\` is which of this pack's own ${pack.policies.length} policies each check can clear. ` +
|
|
3124
|
+
"A deny check that reviews nothing can only ever ADD a deny; an instruct check never answers " +
|
|
3125
|
+
"deny, so nothing pairs with one.",
|
|
3126
|
+
opts,
|
|
3127
|
+
),
|
|
3128
|
+
];
|
|
3129
|
+
}
|
|
3130
|
+
|
|
2955
3131
|
async function listRemote(source: string): Promise<PackCliResult> {
|
|
2956
3132
|
const opts = optsFor(process.stdout);
|
|
2957
3133
|
let preview;
|
|
@@ -2994,22 +3170,13 @@ async function listRemote(source: string): Promise<PackCliResult> {
|
|
|
2994
3170
|
(preview.effect === "observe" ? " This pack OBSERVES — it records and blocks nothing." : ""),
|
|
2995
3171
|
opts,
|
|
2996
3172
|
),
|
|
2997
|
-
// The half that is not in the table below, said in words. It is not
|
|
2998
|
-
// selectable, so it has no rows; and it REPLACES this build's own question
|
|
2999
|
-
// set rather than adding to it, which is the part worth knowing before
|
|
3000
|
-
// installing rather than after.
|
|
3001
|
-
preview.semantic.length > 0
|
|
3002
|
-
? note(
|
|
3003
|
-
`It also carries ${semanticPhrase(preview.semantic.length)} — ${preview.semantic
|
|
3004
|
-
.map((s) => s.name)
|
|
3005
|
-
.join(", ")}. They are not selectable, they apply only where you configured Jev, and they ` +
|
|
3006
|
-
"replace the checks this build ships with.",
|
|
3007
|
-
opts,
|
|
3008
|
-
)
|
|
3009
|
-
: null,
|
|
3010
3173
|
preview.minCliVersion ? note(`Requires failproofai ${preview.minCliVersion} or newer.`, opts) : null,
|
|
3011
3174
|
preview.resolvedFromLatest ? note(`Newest release: ${preview.source}`, opts) : null,
|
|
3012
3175
|
table({ head: ["", "", ""], rows }, opts),
|
|
3176
|
+
// The half the table above cannot hold: its own section, under the
|
|
3177
|
+
// policies rather than above them, because a check is read against the
|
|
3178
|
+
// policies it can clear and those are the rows just passed.
|
|
3179
|
+
jevChecksSection(preview, opts),
|
|
3013
3180
|
nextStep(`failproofai policies add ${source}`, "Install the defaults with:", opts),
|
|
3014
3181
|
note("Or take part of it: --policy <a,b>, --category <x,y>, --all", opts),
|
|
3015
3182
|
),
|
package/src/hooks/pack-store.ts
CHANGED
|
@@ -814,7 +814,7 @@ export function slugifyCategory(category: string): string {
|
|
|
814
814
|
*
|
|
815
815
|
* The default is the pack's OWN `defaultEnabled` set, not everything. A pack
|
|
816
816
|
* carries an opinion about which of its policies are safe to switch on
|
|
817
|
-
* unattended — for the builtins that is 10 of
|
|
817
|
+
* unattended — for the builtins that is 10 of 39 — and installing the whole
|
|
818
818
|
* thing overrode that opinion with one nobody held. `block-kubectl`,
|
|
819
819
|
* `block-terraform` and `require-ci-green-before-stop` are off by default in the
|
|
820
820
|
* npm package precisely because they interrupt legitimate work.
|
|
@@ -37,6 +37,30 @@
|
|
|
37
37
|
*/
|
|
38
38
|
import type { PolicyCatalogEntry, PolicyParamsSchema } from "./policy-types";
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* ── On `authority` and `reviewedBy` in this file ──
|
|
42
|
+
*
|
|
43
|
+
* `reviewable` means Jev may CLEAR this policy's verdict, and only through the
|
|
44
|
+
* semantic checks named here — every one of which must have been asked.
|
|
45
|
+
*
|
|
46
|
+
* Both ways of getting a pairing wrong are silent, and the asymmetry between
|
|
47
|
+
* them is what decides these rows:
|
|
48
|
+
*
|
|
49
|
+
* - a check that is never ASKED never clears, so the block becomes permanent
|
|
50
|
+
* - a check that is asked and does not FIRE answers "no concern", and no
|
|
51
|
+
* concern CLEARS — so naming a check that does not model this policy's
|
|
52
|
+
* shapes does not review the policy, it switches it off for exactly the
|
|
53
|
+
* inputs that check does not understand
|
|
54
|
+
*
|
|
55
|
+
* And an `instruct`-mode check can never answer deny. So the test is not "can
|
|
56
|
+
* the named reviewer keep this block" but "is there anything left that can
|
|
57
|
+
* deny": a deny-mode name in the conjunction, or a deny-mode check covering the
|
|
58
|
+
* same concern independently, or a policy that never denied in the first place.
|
|
59
|
+
* `block-work-on-main` fails all three and is hard for that reason.
|
|
60
|
+
*
|
|
61
|
+
* Each row's own comment says which of those applies. The reasoning was worked
|
|
62
|
+
* out policy by policy in FailproofAI/jev-policies' DECISIONS.md.
|
|
63
|
+
*/
|
|
40
64
|
export const POLICY_CATALOG: PolicyCatalogEntry[] = [
|
|
41
65
|
{
|
|
42
66
|
name: "sanitize-jwt",
|
|
@@ -143,6 +167,17 @@ export const POLICY_CATALOG: PolicyCatalogEntry[] = [
|
|
|
143
167
|
// PermissionRequest is Codex's escalation-approval event; fire the same
|
|
144
168
|
// sudo guard there so Codex sandbox bypasses are blocked too.
|
|
145
169
|
match: { events: ["PreToolUse", "PermissionRequest"], toolNames: ["Bash"] },
|
|
170
|
+
// Hard, although `privilege-escalation` is deny-mode and its probe is a strict superset
|
|
171
|
+
// of this matcher — so the pairing would pass the "is there anything left that can
|
|
172
|
+
// deny" test. The reason it stays hard is the OTHER clearing path: that check is
|
|
173
|
+
// `userCanOverride: true`, so a human naming the operation clears it, and this policy
|
|
174
|
+
// is `defaultEnabled: true`. Reviewable would therefore turn "sudo is blocked" into
|
|
175
|
+
// "sudo is blocked unless you asked for it" on every machine with Jev configured.
|
|
176
|
+
// Measured against what that buys: the false-block reduction on the labelled corpus
|
|
177
|
+
// came from `block-read-outside-cwd`, `protect-env-vars` and `block-env-files`, which
|
|
178
|
+
// were already reviewable. Sudo contributed nothing to it, so the trade is a headline
|
|
179
|
+
// guarantee for no measured gain. The nine opt-in policies that ARE reviewable here
|
|
180
|
+
// reach only people who switched them on deliberately.
|
|
146
181
|
authority: "hard",
|
|
147
182
|
defaultEnabled: true,
|
|
148
183
|
category: "Dangerous Commands",
|
|
@@ -160,6 +195,12 @@ export const POLICY_CATALOG: PolicyCatalogEntry[] = [
|
|
|
160
195
|
impact: "`curl ... | sh` runs unverified remote code on your machine.",
|
|
161
196
|
description: "Block piping downloads to shell",
|
|
162
197
|
match: { events: ["PreToolUse"], toolNames: ["Bash"] },
|
|
198
|
+
// Hard, for the same reason as `block-sudo` above: the `remote-code-execution` pairing is
|
|
199
|
+
// sound, but the check is overridable by an explicit request and this policy is on by
|
|
200
|
+
// default, so reviewable would mean "piping a download to a shell is blocked unless you
|
|
201
|
+
// asked for it". The substring false positive it has — `grep -rn "curl x | sh"` is
|
|
202
|
+
// denied — is real and is the argument for pairing it; it is also rare enough not to
|
|
203
|
+
// pay for weakening the default.
|
|
163
204
|
authority: "hard",
|
|
164
205
|
defaultEnabled: true,
|
|
165
206
|
category: "Dangerous Commands",
|
|
@@ -170,7 +211,13 @@ export const POLICY_CATALOG: PolicyCatalogEntry[] = [
|
|
|
170
211
|
impact: "Catches catastrophic `rm -rf /` and Windows equivalents.",
|
|
171
212
|
description: "Prevent catastrophic deletions",
|
|
172
213
|
match: { events: ["PreToolUse"], toolNames: ["Bash"] },
|
|
173
|
-
|
|
214
|
+
// Reviewable: `destructive-deletion` is deny-mode, and its second probe is this
|
|
215
|
+
// policy's path-depth heuristic done properly — `irreplaceable`'s false criteria
|
|
216
|
+
// (build output, dist/, caches, node_modules, virtualenvs, coverage, temp files) is
|
|
217
|
+
// exactly this heuristic's error term. `rm -rf /` keeps both probes true and stays
|
|
218
|
+
// denied; `rm -rf node_modules` is the false block this pairing exists to remove.
|
|
219
|
+
authority: "reviewable",
|
|
220
|
+
reviewedBy: ["destructive-deletion"],
|
|
174
221
|
defaultEnabled: false,
|
|
175
222
|
category: "Dangerous Commands",
|
|
176
223
|
params: {
|
|
@@ -209,7 +256,12 @@ export const POLICY_CATALOG: PolicyCatalogEntry[] = [
|
|
|
209
256
|
impact: "kubectl can change live cluster state — gated unless allow-listed.",
|
|
210
257
|
description: "Block kubectl commands (Kubernetes cluster mutations)",
|
|
211
258
|
match: { events: ["PreToolUse"], toolNames: ["Bash"] },
|
|
212
|
-
|
|
259
|
+
// Reviewable: `production-infra-change` is deny-mode and names kubectl explicitly. This
|
|
260
|
+
// policy denies the whole CLI, read-only subcommands included; the probe's false
|
|
261
|
+
// criteria is the split a regex cannot make — get, list, describe, logs, status,
|
|
262
|
+
// plan, diff, validate, whoami, --dry-run.
|
|
263
|
+
authority: "reviewable",
|
|
264
|
+
reviewedBy: ["production-infra-change"],
|
|
213
265
|
defaultEnabled: false,
|
|
214
266
|
category: "Infra Commands",
|
|
215
267
|
params: {
|
|
@@ -226,7 +278,10 @@ export const POLICY_CATALOG: PolicyCatalogEntry[] = [
|
|
|
226
278
|
impact: "Terraform mutates real infrastructure — gated unless allow-listed.",
|
|
227
279
|
description: "Block terraform and tofu (OpenTofu) commands",
|
|
228
280
|
match: { events: ["PreToolUse"], toolNames: ["Bash"] },
|
|
229
|
-
|
|
281
|
+
// Reviewable: same pairing as `block-kubectl`; the probe names terraform and tofu, and
|
|
282
|
+
// clears `terraform plan` and `terraform validate`.
|
|
283
|
+
authority: "reviewable",
|
|
284
|
+
reviewedBy: ["production-infra-change"],
|
|
230
285
|
defaultEnabled: false,
|
|
231
286
|
category: "Infra Commands",
|
|
232
287
|
params: {
|
|
@@ -243,7 +298,10 @@ export const POLICY_CATALOG: PolicyCatalogEntry[] = [
|
|
|
243
298
|
impact: "AWS CLI can spend money or break prod — gated.",
|
|
244
299
|
description: "Block aws CLI commands",
|
|
245
300
|
match: { events: ["PreToolUse"], toolNames: ["Bash"] },
|
|
246
|
-
|
|
301
|
+
// Reviewable: same pairing; the probe names aws, and clears `aws sts
|
|
302
|
+
// get-caller-identity` and `aws s3 ls`.
|
|
303
|
+
authority: "reviewable",
|
|
304
|
+
reviewedBy: ["production-infra-change"],
|
|
247
305
|
defaultEnabled: false,
|
|
248
306
|
category: "Infra Commands",
|
|
249
307
|
params: {
|
|
@@ -260,7 +318,10 @@ export const POLICY_CATALOG: PolicyCatalogEntry[] = [
|
|
|
260
318
|
impact: "gcloud can spend money or break prod — gated.",
|
|
261
319
|
description: "Block gcloud (Google Cloud) CLI commands",
|
|
262
320
|
match: { events: ["PreToolUse"], toolNames: ["Bash"] },
|
|
263
|
-
|
|
321
|
+
// Reviewable: same pairing; the probe names gcloud, and clears `gcloud auth list` and
|
|
322
|
+
// `gcloud config list`.
|
|
323
|
+
authority: "reviewable",
|
|
324
|
+
reviewedBy: ["production-infra-change"],
|
|
264
325
|
defaultEnabled: false,
|
|
265
326
|
category: "Infra Commands",
|
|
266
327
|
params: {
|
|
@@ -277,7 +338,9 @@ export const POLICY_CATALOG: PolicyCatalogEntry[] = [
|
|
|
277
338
|
impact: "az can spend money or break prod — gated.",
|
|
278
339
|
description: "Block az (Azure) CLI commands",
|
|
279
340
|
match: { events: ["PreToolUse"], toolNames: ["Bash"] },
|
|
280
|
-
|
|
341
|
+
// Reviewable: same pairing; the probe names az, and clears `az account show`.
|
|
342
|
+
authority: "reviewable",
|
|
343
|
+
reviewedBy: ["production-infra-change"],
|
|
281
344
|
defaultEnabled: false,
|
|
282
345
|
category: "Infra Commands",
|
|
283
346
|
params: {
|
|
@@ -294,7 +357,10 @@ export const POLICY_CATALOG: PolicyCatalogEntry[] = [
|
|
|
294
357
|
impact: "Helm releases mutate cluster state — gated.",
|
|
295
358
|
description: "Block helm commands",
|
|
296
359
|
match: { events: ["PreToolUse"], toolNames: ["Bash"] },
|
|
297
|
-
|
|
360
|
+
// Reviewable: same pairing; the probe names helm, and clears `helm list` and
|
|
361
|
+
// `helm status`.
|
|
362
|
+
authority: "reviewable",
|
|
363
|
+
reviewedBy: ["production-infra-change"],
|
|
298
364
|
defaultEnabled: false,
|
|
299
365
|
category: "Infra Commands",
|
|
300
366
|
params: {
|
|
@@ -328,7 +394,13 @@ export const POLICY_CATALOG: PolicyCatalogEntry[] = [
|
|
|
328
394
|
impact: "Stops the agent from creating `.pem`, `id_rsa`, `credentials.json`, etc.",
|
|
329
395
|
description: "Block writing secret key files",
|
|
330
396
|
match: { events: ["PreToolUse"], toolNames: ["Write"] },
|
|
331
|
-
|
|
397
|
+
// Reviewable: `secret-exposure` is deny-mode and `write` is in its `appliesTo`, so a
|
|
398
|
+
// real private key still comes back deny. What clears is this matcher's substring
|
|
399
|
+
// problem — `/credentials/` and `id_rsa` unanchored against a whole path, which
|
|
400
|
+
// catches `src/auth/credentials.ts`. `credential-exfiltration` would have been a
|
|
401
|
+
// dead name here: it applies to shell and network, and a file write is neither.
|
|
402
|
+
authority: "reviewable",
|
|
403
|
+
reviewedBy: ["secret-exposure"],
|
|
332
404
|
defaultEnabled: false,
|
|
333
405
|
category: "Dangerous Commands",
|
|
334
406
|
params: {
|
|
@@ -362,7 +434,13 @@ export const POLICY_CATALOG: PolicyCatalogEntry[] = [
|
|
|
362
434
|
impact: "Force-pushes rewrite history and can clobber teammates' work.",
|
|
363
435
|
description: "Prevent force-pushing to any branch",
|
|
364
436
|
match: { events: ["PreToolUse"], toolNames: ["Bash"] },
|
|
365
|
-
|
|
437
|
+
// Reviewable: `git-history-rewrite` is deny-mode and its probe is a superset of this
|
|
438
|
+
// matcher — it counts `--force-with-lease` (which `isForcePushFlag` deliberately
|
|
439
|
+
// treats as safe), a `+refspec`, and a remote-branch delete, and says `git -C dir`
|
|
440
|
+
// and an absolute binary path change nothing. A real force-push stays blocked; what
|
|
441
|
+
// clears is the user asking to force-push their own branch.
|
|
442
|
+
authority: "reviewable",
|
|
443
|
+
reviewedBy: ["git-history-rewrite"],
|
|
366
444
|
defaultEnabled: false,
|
|
367
445
|
category: "Git",
|
|
368
446
|
},
|
|
@@ -418,6 +496,67 @@ export const POLICY_CATALOG: PolicyCatalogEntry[] = [
|
|
|
418
496
|
defaultEnabled: false,
|
|
419
497
|
category: "Git",
|
|
420
498
|
},
|
|
499
|
+
{
|
|
500
|
+
name: "warn-git-clean",
|
|
501
|
+
displayTitle: "Tried to delete untracked or ignored files with git clean",
|
|
502
|
+
impact: "`git clean -fdx` takes `.env`, local config and unstaged work — git never had a copy of any of it.",
|
|
503
|
+
description: "Warns before git clean deletes untracked directories (-d) or ignored files (-x / -X)",
|
|
504
|
+
match: { events: ["PreToolUse"], toolNames: ["Bash"] },
|
|
505
|
+
// Hard, and deliberately NOT `reviewable` through `destructive-deletion`,
|
|
506
|
+
// although that check is the one whose whole subject is deleting data that
|
|
507
|
+
// cannot be regenerated.
|
|
508
|
+
//
|
|
509
|
+
// Measured on a real machine, through the real hook, with a Jev config
|
|
510
|
+
// present, on `git clean -fdx`:
|
|
511
|
+
//
|
|
512
|
+
// jev: ok decision=allow applied=two-tier 495ms
|
|
513
|
+
// probes: destructive-deletion.destroys=0.94 beyond_task=0.79 task_step=0.78
|
|
514
|
+
//
|
|
515
|
+
// `destroys` came back 0.94 — the check sees the destruction; its own
|
|
516
|
+
// instructions name `git clean -fdx` by example. The policy still did not
|
|
517
|
+
// fire, because evidence is the MIN over a policy's probes and the partner
|
|
518
|
+
// probe `irreplaceable` came back low (it is absent from the probe line,
|
|
519
|
+
// which lists only what answered above the display floor). That is not a
|
|
520
|
+
// tuning accident: `git clean` carries NO path operand, so `facts.paths` is
|
|
521
|
+
// empty (measured — `extractPaths` skips `clean` as not path-like and
|
|
522
|
+
// `-fdx` as a flag), while `irreplaceable` is written to read
|
|
523
|
+
// `facts.paths[].relation` and to answer false for "only regenerable data
|
|
524
|
+
// inside the project: build output, dist/, caches, node_modules, …". With
|
|
525
|
+
// nothing to point at, the false branch is the honest answer to the
|
|
526
|
+
// question as written.
|
|
527
|
+
//
|
|
528
|
+
// A named check that is asked and does not fire answers "no concern", and
|
|
529
|
+
// that CLEARS (`combine.ts`, "A warning-level answer clears the deny"). So
|
|
530
|
+
// pairing this policy with `destructive-deletion` would not hand the
|
|
531
|
+
// decision to Jev — it would switch the policy off on every machine that
|
|
532
|
+
// configured Jev, which is exactly the `block-work-on-main` mistake. The
|
|
533
|
+
// test is "is there anything left that can DENY", and no other deny-mode
|
|
534
|
+
// semantic check covers untracked-file deletion, so a clear would leave the
|
|
535
|
+
// concern enforced by nothing. Hard until the probe is recalibrated against
|
|
536
|
+
// the corpus; the proposed wording and why it needs a replay are in
|
|
537
|
+
// `PROBE-FOLLOWUP.md`.
|
|
538
|
+
authority: "hard",
|
|
539
|
+
// Off by default, and `instruct` rather than `deny`, because `git clean
|
|
540
|
+
// -fdx` is a command developers run on purpose and often — it is the
|
|
541
|
+
// standard way to get a genuinely clean tree before a build. A default-on
|
|
542
|
+
// deny would fire on ordinary work, and a guard people switch off protects
|
|
543
|
+
// nothing; every policy in this category except `block-push-master` is
|
|
544
|
+
// default-off for the same reason, and `block-read-outside-cwd` was
|
|
545
|
+
// demoted out of the audit's archetype signal for being exactly this kind
|
|
546
|
+
// of ambient. What IS worth saying every time it is enabled is that the
|
|
547
|
+
// blast radius is wider than the operator usually means, so the policy
|
|
548
|
+
// warns and names what goes.
|
|
549
|
+
defaultEnabled: false,
|
|
550
|
+
category: "Git",
|
|
551
|
+
params: {
|
|
552
|
+
destructiveFlags: {
|
|
553
|
+
type: "string[]",
|
|
554
|
+
description:
|
|
555
|
+
"git clean flag letters that make it worth warning about, checked alongside --force. Narrow to ['x','X'] to allow `git clean -fd`, or widen with 'f' to warn on a bare `git clean -f`.",
|
|
556
|
+
default: ["d", "x", "X"],
|
|
557
|
+
},
|
|
558
|
+
} satisfies PolicyParamsSchema,
|
|
559
|
+
},
|
|
421
560
|
{
|
|
422
561
|
name: "warn-all-files-staged",
|
|
423
562
|
displayTitle: "Staged all files with git add -A / .",
|
package/src/hooks/types.ts
CHANGED
|
@@ -1059,7 +1059,7 @@ export type HookEventType = (typeof HOOK_EVENT_TYPES)[number];
|
|
|
1059
1059
|
*
|
|
1060
1060
|
* It stays in `HOOK_EVENT_TYPES` because that list is the canonical set a
|
|
1061
1061
|
* policy may subscribe to; this one governs what we write into settings.json.
|
|
1062
|
-
* No builtin matches it (all
|
|
1062
|
+
* No builtin matches it (all 40 match only PreToolUse / PostToolUse /
|
|
1063
1063
|
* PermissionRequest / Stop), so nothing is lost by not registering.
|
|
1064
1064
|
*/
|
|
1065
1065
|
export const CLAUDE_INSTALL_EVENT_TYPES = HOOK_EVENT_TYPES.filter(
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,64237,e=>{"use strict";var t=e.i(43476),a=e.i(71645),s=e.i(12344),n=e.i(29054);let l=/^[^\s@]+@[^\s@]+\.[^\s@]+$/;function i(e){if((0,n.isAbortError)(e))return"request timed out. check your network and try again.";let t=e instanceof Error?e.message:String(e);return`network error: ${t}`}e.s(["AuthDialog",0,function({open:e,headline:r="where to route the reminder?",subhead:o="we'll send a one-time code to confirm.",onClose:c,onAuthed:d,source:u="unknown"}){let{capture:h}=(0,s.usePostHog)(),[m,f]=(0,a.useState)({kind:"email",error:null}),[v,b]=(0,a.useState)(!1),p=(0,a.useRef)(!1),x=(0,a.useRef)(null),w=(0,a.useRef)(null);(0,a.useEffect)(()=>{e&&(f({kind:"email",error:null}),b(!1),p.current=!1,h("audit_auth_dialog_opened",{source:u}))},[h,e,u]);let j=(0,a.useRef)(!1);(0,a.useEffect)(()=>{if(e){j.current=!0;return}j.current&&!p.current&&h("audit_auth_dialog_dismissed",{source:u,step:m.kind}),j.current=!1},[h,e,u,m.kind]),(0,a.useEffect)(()=>{if(!e)return;let t=setTimeout(()=>{"email"===m.kind?x.current?.focus():"code"===m.kind&&w.current?.focus()},50);return()=>clearTimeout(t)},[e,m.kind]),(0,a.useEffect)(()=>{if(!e)return;let t=e=>{"Escape"!==e.key||v||c()};return window.addEventListener("keydown",t),()=>window.removeEventListener("keydown",t)},[e,v,c]);let g="code"===m.kind&&m.resendIn>0;(0,a.useEffect)(()=>{if(!g)return;let e=setInterval(()=>{f(e=>"code"===e.kind?{...e,resendIn:Math.max(0,e.resendIn-1)}:e)},1e3);return()=>clearInterval(e)},[g]);let y=(0,a.useCallback)(async(e,t={})=>{let{isResend:a=!1}=t,s=e=>{a?f(t=>"code"===t.kind?{...t,error:e}:t):f({kind:"email",error:e})};b(!0);try{let t=await (0,n.fetchWithTimeout)("/api/auth/login-request",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({email:e})}),a=await t.json().catch(()=>({}));if(!t.ok){let e=a.message??"could not send code.";"rate_limited"===a.code&&void 0!==a.retry_after_secs?e=`too many tries. wait ${a.retry_after_secs}s and try again.`:"upstream_unreachable"===a.code&&(e="api-server unreachable. check your network."),s(e);return}f({kind:"code",email:e,error:null,expiresIn:a.expires_in??600,resendIn:a.resend_available_in??30})}catch(e){s(i(e))}finally{b(!1)}},[]),k=(0,a.useCallback)(async(e,t)=>{b(!0);try{let a=await (0,n.fetchWithTimeout)("/api/auth/login-verify",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({email:e,code:t})}),s=await a.json().catch(()=>({}));if(!a.ok||!s.authenticated||!s.user){let e=s.message??"invalid code.";"invalid_code"===s.code&&(e="wrong code, or it expired. try again."),f(t=>"code"===t.kind?{...t,error:e}:t);return}p.current=!0,h("audit_auth_dialog_succeeded",{source:u}),f({kind:"done",user:s.user}),d(s.user)}catch(t){let e=i(t);f(t=>"code"===t.kind?{...t,error:e}:t)}finally{b(!1)}},[h,d,u]),N=(0,a.useCallback)(async e=>{if(e.preventDefault(),v||"email"!==m.kind)return;let t=String(new FormData(e.currentTarget).get("email")??"").trim().toLowerCase();l.test(t)?await y(t):f({kind:"email",error:"that doesn't look like an email."})},[v,m,y]),S=(0,a.useCallback)(async e=>{if(e.preventDefault(),v||"code"!==m.kind)return;let t=String(new FormData(e.currentTarget).get("code")??"").trim();t.length<4||t.length>12?f(e=>"code"===e.kind?{...e,error:"code is 4–12 characters."}:e):await k(m.email,t)},[v,m,k]),C=(0,a.useCallback)(async()=>{"code"!==m.kind||m.resendIn>0||v||await y(m.email,{isResend:!0})},[m,v,y]);return e?(0,t.jsx)("div",{className:"auth-dialog-backdrop",role:"dialog","aria-modal":"true","aria-labelledby":"auth-dialog-title",onClick:e=>{v||e.target!==e.currentTarget||c()},children:(0,t.jsxs)("div",{className:"auth-dialog",children:[(0,t.jsx)("button",{type:"button",className:"auth-close",onClick:c,disabled:v,"aria-label":"close",children:"×"}),(0,t.jsx)("h2",{id:"auth-dialog-title",className:"auth-headline",children:r}),"email"===m.kind&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("p",{className:"auth-sub",children:o}),(0,t.jsxs)("form",{onSubmit:N,className:"auth-form",children:[(0,t.jsx)("input",{ref:x,id:"auth-dialog-email",name:"email",type:"email",autoComplete:"email",inputMode:"email",spellCheck:!1,placeholder:"you@yourdomain.com",disabled:v,className:"auth-input",required:!0}),m.error&&(0,t.jsx)("div",{className:"auth-error",children:m.error}),(0,t.jsxs)("div",{className:"auth-actions",children:[(0,t.jsx)("button",{type:"submit",className:"auth-btn primary",disabled:v,children:v?"sending…":"send code"}),(0,t.jsx)("button",{type:"button",className:"auth-btn",onClick:c,disabled:v,children:"cancel"})]})]})]}),"code"===m.kind&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("p",{className:"auth-sub",children:["code sent to ",(0,t.jsx)("span",{className:"auth-email",children:m.email}),". expires in ",Math.ceil(m.expiresIn/60)," min."]}),(0,t.jsxs)("form",{onSubmit:S,className:"auth-form",children:[(0,t.jsx)("input",{ref:w,id:"auth-dialog-code",name:"code",type:"text",inputMode:"numeric",autoComplete:"one-time-code",spellCheck:!1,placeholder:"123456",disabled:v,className:"auth-input auth-input-code",maxLength:12,required:!0}),m.error&&(0,t.jsx)("div",{className:"auth-error",children:m.error}),(0,t.jsxs)("div",{className:"auth-actions",children:[(0,t.jsx)("button",{type:"submit",className:"auth-btn primary",disabled:v,children:v?"verifying…":"verify"}),(0,t.jsx)("button",{type:"button",className:"auth-btn",onClick:C,disabled:v||m.resendIn>0,children:m.resendIn>0?`resend in ${m.resendIn}s`:"resend code"})]}),(0,t.jsx)("button",{type:"button",className:"auth-back",onClick:()=>f({kind:"email",error:null}),disabled:v,children:"← use a different email"})]})]}),"done"===m.kind&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("p",{className:"auth-sub",children:[(0,t.jsx)("span",{className:"auth-ok",children:"✓"})," signed in as"," ",(0,t.jsx)("span",{className:"auth-email",children:m.user.email}),"."]}),(0,t.jsx)("div",{className:"auth-actions",children:(0,t.jsx)("button",{type:"button",className:"auth-btn primary",onClick:c,children:"continue"})})]})]})}):null}])},86616,e=>{"use strict";var t=e.i(29054);class a extends Error{kind;constructor(e,t){super(t),this.kind=e,this.name="RerunError"}}async function s(e){try{let s=await (0,t.fetchWithTimeout)("/api/audit/run",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({cli:e.cli.length>0?e.cli:void 0,since:"all"===e.since?void 0:e.since,noCache:!!e.noCache||void 0})});if(!s.ok&&409!==s.status){let e=await s.text().catch(()=>"");throw console.error("audit run failed:",s.status,e),new a("post_failed",`audit run failed (${s.status})`)}}catch(e){if(e instanceof a)throw e;throw console.error("audit run request failed:",e),new a((0,t.isAbortError)(e)?"timeout":"network","audit run request failed")}let s=0;for(;;){await new Promise(e=>setTimeout(e,1e3));let e=null;try{let a=await (0,t.fetchWithTimeout)("/api/audit/status",{cache:"no-store"});a.ok&&(e=await a.json())}catch{}if(null===e){if(++s>=10)throw new a("network","audit status poll lost the server");continue}if(s=0,!e.running){if(e.error)throw new a("post_failed",e.error);return}}}e.s(["RerunError",0,a,"triggerRun",0,s])},2917,e=>{"use strict";var t=e.i(43476),a=e.i(71645),s=e.i(95187);let n=(0,s.createServerReference)("00886d6fd442c1b095151f60d50b80218492349ea6",s.callServer,void 0,s.findSourceMapURL,"getJevSettingsAction"),l=(0,s.createServerReference)("0012aa49182201bcf73cdde878f5483546103b60f6",s.callServer,void 0,s.findSourceMapURL,"removeJevConfigAction"),i=(0,s.createServerReference)("40b77dfb7787b11b779dabc19334dcc7f9f73c174d",s.callServer,void 0,s.findSourceMapURL,"saveJevConfigAction");var r=e.i(55574);let o=[{value:"typesafe",label:"typesafe"},{value:"openrouter",label:"openrouter"},{value:"vercel",label:"vercel ai gateway"},{value:"cloudflare",label:"cloudflare workers ai"},{value:"custom",label:"custom endpoint"}],c=[{value:"enforce",label:"enforce — jev's verdict counts"},{value:"shadow",label:"shadow — log only, regex decides"}];function d(e){return{provider:e.provider??"typesafe",baseUrl:e.baseUrl,accountId:e.accountId,mode:e.mode}}function u({id:e,label:a,hint:s,children:n}){return(0,t.jsxs)("div",{className:"set-field",children:[(0,t.jsx)("label",{className:"set-field-label",htmlFor:e,children:a}),n,s?(0,t.jsx)("span",{className:"set-hint",children:s}):null]})}e.s(["default",0,function({initial:e}){var s,h;let m,[f,v]=(0,a.useState)(e),[b,p]=(0,a.useState)(e?d(e):{provider:"typesafe",baseUrl:"",accountId:"",mode:"enforce"}),[x,w]=(0,a.useState)(""),[j,g]=(0,a.useState)(!1),[y,k]=(0,a.useState)(null),[N,S]=(0,a.useState)(!1),C=(0,a.useRef)(!0),M=(0,a.useRef)(!1),$=(0,a.useCallback)(async()=>{try{let e=await n();if(!C.current)return;v(e),M.current||p(d(e))}catch{}},[]);(0,a.useEffect)(()=>(C.current=!0,$(),()=>{C.current=!1}),[$]),(0,a.useEffect)(()=>{let e=()=>void $();return window.addEventListener("focus",e),document.addEventListener("visibilitychange",e),()=>{window.removeEventListener("focus",e),document.removeEventListener("visibilitychange",e)}},[$]);let E=(0,a.useCallback)((e,t)=>{M.current=!0,p(a=>({...a,[e]:t}))},[]),A=(0,a.useCallback)(async()=>{g(!0),k(null);try{let e=await i({provider:b.provider,baseUrl:b.baseUrl,accountId:b.accountId,mode:b.mode,token:x});if(!e.ok){k(e.problem),S(!0===e.needsToken);return}M.current=!1,S(!1),w(""),v(e.view),p(d(e.view)),(0,r.toast)(e.view.on?"jev is on.":"saved.")}catch{k("could not save that.")}finally{g(!1)}},[b,x]),R=(0,a.useCallback)(async()=>{g(!0),k(null),S(!1);try{let e=await l();if(!e.ok)return void k(e.problem);M.current=!1,w(""),v(e.view),p(d(e.view)),(0,r.toast)("jev is off. hooks run the regex policies.")}catch{k("could not turn that off.")}finally{g(!1)}},[]),D=null!==f&&"absent"!==f.status,_=f?.token,I=N?"needed for this save — type the token for this endpoint":_?"env"===_.source?"configured, read from the environment — leave blank to keep it":_.hint?`configured, ending ${_.hint} — leave blank to keep it`:"configured — leave blank to keep it":f?.status==="key-missing"?"read from the environment, which is not set in this shell — leave blank to keep it that way":"sent as a bearer token; stored owner-only at 0600";return(0,t.jsxs)("div",{className:"set-cell set-jev",children:[(0,t.jsx)("h2",{className:"set-cell-title",children:"jev · semantic evaluation"}),(0,t.jsx)("div",{className:"set-row set-row-main",children:(0,t.jsxs)("div",{className:"set-row-copy",children:[(0,t.jsx)("span",{className:f?.on?"set-strong":"set-dim",children:null===f?"reading…":f.on?`on. every judged command is also asked of ${f.provider}.`:"off. hooks run the regex policies exactly as before."}),(0,t.jsx)("span",{className:"set-dim",children:f?.on?"shadow"===f.mode?"shadow: jev's answers are logged, the regex result is what gets enforced.":"enforce: jev's answers can clear a reviewable deny.":"a second opinion on the commands the regex policies flag. needs your own endpoint and token."})]})}),f&&D&&(0,t.jsxs)("dl",{className:"set-how-list",children:[f.endpoint&&(0,t.jsxs)("div",{className:"set-how-row",children:[(0,t.jsx)("dt",{className:"set-how-label",children:"endpoint"}),(0,t.jsx)("dd",{className:"set-how-body",children:f.endpoint})]}),(0,t.jsxs)("div",{className:"set-how-row",children:[(0,t.jsx)("dt",{className:"set-how-label",children:"model"}),(0,t.jsx)("dd",{className:"set-how-body",children:function(e){switch(e.kind){case"id":return e.id;case"withheld":return"set to something that is not a model id — not shown here, in case it is a key";default:return"the provider's default"}}(f.model)})]}),(0,t.jsxs)("div",{className:"set-how-row",children:[(0,t.jsx)("dt",{className:"set-how-label",children:"token"}),(0,t.jsx)("dd",{className:"set-how-body",children:_?"env"===_.source?"from FAILPROOFAI_JEV_API_KEY":_.hint?`configured, ending ${_.hint}`:"configured":"none stored"})]}),f.permissions&&(0,t.jsxs)("div",{className:"set-how-row",children:[(0,t.jsx)("dt",{className:"set-how-label",children:"file"}),(0,t.jsx)("dd",{className:"set-how-body",children:`${f.path} \xb7 ${f.permissions}`})]}),f.reviewable&&(0,t.jsxs)("div",{className:"set-how-row",children:[(0,t.jsx)("dt",{className:"set-how-label",children:"reviewable"}),(0,t.jsx)("dd",{className:"set-how-body",children:f.reviewable.summary})]}),f.stats&&f.stats.total>0&&(0,t.jsxs)("div",{className:"set-how-row",children:[(0,t.jsx)("dt",{className:"set-how-label",children:"fallbacks"}),(0,t.jsx)("dd",{className:"set-how-body",children:`${(s=f.stats.fallbackRate,`${Math.round(100*s)}%`)} of ${f.stats.total} calls in the last ${Number.isInteger(m=(h=f.stats.windowMs)/36e5)&&m>=1?m%24==0?`${m/24}d`:`${m}h`:`${Math.max(1,Math.round(h/6e4))}m`} fell back to the regex engine.`})]})]}),f?.problem&&(0,t.jsxs)("p",{className:"set-warn",children:[f.problem,f.fix?` — ${f.fix}`:""]}),f?.reviewable?.problem&&(0,t.jsx)("p",{className:"set-warn",children:f.reviewable.problem}),(0,t.jsx)("div",{className:"set-rule"}),(0,t.jsxs)("div",{className:"set-jev-fields",children:[(0,t.jsx)(u,{id:"jev-provider",label:"provider",children:(0,t.jsx)("select",{id:"jev-provider",className:"set-select",value:b.provider,disabled:j,onChange:e=>E("provider",e.target.value),children:o.map(e=>(0,t.jsx)("option",{value:e.value,children:e.label},e.value))})}),(0,t.jsx)(u,{id:"jev-url",label:"endpoint url",hint:"custom"===b.provider?"required — https, or http to localhost in shadow mode":"leave blank for the provider's own api",children:(0,t.jsx)("input",{id:"jev-url",type:"text",className:"set-text",inputMode:"url",autoComplete:"off",spellCheck:!1,placeholder:"custom"===b.provider?"https://…":"the provider's own api",value:b.baseUrl,disabled:j,onChange:e=>E("baseUrl",e.target.value)})}),"cloudflare"===b.provider&&(0,t.jsx)(u,{id:"jev-account",label:"account id",hint:"32 lowercase hex characters",children:(0,t.jsx)("input",{id:"jev-account",type:"text",className:"set-text",autoComplete:"off",spellCheck:!1,value:b.accountId,disabled:j,onChange:e=>E("accountId",e.target.value)})}),(0,t.jsx)(u,{id:"jev-token",label:"token",hint:I,children:(0,t.jsx)("input",{id:"jev-token",type:"password",className:"set-text",autoComplete:"off",spellCheck:!1,placeholder:_?"•••• kept":"",value:x,disabled:j,"aria-invalid":N||void 0,onChange:e=>{M.current=!0,w(e.target.value)}})}),(0,t.jsx)(u,{id:"jev-mode",label:"mode",children:(0,t.jsx)("select",{id:"jev-mode",className:"set-select",value:b.mode,disabled:j,onChange:e=>E("mode",e.target.value),children:c.map(e=>(0,t.jsx)("option",{value:e.value,children:e.label},e.value))})})]}),y&&(0,t.jsx)("p",{className:"set-warn",children:y}),(0,t.jsxs)("div",{className:"set-actions set-jev-actions",children:[(0,t.jsx)("button",{type:"button",className:"btn btn-press",disabled:j,onClick:()=>void A(),children:j?"[ saving… ]":D?"[ save changes ]":"[ turn jev on ]"}),D&&(0,t.jsx)("button",{type:"button",className:"set-link",disabled:j,onClick:()=>void R(),children:"turn jev off"})]})]})}],2917)},93237,e=>{"use strict";var t=e.i(43476),a=e.i(71645),s=e.i(95187);let n=(0,s.createServerReference)("00a4b4e13d3b765196cdd39a6bcc3adb9dc9dd1e39",s.callServer,void 0,s.findSourceMapURL,"getScheduledAuditAction"),l=(0,s.createServerReference)("40542c2caee97c1baa6587e21be9b4c5a3e5cb04a7",s.callServer,void 0,s.findSourceMapURL,"setAutoAuditAction"),i=(0,s.createServerReference)("40a98655ac2e11879113abd14dae3692129e3723f4",s.callServer,void 0,s.findSourceMapURL,"setAuditIntervalAction");var r=e.i(86616),o=e.i(64237),c=e.i(55574),d=e.i(34713);function u(e){return new Date(e).toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}function h(e,t){let a=e-t;if(a<=0)return"now";let s=Math.floor(a/864e5),n=Math.floor(a%864e5/36e5);return s>0?n>0?`${s}d ${n}h`:`${s}d`:n>0?`${n}h`:`${Math.max(1,Math.floor(a/6e4))}m`}function m(e){return e.toLocaleString("en-US")}function f({label:e,value:a,sub:s,tone:n}){return(0,t.jsxs)("div",{className:"set-stat",children:[(0,t.jsx)("div",{className:"set-stat-label",children:e}),(0,t.jsx)("div",{className:`set-stat-value${n?` ${n}`:""}`,children:a}),(0,t.jsx)("div",{className:"set-stat-sub",children:s??" "})]})}function v({lastRunAtMs:e,nextDueAtMs:a,now:s}){if(null==e||null==a||a<=e)return null;let n=Math.min(100,Math.max(0,(s-e)/(a-e)*100));return(0,t.jsxs)("div",{className:"tape","aria-hidden":"true",children:[(0,t.jsxs)("div",{className:"tape-rail",children:[(0,t.jsx)("div",{className:"tape-fill",style:{width:`${n}%`}}),(0,t.jsx)("div",{className:"tape-now",style:{left:`${n}%`}})]}),(0,t.jsxs)("div",{className:"tape-ends",children:[(0,t.jsxs)("span",{children:["last scan · ",u(e)]}),(0,t.jsxs)("span",{className:"tape-next",children:["next · ",h(a,s)]})]})]})}function b({enabled:e,onChange:a,disabled:s,label:n}){return(0,t.jsx)("button",{type:"button",role:"switch","aria-checked":e,"aria-label":n,disabled:s,onClick:a,className:"sw","data-on":e?"true":"false",children:(0,t.jsx)("span",{className:"sw-knob"})})}let p=[{label:"reads",body:"every session transcript on disk — your prompts, the files your agents read and wrote, and command output."},{label:"runs",body:"entirely on this machine. the transcripts never leave it."},{label:"sends",body:"counts, redacted examples, and this machine's name — and only when a scan finds something harmful."}];e.s(["default",0,function({initial:e,jevPanel:s}){let[x,w]=(0,a.useState)(e),[j,g]=(0,a.useState)(e?.auto??!1),[y,k]=(0,a.useState)(e?.intervalDays??7),[N,S]=(0,a.useState)(!1),[C,M]=(0,a.useState)(!1),[$,E]=(0,a.useState)(!1),[A,R]=(0,a.useState)(null===e),[D,_]=(0,a.useState)(0),I=(0,a.useRef)(!0),T=(0,a.useRef)(null!==e),L=(0,a.useCallback)(async()=>{try{let e=await n();if(!I.current)return;w(e),T.current=!0,g(e.auto),k(e.intervalDays),_(Date.now()),R(!1)}catch{I.current&&!T.current&&R(!0)}},[]);(0,a.useEffect)(()=>(I.current=!0,L(),()=>{I.current=!1}),[L]),(0,a.useEffect)(()=>{let e=()=>void L();return window.addEventListener("focus",e),document.addEventListener("visibilitychange",e),()=>{window.removeEventListener("focus",e),document.removeEventListener("visibilitychange",e)}},[L]);let U=x?.signedInAs??null,F=x?.daemon==="running",O=x?.daemon==="unsupported-platform",P=x?.schedule??null,q=x?.lastScan??null,J=P?.lastExitCode!=null&&0!==P.lastExitCode&&75!==P.lastExitCode,W=(0,a.useCallback)(async()=>{S(!0);try{let e=await l(!0);if(!e.ok){if(g(!1),"unreachable"===e.reason)return void(0,c.toast)("could not reach the server. check your connection and try again.");await L(),E(!0),(0,c.toast)("that sign-in expired. one more code and it's on.");return}g(e.auto),(0,c.toast)("scheduled audits on."),await L()}catch{g(!1),(0,c.toast)("could not turn that on.")}finally{S(!1)}},[L]),B=(0,a.useCallback)(async()=>{if(j){S(!0);try{let e=await l(!1);e.ok&&g(e.auto),(0,c.toast)("scheduled audits off."),await L()}catch{(0,c.toast)("could not turn that off.")}finally{S(!1)}return}U?await W():E(!0)},[j,W,L,U]),K=(0,a.useCallback)(async e=>{S(!0);try{let t=await i(e);k(t.intervalDays),w(e=>e?{...e,intervalDays:t.intervalDays}:e),(0,c.toast)(`scanning every ${t.intervalDays} day${1===t.intervalDays?"":"s"}.`)}catch{k(x?.intervalDays??7),(0,c.toast)("could not save that.")}finally{S(!1)}},[x?.intervalDays]),H=(0,a.useCallback)(async()=>{S(!0);try{await fetch("/api/auth/logout",{method:"POST"}),(0,c.toast)("signed out. scans continue; digests pause."),await L()}catch{(0,c.toast)("could not sign out.")}finally{S(!1)}},[L]),V=(0,a.useCallback)(async()=>{if(!C){M(!0);try{await (0,r.triggerRun)({cli:[],since:"all",noCache:!1}),(0,c.toast)("scan complete."),await L()}catch(e){(0,c.toast)(e instanceof r.RerunError&&"timeout"===e.kind?"the scan is taking a while — it will finish in the background.":"the scan could not be completed.")}finally{M(!1)}}},[L,C]),Y=(0,a.useCallback)(async e=>{E(!1),await L(),await W()},[W,L]),z=x?F?{value:"running",sub:null!=x.daemonStartedAtMs&&D>0?`up ${function(e){let t=Math.floor(e/864e5);if(t>0)return`${t}d`;let a=Math.floor(e/36e5);return a>0?`${a}h`:`${Math.max(1,Math.floor(e/6e4))}m`}(Math.max(0,D-x.daemonStartedAtMs))}`:"",tone:"ok"}:O?{value:"unavailable",sub:"not on this platform"}:"not-installed"===x.daemon?{value:"not installed",sub:"run failproofai config",tone:"warn"}:"unknown"===x.daemon?{value:"unknown",sub:"could not read it"}:{value:"stopped",sub:"run failproofai config",tone:"warn"}:{value:"…",sub:"reading"},G=j?P?.nextDueAtMs==null?{value:"pending",sub:"after the next scan"}:{value:D>0?h(P.nextDueAtMs,D):"—",sub:u(P.nextDueAtMs)}:{value:"off",sub:"nothing scheduled"},Q=q?{value:(0,d.formatRelativeTime)(Date.parse(q.finishedAt)),sub:null!=q.sessionsScanned?`${m(q.sessionsScanned)} sessions`:"scanned"}:{value:"none yet",sub:"run one below"},X=q?null==q.findings?{value:"—",sub:"unreadable"}:{value:m(q.findings),sub:"this scan",...q.findings>0?{tone:"warn"}:{}}:{value:"—",sub:"no scan yet"};return(0,t.jsxs)("main",{className:"report",children:[(0,t.jsxs)("section",{className:"section set-sec",children:[(0,t.jsxs)("div",{className:"set-mast",children:[(0,t.jsx)("h1",{className:"set-title",children:"settings"}),(0,t.jsx)("p",{className:"set-lede",children:"keeping watch, so you don't have to."})]}),A?(0,t.jsxs)("div",{className:"set-console",children:[(0,t.jsx)("div",{className:"set-cell",children:(0,t.jsxs)("p",{className:"set-warn",children:["could not read this machine's settings. check that the dashboard can reach ",(0,t.jsx)("code",{children:"~/.failproofai/config.json"}),"."]})}),s]}):(0,t.jsxs)("div",{className:"set-console",children:[(0,t.jsxs)("div",{className:"set-stats",children:[(0,t.jsx)(f,{label:"daemon",...z}),(0,t.jsx)(f,{label:"next scan",...G}),(0,t.jsx)(f,{label:"last scan",...Q}),(0,t.jsx)(f,{label:"findings",...X})]}),(0,t.jsxs)("div",{className:"set-cols",children:[(0,t.jsxs)("div",{className:"set-cell set-config",children:[(0,t.jsx)("h2",{className:"set-cell-title",children:"scheduled audit"}),(0,t.jsxs)("div",{className:"set-row set-row-main",children:[(0,t.jsx)(b,{enabled:j,disabled:N||null===x,onChange:()=>void B(),label:j?"turn off scheduled audits":"turn on scheduled audits"}),(0,t.jsxs)("div",{className:"set-row-copy",children:[(0,t.jsx)("span",{className:"set-strong",children:j?"scanning on a schedule.":"scan on a schedule."}),(0,t.jsx)("span",{className:"set-dim",children:j?"you'll get an email only when a scan finds something.":"off. nothing runs and nothing is sent."})]})]}),(0,t.jsxs)("div",{className:"set-row set-row-interval",children:[(0,t.jsx)("span",{className:"set-dim",children:"scan every"}),(0,t.jsx)("input",{type:"number",className:"set-num",min:1,max:90,value:y,disabled:N||null===x,"aria-label":"days between scheduled scans",onChange:e=>k(Number(e.target.value)),onBlur:e=>{let t=Number(e.target.value);Number.isFinite(t)?t!==x?.intervalDays&&K(t):k(x?.intervalDays??7)}}),(0,t.jsx)("span",{className:"set-dim",children:"days"}),(0,t.jsxs)("span",{className:"set-hint",children:[1,"–",90]})]}),(0,t.jsx)("div",{className:"set-rule"}),(0,t.jsx)("div",{className:"set-row set-row-identity",children:U?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("span",{className:"set-dim",children:"reports go to"}),(0,t.jsx)("span",{className:"set-email",children:U.email}),(0,t.jsx)("button",{type:"button",className:"set-link",disabled:N,onClick:()=>void H(),children:"sign out"})]}):j?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("span",{className:"set-warn",children:"signed out — scans continue, digests are paused."}),(0,t.jsx)("button",{type:"button",className:"set-link",disabled:N,onClick:()=>E(!0),children:"sign in to resume"})]}):(0,t.jsx)("span",{className:"set-dim",children:"turning this on asks for an email, so there is somewhere to send the report."})}),j&&x&&!F&&(0,t.jsx)("p",{className:"set-warn",children:O?"the background service isn't available on this platform, so scheduled scans can't run here. you can still run one now.":"not-installed"===x.daemon?"the background service isn't installed, so nothing will run on the timer. install it with `failproofai config`.":"the background service is stopped, so nothing will run until it starts. repair it with `failproofai config`."}),J&&(0,t.jsxs)("p",{className:"set-warn",children:["the last scheduled scan exited ",P?.lastExitCode,". the next one will still run."]}),(0,t.jsx)("div",{className:"set-actions",children:(0,t.jsx)("button",{type:"button",className:"btn btn-press",disabled:C,onClick:()=>void V(),children:C?"[ scanning… ]":"[ run a scan now ]"})})]}),(0,t.jsxs)("div",{className:"set-cell set-how",children:[(0,t.jsx)("h2",{className:"set-cell-title",children:"how it works"}),(0,t.jsx)("dl",{className:"set-how-list",children:p.map(e=>(0,t.jsxs)("div",{className:"set-how-row",children:[(0,t.jsx)("dt",{className:"set-how-label",children:e.label}),(0,t.jsx)("dd",{className:"set-how-body",children:e.body})]},e.label))})]})]}),s]}),j&&D>0&&(0,t.jsx)(v,{lastRunAtMs:P?.lastRunAtMs??null,nextDueAtMs:P?.nextDueAtMs??null,now:D})]}),(0,t.jsx)(o.AuthDialog,{open:$,source:"settings_scheduled_audit",headline:"where should the report go?",subhead:"we'll send a one-time code to confirm.",onClose:()=>E(!1),onAuthed:e=>void Y(e)})]})}],93237)},29054,e=>{"use strict";e.s(["fetchWithTimeout",0,function(e,t={},a=15e3){let s=AbortSignal.timeout(a),n=t.signal?AbortSignal.any([t.signal,s]):s;return fetch(e,{...t,signal:n})},"isAbortError",0,function(e){if(null===e||"object"!=typeof e)return!1;let t=e.name;return"AbortError"===t||"TimeoutError"===t}])},34713,e=>{"use strict";e.s(["formatDuration",0,function(e){if(e<1e3)return`${e}ms`;let t=Math.round(e/100);if(t<600)return`${(t/10).toFixed(1)}s`;let a=Math.round(e/1e3);if(a<3600){let e=Math.floor(a/60);return`${e}m ${a%60}s`}let s=Math.round(e/6e4),n=Math.floor(s/60);return`${n}h ${s%60}m`},"formatRelativeTime",0,function(e){let t=Date.now()-e;return t<6e4?`${Math.max(1,Math.floor(t/1e3))}s ago`:t<36e5?`${Math.floor(t/6e4)}m ago`:t<864e5?`${Math.floor(t/36e5)}h ago`:`${Math.floor(t/864e5)}d ago`}])}]);
|