failproofai 0.0.14-beta.0 → 0.0.14-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/.codex/hooks.json +6 -6
- package/.next/standalone/.cursor/hooks.json +6 -6
- package/.next/standalone/.factory/hooks.json +9 -9
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +5 -5
- 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/build-manifest.json +2 -2
- 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 +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 +2 -2
- 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/_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.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/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/reminder/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/build-manifest.json +2 -2
- 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 +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 +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/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
- 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 +2 -2
- 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/build-manifest.json +2 -2
- 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/build-manifest.json +2 -2
- 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/chunks/[root-of-the-server]__0--lkk6._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-219ec._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__04_h-a5._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06cuf1y._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__08w4wmd._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0g6bbuw._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0jnjf2t._.js +1 -1
- 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]__0q0qzx1._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q2nbsl._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rv7m0k._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xuaoik._.js +3 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__16le-kd._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ffkmds._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fwl2mz._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1legmza._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1mrihkj._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1myjm-d._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qb590j._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qxztj-._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1shcqgr._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1xuedea._.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +4 -4
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +1 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__00cz9as._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__015_i4t._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__030k0c6._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__03lv-pe._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__042d3cd._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__05r_17v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__09q1168._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__07qfsfa._.js → [root-of-the-server]__09v9cwb._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e2l3c1._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h12me5._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0hci7t3._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0hdsupo._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p84xee._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qeuy9c._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s89hoe._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0twi4fj._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ynf7tx._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11rtg6s._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__14dd6h8._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__170799-._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17ai7sy._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1dky4g0._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1nq7ivq._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1tkjqka._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__212nf49._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_05whahf._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1kje4fm._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_087bt9w._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_1fvisnp._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_209u41o._.js +1 -1
- 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 +1 -1
- package/.next/standalone/.next/server/chunks/ssr/lib_0xkhw_v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_html-to-image_es_index_0g5r64e.js → node_modules_html-to-image_es_index_06xsmte.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0-uvagv.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_03c7gi5.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_09p-8om.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0v-kfiu.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0xrgzyz.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_1806lsc.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_1j6dd-e.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_1sa65r-.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1ezd2jf._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1tnuifj._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +5 -5
- 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 +10 -10
- package/.next/standalone/.next/static/chunks/{13f1kmjea-0md.js → 02jcotghcxrbu.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1374x9bv_s_vg.js → 0h-6ymo9v86b0.js} +2 -2
- package/.next/standalone/.next/static/chunks/0pndjhcxfu-0t.js +1 -0
- package/.next/standalone/.next/static/chunks/1-33f82_l32or.js +1 -0
- package/.next/standalone/.next/static/chunks/{003uz088wbmz7.js → 1bg_g3g359c_d.js} +1 -1
- package/.next/standalone/.next/static/chunks/{454dyizqik6t9.js → 1gg-8e9q_m__9.js} +2 -2
- package/.next/standalone/.next/static/chunks/{2ufuwhv03yvtb.js → 29zkom4s9de2d.js} +1 -1
- package/.next/standalone/.next/static/chunks/{17sdztgbcc0fi.js → 2llkdafnaejw_.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0iinhn4417nk1.js → 3-ogr79xqbw0h.js} +1 -1
- package/.next/standalone/.next/static/chunks/36j05kb2x323i.css +2 -0
- package/.next/standalone/.next/static/chunks/{43weu8f59tlix.js → 388hgfqye67xa.js} +1 -1
- package/.next/standalone/.next/static/chunks/396764jgd7-9j.js +1 -0
- package/.next/standalone/.next/static/chunks/3w7g0n0iwwnbs.js +1 -0
- package/.next/standalone/.next/static/chunks/{turbopack-0vavqo2d-tlt3.js → turbopack-10hj8t5pf33tu.js} +1 -1
- package/.next/standalone/.opencode/plugins/failproofai.mjs +30 -11
- package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +11 -2
- package/.next/standalone/app/components/copy-button.tsx +22 -6
- package/.next/standalone/app/components/global-error-listeners.tsx +27 -0
- package/.next/standalone/components/reach-developers.tsx +1 -1
- package/.next/standalone/docker-hook-sync/Dockerfile +8 -4
- package/.next/standalone/integration-suite/Dockerfile +47 -0
- package/.next/standalone/integration-suite/README.md +87 -0
- package/.next/standalone/integration-suite/canary-policies.mjs +45 -0
- package/.next/standalone/integration-suite/capture-tokens.sh +48 -0
- package/.next/standalone/integration-suite/ci-entrypoint.sh +164 -0
- package/.next/standalone/integration-suite/inject-tokens.sh +44 -0
- package/.next/standalone/integration-suite/install-clis.sh +91 -0
- package/.next/standalone/integration-suite/probe-cli.sh +208 -0
- package/.next/standalone/integration-suite/report.js +74 -0
- package/.next/standalone/integration-suite/run.sh +107 -0
- package/.next/standalone/lib/error-origin.ts +67 -0
- package/.next/standalone/lib/format-duration.ts +23 -9
- package/.next/standalone/lib/install-check.ts +231 -0
- package/.next/standalone/package.json +1 -3
- package/.next/standalone/server.js +1 -1
- package/README.md +1 -17
- package/bin/failproofai.mjs +11 -1
- package/dist/cli.mjs +818 -320
- package/lib/error-origin.ts +67 -0
- package/lib/format-duration.ts +23 -9
- package/lib/install-check.ts +231 -0
- package/package.json +1 -3
- package/scripts/dev-hook.mjs +292 -0
- package/scripts/install-diagnosis.mjs +5 -8
- package/scripts/install-telemetry.mjs +12 -4
- package/scripts/translate-docs/cli.ts +53 -1
- package/scripts/translate-docs/mdx-translator.ts +158 -18
- package/scripts/translate-docs/readme-translator.ts +36 -18
- package/scripts/translate-docs/translator.ts +180 -9
- package/scripts/translate-docs/types.ts +6 -0
- package/scripts/translate-docs/validate-translation.ts +132 -0
- package/scripts/validate-mdx.ts +92 -15
- package/src/audit/cli.ts +53 -15
- package/src/auth/cli.ts +14 -5
- package/src/hooks/builtin-policies.ts +168 -50
- package/src/hooks/configure-wizard.ts +238 -22
- package/src/hooks/custom-hooks-loader.ts +70 -4
- package/src/hooks/handler.ts +4 -1
- package/src/hooks/policy-types.ts +8 -0
- package/src/hooks/tui.ts +96 -29
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ge8e7w._.js +0 -3
- package/.next/standalone/.next/static/chunks/0405htbxay9vd.js +0 -1
- package/.next/standalone/.next/static/chunks/2m_tbl39fcedn.js +0 -1
- package/.next/standalone/.next/static/chunks/2o3ql0n5owqsw.js +0 -1
- package/.next/standalone/.next/static/chunks/35-90m9py64d4.js +0 -1
- package/.next/standalone/.next/static/chunks/3r--yyjkp9_7b.css +0 -2
- package/scripts/postinstall.mjs +0 -242
- package/scripts/preuninstall.mjs +0 -131
- /package/.next/standalone/.next/static/{MNJWFb2jLRrxRKGFNK6Hy → YKxI22hC-F_nHp7MEKfb1}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{MNJWFb2jLRrxRKGFNK6Hy → YKxI22hC-F_nHp7MEKfb1}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{MNJWFb2jLRrxRKGFNK6Hy → YKxI22hC-F_nHp7MEKfb1}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,{otherChunks:["static/chunks/0zbxssxh53n-3.js","static/chunks/1__i9af9g78vd.js","static/chunks/13f1kmjea-0md.js","static/chunks/1ua5armwfph8o.js","static/chunks/03fmihek9n986.js"],runtimeModuleIds:[94553]}]),(()=>{let e;if(!Array.isArray(globalThis.TURBOPACK))return;let t="/_next/",r=function(){if(null!=self.TURBOPACK_ASSET_SUFFIX)return self.TURBOPACK_ASSET_SUFFIX;let e=document?.currentScript?.getAttribute?.("src")??"",t=e.indexOf("?");return t>=0?e.slice(t):""}(),n=["NEXT_DEPLOYMENT_ID","NEXT_CLIENT_ASSET_SUFFIX"];var o,i=((o=i||{})[o.Runtime=0]="Runtime",o[o.Parent=1]="Parent",o[o.Update=2]="Update",o);let l=new WeakMap;function s(e,t){this.m=e,this.e=t}let u=s.prototype,a=Object.prototype.hasOwnProperty,c="u">typeof Symbol&&Symbol.toStringTag;function f(e,t,r){a.call(e,t)||Object.defineProperty(e,t,r)}function p(e,t){let r=e[t];return r||(r=h(t),e[t]=r),r}function h(e){return{exports:{},error:void 0,id:e,namespaceObject:void 0}}function d(e,t){f(e,"__esModule",{value:!0}),c&&f(e,c,{value:"Module"});let r=0;for(;r<t.length;){let n=t[r++],o=t[r++];if("number"==typeof o)if(0===o)f(e,n,{value:t[r++],enumerable:!0,writable:!1});else throw Error(`unexpected tag: ${o}`);else"function"==typeof t[r]?f(e,n,{get:o,set:t[r++],enumerable:!0}):f(e,n,{get:o,enumerable:!0})}Object.seal(e)}function m(e,t){(null!=t?p(this.c,t):this.m).exports=e}u.s=function(e,t){let r,n;null!=t?n=(r=p(this.c,t)).exports:(r=this.m,n=this.e),r.namespaceObject=n,d(n,e)},u.j=function(e,t){var r,n;let o,i,s;null!=t?i=(o=p(this.c,t)).exports:(o=this.m,i=this.e);let u=(r=o,n=i,(s=l.get(r))||(l.set(r,s=[]),r.exports=r.namespaceObject=new Proxy(n,{get(e,t){if(a.call(e,t)||"default"===t||"__esModule"===t)return Reflect.get(e,t);for(let e of s){let r=Reflect.get(e,t);if(void 0!==r)return r}},ownKeys(e){let t=Reflect.ownKeys(e);for(let e of s)for(let r of Reflect.ownKeys(e))"default"===r||t.includes(r)||t.push(r);return t}})),s);"object"==typeof e&&null!==e&&u.push(e)},u.v=m,u.n=function(e,t){let r;(r=null!=t?p(this.c,t):this.m).exports=r.namespaceObject=e};let b=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,y=[null,b({}),b([]),b(b)];function g(e,t,r){let n=[],o=-1;for(let t=e;("object"==typeof t||"function"==typeof t)&&!y.includes(t);t=b(t))for(let r of Object.getOwnPropertyNames(t))n.push(r,function(e,t){return()=>e[t]}(e,r)),-1===o&&"default"===r&&(o=n.length-1);return r&&o>=0||(o>=0?n.splice(o,1,0,e):n.push("default",0,e)),d(t,n),t}function O(e){let t=B(e,this.m);if(t.namespaceObject)return t.namespaceObject;let r=t.exports;return t.namespaceObject=g(r,"function"==typeof r?function(...e){return r.apply(this,e)}:Object.create(null),r&&r.__esModule)}function w(e){let t=e.indexOf("#");-1!==t&&(e=e.substring(0,t));let r=e.indexOf("?");return -1!==r&&(e=e.substring(0,r)),e}function k(){let e,t;return{promise:new Promise((r,n)=>{t=n,e=r}),resolve:e,reject:t}}u.i=O,u.A=function(e){return this.r(e)(O.bind(this))},u.t="function"==typeof require?require:function(){throw Error("Unexpected use of runtime require")},u.r=function(e){return B(e,this.m).exports},u.f=function(e){function t(t){if(t=w(t),a.call(e,t))return e[t].module();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r}return t.keys=()=>Object.keys(e),t.resolve=t=>{if(t=w(t),a.call(e,t))return e[t].id();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r},t.import=async e=>await t(e),t};let j=Symbol("turbopack queues"),U=Symbol("turbopack exports"),v=Symbol("turbopack error");function C(e){e&&1!==e.status&&(e.status=1,e.forEach(e=>e.queueCount--),e.forEach(e=>e.queueCount--?e.queueCount++:e()))}u.a=function(e,t){let r=this.m,n=t?Object.assign([],{status:-1}):void 0,o=new Set,{resolve:i,reject:l,promise:s}=k(),u=Object.assign(s,{[U]:r.exports,[j]:e=>{n&&e(n),o.forEach(e),u.catch(()=>{})}}),a={get:()=>u,set(e){e!==u&&(u[U]=e)}};Object.defineProperty(r,"exports",a),Object.defineProperty(r,"namespaceObject",a),e(function(e){let t=e.map(e=>{if(null!==e&&"object"==typeof e){if(j in e)return e;if(null!=e&&"object"==typeof e&&"then"in e&&"function"==typeof e.then){let t=Object.assign([],{status:0}),r={[U]:{},[j]:e=>e(t)};return e.then(e=>{r[U]=e,C(t)},e=>{r[v]=e,C(t)}),r}}return{[U]:e,[j]:()=>{}}}),r=()=>t.map(e=>{if(e[v])throw e[v];return e[U]}),{promise:i,resolve:l}=k(),s=Object.assign(()=>l(r),{queueCount:0});function u(e){e!==n&&!o.has(e)&&(o.add(e),e&&0===e.status&&(s.queueCount++,e.push(s)))}return t.map(e=>e[j](u)),s.queueCount?i:r()},function(e){e?l(u[v]=e):i(u[U]),C(n)}),n&&-1===n.status&&(n.status=0)};let P=function(e){let t=new URL(e,"x:/"),r={};for(let e in t)r[e]=t[e];for(let t in r.href=e,r.pathname=e.replace(/[?#].*/,""),r.origin=r.protocol="",r.toString=r.toJSON=(...t)=>e,r)Object.defineProperty(this,t,{enumerable:!0,configurable:!0,value:r[t]})};function R(e,t){throw Error(`Invariant: ${t(e)}`)}P.prototype=URL.prototype,u.U=P,u.z=function(e){throw Error("dynamic usage of require is not supported")},u.g=globalThis;let S=s.prototype,$=new Map;u.M=$;let _=new Map,E=new Map;async function T(e,t,r){let n;if("string"==typeof r)return M(e,t,N(r));let o=r.included||[],i=o.map(e=>!!$.has(e)||_.get(e));if(i.length>0&&i.every(e=>e))return void await Promise.all(i);let l=r.moduleChunks||[],s=l.map(e=>E.get(e)).filter(e=>e);if(s.length>0){if(s.length===l.length)return void await Promise.all(s);let r=new Set;for(let e of l)E.has(e)||r.add(e);for(let n of r){let r=M(e,t,N(n));E.set(n,r),s.push(r)}n=Promise.all(s)}else{for(let o of(n=M(e,t,N(r.path)),l))E.has(o)||E.set(o,n)}for(let e of o)_.has(e)||_.set(e,n);await n}S.l=function(e){return T(i.Parent,this.m.id,e)};let A=Promise.resolve(void 0),x=new WeakMap;function M(t,r,n){let o=e.loadChunkCached(t,n),l=x.get(o);if(void 0===l){let e=x.set.bind(x,o,A);l=o.then(e).catch(e=>{let o;switch(t){case i.Runtime:o=`as a runtime dependency of chunk ${r}`;break;case i.Parent:o=`from module ${r}`;break;case i.Update:o="from an HMR update";break;default:R(t,e=>`Unknown source type: ${e}`)}let l=Error(`Failed to load chunk ${n} ${o}${e?`: ${e}`:""}`,e?{cause:e}:void 0);throw l.name="ChunkLoadError",l}),x.set(o,l)}return l}function N(e){return`${t}${e.split("/").map(e=>encodeURIComponent(e)).join("/")}${r}`}S.L=function(e){return M(i.Parent,this.m.id,e)},S.R=function(e){let t=this.r(e);return t?.default??t},S.P=function(e){return`/ROOT/${e??""}`},S.q=function(e,t){m.call(this,`${e}${r}`,t)},S.b=function(e,t,o,i){let l="SharedWorker"===e.name,s=[o.map(e=>N(e)).reverse(),r];for(let e of n)s.push(globalThis[e]);let u=new URL(N(t),location.origin),a=JSON.stringify(s);return l?u.searchParams.set("params",a):u.hash="#params="+encodeURIComponent(a),new e(u,i?{...i,type:void 0}:void 0)};let K=/\.js(?:\?[^#]*)?(?:#.*)?$/,q=/\.css(?:\?[^#]*)?(?:#.*)?$/;function L(e){return q.test(e)}u.w=function(t,r,n){return e.loadWebAssembly(i.Parent,this.m.id,t,r,n)},u.u=function(t,r){return e.loadWebAssemblyModule(i.Parent,this.m.id,t,r)};let I={};u.c=I;let B=(e,t)=>{let r=I[e];if(r){if(r.error)throw r.error;return r}return W(e,i.Parent,t.id)};function W(e,t,r){let n=$.get(e);if("function"!=typeof n)throw Error(function(e,t,r){let n;switch(t){case 0:n=`as a runtime entry of chunk ${r}`;break;case 1:n=`because it was required from module ${r}`;break;case 2:n="because of an HMR update";break;default:R(t,e=>`Unknown source type: ${e}`)}return`Module ${e} was instantiated ${n}, but the module factory is not available.`}(e,t,r));let o=h(e),i=o.exports;I[e]=o;let l=new s(o,i);try{n(l,o,i)}catch(e){throw o.error=e,e}return o.namespaceObject&&o.exports!==o.namespaceObject&&g(o.exports,o.namespaceObject),o}function F(t){let r,n=function(e){if("string"==typeof e)return e;if(e)return{src:e.getAttribute("src")};if("u">typeof TURBOPACK_NEXT_CHUNK_URLS)return{src:TURBOPACK_NEXT_CHUNK_URLS.pop()};throw Error("chunk path empty but not in a worker")}(t[0]);return 2===t.length?r=t[1]:(r=void 0,!function(e,t){let r=1;for(;r<e.length;){let n,o=r+1;for(;o<e.length&&"function"!=typeof e[o];)o++;if(o===e.length)throw Error("malformed chunk format, expected a factory function");let i=e[o];for(let i=r;i<o;i++){let r=e[i],o=t.get(r);if(o){n=o;break}}let l=n??i,s=!1;for(let n=r;n<o;n++){let r=e[n];t.has(r)||(s||(l===i&&Object.defineProperty(i,"name",{value:"module evaluation"}),s=!0),t.set(r,l))}r=o+1}}(t,$)),e.registerChunk(n,r)}let X=new Map;function D(e){let t=X.get(e);if(!t){let r,n;t={resolved:!1,loadingStarted:!1,promise:new Promise((e,t)=>{r=e,n=t}),resolve:()=>{t.resolved=!0,r()},reject:n},X.set(e,t)}return t}e={async registerChunk(e,r){let n=function(e){if("string"==typeof e)return e;let r=decodeURIComponent(e.src.replace(/[?#].*$/,""));return r.startsWith(t)?r.slice(t.length):r}(e);if(D("string"==typeof e?N(e):e.src).resolve(),null!=r){for(let e of r.otherChunks)D(N("string"==typeof e?e:e.path));if(await Promise.all(r.otherChunks.map(e=>T(i.Runtime,n,e))),r.runtimeModuleIds.length>0)for(let e of r.runtimeModuleIds)!function(e,t){let r=I[t];if(r){if(r.error)throw r.error;return}W(t,i.Runtime,e)}(n,e)}},loadChunkCached:(e,t)=>(function(e,t){let r=D(t);if(r.loadingStarted)return r.promise;if(e===i.Runtime)return r.loadingStarted=!0,L(t)&&r.resolve(),r.promise;if("function"==typeof importScripts)if(L(t));else if(K.test(t))self.TURBOPACK_NEXT_CHUNK_URLS.push(t),importScripts(t);else throw Error(`can't infer type of chunk from URL ${t} in worker`);else{let e=decodeURI(t);if(L(t))if(document.querySelectorAll(`link[rel=stylesheet][href="${t}"],link[rel=stylesheet][href^="${t}?"],link[rel=stylesheet][href="${e}"],link[rel=stylesheet][href^="${e}?"]`).length>0)r.resolve();else{let e=document.createElement("link");e.rel="stylesheet",e.href=t,e.onerror=()=>{r.reject()},e.onload=()=>{r.resolve()},document.head.appendChild(e)}else if(K.test(t)){let n=document.querySelectorAll(`script[src="${t}"],script[src^="${t}?"],script[src="${e}"],script[src^="${e}?"]`);if(n.length>0)for(let e of Array.from(n))e.addEventListener("error",()=>{r.reject()});else{let e=document.createElement("script");e.src=t,e.onerror=()=>{r.reject()},document.head.appendChild(e)}}else throw Error(`can't infer type of chunk from URL ${t}`)}return r.loadingStarted=!0,r.promise})(e,t),async loadWebAssembly(e,t,r,n,o){let i=fetch(N(r)),{instance:l}=await WebAssembly.instantiateStreaming(i,o);return l.exports},async loadWebAssemblyModule(e,t,r,n){let o=fetch(N(r));return await WebAssembly.compileStreaming(o)}};let H=globalThis.TURBOPACK;globalThis.TURBOPACK={push:F},H.forEach(F)})();
|
|
1
|
+
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,{otherChunks:["static/chunks/0zbxssxh53n-3.js","static/chunks/1__i9af9g78vd.js","static/chunks/02jcotghcxrbu.js","static/chunks/1ua5armwfph8o.js","static/chunks/03fmihek9n986.js"],runtimeModuleIds:[94553]}]),(()=>{let e;if(!Array.isArray(globalThis.TURBOPACK))return;let t="/_next/",r=function(){if(null!=self.TURBOPACK_ASSET_SUFFIX)return self.TURBOPACK_ASSET_SUFFIX;let e=document?.currentScript?.getAttribute?.("src")??"",t=e.indexOf("?");return t>=0?e.slice(t):""}(),n=["NEXT_DEPLOYMENT_ID","NEXT_CLIENT_ASSET_SUFFIX"];var o,i=((o=i||{})[o.Runtime=0]="Runtime",o[o.Parent=1]="Parent",o[o.Update=2]="Update",o);let l=new WeakMap;function s(e,t){this.m=e,this.e=t}let u=s.prototype,a=Object.prototype.hasOwnProperty,c="u">typeof Symbol&&Symbol.toStringTag;function f(e,t,r){a.call(e,t)||Object.defineProperty(e,t,r)}function p(e,t){let r=e[t];return r||(r=h(t),e[t]=r),r}function h(e){return{exports:{},error:void 0,id:e,namespaceObject:void 0}}function d(e,t){f(e,"__esModule",{value:!0}),c&&f(e,c,{value:"Module"});let r=0;for(;r<t.length;){let n=t[r++],o=t[r++];if("number"==typeof o)if(0===o)f(e,n,{value:t[r++],enumerable:!0,writable:!1});else throw Error(`unexpected tag: ${o}`);else"function"==typeof t[r]?f(e,n,{get:o,set:t[r++],enumerable:!0}):f(e,n,{get:o,enumerable:!0})}Object.seal(e)}function m(e,t){(null!=t?p(this.c,t):this.m).exports=e}u.s=function(e,t){let r,n;null!=t?n=(r=p(this.c,t)).exports:(r=this.m,n=this.e),r.namespaceObject=n,d(n,e)},u.j=function(e,t){var r,n;let o,i,s;null!=t?i=(o=p(this.c,t)).exports:(o=this.m,i=this.e);let u=(r=o,n=i,(s=l.get(r))||(l.set(r,s=[]),r.exports=r.namespaceObject=new Proxy(n,{get(e,t){if(a.call(e,t)||"default"===t||"__esModule"===t)return Reflect.get(e,t);for(let e of s){let r=Reflect.get(e,t);if(void 0!==r)return r}},ownKeys(e){let t=Reflect.ownKeys(e);for(let e of s)for(let r of Reflect.ownKeys(e))"default"===r||t.includes(r)||t.push(r);return t}})),s);"object"==typeof e&&null!==e&&u.push(e)},u.v=m,u.n=function(e,t){let r;(r=null!=t?p(this.c,t):this.m).exports=r.namespaceObject=e};let b=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,y=[null,b({}),b([]),b(b)];function g(e,t,r){let n=[],o=-1;for(let t=e;("object"==typeof t||"function"==typeof t)&&!y.includes(t);t=b(t))for(let r of Object.getOwnPropertyNames(t))n.push(r,function(e,t){return()=>e[t]}(e,r)),-1===o&&"default"===r&&(o=n.length-1);return r&&o>=0||(o>=0?n.splice(o,1,0,e):n.push("default",0,e)),d(t,n),t}function O(e){let t=B(e,this.m);if(t.namespaceObject)return t.namespaceObject;let r=t.exports;return t.namespaceObject=g(r,"function"==typeof r?function(...e){return r.apply(this,e)}:Object.create(null),r&&r.__esModule)}function w(e){let t=e.indexOf("#");-1!==t&&(e=e.substring(0,t));let r=e.indexOf("?");return -1!==r&&(e=e.substring(0,r)),e}function j(){let e,t;return{promise:new Promise((r,n)=>{t=n,e=r}),resolve:e,reject:t}}u.i=O,u.A=function(e){return this.r(e)(O.bind(this))},u.t="function"==typeof require?require:function(){throw Error("Unexpected use of runtime require")},u.r=function(e){return B(e,this.m).exports},u.f=function(e){function t(t){if(t=w(t),a.call(e,t))return e[t].module();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r}return t.keys=()=>Object.keys(e),t.resolve=t=>{if(t=w(t),a.call(e,t))return e[t].id();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r},t.import=async e=>await t(e),t};let k=Symbol("turbopack queues"),U=Symbol("turbopack exports"),v=Symbol("turbopack error");function C(e){e&&1!==e.status&&(e.status=1,e.forEach(e=>e.queueCount--),e.forEach(e=>e.queueCount--?e.queueCount++:e()))}u.a=function(e,t){let r=this.m,n=t?Object.assign([],{status:-1}):void 0,o=new Set,{resolve:i,reject:l,promise:s}=j(),u=Object.assign(s,{[U]:r.exports,[k]:e=>{n&&e(n),o.forEach(e),u.catch(()=>{})}}),a={get:()=>u,set(e){e!==u&&(u[U]=e)}};Object.defineProperty(r,"exports",a),Object.defineProperty(r,"namespaceObject",a),e(function(e){let t=e.map(e=>{if(null!==e&&"object"==typeof e){if(k in e)return e;if(null!=e&&"object"==typeof e&&"then"in e&&"function"==typeof e.then){let t=Object.assign([],{status:0}),r={[U]:{},[k]:e=>e(t)};return e.then(e=>{r[U]=e,C(t)},e=>{r[v]=e,C(t)}),r}}return{[U]:e,[k]:()=>{}}}),r=()=>t.map(e=>{if(e[v])throw e[v];return e[U]}),{promise:i,resolve:l}=j(),s=Object.assign(()=>l(r),{queueCount:0});function u(e){e!==n&&!o.has(e)&&(o.add(e),e&&0===e.status&&(s.queueCount++,e.push(s)))}return t.map(e=>e[k](u)),s.queueCount?i:r()},function(e){e?l(u[v]=e):i(u[U]),C(n)}),n&&-1===n.status&&(n.status=0)};let P=function(e){let t=new URL(e,"x:/"),r={};for(let e in t)r[e]=t[e];for(let t in r.href=e,r.pathname=e.replace(/[?#].*/,""),r.origin=r.protocol="",r.toString=r.toJSON=(...t)=>e,r)Object.defineProperty(this,t,{enumerable:!0,configurable:!0,value:r[t]})};function R(e,t){throw Error(`Invariant: ${t(e)}`)}P.prototype=URL.prototype,u.U=P,u.z=function(e){throw Error("dynamic usage of require is not supported")},u.g=globalThis;let S=s.prototype,$=new Map;u.M=$;let _=new Map,E=new Map;async function T(e,t,r){let n;if("string"==typeof r)return M(e,t,N(r));let o=r.included||[],i=o.map(e=>!!$.has(e)||_.get(e));if(i.length>0&&i.every(e=>e))return void await Promise.all(i);let l=r.moduleChunks||[],s=l.map(e=>E.get(e)).filter(e=>e);if(s.length>0){if(s.length===l.length)return void await Promise.all(s);let r=new Set;for(let e of l)E.has(e)||r.add(e);for(let n of r){let r=M(e,t,N(n));E.set(n,r),s.push(r)}n=Promise.all(s)}else{for(let o of(n=M(e,t,N(r.path)),l))E.has(o)||E.set(o,n)}for(let e of o)_.has(e)||_.set(e,n);await n}S.l=function(e){return T(i.Parent,this.m.id,e)};let x=Promise.resolve(void 0),A=new WeakMap;function M(t,r,n){let o=e.loadChunkCached(t,n),l=A.get(o);if(void 0===l){let e=A.set.bind(A,o,x);l=o.then(e).catch(e=>{let o;switch(t){case i.Runtime:o=`as a runtime dependency of chunk ${r}`;break;case i.Parent:o=`from module ${r}`;break;case i.Update:o="from an HMR update";break;default:R(t,e=>`Unknown source type: ${e}`)}let l=Error(`Failed to load chunk ${n} ${o}${e?`: ${e}`:""}`,e?{cause:e}:void 0);throw l.name="ChunkLoadError",l}),A.set(o,l)}return l}function N(e){return`${t}${e.split("/").map(e=>encodeURIComponent(e)).join("/")}${r}`}S.L=function(e){return M(i.Parent,this.m.id,e)},S.R=function(e){let t=this.r(e);return t?.default??t},S.P=function(e){return`/ROOT/${e??""}`},S.q=function(e,t){m.call(this,`${e}${r}`,t)},S.b=function(e,t,o,i){let l="SharedWorker"===e.name,s=[o.map(e=>N(e)).reverse(),r];for(let e of n)s.push(globalThis[e]);let u=new URL(N(t),location.origin),a=JSON.stringify(s);return l?u.searchParams.set("params",a):u.hash="#params="+encodeURIComponent(a),new e(u,i?{...i,type:void 0}:void 0)};let K=/\.js(?:\?[^#]*)?(?:#.*)?$/,q=/\.css(?:\?[^#]*)?(?:#.*)?$/;function L(e){return q.test(e)}u.w=function(t,r,n){return e.loadWebAssembly(i.Parent,this.m.id,t,r,n)},u.u=function(t,r){return e.loadWebAssemblyModule(i.Parent,this.m.id,t,r)};let I={};u.c=I;let B=(e,t)=>{let r=I[e];if(r){if(r.error)throw r.error;return r}return W(e,i.Parent,t.id)};function W(e,t,r){let n=$.get(e);if("function"!=typeof n)throw Error(function(e,t,r){let n;switch(t){case 0:n=`as a runtime entry of chunk ${r}`;break;case 1:n=`because it was required from module ${r}`;break;case 2:n="because of an HMR update";break;default:R(t,e=>`Unknown source type: ${e}`)}return`Module ${e} was instantiated ${n}, but the module factory is not available.`}(e,t,r));let o=h(e),i=o.exports;I[e]=o;let l=new s(o,i);try{n(l,o,i)}catch(e){throw o.error=e,e}return o.namespaceObject&&o.exports!==o.namespaceObject&&g(o.exports,o.namespaceObject),o}function F(t){let r,n=function(e){if("string"==typeof e)return e;if(e)return{src:e.getAttribute("src")};if("u">typeof TURBOPACK_NEXT_CHUNK_URLS)return{src:TURBOPACK_NEXT_CHUNK_URLS.pop()};throw Error("chunk path empty but not in a worker")}(t[0]);return 2===t.length?r=t[1]:(r=void 0,!function(e,t){let r=1;for(;r<e.length;){let n,o=r+1;for(;o<e.length&&"function"!=typeof e[o];)o++;if(o===e.length)throw Error("malformed chunk format, expected a factory function");let i=e[o];for(let i=r;i<o;i++){let r=e[i],o=t.get(r);if(o){n=o;break}}let l=n??i,s=!1;for(let n=r;n<o;n++){let r=e[n];t.has(r)||(s||(l===i&&Object.defineProperty(i,"name",{value:"module evaluation"}),s=!0),t.set(r,l))}r=o+1}}(t,$)),e.registerChunk(n,r)}let X=new Map;function D(e){let t=X.get(e);if(!t){let r,n;t={resolved:!1,loadingStarted:!1,promise:new Promise((e,t)=>{r=e,n=t}),resolve:()=>{t.resolved=!0,r()},reject:n},X.set(e,t)}return t}e={async registerChunk(e,r){let n=function(e){if("string"==typeof e)return e;let r=decodeURIComponent(e.src.replace(/[?#].*$/,""));return r.startsWith(t)?r.slice(t.length):r}(e);if(D("string"==typeof e?N(e):e.src).resolve(),null!=r){for(let e of r.otherChunks)D(N("string"==typeof e?e:e.path));if(await Promise.all(r.otherChunks.map(e=>T(i.Runtime,n,e))),r.runtimeModuleIds.length>0)for(let e of r.runtimeModuleIds)!function(e,t){let r=I[t];if(r){if(r.error)throw r.error;return}W(t,i.Runtime,e)}(n,e)}},loadChunkCached:(e,t)=>(function(e,t){let r=D(t);if(r.loadingStarted)return r.promise;if(e===i.Runtime)return r.loadingStarted=!0,L(t)&&r.resolve(),r.promise;if("function"==typeof importScripts)if(L(t));else if(K.test(t))self.TURBOPACK_NEXT_CHUNK_URLS.push(t),importScripts(t);else throw Error(`can't infer type of chunk from URL ${t} in worker`);else{let e=decodeURI(t);if(L(t))if(document.querySelectorAll(`link[rel=stylesheet][href="${t}"],link[rel=stylesheet][href^="${t}?"],link[rel=stylesheet][href="${e}"],link[rel=stylesheet][href^="${e}?"]`).length>0)r.resolve();else{let e=document.createElement("link");e.rel="stylesheet",e.href=t,e.onerror=()=>{r.reject()},e.onload=()=>{r.resolve()},document.head.appendChild(e)}else if(K.test(t)){let n=document.querySelectorAll(`script[src="${t}"],script[src^="${t}?"],script[src="${e}"],script[src^="${e}?"]`);if(n.length>0)for(let e of Array.from(n))e.addEventListener("error",()=>{r.reject()});else{let e=document.createElement("script");e.src=t,e.onerror=()=>{r.reject()},document.head.appendChild(e)}}else throw Error(`can't infer type of chunk from URL ${t}`)}return r.loadingStarted=!0,r.promise})(e,t),async loadWebAssembly(e,t,r,n,o){let i=fetch(N(r)),{instance:l}=await WebAssembly.instantiateStreaming(i,o);return l.exports},async loadWebAssemblyModule(e,t,r,n){let o=fetch(N(r));return await WebAssembly.compileStreaming(o)}};let H=globalThis.TURBOPACK;globalThis.TURBOPACK={push:F},H.forEach(F)})();
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
// AUTO-GENERATED by failproofai. __failproofai_hook__
|
|
2
2
|
// Re-generate via: failproofai policies --install --cli opencode
|
|
3
3
|
//
|
|
4
|
-
// DEV variant: this repo's contributors run failproofai from source via
|
|
5
|
-
// `
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
4
|
+
// DEV variant: this repo's contributors run failproofai from source, via
|
|
5
|
+
// the shared `scripts/dev-hook.mjs` resolver rather than `npx -y failproofai`.
|
|
6
|
+
// That resolver locates bun across PATH, $BUN_INSTALL/bin, ~/.bun/bin, Homebrew
|
|
7
|
+
// and every nvm version dir — a bare `spawnSync("bun")` silently fails open the
|
|
8
|
+
// moment bun is off the hook's PATH. The production shape (npx-based) is
|
|
9
|
+
// generated by `src/hooks/integrations.ts` on install for end users — see
|
|
10
|
+
// `buildOpenCodePluginShim` there.
|
|
9
11
|
//
|
|
10
12
|
// Do NOT install this repo via `failproofai policies --install --cli
|
|
11
13
|
// opencode --scope project` — it would overwrite this dev path with the
|
|
@@ -17,10 +19,7 @@
|
|
|
17
19
|
// When #337 landed, this dev shim drifted and `block-read-outside-cwd`
|
|
18
20
|
// silently no-op'd on every opencode `read` call inside this repo.
|
|
19
21
|
import { spawnSync } from "node:child_process";
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
const REPO_ROOT = resolve(import.meta.dirname, "..", "..");
|
|
23
|
-
const FAILPROOFAI_DEV_BIN = resolve(REPO_ROOT, "bin", "failproofai.mjs");
|
|
22
|
+
import { resolveDevSpawn } from "../../scripts/dev-hook.mjs";
|
|
24
23
|
|
|
25
24
|
const BUS_EVENT_MAP = {
|
|
26
25
|
"session.created": "SessionStart",
|
|
@@ -72,13 +71,33 @@ function canonicalizeToolInput(canonicalToolName, args) {
|
|
|
72
71
|
}
|
|
73
72
|
|
|
74
73
|
function runFailproofai(eventName, payload, directory) {
|
|
75
|
-
|
|
74
|
+
// Shared with the JSON configs' launcher: locates bun across PATH, ~/.bun/bin,
|
|
75
|
+
// $BUN_INSTALL, Homebrew and every nvm version dir. A bare spawnSync("bun")
|
|
76
|
+
// dies with ENOENT the moment bun is off the hook's PATH.
|
|
77
|
+
const spawn = resolveDevSpawn();
|
|
78
|
+
if (!spawn) {
|
|
79
|
+
process.stderr.write(
|
|
80
|
+
"[failproofai-dev] bun not found — opencode policies are NOT enforcing. " +
|
|
81
|
+
"Install bun: curl -fsSL https://bun.sh/install | bash\n",
|
|
82
|
+
);
|
|
83
|
+
return { exitCode: 0, stdout: "", stderr: "" };
|
|
84
|
+
}
|
|
85
|
+
const r = spawnSync(spawn.cmd, [...spawn.args, "--hook", eventName, "--cli", "opencode"], {
|
|
76
86
|
input: JSON.stringify(payload),
|
|
77
87
|
encoding: "utf8",
|
|
78
88
|
timeout: 60_000,
|
|
79
89
|
cwd: directory,
|
|
80
90
|
});
|
|
81
|
-
|
|
91
|
+
// `r.status` is null when the spawn never ran (ENOENT) or the child was
|
|
92
|
+
// killed. Coercing that to 0 reports "allowed" for a policy that never got
|
|
93
|
+
// to run, so say so on stderr rather than failing open in silence.
|
|
94
|
+
if (r.status === null) {
|
|
95
|
+
process.stderr.write(
|
|
96
|
+
`[failproofai-dev] ${eventName} hook did not run (${r.error?.code ?? r.signal ?? "unknown"}) — not enforcing\n`,
|
|
97
|
+
);
|
|
98
|
+
return { exitCode: 0, stdout: "", stderr: "" };
|
|
99
|
+
}
|
|
100
|
+
return { exitCode: r.status, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
|
|
82
101
|
}
|
|
83
102
|
|
|
84
103
|
async function applyDecision(result, ctx, eventName) {
|
|
@@ -84,10 +84,19 @@ function buildFixes(result: AuditResult): FixRow[] {
|
|
|
84
84
|
}));
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
/**
|
|
88
|
+
* The "install all" command.
|
|
89
|
+
*
|
|
90
|
+
* `policy add` and `policies --install` are DIFFERENT commands, not aliases:
|
|
91
|
+
* `policy add` enables exactly one policy and rejects a second name outright
|
|
92
|
+
* ("`policy add` takes exactly one policy name"). This button is almost always
|
|
93
|
+
* multi-policy — listing the gaps is the section's whole job — so it must use
|
|
94
|
+
* the plural form, which is the one that accepts a list. Using `policy add`
|
|
95
|
+
* here handed the user a command that errored on paste.
|
|
96
|
+
*/
|
|
87
97
|
function bulkInstall(fixes: FixRow[]): string {
|
|
88
98
|
if (fixes.length === 0) return "";
|
|
89
|
-
|
|
90
|
-
return `failproofai policy add ${fixes.map((f) => f.name).join(" ")}`;
|
|
99
|
+
return `failproofai policies --install ${fixes.map((f) => f.name).join(" ")}`;
|
|
91
100
|
}
|
|
92
101
|
|
|
93
102
|
export function HowToImproveSection({ result, projected, projectedGrade }: Props) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useState, useCallback } from "react";
|
|
3
|
+
import { useState, useCallback, useEffect, useRef } from "react";
|
|
4
4
|
import { Copy, Check } from "lucide-react";
|
|
5
5
|
import { cn } from "@/lib/utils";
|
|
6
6
|
|
|
@@ -25,6 +25,23 @@ interface CopyButtonProps {
|
|
|
25
25
|
|
|
26
26
|
export function CopyButton({ text, className }: CopyButtonProps) {
|
|
27
27
|
const [copied, setCopied] = useState(false);
|
|
28
|
+
const revertTimerRef = useRef<ReturnType<typeof setTimeout>>(undefined);
|
|
29
|
+
|
|
30
|
+
// Clear any pending revert timer on unmount so `setCopied` never fires
|
|
31
|
+
// after the component is gone.
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
return () => {
|
|
34
|
+
if (revertTimerRef.current) clearTimeout(revertTimerRef.current);
|
|
35
|
+
};
|
|
36
|
+
}, []);
|
|
37
|
+
|
|
38
|
+
const armRevertTimer = useCallback(() => {
|
|
39
|
+
// A re-click resets the 2s window rather than being cut short by the
|
|
40
|
+
// previous (stale) timer.
|
|
41
|
+
if (revertTimerRef.current) clearTimeout(revertTimerRef.current);
|
|
42
|
+
setCopied(true);
|
|
43
|
+
revertTimerRef.current = setTimeout(() => setCopied(false), 2000);
|
|
44
|
+
}, []);
|
|
28
45
|
|
|
29
46
|
const handleCopy = useCallback(async () => {
|
|
30
47
|
try {
|
|
@@ -33,24 +50,23 @@ export function CopyButton({ text, className }: CopyButtonProps) {
|
|
|
33
50
|
} else if (!fallbackCopyText(text)) {
|
|
34
51
|
throw new Error("Both clipboard methods failed");
|
|
35
52
|
}
|
|
36
|
-
|
|
37
|
-
setTimeout(() => setCopied(false), 2000);
|
|
53
|
+
armRevertTimer();
|
|
38
54
|
} catch (err) {
|
|
39
55
|
console.error("Failed to copy to clipboard:", err);
|
|
40
56
|
// Try fallback if the modern API threw
|
|
41
57
|
try {
|
|
42
58
|
if (fallbackCopyText(text)) {
|
|
43
|
-
|
|
44
|
-
setTimeout(() => setCopied(false), 2000);
|
|
59
|
+
armRevertTimer();
|
|
45
60
|
}
|
|
46
61
|
} catch {
|
|
47
62
|
// Both methods failed — do nothing
|
|
48
63
|
}
|
|
49
64
|
}
|
|
50
|
-
}, [text]);
|
|
65
|
+
}, [text, armRevertTimer]);
|
|
51
66
|
|
|
52
67
|
return (
|
|
53
68
|
<button
|
|
69
|
+
type="button"
|
|
54
70
|
onClick={handleCopy}
|
|
55
71
|
title="Copy to clipboard"
|
|
56
72
|
className={cn(
|
|
@@ -2,10 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
import { useEffect } from "react";
|
|
4
4
|
import { captureClientEvent } from "@/lib/client-telemetry";
|
|
5
|
+
import { isAppError } from "@/lib/error-origin";
|
|
5
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Reports uncaught dashboard errors.
|
|
9
|
+
*
|
|
10
|
+
* Both listeners are page-global, so they also see failures from browser
|
|
11
|
+
* extensions injected into the page (MetaMask and friends). Those are filtered
|
|
12
|
+
* out — see lib/error-origin.ts — so this reports only our own failures.
|
|
13
|
+
*/
|
|
6
14
|
export function GlobalErrorListeners() {
|
|
7
15
|
useEffect(() => {
|
|
8
16
|
const handleError = (event: ErrorEvent) => {
|
|
17
|
+
if (
|
|
18
|
+
!isAppError({
|
|
19
|
+
stack: event.error?.stack,
|
|
20
|
+
filename: event.filename,
|
|
21
|
+
appOrigin: window.location.origin,
|
|
22
|
+
})
|
|
23
|
+
) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
9
26
|
captureClientEvent("unhandled_exception", {
|
|
10
27
|
error_message: event.message,
|
|
11
28
|
error_name: event.error?.name,
|
|
@@ -17,6 +34,16 @@ export function GlobalErrorListeners() {
|
|
|
17
34
|
|
|
18
35
|
const handleUnhandledRejection = (event: PromiseRejectionEvent) => {
|
|
19
36
|
const reason = event.reason;
|
|
37
|
+
// A rejection carries no filename, so the stack is the only evidence of
|
|
38
|
+
// where it came from. A non-Error reason has none and stays unattributed.
|
|
39
|
+
if (
|
|
40
|
+
!isAppError({
|
|
41
|
+
stack: reason instanceof Error ? reason.stack : undefined,
|
|
42
|
+
appOrigin: window.location.origin,
|
|
43
|
+
})
|
|
44
|
+
) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
20
47
|
captureClientEvent("unhandled_rejection", {
|
|
21
48
|
error_message: reason instanceof Error ? reason.message : String(reason),
|
|
22
49
|
error_name: reason instanceof Error ? reason.name : undefined,
|
|
@@ -5,10 +5,14 @@
|
|
|
5
5
|
# harness we integrate with and this repo, and opens ONE auto-PR with the fix.
|
|
6
6
|
#
|
|
7
7
|
# Bundles:
|
|
8
|
-
# - Node 20 + npm
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
8
|
+
# - Node 20 + npm (npm is a fallback bun installer for scripts/dev-hook.mjs;
|
|
9
|
+
# node runs the launcher itself)
|
|
10
|
+
# - bun (STILL REQUIRED: the cloned repo's .claude/settings.json fires hooks via
|
|
11
|
+
# `node "$CLAUDE_PROJECT_DIR/scripts/dev-hook.mjs" --hook <Event>`, and that
|
|
12
|
+
# launcher only *locates* bun — it cannot conjure one. Without this layer the
|
|
13
|
+
# dogfooded require-*-before-stop policies never fire and the auto-PR is
|
|
14
|
+
# never committed/pushed. We install to BUN_INSTALL=/home/appuser/.bun, which
|
|
15
|
+
# the launcher probes explicitly, so enforcement survives a broken PATH.)
|
|
12
16
|
# - Claude Code CLI (`claude`) — run headless with --effort ultracode
|
|
13
17
|
# - failproofai@latest on PATH (belt-and-suspenders; the dogfood hooks actually
|
|
14
18
|
# run the clone's SOURCE via bun, not this global)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# failproofai CLI-canary sandbox — base image
|
|
2
|
+
#
|
|
3
|
+
# Design goals (see failproofai-cli-canary-design.md §4):
|
|
4
|
+
# - SAFE: non-root user, NO sudo installed, no host FS mounted at runtime.
|
|
5
|
+
# The canary fires `sudo whoami` / `.env`-read deny-probes; here they
|
|
6
|
+
# are inert BY CONSTRUCTION even on a day enforcement is broken.
|
|
7
|
+
# - LIGHT: ephemeral daily container (`docker run --rm`), not a daemon.
|
|
8
|
+
# Only this image + one named volume persist; zero idle CPU/RAM.
|
|
9
|
+
# - FRESH: CLIs are NOT baked in — they are `@latest`-installed into the
|
|
10
|
+
# persistent HOME volume at run time (the whole point of the canary),
|
|
11
|
+
# so this base image rebuilds rarely.
|
|
12
|
+
#
|
|
13
|
+
# The HOME volume (mounted at /home/canary) holds: npm-global CLIs, every
|
|
14
|
+
# vendor login/token, and per-CLI config — so logins survive across daily runs.
|
|
15
|
+
|
|
16
|
+
FROM node:22-bookworm-slim
|
|
17
|
+
|
|
18
|
+
# bun from the official image — no `curl | bash` needed at build time.
|
|
19
|
+
COPY --from=oven/bun:latest /usr/local/bin/bun /usr/local/bin/bun
|
|
20
|
+
|
|
21
|
+
# Minimal tooling for the various vendor CLI installers. Deliberately NO sudo.
|
|
22
|
+
# Tooling for the various vendor installers. Deliberately NO sudo.
|
|
23
|
+
# bzip2/xz-utils : goose extracts its Rust binary with these
|
|
24
|
+
# libsecret-1-0 : antigravity caches login tokens via libsecret (best-effort)
|
|
25
|
+
RUN apt-get update -qq \
|
|
26
|
+
&& apt-get install -y -qq --no-install-recommends \
|
|
27
|
+
git ca-certificates curl unzip bzip2 xz-utils libsecret-1-0 \
|
|
28
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
29
|
+
|
|
30
|
+
# Unprivileged user. HOME is the mount point for the persistent named volume;
|
|
31
|
+
# because the image ships a canary-owned /home/canary, an empty named volume
|
|
32
|
+
# mounted here is initialised canary-owned (Docker copies image content+owner).
|
|
33
|
+
# node:22-slim already ships a `node` user at UID 1000, so pin canary to 1001.
|
|
34
|
+
RUN useradd --create-home --uid 1001 --shell /bin/bash canary
|
|
35
|
+
USER canary
|
|
36
|
+
WORKDIR /home/canary
|
|
37
|
+
RUN mkdir -p /home/canary/.npm-global/bin /home/canary/.local/bin
|
|
38
|
+
|
|
39
|
+
# NPM_CONFIG_PREFIX via ENV (not `npm config set`) so it survives the volume
|
|
40
|
+
# mount shadowing /home/canary at runtime. Runtime `npm i -g` lands in the volume.
|
|
41
|
+
ENV NPM_CONFIG_PREFIX=/home/canary/.npm-global
|
|
42
|
+
ENV PATH=/home/canary/.npm-global/bin:/home/canary/.local/bin:/usr/local/bin:/usr/bin:/bin
|
|
43
|
+
|
|
44
|
+
# Sanity: fail the build if bun/node/npm aren't all runnable as the canary user.
|
|
45
|
+
RUN bun --version && node --version && npm --version
|
|
46
|
+
|
|
47
|
+
CMD ["bash"]
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Integration suite
|
|
2
|
+
|
|
3
|
+
A daily **live-enforcement integration test** for failproofai. It answers one
|
|
4
|
+
question the unit/e2e suites can't: *does failproofai still enforce against every
|
|
5
|
+
supported agent CLI, at the versions users actually install today?*
|
|
6
|
+
|
|
7
|
+
Every day (`.github/workflows/integration-suite.yml`) it installs all 12 agent
|
|
8
|
+
CLIs **@latest** into an isolated Docker sandbox, drives each one against
|
|
9
|
+
failproofai's own policies (built from this repo's HEAD), and confirms the hook
|
|
10
|
+
log shows a **DENY**. A *silent-allow* — a blocked action that ran with no deny —
|
|
11
|
+
means enforcement broke against that CLI (e.g. a vendor changed their hook schema
|
|
12
|
+
out from under us). The test asserts the deny **positively**, so drift surfaces
|
|
13
|
+
as a red run + a Slack alert instead of going unnoticed until a user hits it.
|
|
14
|
+
|
|
15
|
+
## Why it's separate from `__tests__/`
|
|
16
|
+
|
|
17
|
+
It drives **real vendor CLIs against real gateway models** — it needs network,
|
|
18
|
+
Docker, credentials, and ~7-10 min, none of which belong in the fast in-process
|
|
19
|
+
vitest suites. So it's a scheduled workflow, not a PR gate.
|
|
20
|
+
|
|
21
|
+
## How a run works
|
|
22
|
+
|
|
23
|
+
The workflow is a thin trigger; `ci-entrypoint.sh` is the front door and does
|
|
24
|
+
everything below except the Actions cache restore/save.
|
|
25
|
+
|
|
26
|
+
1. Restore `integration-suite-state.json` from Actions cache (version-gate +
|
|
27
|
+
broke/recovered diff) — *workflow*.
|
|
28
|
+
2. Build failproofai under test (`dist/index.js` + `dist/cli.mjs`) from this repo.
|
|
29
|
+
3. Decode the OAuth token secrets, build the sandbox image, create the per-run
|
|
30
|
+
HOME volume, install all 12 CLIs (`install-clis.sh`), inject the credential
|
|
31
|
+
files (`inject-tokens.sh`), assemble the gateway env-file.
|
|
32
|
+
4. `run.sh` probes each non-gated CLI (`probe-cli.sh`), builds the report
|
|
33
|
+
(`report.js`), and POSTs it to Slack.
|
|
34
|
+
5. Cleanup (env-file + volume) runs via `trap`, so it happens on failure too.
|
|
35
|
+
|
|
36
|
+
Run it locally the same way CI does — every input is an env var:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
CANARY_LLM_API_KEY=... CANARY_SKIP_BUILD=1 \
|
|
40
|
+
bash integration-suite/ci-entrypoint.sh
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Version-gate:** a CLI is re-probed only when its binary version **or**
|
|
44
|
+
failproofai's HEAD changed since its last green run — unchanged ⇒ can't have
|
|
45
|
+
drifted ⇒ skip, protecting LLM/vendor quota. `FAIL`/`INCONCLUSIVE`/`ERROR` always
|
|
46
|
+
re-probe until they recover. Dispatch with **force** to probe everything.
|
|
47
|
+
|
|
48
|
+
## Auth & secrets (the `cli-integration` Environment)
|
|
49
|
+
|
|
50
|
+
> The GitHub **Environment** is still named `cli-integration` — it's configured in
|
|
51
|
+
> repo settings, not in this tree, so it was deliberately left alone when this
|
|
52
|
+
> directory was renamed. Renaming it there means renaming `environment:` in the
|
|
53
|
+
> workflow at the same time, or the job loses access to every secret.
|
|
54
|
+
|
|
55
|
+
Because this repo is public, all credentials live in a scoped **GitHub
|
|
56
|
+
Environment** (`cli-integration`) — only this workflow's job can read them — and
|
|
57
|
+
the workflow triggers on `schedule`/`workflow_dispatch` **only**, so fork PRs can
|
|
58
|
+
never reach them.
|
|
59
|
+
|
|
60
|
+
| Auth | CLIs | Secret(s) |
|
|
61
|
+
|------|------|-----------|
|
|
62
|
+
| Env-var (gateway) | claude, codex, goose, opencode, pi, hermes, openclaw, factory | `CANARY_LLM_API_KEY`, `CANARY_LLM_BASE_URL` |
|
|
63
|
+
| Env-var (PAT) | copilot | `COPILOT_GITHUB_TOKEN` |
|
|
64
|
+
| Injected token file | cursor, devin, antigravity | `CURSOR_/DEVIN_/ANTIGRAVITY_TOKEN_TGZ_B64` |
|
|
65
|
+
| Delivery | — | `SLACK_WEBHOOK_URL` |
|
|
66
|
+
|
|
67
|
+
The injected-token CLIs carry OAuth session tokens captured from a logged-in
|
|
68
|
+
machine (see `capture-tokens.sh`). They authenticate on a fresh runner, but may
|
|
69
|
+
eventually expire — when that happens the test reports `⚠️ ERROR` for that CLI;
|
|
70
|
+
re-login on the capture machine and refresh the secret.
|
|
71
|
+
|
|
72
|
+
> Note: env-var / secret names keep the historical `CANARY_` prefix internally —
|
|
73
|
+
> renaming them across the harness would be churn with no user-visible benefit.
|
|
74
|
+
|
|
75
|
+
## Files
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
ci-entrypoint.sh CI front door: build -> sandbox -> install -> probe -> cleanup
|
|
79
|
+
Dockerfile non-root sandbox base image
|
|
80
|
+
install-clis.sh install/upgrade all 12 CLIs @latest (with retries)
|
|
81
|
+
inject-tokens.sh write captured OAuth creds into the fresh volume
|
|
82
|
+
probe-cli.sh live enforcement probe for ONE CLI (the oracle)
|
|
83
|
+
canary-policies.mjs benign-marker custom policies the probe trips
|
|
84
|
+
run.sh orchestrator (gate → probe → report → Slack)
|
|
85
|
+
report.js build the Slack report + diff state (broke/recovered)
|
|
86
|
+
capture-tokens.sh (run on a logged-in machine) refresh the OAuth token secrets
|
|
87
|
+
```
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canary custom policies — the DEFINITE probe.
|
|
3
|
+
*
|
|
4
|
+
* The canary probes use BENIGN actions an agent never refuses: `echo`-ing a
|
|
5
|
+
* token, and reading a plain local file. Because there's nothing scary about
|
|
6
|
+
* them, the model reliably issues the tool call — eliminating the self-censorship
|
|
7
|
+
* that made sudo/.env/system-read probes come back INCONCLUSIVE.
|
|
8
|
+
*
|
|
9
|
+
* These policies intercept exactly those benign markers. A deny in the hook log
|
|
10
|
+
* is therefore positive proof that the full enforcement pipeline works against
|
|
11
|
+
* the CLI's REAL tool payload: hook fired → payload normalized (tool_name +
|
|
12
|
+
* tool_input.command / file_path — the drift-prone fields behind the Copilot
|
|
13
|
+
* 1.0.70 silent-allow) → policy evaluated → deny emitted. If normalization ever
|
|
14
|
+
* drifts, ctx.toolInput.command/file_path go empty, no deny fires, the benign
|
|
15
|
+
* command runs, and the probe reports FAIL — never a false alarm, never a miss.
|
|
16
|
+
*/
|
|
17
|
+
import { customPolicies, allow, deny } from "failproofai";
|
|
18
|
+
|
|
19
|
+
// Bash-command path: deny a benign shell command carrying the probe token.
|
|
20
|
+
customPolicies.add({
|
|
21
|
+
name: "canary-bash",
|
|
22
|
+
description: "Canary: deny the benign probe shell command (CANARY_PROBE token)",
|
|
23
|
+
match: { events: ["PreToolUse"] },
|
|
24
|
+
fn: async (ctx) => {
|
|
25
|
+
if (ctx.toolName !== "Bash") return allow();
|
|
26
|
+
const cmd = String(ctx.toolInput?.command ?? "");
|
|
27
|
+
if (cmd.includes("CANARY_PROBE")) return deny("canary-bash probe intercepted");
|
|
28
|
+
return allow();
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// File-path path: deny reading the benign marker file (via Read tool OR `cat`).
|
|
33
|
+
customPolicies.add({
|
|
34
|
+
name: "canary-read",
|
|
35
|
+
description: "Canary: deny reading the benign probe marker file (CANARY_MARKER)",
|
|
36
|
+
match: { events: ["PreToolUse"] },
|
|
37
|
+
fn: async (ctx) => {
|
|
38
|
+
const path = String(ctx.toolInput?.file_path ?? "");
|
|
39
|
+
const cmd = String(ctx.toolInput?.command ?? "");
|
|
40
|
+
if (path.includes("CANARY_MARKER") || cmd.includes("CANARY_MARKER")) {
|
|
41
|
+
return deny("canary-read probe intercepted");
|
|
42
|
+
}
|
|
43
|
+
return allow();
|
|
44
|
+
},
|
|
45
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
3
|
+
# capture-tokens.sh — run on the OFFICE BOX (has the logged-in canary volume).
|
|
4
|
+
# ./capture-tokens.sh <owner/repo>
|
|
5
|
+
#
|
|
6
|
+
# Captures each OAuth CLI's credential tree from the persistent HOME volume as a
|
|
7
|
+
# base64 gzip-tar rooted at $HOME, and stores it as a GitHub Actions secret on
|
|
8
|
+
# the canary repo. The CI workflow decodes it back onto the ephemeral runner's
|
|
9
|
+
# volume (see sandbox/inject-tokens.sh), so cursor/devin/antigravity authenticate
|
|
10
|
+
# in CI without an interactive login.
|
|
11
|
+
#
|
|
12
|
+
# Re-run this whenever the canary reports ERROR (not-logged-in / 401) for one of
|
|
13
|
+
# these CLIs — i.e. after you re-login on the box — to refresh the secret.
|
|
14
|
+
#
|
|
15
|
+
# NB: these are real credentials for internal@exosphere.host. They live only in
|
|
16
|
+
# GitHub *encrypted secrets*, never in the repo tree.
|
|
17
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
REPO="${1:?usage: capture-tokens.sh <owner/repo>}"
|
|
20
|
+
VOL="${CANARY_VOL:-failproofai-canary-home}"
|
|
21
|
+
IMAGE="${CANARY_IMAGE:-failproofai-canary:base}"
|
|
22
|
+
|
|
23
|
+
# secret-name → $HOME-relative path(s) to tar from the volume
|
|
24
|
+
capture() {
|
|
25
|
+
local secret="$1"; shift
|
|
26
|
+
local paths=("$@")
|
|
27
|
+
echo "── $secret ($(printf '%s ' "${paths[@]}"))"
|
|
28
|
+
# Tar the paths (rooted at $HOME) inside the container, gzip, base64 → host.
|
|
29
|
+
local b64
|
|
30
|
+
b64="$(docker run --rm -v "$VOL:/home/canary" "$IMAGE" bash -c "
|
|
31
|
+
cd \$HOME || exit 1
|
|
32
|
+
miss=1
|
|
33
|
+
for p in ${paths[*]}; do [ -e \"\$p\" ] && miss=0; done
|
|
34
|
+
[ \$miss = 1 ] && { echo 'MISSING' >&2; exit 3; }
|
|
35
|
+
tar -czf - ${paths[*]} 2>/dev/null | base64 -w0
|
|
36
|
+
")" || { echo " ⚠️ none of the paths exist in the volume — skipping (login first)"; return 0; }
|
|
37
|
+
if [ -z "$b64" ]; then echo " ⚠️ empty capture — skipping"; return 0; fi
|
|
38
|
+
printf '%s' "$b64" | gh secret set "$secret" --repo "$REPO" --body -
|
|
39
|
+
echo " ✓ set $secret (${#b64} b64 chars)"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
echo "Capturing OAuth credential trees from volume '$VOL' → secrets on $REPO"
|
|
43
|
+
capture CURSOR_TOKEN_TGZ_B64 .config/cursor
|
|
44
|
+
capture DEVIN_TOKEN_TGZ_B64 .local/share/devin/credentials.toml
|
|
45
|
+
# antigravity: capture ONLY the small OAuth token file — the full ~/.gemini tree
|
|
46
|
+
# is ~15 MB (CLI binary + brain/ + logs), far over GitHub's 48 KB secret cap.
|
|
47
|
+
capture ANTIGRAVITY_TOKEN_TGZ_B64 .gemini/antigravity-cli/antigravity-oauth-token
|
|
48
|
+
echo "done."
|