miclaw-app 0.1.0
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 -0
- package/.next/standalone/.next/app-path-routes-manifest.json +14 -0
- package/.next/standalone/.next/build-manifest.json +20 -0
- package/.next/standalone/.next/package.json +1 -0
- package/.next/standalone/.next/prerender-manifest.json +282 -0
- package/.next/standalone/.next/required-server-files.json +333 -0
- package/.next/standalone/.next/routes-manifest.json +120 -0
- package/.next/standalone/.next/server/app/_global-error/page/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +16 -0
- package/.next/standalone/.next/server/app/_global-error/page/next-font-manifest.json +6 -0
- package/.next/standalone/.next/server/app/_global-error/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/_global-error/page.js +10 -0
- package/.next/standalone/.next/server/app/_global-error/page.js.map +5 -0
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/_global-error.html +1 -0
- package/.next/standalone/.next/server/app/_global-error.meta +15 -0
- package/.next/standalone/.next/server/app/_global-error.rsc +15 -0
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +15 -0
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -0
- package/.next/standalone/.next/server/app/_not-found/page/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +16 -0
- package/.next/standalone/.next/server/app/_not-found/page/next-font-manifest.json +12 -0
- package/.next/standalone/.next/server/app/_not-found/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/_not-found/page.js +13 -0
- package/.next/standalone/.next/server/app/_not-found/page.js.map +5 -0
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/_not-found.html +9 -0
- package/.next/standalone/.next/server/app/_not-found.meta +16 -0
- package/.next/standalone/.next/server/app/_not-found.rsc +17 -0
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +17 -0
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -0
- package/.next/standalone/.next/server/app/agents/page/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/agents/page/build-manifest.json +16 -0
- package/.next/standalone/.next/server/app/agents/page/next-font-manifest.json +12 -0
- package/.next/standalone/.next/server/app/agents/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/agents/page/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/agents/page.js +15 -0
- package/.next/standalone/.next/server/app/agents/page.js.map +5 -0
- package/.next/standalone/.next/server/app/agents/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/agents/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/agents.html +30 -0
- package/.next/standalone/.next/server/app/agents.meta +15 -0
- package/.next/standalone/.next/server/app/agents.rsc +345 -0
- package/.next/standalone/.next/server/app/agents.segments/_full.segment.rsc +345 -0
- package/.next/standalone/.next/server/app/agents.segments/_head.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/agents.segments/_index.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/agents.segments/_tree.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/agents.segments/agents/__PAGE__.segment.rsc +331 -0
- package/.next/standalone/.next/server/app/agents.segments/agents.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/commands/page/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/commands/page/build-manifest.json +16 -0
- package/.next/standalone/.next/server/app/commands/page/next-font-manifest.json +12 -0
- package/.next/standalone/.next/server/app/commands/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/commands/page/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/commands/page.js +15 -0
- package/.next/standalone/.next/server/app/commands/page.js.map +5 -0
- package/.next/standalone/.next/server/app/commands/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/commands/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/commands.html +33 -0
- package/.next/standalone/.next/server/app/commands.meta +15 -0
- package/.next/standalone/.next/server/app/commands.rsc +1672 -0
- package/.next/standalone/.next/server/app/commands.segments/_full.segment.rsc +1672 -0
- package/.next/standalone/.next/server/app/commands.segments/_head.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/commands.segments/_index.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/commands.segments/_tree.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/commands.segments/commands/__PAGE__.segment.rsc +1658 -0
- package/.next/standalone/.next/server/app/commands.segments/commands.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/favicon.ico/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/favicon.ico/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/favicon.ico/route.js +6 -0
- package/.next/standalone/.next/server/app/favicon.ico/route.js.map +5 -0
- package/.next/standalone/.next/server/app/favicon.ico/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/favicon.ico.body +0 -0
- package/.next/standalone/.next/server/app/favicon.ico.meta +1 -0
- package/.next/standalone/.next/server/app/hooks/page/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/hooks/page/build-manifest.json +16 -0
- package/.next/standalone/.next/server/app/hooks/page/next-font-manifest.json +12 -0
- package/.next/standalone/.next/server/app/hooks/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/hooks/page/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/hooks/page.js +15 -0
- package/.next/standalone/.next/server/app/hooks/page.js.map +5 -0
- package/.next/standalone/.next/server/app/hooks/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/hooks/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/hooks.html +9 -0
- package/.next/standalone/.next/server/app/hooks.meta +15 -0
- package/.next/standalone/.next/server/app/hooks.rsc +21 -0
- package/.next/standalone/.next/server/app/hooks.segments/_full.segment.rsc +21 -0
- package/.next/standalone/.next/server/app/hooks.segments/_head.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/hooks.segments/_index.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/hooks.segments/_tree.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/hooks.segments/hooks/__PAGE__.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/hooks.segments/hooks.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/index.html +83 -0
- package/.next/standalone/.next/server/app/index.meta +14 -0
- package/.next/standalone/.next/server/app/index.rsc +20 -0
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +8 -0
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +20 -0
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/mcp/page/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/mcp/page/build-manifest.json +16 -0
- package/.next/standalone/.next/server/app/mcp/page/next-font-manifest.json +12 -0
- package/.next/standalone/.next/server/app/mcp/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/mcp/page/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/mcp/page.js +15 -0
- package/.next/standalone/.next/server/app/mcp/page.js.map +5 -0
- package/.next/standalone/.next/server/app/mcp/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/mcp/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/mcp.html +9 -0
- package/.next/standalone/.next/server/app/mcp.meta +15 -0
- package/.next/standalone/.next/server/app/mcp.rsc +23 -0
- package/.next/standalone/.next/server/app/mcp.segments/_full.segment.rsc +23 -0
- package/.next/standalone/.next/server/app/mcp.segments/_head.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/mcp.segments/_index.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/mcp.segments/_tree.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/mcp.segments/mcp/__PAGE__.segment.rsc +8 -0
- package/.next/standalone/.next/server/app/mcp.segments/mcp.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/page/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/page/build-manifest.json +16 -0
- package/.next/standalone/.next/server/app/page/next-font-manifest.json +12 -0
- package/.next/standalone/.next/server/app/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/page.js +15 -0
- package/.next/standalone/.next/server/app/page.js.map +5 -0
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/projects/[slug]/page/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/projects/[slug]/page/build-manifest.json +16 -0
- package/.next/standalone/.next/server/app/projects/[slug]/page/next-font-manifest.json +12 -0
- package/.next/standalone/.next/server/app/projects/[slug]/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/projects/[slug]/page/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/projects/[slug]/page.js +16 -0
- package/.next/standalone/.next/server/app/projects/[slug]/page.js.map +5 -0
- package/.next/standalone/.next/server/app/projects/[slug]/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/projects/[slug]/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/rules/page/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/rules/page/build-manifest.json +16 -0
- package/.next/standalone/.next/server/app/rules/page/next-font-manifest.json +12 -0
- package/.next/standalone/.next/server/app/rules/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/rules/page/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/rules/page.js +15 -0
- package/.next/standalone/.next/server/app/rules/page.js.map +5 -0
- package/.next/standalone/.next/server/app/rules/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/rules/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/rules.html +72 -0
- package/.next/standalone/.next/server/app/rules.meta +15 -0
- package/.next/standalone/.next/server/app/rules.rsc +2358 -0
- package/.next/standalone/.next/server/app/rules.segments/_full.segment.rsc +2358 -0
- package/.next/standalone/.next/server/app/rules.segments/_head.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/rules.segments/_index.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/rules.segments/_tree.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/rules.segments/rules/__PAGE__.segment.rsc +2344 -0
- package/.next/standalone/.next/server/app/rules.segments/rules.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/settings/page/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/settings/page/build-manifest.json +16 -0
- package/.next/standalone/.next/server/app/settings/page/next-font-manifest.json +12 -0
- package/.next/standalone/.next/server/app/settings/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/settings/page.js +15 -0
- package/.next/standalone/.next/server/app/settings/page.js.map +5 -0
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/settings.html +56 -0
- package/.next/standalone/.next/server/app/settings.meta +15 -0
- package/.next/standalone/.next/server/app/settings.rsc +226 -0
- package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +226 -0
- package/.next/standalone/.next/server/app/settings.segments/_head.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/settings.segments/_index.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +211 -0
- package/.next/standalone/.next/server/app/settings.segments/settings.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/skills/page/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/skills/page/build-manifest.json +16 -0
- package/.next/standalone/.next/server/app/skills/page/next-font-manifest.json +12 -0
- package/.next/standalone/.next/server/app/skills/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/skills/page/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/skills/page.js +15 -0
- package/.next/standalone/.next/server/app/skills/page.js.map +5 -0
- package/.next/standalone/.next/server/app/skills/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/skills/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/skills.html +30 -0
- package/.next/standalone/.next/server/app/skills.meta +15 -0
- package/.next/standalone/.next/server/app/skills.rsc +1111 -0
- package/.next/standalone/.next/server/app/skills.segments/_full.segment.rsc +1111 -0
- package/.next/standalone/.next/server/app/skills.segments/_head.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/skills.segments/_index.segment.rsc +6 -0
- package/.next/standalone/.next/server/app/skills.segments/_tree.segment.rsc +5 -0
- package/.next/standalone/.next/server/app/skills.segments/skills/__PAGE__.segment.rsc +1097 -0
- package/.next/standalone/.next/server/app/skills.segments/skills.segment.rsc +5 -0
- package/.next/standalone/.next/server/app-paths-manifest.json +14 -0
- package/.next/standalone/.next/server/chunks/[externals]_next_dist_0arv.vj._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0teziyo._.js +13 -0
- package/.next/standalone/.next/server/chunks/[turbopack]_runtime.js +903 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_favicon_ico_route_actions_095lj93.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0.pno0_._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__06czxzo._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__06ipj7k._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__08c9t2b._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__09x1iac._.js +33 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__09z7o2x._.js +19 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0beg-.s._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0bm8p5g._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ca-xeh._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0dey16.._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0fvw3d8._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qk5gqw._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s0h9e0._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0u-t242._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0xl6e~c._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0xrk31o._.js +33 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0y_d026._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[turbopack]_runtime.js +903 -0
- package/.next/standalone/.next/server/chunks/ssr/_09kkdgy._.js +6 -0
- package/.next/standalone/.next/server/chunks/ssr/_0g8yqoe._.js +7 -0
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app__global-error_page_actions_0k77kol.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app__not-found_page_actions_0eq97pa.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_agents_page_actions_07l1ss4.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_commands_page_actions_0npst50.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_hooks_page_actions_0a_tx-6.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_mcp_page_actions_00_op~_.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_page_actions_09-gtaw.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_projects_[slug]_page_actions_0xg3f7c.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_rules_page_actions_0xcrbur.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_settings_page_actions_0mr68ai.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_skills_page_actions_0cxzzu-.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_09w7yel._.js +33 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_0sy8gnb._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_0e1izl_._.js +6 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_client_components_0inhx6q._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_forbidden_0ghu-f7.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_0lgvd_..js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_unauthorized_0cjv-23.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_03-z2qq.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_06b_a87.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_071geea.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_07vh7rm.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_08617.g.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0dlz56b.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0fnc180.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0iktlcc.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0qp4u6g.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0t-uic4.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0v9mjz4.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/src_components_ExpandableBody_tsx_0-ivqwg._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/src_components_SphereView_tsx_0q2ope8._.js +13 -0
- package/.next/standalone/.next/server/functions-config-manifest.json +4 -0
- package/.next/standalone/.next/server/middleware-build-manifest.js +20 -0
- package/.next/standalone/.next/server/middleware-manifest.json +6 -0
- package/.next/standalone/.next/server/next-font-manifest.js +1 -0
- package/.next/standalone/.next/server/next-font-manifest.json +57 -0
- package/.next/standalone/.next/server/pages/404.html +9 -0
- package/.next/standalone/.next/server/pages/500.html +1 -0
- package/.next/standalone/.next/server/pages-manifest.json +4 -0
- package/.next/standalone/.next/server/prefetch-hints.json +1 -0
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -0
- package/.next/standalone/.next/server/server-reference-manifest.json +5 -0
- package/.next/standalone/node_modules/@img/colour/color.cjs +1596 -0
- package/.next/standalone/node_modules/@img/colour/index.cjs +1 -0
- package/.next/standalone/node_modules/@img/colour/package.json +58 -0
- package/.next/standalone/node_modules/@img/sharp-darwin-arm64/lib/sharp-darwin-arm64.node +0 -0
- package/.next/standalone/node_modules/@img/sharp-darwin-arm64/package.json +40 -0
- package/.next/standalone/node_modules/@img/sharp-libvips-darwin-arm64/README.md +46 -0
- package/.next/standalone/node_modules/@img/sharp-libvips-darwin-arm64/lib/glib-2.0/include/glibconfig.h +220 -0
- package/.next/standalone/node_modules/@img/sharp-libvips-darwin-arm64/lib/index.js +1 -0
- package/.next/standalone/node_modules/@img/sharp-libvips-darwin-arm64/lib/libvips-cpp.8.17.3.dylib +0 -0
- package/.next/standalone/node_modules/@img/sharp-libvips-darwin-arm64/package.json +36 -0
- package/.next/standalone/node_modules/@img/sharp-libvips-darwin-arm64/versions.json +30 -0
- package/.next/standalone/node_modules/@next/env/dist/index.js +1 -0
- package/.next/standalone/node_modules/@next/env/package.json +36 -0
- package/.next/standalone/node_modules/@swc/helpers/cjs/_interop_require_default.cjs +6 -0
- package/.next/standalone/node_modules/@swc/helpers/cjs/_interop_require_wildcard.cjs +38 -0
- package/.next/standalone/node_modules/@swc/helpers/package.json +471 -0
- package/.next/standalone/node_modules/client-only/index.js +0 -0
- package/.next/standalone/node_modules/client-only/package.json +19 -0
- package/.next/standalone/node_modules/detect-libc/lib/detect-libc.js +313 -0
- package/.next/standalone/node_modules/detect-libc/lib/elf.js +39 -0
- package/.next/standalone/node_modules/detect-libc/lib/filesystem.js +51 -0
- package/.next/standalone/node_modules/detect-libc/lib/process.js +24 -0
- package/.next/standalone/node_modules/detect-libc/package.json +44 -0
- package/.next/standalone/node_modules/next/dist/build/adapter/setup-node-env.external.js +15 -0
- package/.next/standalone/node_modules/next/dist/build/define-env.js +255 -0
- package/.next/standalone/node_modules/next/dist/build/duration-to-string.js +99 -0
- package/.next/standalone/node_modules/next/dist/build/get-supported-browsers.js +38 -0
- package/.next/standalone/node_modules/next/dist/build/next-config-ts/require-hook.js +85 -0
- package/.next/standalone/node_modules/next/dist/build/next-config-ts/transpile-config.js +251 -0
- package/.next/standalone/node_modules/next/dist/build/output/format.js +84 -0
- package/.next/standalone/node_modules/next/dist/build/output/log.js +135 -0
- package/.next/standalone/node_modules/next/dist/build/segment-config/app/app-segment-config.js +162 -0
- package/.next/standalone/node_modules/next/dist/build/segment-config/app/app-segments.js +137 -0
- package/.next/standalone/node_modules/next/dist/build/segment-config/app/collect-root-param-keys.js +52 -0
- package/.next/standalone/node_modules/next/dist/build/static-paths/app/extract-pathname-route-param-segments-from-loader-tree.js +137 -0
- package/.next/standalone/node_modules/next/dist/build/static-paths/app.js +735 -0
- package/.next/standalone/node_modules/next/dist/build/static-paths/pages.js +169 -0
- package/.next/standalone/node_modules/next/dist/build/static-paths/utils.js +119 -0
- package/.next/standalone/node_modules/next/dist/build/swc/helpers.js +15 -0
- package/.next/standalone/node_modules/next/dist/build/swc/index.js +1348 -0
- package/.next/standalone/node_modules/next/dist/build/swc/install-bindings.js +30 -0
- package/.next/standalone/node_modules/next/dist/build/swc/jest-transformer.js +76 -0
- package/.next/standalone/node_modules/next/dist/build/swc/loaderWorkerPool.js +40 -0
- package/.next/standalone/node_modules/next/dist/build/swc/options.js +403 -0
- package/.next/standalone/node_modules/next/dist/build/swc/types.js +6 -0
- package/.next/standalone/node_modules/next/dist/build/utils.js +1215 -0
- package/.next/standalone/node_modules/next/dist/cli/next-test.js +170 -0
- package/.next/standalone/node_modules/next/dist/client/add-base-path.js +24 -0
- package/.next/standalone/node_modules/next/dist/client/app-call-server.js +34 -0
- package/.next/standalone/node_modules/next/dist/client/app-find-source-map-url.js +39 -0
- package/.next/standalone/node_modules/next/dist/client/assign-location.js +29 -0
- package/.next/standalone/node_modules/next/dist/client/components/app-router-announcer.js +78 -0
- package/.next/standalone/node_modules/next/dist/client/components/app-router-headers.js +138 -0
- package/.next/standalone/node_modules/next/dist/client/components/app-router-instance.js +397 -0
- package/.next/standalone/node_modules/next/dist/client/components/app-router-utils.js +62 -0
- package/.next/standalone/node_modules/next/dist/client/components/app-router.js +514 -0
- package/.next/standalone/node_modules/next/dist/client/components/builtin/default.js +35 -0
- package/.next/standalone/node_modules/next/dist/client/components/builtin/error-styles.js +165 -0
- package/.next/standalone/node_modules/next/dist/client/components/builtin/global-error.js +100 -0
- package/.next/standalone/node_modules/next/dist/client/components/dev-root-http-access-fallback-boundary.js +52 -0
- package/.next/standalone/node_modules/next/dist/client/components/error-boundary.js +144 -0
- package/.next/standalone/node_modules/next/dist/client/components/errors/graceful-degrade-boundary.js +86 -0
- package/.next/standalone/node_modules/next/dist/client/components/errors/root-error-boundary.js +41 -0
- package/.next/standalone/node_modules/next/dist/client/components/forbidden.js +48 -0
- package/.next/standalone/node_modules/next/dist/client/components/handle-isr-error.js +30 -0
- package/.next/standalone/node_modules/next/dist/client/components/hooks-server-context.js +42 -0
- package/.next/standalone/node_modules/next/dist/client/components/http-access-fallback/error-boundary.js +125 -0
- package/.next/standalone/node_modules/next/dist/client/components/http-access-fallback/http-access-fallback.js +72 -0
- package/.next/standalone/node_modules/next/dist/client/components/is-next-router-error.js +23 -0
- package/.next/standalone/node_modules/next/dist/client/components/links.js +299 -0
- package/.next/standalone/node_modules/next/dist/client/components/match-segments.js +32 -0
- package/.next/standalone/node_modules/next/dist/client/components/nav-failure-handler.js +61 -0
- package/.next/standalone/node_modules/next/dist/client/components/navigation-devtools.js +126 -0
- package/.next/standalone/node_modules/next/dist/client/components/navigation-untracked.js +67 -0
- package/.next/standalone/node_modules/next/dist/client/components/navigation.js +225 -0
- package/.next/standalone/node_modules/next/dist/client/components/navigation.react-server.js +75 -0
- package/.next/standalone/node_modules/next/dist/client/components/not-found.js +42 -0
- package/.next/standalone/node_modules/next/dist/client/components/readonly-url-search-params.js +41 -0
- package/.next/standalone/node_modules/next/dist/client/components/redirect-boundary.js +107 -0
- package/.next/standalone/node_modules/next/dist/client/components/redirect-error.js +43 -0
- package/.next/standalone/node_modules/next/dist/client/components/redirect-status-code.js +24 -0
- package/.next/standalone/node_modules/next/dist/client/components/redirect.js +91 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/compute-changed-path.js +201 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/create-href-from-url.js +21 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/create-initial-router-state.js +153 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/create-router-cache-key.js +32 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/fetch-server-response.js +457 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/is-navigating-to-new-root-layout.js +59 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/ppr-navigations.js +1341 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/reducers/committed-state.js +49 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/reducers/find-head-in-cache.js +63 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/reducers/has-interception-route-in-current-tree.js +38 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/reducers/hmr-refresh-reducer.js +23 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/reducers/navigate-reducer.js +56 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/reducers/refresh-reducer.js +83 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/reducers/restore-reducer.js +62 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/reducers/server-action-reducer.js +320 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/reducers/server-patch-reducer.js +58 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/router-reducer-types.js +70 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/router-reducer.js +66 -0
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/set-cache-busting-search-param.js +60 -0
- package/.next/standalone/node_modules/next/dist/client/components/segment-cache/bfcache.js +128 -0
- package/.next/standalone/node_modules/next/dist/client/components/segment-cache/cache-key.js +28 -0
- package/.next/standalone/node_modules/next/dist/client/components/segment-cache/cache-map.js +305 -0
- package/.next/standalone/node_modules/next/dist/client/components/segment-cache/cache.js +1933 -0
- package/.next/standalone/node_modules/next/dist/client/components/segment-cache/lru.js +152 -0
- package/.next/standalone/node_modules/next/dist/client/components/segment-cache/navigation-testing-lock.js +194 -0
- package/.next/standalone/node_modules/next/dist/client/components/segment-cache/navigation.js +597 -0
- package/.next/standalone/node_modules/next/dist/client/components/segment-cache/optimistic-routes.js +543 -0
- package/.next/standalone/node_modules/next/dist/client/components/segment-cache/prefetch.js +31 -0
- package/.next/standalone/node_modules/next/dist/client/components/segment-cache/scheduler.js +1249 -0
- package/.next/standalone/node_modules/next/dist/client/components/segment-cache/types.js +69 -0
- package/.next/standalone/node_modules/next/dist/client/components/segment-cache/vary-path.js +278 -0
- package/.next/standalone/node_modules/next/dist/client/components/static-generation-bailout.js +42 -0
- package/.next/standalone/node_modules/next/dist/client/components/unauthorized.js +49 -0
- package/.next/standalone/node_modules/next/dist/client/components/unrecognized-action-error.js +39 -0
- package/.next/standalone/node_modules/next/dist/client/components/unresolved-thenable.js +23 -0
- package/.next/standalone/node_modules/next/dist/client/components/unstable-rethrow.browser.js +28 -0
- package/.next/standalone/node_modules/next/dist/client/components/unstable-rethrow.js +25 -0
- package/.next/standalone/node_modules/next/dist/client/components/unstable-rethrow.server.js +32 -0
- package/.next/standalone/node_modules/next/dist/client/components/use-action-queue.js +148 -0
- package/.next/standalone/node_modules/next/dist/client/dev/debug-channel.js +72 -0
- package/.next/standalone/node_modules/next/dist/client/flight-data-helpers.js +232 -0
- package/.next/standalone/node_modules/next/dist/client/has-base-path.js +23 -0
- package/.next/standalone/node_modules/next/dist/client/lib/console.js +177 -0
- package/.next/standalone/node_modules/next/dist/client/lib/javascript-url.js +32 -0
- package/.next/standalone/node_modules/next/dist/client/navigation-build-id.js +53 -0
- package/.next/standalone/node_modules/next/dist/client/normalize-trailing-slash.js +36 -0
- package/.next/standalone/node_modules/next/dist/client/remove-base-path.js +32 -0
- package/.next/standalone/node_modules/next/dist/client/route-params.js +230 -0
- package/.next/standalone/node_modules/next/dist/compiled/@edge-runtime/cookies/index.js +339 -0
- package/.next/standalone/node_modules/next/dist/compiled/@edge-runtime/cookies/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/@edge-runtime/ponyfill/index.js +46 -0
- package/.next/standalone/node_modules/next/dist/compiled/@edge-runtime/ponyfill/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/@edge-runtime/primitives/abort-controller.js.text.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/@edge-runtime/primitives/console.js.text.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/@edge-runtime/primitives/events.js.text.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/@edge-runtime/primitives/index.js +5 -0
- package/.next/standalone/node_modules/next/dist/compiled/@edge-runtime/primitives/load.js +18713 -0
- package/.next/standalone/node_modules/next/dist/compiled/@edge-runtime/primitives/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/@edge-runtime/primitives/stream.js +44 -0
- package/.next/standalone/node_modules/next/dist/compiled/@edge-runtime/primitives/timers.js.text.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/@edge-runtime/primitives/url.js.text.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/@hapi/accept/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/@hapi/accept/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/@mswjs/interceptors/ClientRequest/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/@mswjs/interceptors/ClientRequest/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/@napi-rs/triples/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/@napi-rs/triples/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/@opentelemetry/api/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/@opentelemetry/api/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/async-retry/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/async-retry/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/async-sema/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/async-sema/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/busboy/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/busboy/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/bytes/index.js +8 -0
- package/.next/standalone/node_modules/next/dist/compiled/bytes/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/ci-info/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/ci-info/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/commander/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/commander/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/comment-json/index.js +7 -0
- package/.next/standalone/node_modules/next/dist/compiled/comment-json/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/compression/index.js +58 -0
- package/.next/standalone/node_modules/next/dist/compiled/compression/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/conf/index.js +15 -0
- package/.next/standalone/node_modules/next/dist/compiled/conf/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/content-disposition/index.js +6 -0
- package/.next/standalone/node_modules/next/dist/compiled/content-disposition/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/cookie/index.js +7 -0
- package/.next/standalone/node_modules/next/dist/compiled/cookie/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/cross-spawn/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/cross-spawn/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/debug/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/debug/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/edge-runtime/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/edge-runtime/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/find-up/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/find-up/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/fresh/index.js +8 -0
- package/.next/standalone/node_modules/next/dist/compiled/fresh/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/http-proxy/index.js +34 -0
- package/.next/standalone/node_modules/next/dist/compiled/http-proxy/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/image-detector/detector.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/image-size/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/image-size/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/ipaddr.js/ipaddr.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/ipaddr.js/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/is-animated/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/is-animated/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/is-docker/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/is-docker/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/is-wsl/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/is-wsl/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/jsonwebtoken/index.js +11 -0
- package/.next/standalone/node_modules/next/dist/compiled/jsonwebtoken/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/nanoid/index.cjs +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/nanoid/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js +54 -0
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo.runtime.prod.js +54 -0
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-route-turbo.runtime.prod.js +6 -0
- package/.next/standalone/node_modules/next/dist/compiled/next-server/pages-turbo.runtime.prod.js +20 -0
- package/.next/standalone/node_modules/next/dist/compiled/p-limit/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/p-limit/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/p-queue/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/p-queue/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/path-browserify/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/path-browserify/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/path-to-regexp/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/path-to-regexp/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/picomatch/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/picomatch/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/react-is/cjs/react-is.development.js +133 -0
- package/.next/standalone/node_modules/next/dist/compiled/react-is/cjs/react-is.production.js +130 -0
- package/.next/standalone/node_modules/next/dist/compiled/react-is/index.js +7 -0
- package/.next/standalone/node_modules/next/dist/compiled/react-is/package.json +26 -0
- package/.next/standalone/node_modules/next/dist/compiled/regenerator-runtime/package.json +19 -0
- package/.next/standalone/node_modules/next/dist/compiled/regenerator-runtime/runtime.js +729 -0
- package/.next/standalone/node_modules/next/dist/compiled/semver/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/semver/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/send/index.js +70 -0
- package/.next/standalone/node_modules/next/dist/compiled/send/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/source-map/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/source-map/source-map.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/stacktrace-parser/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/stacktrace-parser/stack-trace-parser.cjs.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/string-hash/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/string-hash/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/strip-ansi/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/strip-ansi/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/superstruct/index.cjs +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/superstruct/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/tar/index.min.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/tar/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/text-table/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/text-table/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/watchpack/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/watchpack/watchpack.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/ws/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/ws/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/zod/index.cjs +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/zod/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/zod-validation-error/index.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/zod-validation-error/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/experimental/testmode/context.js +57 -0
- package/.next/standalone/node_modules/next/dist/experimental/testmode/fetch.js +142 -0
- package/.next/standalone/node_modules/next/dist/experimental/testmode/httpget.js +26 -0
- package/.next/standalone/node_modules/next/dist/experimental/testmode/server-edge.js +32 -0
- package/.next/standalone/node_modules/next/dist/experimental/testmode/server.js +62 -0
- package/.next/standalone/node_modules/next/dist/export/helpers/create-incremental-cache.js +61 -0
- package/.next/standalone/node_modules/next/dist/lib/batcher.js +65 -0
- package/.next/standalone/node_modules/next/dist/lib/build-custom-route.js +46 -0
- package/.next/standalone/node_modules/next/dist/lib/bundler.js +97 -0
- package/.next/standalone/node_modules/next/dist/lib/client-and-server-references.js +54 -0
- package/.next/standalone/node_modules/next/dist/lib/coalesced-function.js +39 -0
- package/.next/standalone/node_modules/next/dist/lib/compile-error.js +14 -0
- package/.next/standalone/node_modules/next/dist/lib/constants.js +420 -0
- package/.next/standalone/node_modules/next/dist/lib/create-client-router-filter.js +67 -0
- package/.next/standalone/node_modules/next/dist/lib/default-transpiled-packages.json +1 -0
- package/.next/standalone/node_modules/next/dist/lib/detached-promise.js +32 -0
- package/.next/standalone/node_modules/next/dist/lib/detect-typo.js +51 -0
- package/.next/standalone/node_modules/next/dist/lib/download-swc.js +183 -0
- package/.next/standalone/node_modules/next/dist/lib/error-telemetry-utils.js +42 -0
- package/.next/standalone/node_modules/next/dist/lib/fallback.js +100 -0
- package/.next/standalone/node_modules/next/dist/lib/fatal-error.js +14 -0
- package/.next/standalone/node_modules/next/dist/lib/file-exists.js +53 -0
- package/.next/standalone/node_modules/next/dist/lib/find-config.js +102 -0
- package/.next/standalone/node_modules/next/dist/lib/find-pages-dir.js +65 -0
- package/.next/standalone/node_modules/next/dist/lib/find-root.js +126 -0
- package/.next/standalone/node_modules/next/dist/lib/format-cli-help-output.js +84 -0
- package/.next/standalone/node_modules/next/dist/lib/format-dynamic-import-path.js +24 -0
- package/.next/standalone/node_modules/next/dist/lib/format-server-error.js +75 -0
- package/.next/standalone/node_modules/next/dist/lib/framework/boundary-components.js +62 -0
- package/.next/standalone/node_modules/next/dist/lib/framework/boundary-constants.js +36 -0
- package/.next/standalone/node_modules/next/dist/lib/fs/rename.js +87 -0
- package/.next/standalone/node_modules/next/dist/lib/fs/write-atomic.js +28 -0
- package/.next/standalone/node_modules/next/dist/lib/generate-interception-routes-rewrites.js +52 -0
- package/.next/standalone/node_modules/next/dist/lib/get-files-in-dir.js +33 -0
- package/.next/standalone/node_modules/next/dist/lib/get-network-host.js +44 -0
- package/.next/standalone/node_modules/next/dist/lib/get-package-version.js +118 -0
- package/.next/standalone/node_modules/next/dist/lib/get-project-dir.js +51 -0
- package/.next/standalone/node_modules/next/dist/lib/has-necessary-dependencies.js +49 -0
- package/.next/standalone/node_modules/next/dist/lib/helpers/get-cache-directory.js +66 -0
- package/.next/standalone/node_modules/next/dist/lib/helpers/get-npx-command.js +29 -0
- package/.next/standalone/node_modules/next/dist/lib/helpers/get-online.js +50 -0
- package/.next/standalone/node_modules/next/dist/lib/helpers/get-pkg-manager.js +63 -0
- package/.next/standalone/node_modules/next/dist/lib/helpers/get-registry.js +45 -0
- package/.next/standalone/node_modules/next/dist/lib/helpers/get-reserved-port.js +116 -0
- package/.next/standalone/node_modules/next/dist/lib/helpers/install.js +83 -0
- package/.next/standalone/node_modules/next/dist/lib/import-next-warning.js +50 -0
- package/.next/standalone/node_modules/next/dist/lib/inline-static-env.js +112 -0
- package/.next/standalone/node_modules/next/dist/lib/install-dependencies.js +40 -0
- package/.next/standalone/node_modules/next/dist/lib/interop-default.js +16 -0
- package/.next/standalone/node_modules/next/dist/lib/is-api-route.js +15 -0
- package/.next/standalone/node_modules/next/dist/lib/is-app-page-route.js +15 -0
- package/.next/standalone/node_modules/next/dist/lib/is-app-route-route.js +15 -0
- package/.next/standalone/node_modules/next/dist/lib/is-edge-runtime.js +16 -0
- package/.next/standalone/node_modules/next/dist/lib/is-error.js +78 -0
- package/.next/standalone/node_modules/next/dist/lib/is-interception-route-rewrite.js +18 -0
- package/.next/standalone/node_modules/next/dist/lib/is-internal-component.js +36 -0
- package/.next/standalone/node_modules/next/dist/lib/is-serializable-props.js +106 -0
- package/.next/standalone/node_modules/next/dist/lib/known-edge-safe-packages.json +1 -0
- package/.next/standalone/node_modules/next/dist/lib/load-custom-routes.js +594 -0
- package/.next/standalone/node_modules/next/dist/lib/memory/gc-observer.js +53 -0
- package/.next/standalone/node_modules/next/dist/lib/memory/shutdown.js +29 -0
- package/.next/standalone/node_modules/next/dist/lib/memory/startup.js +47 -0
- package/.next/standalone/node_modules/next/dist/lib/memory/trace.js +109 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/constants.js +40 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/default-metadata.js +82 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/generate/icon-mark.js +22 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/generate/utils.js +52 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/get-metadata-route.js +123 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/is-metadata-route.js +221 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/metadata-context.js +18 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/metadata.js +1686 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/resolve-metadata.js +884 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/resolvers/resolve-basics.js +232 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/resolvers/resolve-icons.js +56 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/resolvers/resolve-opengraph.js +199 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/resolvers/resolve-title.js +40 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/resolvers/resolve-url.js +135 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/types/alternative-urls-types.js +7 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/types/extra-types.js +9 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/types/icons.js +6 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/types/manifest-types.js +6 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/types/metadata-interface.js +18 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/types/metadata-types.js +10 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/types/opengraph-types.js +6 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/types/resolvers.js +6 -0
- package/.next/standalone/node_modules/next/dist/lib/metadata/types/twitter-types.js +7 -0
- package/.next/standalone/node_modules/next/dist/lib/mime-type.js +20 -0
- package/.next/standalone/node_modules/next/dist/lib/mkcert.js +204 -0
- package/.next/standalone/node_modules/next/dist/lib/multi-file-writer.js +75 -0
- package/.next/standalone/node_modules/next/dist/lib/needs-experimental-react.js +16 -0
- package/.next/standalone/node_modules/next/dist/lib/non-nullable.js +15 -0
- package/.next/standalone/node_modules/next/dist/lib/normalize-path.js +21 -0
- package/.next/standalone/node_modules/next/dist/lib/oxford-comma-list.js +15 -0
- package/.next/standalone/node_modules/next/dist/lib/page-types.js +18 -0
- package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +185 -0
- package/.next/standalone/node_modules/next/dist/lib/pick.js +19 -0
- package/.next/standalone/node_modules/next/dist/lib/picocolors.js +177 -0
- package/.next/standalone/node_modules/next/dist/lib/pretty-bytes.js +74 -0
- package/.next/standalone/node_modules/next/dist/lib/realpath.js +20 -0
- package/.next/standalone/node_modules/next/dist/lib/recursive-copy.js +76 -0
- package/.next/standalone/node_modules/next/dist/lib/recursive-delete.js +137 -0
- package/.next/standalone/node_modules/next/dist/lib/recursive-readdir.js +124 -0
- package/.next/standalone/node_modules/next/dist/lib/redirect-status.js +46 -0
- package/.next/standalone/node_modules/next/dist/lib/require-instrumentation-client.js +26 -0
- package/.next/standalone/node_modules/next/dist/lib/resolve-build-paths.js +154 -0
- package/.next/standalone/node_modules/next/dist/lib/resolve-from.js +65 -0
- package/.next/standalone/node_modules/next/dist/lib/route-pattern-normalizer.js +107 -0
- package/.next/standalone/node_modules/next/dist/lib/scheduler.js +64 -0
- package/.next/standalone/node_modules/next/dist/lib/semver-noop.js +18 -0
- package/.next/standalone/node_modules/next/dist/lib/server-external-packages.jsonc +103 -0
- package/.next/standalone/node_modules/next/dist/lib/setup-exception-listeners.js +11 -0
- package/.next/standalone/node_modules/next/dist/lib/static-env.js +92 -0
- package/.next/standalone/node_modules/next/dist/lib/try-to-parse-path.js +67 -0
- package/.next/standalone/node_modules/next/dist/lib/turbopack-warning.js +185 -0
- package/.next/standalone/node_modules/next/dist/lib/typescript/diagnosticFormatter.js +243 -0
- package/.next/standalone/node_modules/next/dist/lib/typescript/getTypeScriptConfiguration.js +153 -0
- package/.next/standalone/node_modules/next/dist/lib/typescript/getTypeScriptIntent.js +52 -0
- package/.next/standalone/node_modules/next/dist/lib/typescript/missingDependencyError.js +27 -0
- package/.next/standalone/node_modules/next/dist/lib/typescript/runTypeCheck.js +149 -0
- package/.next/standalone/node_modules/next/dist/lib/typescript/type-paths.js +51 -0
- package/.next/standalone/node_modules/next/dist/lib/typescript/writeAppTypeDeclarations.js +75 -0
- package/.next/standalone/node_modules/next/dist/lib/typescript/writeConfigurationDefaults.js +395 -0
- package/.next/standalone/node_modules/next/dist/lib/url.js +75 -0
- package/.next/standalone/node_modules/next/dist/lib/verify-partytown-setup.js +115 -0
- package/.next/standalone/node_modules/next/dist/lib/verify-root-layout.js +165 -0
- package/.next/standalone/node_modules/next/dist/lib/verify-typescript-setup.js +228 -0
- package/.next/standalone/node_modules/next/dist/lib/wait.js +19 -0
- package/.next/standalone/node_modules/next/dist/lib/with-promise-cache.js +24 -0
- package/.next/standalone/node_modules/next/dist/lib/worker.js +234 -0
- package/.next/standalone/node_modules/next/dist/server/ReactDOMServerPages.js +16 -0
- package/.next/standalone/node_modules/next/dist/server/accept-header.js +132 -0
- package/.next/standalone/node_modules/next/dist/server/after/after-context.js +140 -0
- package/.next/standalone/node_modules/next/dist/server/after/after.js +26 -0
- package/.next/standalone/node_modules/next/dist/server/after/awaiter.js +74 -0
- package/.next/standalone/node_modules/next/dist/server/after/builtin-request-context.js +38 -0
- package/.next/standalone/node_modules/next/dist/server/after/index.js +21 -0
- package/.next/standalone/node_modules/next/dist/server/after/run-with-after.js +35 -0
- package/.next/standalone/node_modules/next/dist/server/api-utils/get-cookie-parser.js +22 -0
- package/.next/standalone/node_modules/next/dist/server/api-utils/index.js +201 -0
- package/.next/standalone/node_modules/next/dist/server/api-utils/node/api-resolver.js +395 -0
- package/.next/standalone/node_modules/next/dist/server/api-utils/node/parse-body.js +79 -0
- package/.next/standalone/node_modules/next/dist/server/api-utils/node/try-get-preview-data.js +86 -0
- package/.next/standalone/node_modules/next/dist/server/api-utils/web.js +17 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/action-async-storage-instance.js +14 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/action-async-storage.external.js +13 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/action-handler.js +1020 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/after-task-async-storage-instance.js +14 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/after-task-async-storage.external.js +13 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/app-render-prerender-utils.js +167 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/app-render-render-utils.js +76 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/app-render-scheduling.js +188 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/app-render.js +4469 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/async-local-storage.js +76 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/cache-signal.js +181 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/collect-segment-data.js +600 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/console-async-storage-instance.js +14 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/console-async-storage.external.js +13 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/create-component-styles-and-scripts.js +33 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/create-component-tree.js +840 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/create-error-handler.js +189 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/create-flight-router-state-from-loader-tree.js +102 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/csrf-protection.js +86 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/debug-channel-server.js +30 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/debug-channel-server.web.js +71 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/dynamic-access-async-storage-instance.js +14 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/dynamic-access-async-storage.external.js +13 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/dynamic-rendering.js +1144 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/encryption-utils-server.js +114 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/encryption-utils.js +93 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/encryption.js +259 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/entry-base.js +256 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/flight-render-result.js +28 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/get-asset-query-string.js +29 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/get-css-inlined-link-tags.js +49 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/get-layer-assets.js +65 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/get-preloadable-fonts.js +39 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/get-script-nonce-from-header.js +44 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/get-short-dynamic-param-type.js +25 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/has-loading-component-in-tree.js +19 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/instant-validation/boundary-constants.js +13 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/instant-validation/boundary-impl.js +103 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/instant-validation/boundary-tracking.js +18 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/instant-validation/instant-config.js +181 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/instant-validation/instant-samples-client.js +128 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/instant-validation/instant-samples.js +432 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/instant-validation/instant-validation-error.js +33 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/instant-validation/instant-validation.js +713 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/instant-validation/stream-utils.js +96 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/interop-default.js +17 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/make-get-server-inserted-html.js +92 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/manifests-singleton.js +264 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/metadata-insertion/create-server-inserted-metadata.js +28 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/module-loading/track-dynamic-import.js +57 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/module-loading/track-module-loading.external.js +32 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/module-loading/track-module-loading.instance.js +66 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/parse-and-validate-flight-router-state.js +49 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/postponed-state.js +157 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/prospective-render-utils.js +74 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/react-large-shell-error.js +17 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/react-server.node.js +39 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/render-css-resource.js +52 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/required-scripts.js +76 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/rsc/postpone.js +18 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/rsc/preloads.js +74 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/rsc/taint.js +79 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/segment-explorer-path.js +128 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/server-inserted-html.js +77 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/staged-rendering.js +343 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/stale-time.js +111 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/stream-ops.js +106 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/stream-ops.web.js +163 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/strip-flight-headers.js +18 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/types.js +65 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/use-flight-response.js +214 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/vary-params.js +336 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/walk-tree-with-flight-router-state.js +232 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/work-async-storage-instance.js +14 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/work-async-storage.external.js +13 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/work-unit-async-storage-instance.js +14 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/work-unit-async-storage.external.js +280 -0
- package/.next/standalone/node_modules/next/dist/server/async-storage/draft-mode-provider.js +62 -0
- package/.next/standalone/node_modules/next/dist/server/async-storage/request-store.js +144 -0
- package/.next/standalone/node_modules/next/dist/server/async-storage/with-store.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/async-storage/work-store.js +91 -0
- package/.next/standalone/node_modules/next/dist/server/base-http/helpers.js +36 -0
- package/.next/standalone/node_modules/next/dist/server/base-http/index.js +54 -0
- package/.next/standalone/node_modules/next/dist/server/base-http/node.js +147 -0
- package/.next/standalone/node_modules/next/dist/server/base-http/web.js +124 -0
- package/.next/standalone/node_modules/next/dist/server/base-server.js +1874 -0
- package/.next/standalone/node_modules/next/dist/server/body-streams.js +114 -0
- package/.next/standalone/node_modules/next/dist/server/cache-dir.js +26 -0
- package/.next/standalone/node_modules/next/dist/server/capsize-font-metrics.json +181516 -0
- package/.next/standalone/node_modules/next/dist/server/ci-info.js +41 -0
- package/.next/standalone/node_modules/next/dist/server/client-component-renderer-logger.js +70 -0
- package/.next/standalone/node_modules/next/dist/server/config-schema.js +718 -0
- package/.next/standalone/node_modules/next/dist/server/config-shared.js +369 -0
- package/.next/standalone/node_modules/next/dist/server/config-utils.js +185 -0
- package/.next/standalone/node_modules/next/dist/server/config.js +1545 -0
- package/.next/standalone/node_modules/next/dist/server/create-deduped-by-callsite-server-error-logger.js +96 -0
- package/.next/standalone/node_modules/next/dist/server/crypto-utils.js +70 -0
- package/.next/standalone/node_modules/next/dist/server/dev/browser-logs/file-logger.js +186 -0
- package/.next/standalone/node_modules/next/dist/server/dev/browser-logs/receive-logs.js +558 -0
- package/.next/standalone/node_modules/next/dist/server/dev/browser-logs/source-map.js +222 -0
- package/.next/standalone/node_modules/next/dist/server/dev/debug-channel.js +87 -0
- package/.next/standalone/node_modules/next/dist/server/dev/dev-indicator-server-state.js +15 -0
- package/.next/standalone/node_modules/next/dist/server/dev/get-source-map-from-file.js +100 -0
- package/.next/standalone/node_modules/next/dist/server/dev/hot-middleware.js +274 -0
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-rspack.js +171 -0
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-shared-utils.js +56 -0
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-turbopack.js +1475 -0
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-types.js +58 -0
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-webpack.js +1386 -0
- package/.next/standalone/node_modules/next/dist/server/dev/log-requests.js +149 -0
- package/.next/standalone/node_modules/next/dist/server/dev/messages.js +74 -0
- package/.next/standalone/node_modules/next/dist/server/dev/middleware-turbopack.js +403 -0
- package/.next/standalone/node_modules/next/dist/server/dev/middleware-webpack.js +483 -0
- package/.next/standalone/node_modules/next/dist/server/dev/node-stack-frames.js +72 -0
- package/.next/standalone/node_modules/next/dist/server/dev/on-demand-entry-handler.js +773 -0
- package/.next/standalone/node_modules/next/dist/server/dev/parse-version-info.js +108 -0
- package/.next/standalone/node_modules/next/dist/server/dev/require-cache.js +79 -0
- package/.next/standalone/node_modules/next/dist/server/dev/serialized-errors.js +67 -0
- package/.next/standalone/node_modules/next/dist/server/dev/server-action-logger.js +37 -0
- package/.next/standalone/node_modules/next/dist/server/dev/static-paths-worker.js +104 -0
- package/.next/standalone/node_modules/next/dist/server/dev/turbopack-utils.js +687 -0
- package/.next/standalone/node_modules/next/dist/server/dynamic-rendering-utils.js +108 -0
- package/.next/standalone/node_modules/next/dist/server/font-utils.js +43 -0
- package/.next/standalone/node_modules/next/dist/server/get-app-route-from-entrypoint.js +30 -0
- package/.next/standalone/node_modules/next/dist/server/get-page-files.js +23 -0
- package/.next/standalone/node_modules/next/dist/server/get-route-from-entrypoint.js +35 -0
- package/.next/standalone/node_modules/next/dist/server/htmlescape.js +37 -0
- package/.next/standalone/node_modules/next/dist/server/image-optimizer.js +1220 -0
- package/.next/standalone/node_modules/next/dist/server/instrumentation/types.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/instrumentation/utils.js +21 -0
- package/.next/standalone/node_modules/next/dist/server/internal-utils.js +39 -0
- package/.next/standalone/node_modules/next/dist/server/is-private-ip.js +36 -0
- package/.next/standalone/node_modules/next/dist/server/lib/app-dir-module.js +59 -0
- package/.next/standalone/node_modules/next/dist/server/lib/app-info-log.js +132 -0
- package/.next/standalone/node_modules/next/dist/server/lib/async-callback-set.js +29 -0
- package/.next/standalone/node_modules/next/dist/server/lib/cache-control.js +22 -0
- package/.next/standalone/node_modules/next/dist/server/lib/cache-handlers/default.external.js +18 -0
- package/.next/standalone/node_modules/next/dist/server/lib/cache-handlers/default.js +160 -0
- package/.next/standalone/node_modules/next/dist/server/lib/cache-handlers/types.js +8 -0
- package/.next/standalone/node_modules/next/dist/server/lib/chrome-devtools-workspace.js +116 -0
- package/.next/standalone/node_modules/next/dist/server/lib/clone-response.js +77 -0
- package/.next/standalone/node_modules/next/dist/server/lib/cpu-profile.js +59 -0
- package/.next/standalone/node_modules/next/dist/server/lib/decode-query-path-parameter.js +26 -0
- package/.next/standalone/node_modules/next/dist/server/lib/dedupe-fetch.js +163 -0
- package/.next/standalone/node_modules/next/dist/server/lib/dev-bundler-service.js +95 -0
- package/.next/standalone/node_modules/next/dist/server/lib/disk-lru-cache.external.js +57 -0
- package/.next/standalone/node_modules/next/dist/server/lib/etag.js +56 -0
- package/.next/standalone/node_modules/next/dist/server/lib/experimental/create-env-definitions.js +48 -0
- package/.next/standalone/node_modules/next/dist/server/lib/experimental/ppr.js +47 -0
- package/.next/standalone/node_modules/next/dist/server/lib/find-page-file.js +147 -0
- package/.next/standalone/node_modules/next/dist/server/lib/fix-mojibake.js +25 -0
- package/.next/standalone/node_modules/next/dist/server/lib/format-hostname.js +16 -0
- package/.next/standalone/node_modules/next/dist/server/lib/i18n-provider.js +129 -0
- package/.next/standalone/node_modules/next/dist/server/lib/implicit-tags.js +77 -0
- package/.next/standalone/node_modules/next/dist/server/lib/incremental-cache/file-system-cache.js +335 -0
- package/.next/standalone/node_modules/next/dist/server/lib/incremental-cache/index.js +501 -0
- package/.next/standalone/node_modules/next/dist/server/lib/incremental-cache/memory-cache.external.js +57 -0
- package/.next/standalone/node_modules/next/dist/server/lib/incremental-cache/shared-cache-controls.external.js +73 -0
- package/.next/standalone/node_modules/next/dist/server/lib/incremental-cache/tags-manifest.external.js +55 -0
- package/.next/standalone/node_modules/next/dist/server/lib/install-code-frame.js +22 -0
- package/.next/standalone/node_modules/next/dist/server/lib/is-ipv6.js +41 -0
- package/.next/standalone/node_modules/next/dist/server/lib/lazy-result.js +46 -0
- package/.next/standalone/node_modules/next/dist/server/lib/lru-cache.js +191 -0
- package/.next/standalone/node_modules/next/dist/server/lib/match-next-data-pathname.js +18 -0
- package/.next/standalone/node_modules/next/dist/server/lib/mock-request.js +416 -0
- package/.next/standalone/node_modules/next/dist/server/lib/module-loader/module-loader.js +8 -0
- package/.next/standalone/node_modules/next/dist/server/lib/module-loader/node-module-loader.js +25 -0
- package/.next/standalone/node_modules/next/dist/server/lib/module-loader/route-module-loader.js +26 -0
- package/.next/standalone/node_modules/next/dist/server/lib/node-fs-methods.js +28 -0
- package/.next/standalone/node_modules/next/dist/server/lib/parse-stack.js +46 -0
- package/.next/standalone/node_modules/next/dist/server/lib/patch-fetch.js +978 -0
- package/.next/standalone/node_modules/next/dist/server/lib/patch-set-header.js +38 -0
- package/.next/standalone/node_modules/next/dist/server/lib/postponed-request-body.js +64 -0
- package/.next/standalone/node_modules/next/dist/server/lib/render-server.js +155 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-server.js +696 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/block-cross-site-dev.js +110 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/build-data-route.js +48 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/build-prefetch-segment-data-route.js +50 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/cache-life-type-utils.js +211 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/decode-path-params.js +42 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/filesystem.js +591 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/instrumentation-globals.external.js +89 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/instrumentation-node-extensions.js +96 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/is-postpone.js +16 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/proxy-request.js +118 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/resolve-routes.js +629 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/route-types-utils.js +286 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/router-server-context.js +26 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/typegen.js +858 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/types.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/lib/server-action-request-meta.js +53 -0
- package/.next/standalone/node_modules/next/dist/server/lib/server-ipc/utils.js +81 -0
- package/.next/standalone/node_modules/next/dist/server/lib/source-maps.js +196 -0
- package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +494 -0
- package/.next/standalone/node_modules/next/dist/server/lib/streaming-metadata.js +38 -0
- package/.next/standalone/node_modules/next/dist/server/lib/to-route.js +37 -0
- package/.next/standalone/node_modules/next/dist/server/lib/trace/constants.js +203 -0
- package/.next/standalone/node_modules/next/dist/server/lib/trace/tracer.js +280 -0
- package/.next/standalone/node_modules/next/dist/server/lib/trace/utils.js +16 -0
- package/.next/standalone/node_modules/next/dist/server/lib/types.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/lib/utils.js +278 -0
- package/.next/standalone/node_modules/next/dist/server/lib/worker-utils.js +36 -0
- package/.next/standalone/node_modules/next/dist/server/load-components.js +179 -0
- package/.next/standalone/node_modules/next/dist/server/load-default-error-components.js +41 -0
- package/.next/standalone/node_modules/next/dist/server/load-manifest.external.js +117 -0
- package/.next/standalone/node_modules/next/dist/server/match-bundle.js +25 -0
- package/.next/standalone/node_modules/next/dist/server/mcp/get-mcp-middleware.js +49 -0
- package/.next/standalone/node_modules/next/dist/server/mcp/get-or-create-mcp-server.js +41 -0
- package/.next/standalone/node_modules/next/dist/server/mcp/mcp-telemetry-tracker.js +82 -0
- package/.next/standalone/node_modules/next/dist/server/mcp/tools/get-errors.js +114 -0
- package/.next/standalone/node_modules/next/dist/server/mcp/tools/get-logs.js +67 -0
- package/.next/standalone/node_modules/next/dist/server/mcp/tools/get-page-metadata.js +188 -0
- package/.next/standalone/node_modules/next/dist/server/mcp/tools/get-project-metadata.js +59 -0
- package/.next/standalone/node_modules/next/dist/server/mcp/tools/get-routes.js +136 -0
- package/.next/standalone/node_modules/next/dist/server/mcp/tools/get-server-action-by-id.js +121 -0
- package/.next/standalone/node_modules/next/dist/server/mcp/tools/next-instance-error-state.js +31 -0
- package/.next/standalone/node_modules/next/dist/server/mcp/tools/utils/browser-communication.js +90 -0
- package/.next/standalone/node_modules/next/dist/server/mcp/tools/utils/format-errors.js +137 -0
- package/.next/standalone/node_modules/next/dist/server/next-server.js +1429 -0
- package/.next/standalone/node_modules/next/dist/server/next-typescript.js +13 -0
- package/.next/standalone/node_modules/next/dist/server/next.js +455 -0
- package/.next/standalone/node_modules/next/dist/server/node-environment-baseline.js +25 -0
- package/.next/standalone/node_modules/next/dist/server/node-environment-extensions/console-dim.external.js +301 -0
- package/.next/standalone/node_modules/next/dist/server/node-environment-extensions/console-exit.js +49 -0
- package/.next/standalone/node_modules/next/dist/server/node-environment-extensions/console-file.js +56 -0
- package/.next/standalone/node_modules/next/dist/server/node-environment-extensions/date.js +52 -0
- package/.next/standalone/node_modules/next/dist/server/node-environment-extensions/error-inspect.js +8 -0
- package/.next/standalone/node_modules/next/dist/server/node-environment-extensions/fast-set-immediate.external.js +577 -0
- package/.next/standalone/node_modules/next/dist/server/node-environment-extensions/global-behaviors.js +33 -0
- package/.next/standalone/node_modules/next/dist/server/node-environment-extensions/io-utils.js +195 -0
- package/.next/standalone/node_modules/next/dist/server/node-environment-extensions/node-crypto.js +103 -0
- package/.next/standalone/node_modules/next/dist/server/node-environment-extensions/process-error-handlers.js +91 -0
- package/.next/standalone/node_modules/next/dist/server/node-environment-extensions/random.js +28 -0
- package/.next/standalone/node_modules/next/dist/server/node-environment-extensions/unhandled-rejection.external.js +508 -0
- package/.next/standalone/node_modules/next/dist/server/node-environment-extensions/web-crypto.js +45 -0
- package/.next/standalone/node_modules/next/dist/server/node-environment.js +19 -0
- package/.next/standalone/node_modules/next/dist/server/node-polyfill-crypto.js +21 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/absolute-filename-normalizer.js +33 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/built/app/app-bundle-path-normalizer.js +54 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/built/app/app-filename-normalizer.js +22 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/built/app/app-page-normalizer.js +40 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/built/app/app-pathname-normalizer.js +55 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/built/app/index.js +42 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/built/pages/index.js +44 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/built/pages/pages-bundle-path-normalizer.js +55 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/built/pages/pages-filename-normalizer.js +22 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/built/pages/pages-page-normalizer.js +19 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/built/pages/pages-pathname-normalizer.js +19 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/locale-route-normalizer.js +26 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/normalizer.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/normalizers.js +23 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/prefixing-normalizer.js +26 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/request/base-path.js +25 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/request/next-data.js +38 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/request/pathname-normalizer.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/request/prefix.js +39 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/request/rsc.js +19 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/request/segment-prefix-rsc.js +33 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/request/suffix.js +27 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/underscore-normalizer.js +17 -0
- package/.next/standalone/node_modules/next/dist/server/normalizers/wrap-normalizer-fn.js +17 -0
- package/.next/standalone/node_modules/next/dist/server/og/image-response.js +53 -0
- package/.next/standalone/node_modules/next/dist/server/patch-error-inspect.js +453 -0
- package/.next/standalone/node_modules/next/dist/server/pipe-readable.js +140 -0
- package/.next/standalone/node_modules/next/dist/server/post-process.js +39 -0
- package/.next/standalone/node_modules/next/dist/server/render-result.js +204 -0
- package/.next/standalone/node_modules/next/dist/server/render.js +1140 -0
- package/.next/standalone/node_modules/next/dist/server/request/connection.js +133 -0
- package/.next/standalone/node_modules/next/dist/server/request/cookies.js +235 -0
- package/.next/standalone/node_modules/next/dist/server/request/draft-mode.js +230 -0
- package/.next/standalone/node_modules/next/dist/server/request/fallback-params.js +69 -0
- package/.next/standalone/node_modules/next/dist/server/request/headers.js +229 -0
- package/.next/standalone/node_modules/next/dist/server/request/params.js +527 -0
- package/.next/standalone/node_modules/next/dist/server/request/pathname.js +119 -0
- package/.next/standalone/node_modules/next/dist/server/request/root-params.js +194 -0
- package/.next/standalone/node_modules/next/dist/server/request/search-params.js +526 -0
- package/.next/standalone/node_modules/next/dist/server/request/utils.js +51 -0
- package/.next/standalone/node_modules/next/dist/server/request-meta.js +55 -0
- package/.next/standalone/node_modules/next/dist/server/require-hook.js +82 -0
- package/.next/standalone/node_modules/next/dist/server/require.js +109 -0
- package/.next/standalone/node_modules/next/dist/server/response-cache/index.js +311 -0
- package/.next/standalone/node_modules/next/dist/server/response-cache/types.js +41 -0
- package/.next/standalone/node_modules/next/dist/server/response-cache/utils.js +104 -0
- package/.next/standalone/node_modules/next/dist/server/response-cache/web.js +101 -0
- package/.next/standalone/node_modules/next/dist/server/resume-data-cache/cache-store.js +96 -0
- package/.next/standalone/node_modules/next/dist/server/resume-data-cache/resume-data-cache.js +124 -0
- package/.next/standalone/node_modules/next/dist/server/revalidation-utils.js +157 -0
- package/.next/standalone/node_modules/next/dist/server/route-definitions/app-page-route-definition.js +16 -0
- package/.next/standalone/node_modules/next/dist/server/route-definitions/app-route-route-definition.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/route-definitions/locale-route-definition.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/route-definitions/pages-api-route-definition.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/route-definitions/pages-route-definition.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/route-definitions/route-definition.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/route-kind.js +32 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-managers/default-route-matcher-manager.js +239 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-managers/dev-route-matcher-manager.js +120 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-managers/route-matcher-manager.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/app-page-route-matcher-provider.js +55 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/app-route-route-matcher-provider.js +43 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/dev/dev-app-page-route-matcher-provider.js +91 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/dev/dev-app-route-route-matcher-provider.js +112 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/dev/dev-pages-api-route-matcher-provider.js +77 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/dev/dev-pages-route-matcher-provider.js +77 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/dev/file-cache-route-matcher-provider.js +28 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/dev/helpers/file-reader/batched-file-reader.js +106 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/dev/helpers/file-reader/default-file-reader.js +42 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/dev/helpers/file-reader/file-reader.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/helpers/cached-route-matcher-provider.js +30 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/helpers/manifest-loaders/manifest-loader.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/helpers/manifest-loaders/node-manifest-loader.js +34 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/helpers/manifest-loaders/server-manifest-loader.js +20 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/manifest-route-matcher-provider.js +21 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/pages-api-route-matcher-provider.js +55 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/pages-route-matcher-provider.js +64 -0
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/route-matcher-provider.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/route-matchers/app-page-route-matcher.js +18 -0
- package/.next/standalone/node_modules/next/dist/server/route-matchers/app-route-route-matcher.js +15 -0
- package/.next/standalone/node_modules/next/dist/server/route-matchers/locale-route-matcher.js +68 -0
- package/.next/standalone/node_modules/next/dist/server/route-matchers/pages-api-route-matcher.js +30 -0
- package/.next/standalone/node_modules/next/dist/server/route-matchers/pages-route-matcher.js +30 -0
- package/.next/standalone/node_modules/next/dist/server/route-matchers/route-matcher.js +54 -0
- package/.next/standalone/node_modules/next/dist/server/route-matches/app-page-route-match.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/route-matches/app-route-route-match.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/route-matches/locale-route-match.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/route-matches/pages-api-route-match.js +16 -0
- package/.next/standalone/node_modules/next/dist/server/route-matches/pages-route-match.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/route-matches/route-match.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/helpers/prerender-manifest-matcher.js +51 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/module.compiled.js +36 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/module.js +162 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/module.render.js +24 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/normalize-request-url.js +25 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/contexts/app-router-context.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/contexts/entrypoints.js +87 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/contexts/head-manager-context.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/contexts/hooks-client-context.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/contexts/image-config-context.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/contexts/router-context.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/contexts/server-inserted-html.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/rsc/entrypoints.js +140 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/rsc/react-compiler-runtime.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/rsc/react-dom.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/rsc/react-jsx-dev-runtime.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/rsc/react-jsx-runtime.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/rsc/react-server-dom-turbopack-server.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/rsc/react-server-dom-turbopack-static.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/rsc/react-server-dom-webpack-server.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/rsc/react-server-dom-webpack-static.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/rsc/react.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/ssr/entrypoints.js +125 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/ssr/react-compiler-runtime.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/ssr/react-dom-server.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/ssr/react-dom.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/ssr/react-jsx-dev-runtime.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/ssr/react-jsx-runtime.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/ssr/react-server-dom-turbopack-client.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/ssr/react-server-dom-webpack-client.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-page/vendored/ssr/react.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-route/helpers/auto-implement-methods.js +85 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-route/helpers/clean-url.js +24 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-route/helpers/get-pathname-from-absolute-path.js +29 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-route/helpers/is-static-gen-enabled.js +15 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-route/helpers/parsed-url-query-to-params.js +20 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-route/module.compiled.js +36 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-route/module.js +914 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-route/shared-modules.js +56 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/checks.js +45 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/builtin/_error.js +100 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/module.compiled.js +20 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/module.js +92 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/module.render.js +24 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/pages-handler.js +545 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/vendored/contexts/app-router-context.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/vendored/contexts/entrypoints.js +102 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/vendored/contexts/head-manager-context.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/vendored/contexts/hooks-client-context.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/vendored/contexts/html-context.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/vendored/contexts/image-config-context.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/vendored/contexts/loadable-context.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/vendored/contexts/loadable.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/vendored/contexts/router-context.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/vendored/contexts/server-inserted-html.js +4 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages-api/module.compiled.js +20 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages-api/module.js +58 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/route-module.js +650 -0
- package/.next/standalone/node_modules/next/dist/server/runtime-reacts.external.js +46 -0
- package/.next/standalone/node_modules/next/dist/server/send-payload.js +88 -0
- package/.next/standalone/node_modules/next/dist/server/send-response.js +70 -0
- package/.next/standalone/node_modules/next/dist/server/serve-static.js +66 -0
- package/.next/standalone/node_modules/next/dist/server/server-route-utils.js +30 -0
- package/.next/standalone/node_modules/next/dist/server/server-utils.js +323 -0
- package/.next/standalone/node_modules/next/dist/server/setup-http-agent-env.js +31 -0
- package/.next/standalone/node_modules/next/dist/server/stream-utils/encoded-tags.js +122 -0
- package/.next/standalone/node_modules/next/dist/server/stream-utils/node-web-streams-helper.js +918 -0
- package/.next/standalone/node_modules/next/dist/server/stream-utils/uint8array-helpers.js +74 -0
- package/.next/standalone/node_modules/next/dist/server/typescript/constant.js +98 -0
- package/.next/standalone/node_modules/next/dist/server/typescript/index.js +199 -0
- package/.next/standalone/node_modules/next/dist/server/typescript/rules/client-boundary.js +97 -0
- package/.next/standalone/node_modules/next/dist/server/typescript/rules/config.js +512 -0
- package/.next/standalone/node_modules/next/dist/server/typescript/rules/entry.js +149 -0
- package/.next/standalone/node_modules/next/dist/server/typescript/rules/error.js +38 -0
- package/.next/standalone/node_modules/next/dist/server/typescript/rules/metadata.js +234 -0
- package/.next/standalone/node_modules/next/dist/server/typescript/rules/server-boundary.js +115 -0
- package/.next/standalone/node_modules/next/dist/server/typescript/rules/server.js +79 -0
- package/.next/standalone/node_modules/next/dist/server/typescript/utils.js +212 -0
- package/.next/standalone/node_modules/next/dist/server/use-cache/cache-life.js +163 -0
- package/.next/standalone/node_modules/next/dist/server/use-cache/cache-tag.js +52 -0
- package/.next/standalone/node_modules/next/dist/server/use-cache/constants.js +28 -0
- package/.next/standalone/node_modules/next/dist/server/use-cache/handlers.js +121 -0
- package/.next/standalone/node_modules/next/dist/server/use-cache/use-cache-errors.js +36 -0
- package/.next/standalone/node_modules/next/dist/server/use-cache/use-cache-wrapper.js +1588 -0
- package/.next/standalone/node_modules/next/dist/server/utils.js +73 -0
- package/.next/standalone/node_modules/next/dist/server/web/adapter.js +392 -0
- package/.next/standalone/node_modules/next/dist/server/web/edge-route-module-wrapper.js +123 -0
- package/.next/standalone/node_modules/next/dist/server/web/error.js +54 -0
- package/.next/standalone/node_modules/next/dist/server/web/exports/index.js +56 -0
- package/.next/standalone/node_modules/next/dist/server/web/get-edge-preview-props.js +23 -0
- package/.next/standalone/node_modules/next/dist/server/web/globals.js +128 -0
- package/.next/standalone/node_modules/next/dist/server/web/http.js +39 -0
- package/.next/standalone/node_modules/next/dist/server/web/internal-edge-wait-until.js +64 -0
- package/.next/standalone/node_modules/next/dist/server/web/next-url.js +199 -0
- package/.next/standalone/node_modules/next/dist/server/web/sandbox/context.js +462 -0
- package/.next/standalone/node_modules/next/dist/server/web/sandbox/fetch-inline-assets.js +35 -0
- package/.next/standalone/node_modules/next/dist/server/web/sandbox/index.js +28 -0
- package/.next/standalone/node_modules/next/dist/server/web/sandbox/resource-managers.js +88 -0
- package/.next/standalone/node_modules/next/dist/server/web/sandbox/sandbox.js +137 -0
- package/.next/standalone/node_modules/next/dist/server/web/spec-extension/adapters/headers.js +192 -0
- package/.next/standalone/node_modules/next/dist/server/web/spec-extension/adapters/next-request.js +142 -0
- package/.next/standalone/node_modules/next/dist/server/web/spec-extension/adapters/reflect.js +30 -0
- package/.next/standalone/node_modules/next/dist/server/web/spec-extension/adapters/request-cookies.js +211 -0
- package/.next/standalone/node_modules/next/dist/server/web/spec-extension/cookies.js +29 -0
- package/.next/standalone/node_modules/next/dist/server/web/spec-extension/fetch-event.js +98 -0
- package/.next/standalone/node_modules/next/dist/server/web/spec-extension/image-response.js +22 -0
- package/.next/standalone/node_modules/next/dist/server/web/spec-extension/request.js +99 -0
- package/.next/standalone/node_modules/next/dist/server/web/spec-extension/response.js +136 -0
- package/.next/standalone/node_modules/next/dist/server/web/spec-extension/revalidate.js +214 -0
- package/.next/standalone/node_modules/next/dist/server/web/spec-extension/unstable-cache.js +289 -0
- package/.next/standalone/node_modules/next/dist/server/web/spec-extension/unstable-no-store.js +51 -0
- package/.next/standalone/node_modules/next/dist/server/web/spec-extension/url-pattern.js +14 -0
- package/.next/standalone/node_modules/next/dist/server/web/spec-extension/user-agent.js +46 -0
- package/.next/standalone/node_modules/next/dist/server/web/types.js +6 -0
- package/.next/standalone/node_modules/next/dist/server/web/utils.js +151 -0
- package/.next/standalone/node_modules/next/dist/server/web/web-on-close.js +87 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/action-revalidation-kind.js +31 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/app-router-context.shared-runtime.js +50 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/app-router-types.js +46 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/constants.js +448 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/deep-freeze.js +30 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/deployment-id.js +63 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/dset.js +34 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/encode-uri-path.js +15 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/entry-constants.js +36 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/error-source.js +36 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/errors/canary-only-config-error.js +39 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/errors/code-frame.js +20 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/errors/constants.js +19 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/errors/empty-generate-static-params-error.js +24 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/errors/hard-deprecated-config-error.js +20 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/escape-regexp.js +22 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/get-hostname.js +23 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/hash.js +42 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/head-manager-context.shared-runtime.js +18 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/head.js +163 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/hooks-client-context.shared-runtime.js +60 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/html-context.shared-runtime.js +40 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/i18n/detect-domain-locale.js +25 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/i18n/get-locale-redirect.js +59 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/i18n/normalize-locale-path.js +54 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/image-blur-svg.js +22 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/image-config-context.shared-runtime.js +19 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/image-config.js +77 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/invariant-error.js +18 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/is-plain-object.js +42 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/is-thenable.js +20 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/isomorphic/path.js +14 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/lazy-dynamic/bailout-to-csr.js +37 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/loadable-context.shared-runtime.js +19 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/loadable.shared-runtime.js +246 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/match-local-pattern.js +46 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/match-remote-pattern.js +63 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/modern-browserslist-target.js +15 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/no-fallback-error.external.js +18 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/normalized-asset-prefix.js +28 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/page-path/absolute-path-to-page.js +26 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/page-path/denormalize-page-path.js +18 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/page-path/ensure-leading-slash.js +18 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/page-path/get-page-paths.js +40 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/page-path/normalize-data-path.js +23 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/page-path/normalize-page-path.js +26 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/page-path/normalize-path-sep.js +19 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/page-path/remove-page-path-tail.js +20 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/promise-with-resolvers.js +26 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/adapters.js +136 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/routes/app.js +122 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/add-locale.js +28 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/add-path-prefix.js +20 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/add-path-suffix.js +20 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/app-paths.js +62 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/as-path-to-search-params.js +17 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/cache-busting-search-param.js +24 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/escape-path-delimiters.js +16 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/format-next-pathname-info.js +27 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/format-url.js +111 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/get-dynamic-param.js +174 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/get-next-pathname-info.js +52 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/get-route-from-asset-path.js +25 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/get-segment-param.js +90 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/html-bots.js +17 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/index.js +30 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/interception-prefix-from-param-type.js +33 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/interception-routes.js +108 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/is-bot.js +57 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/is-dynamic.js +26 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/middleware-route-matcher.js +31 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/parse-loader-tree.js +30 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/parse-path.js +33 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/parse-relative-url.js +43 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/parse-url.js +38 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/path-has-prefix.js +20 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/path-match.js +49 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/prepare-destination.js +292 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/querystring.js +79 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/relativize-url.js +40 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/remove-path-prefix.js +39 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/remove-trailing-slash.js +21 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/resolve-param-value.js +116 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/route-match-utils.js +113 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/route-matcher.js +45 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/route-regex.js +256 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/sorted-routes.js +244 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router-context.shared-runtime.js +18 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/segment-cache/segment-value-encoding.js +99 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/segment-cache/vary-params-decoding.js +32 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/segment.js +102 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/server-inserted-html.shared-runtime.js +35 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/server-reference-info.js +56 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/side-effect.js +63 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/size-limit.js +40 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/turbopack/internal-error.js +53 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/utils/reflect-utils.js +69 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/utils/warn-once.js +22 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/utils.js +207 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/zod.js +101 -0
- package/.next/standalone/node_modules/next/dist/telemetry/anonymous-meta.js +89 -0
- package/.next/standalone/node_modules/next/dist/telemetry/detached-flush.js +56 -0
- package/.next/standalone/node_modules/next/dist/telemetry/events/build.js +174 -0
- package/.next/standalone/node_modules/next/dist/telemetry/events/index.js +41 -0
- package/.next/standalone/node_modules/next/dist/telemetry/events/plugins.js +51 -0
- package/.next/standalone/node_modules/next/dist/telemetry/events/swc-load-failure.js +55 -0
- package/.next/standalone/node_modules/next/dist/telemetry/events/version.js +66 -0
- package/.next/standalone/node_modules/next/dist/telemetry/flush-telemetry.js +19 -0
- package/.next/standalone/node_modules/next/dist/telemetry/post-telemetry-payload.js +48 -0
- package/.next/standalone/node_modules/next/dist/telemetry/project-id.js +48 -0
- package/.next/standalone/node_modules/next/dist/telemetry/storage.js +301 -0
- package/.next/standalone/node_modules/next/dist/trace/index.js +58 -0
- package/.next/standalone/node_modules/next/dist/trace/report/index.js +37 -0
- package/.next/standalone/node_modules/next/dist/trace/report/to-json-build.js +40 -0
- package/.next/standalone/node_modules/next/dist/trace/report/to-json.js +165 -0
- package/.next/standalone/node_modules/next/dist/trace/report/to-telemetry.js +36 -0
- package/.next/standalone/node_modules/next/dist/trace/shared.js +39 -0
- package/.next/standalone/node_modules/next/dist/trace/trace.js +211 -0
- package/.next/standalone/node_modules/next/package.json +378 -0
- package/.next/standalone/node_modules/react/cjs/react-compiler-runtime.production.js +16 -0
- package/.next/standalone/node_modules/react/cjs/react-jsx-dev-runtime.production.js +14 -0
- package/.next/standalone/node_modules/react/cjs/react-jsx-runtime.production.js +34 -0
- package/.next/standalone/node_modules/react/cjs/react.development.js +1284 -0
- package/.next/standalone/node_modules/react/cjs/react.production.js +542 -0
- package/.next/standalone/node_modules/react/compiler-runtime.js +14 -0
- package/.next/standalone/node_modules/react/index.js +7 -0
- package/.next/standalone/node_modules/react/jsx-dev-runtime.js +7 -0
- package/.next/standalone/node_modules/react/jsx-runtime.js +7 -0
- package/.next/standalone/node_modules/react/package.json +51 -0
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.js +6603 -0
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.node.production.js +6692 -0
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.browser.production.js +7410 -0
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.edge.production.js +7512 -0
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.node.production.js +7707 -0
- package/.next/standalone/node_modules/react-dom/cjs/react-dom.production.js +210 -0
- package/.next/standalone/node_modules/react-dom/index.js +38 -0
- package/.next/standalone/node_modules/react-dom/package.json +117 -0
- package/.next/standalone/node_modules/react-dom/server.browser.js +16 -0
- package/.next/standalone/node_modules/react-dom/server.edge.js +17 -0
- package/.next/standalone/node_modules/react-dom/server.node.js +18 -0
- package/.next/standalone/node_modules/react-dom/static.node.js +14 -0
- package/.next/standalone/node_modules/sharp/lib/channel.js +177 -0
- package/.next/standalone/node_modules/sharp/lib/colour.js +195 -0
- package/.next/standalone/node_modules/sharp/lib/composite.js +212 -0
- package/.next/standalone/node_modules/sharp/lib/constructor.js +499 -0
- package/.next/standalone/node_modules/sharp/lib/index.js +16 -0
- package/.next/standalone/node_modules/sharp/lib/input.js +809 -0
- package/.next/standalone/node_modules/sharp/lib/is.js +143 -0
- package/.next/standalone/node_modules/sharp/lib/libvips.js +207 -0
- package/.next/standalone/node_modules/sharp/lib/operation.js +1016 -0
- package/.next/standalone/node_modules/sharp/lib/output.js +1666 -0
- package/.next/standalone/node_modules/sharp/lib/resize.js +595 -0
- package/.next/standalone/node_modules/sharp/lib/sharp.js +121 -0
- package/.next/standalone/node_modules/sharp/lib/utility.js +291 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/classes/comparator.js +143 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/classes/range.js +557 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/classes/semver.js +333 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/cmp.js +54 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/coerce.js +62 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/compare.js +7 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/eq.js +5 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/gt.js +5 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/gte.js +5 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/lt.js +5 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/lte.js +5 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/neq.js +5 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/parse.js +18 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/satisfies.js +12 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/internal/constants.js +37 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/internal/debug.js +11 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/internal/identifiers.js +29 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/internal/lrucache.js +42 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/internal/parse-options.js +17 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/internal/re.js +223 -0
- package/.next/standalone/node_modules/sharp/node_modules/semver/package.json +78 -0
- package/.next/standalone/node_modules/sharp/package.json +202 -0
- package/.next/standalone/node_modules/styled-jsx/dist/index/index.js +499 -0
- package/.next/standalone/node_modules/styled-jsx/index.js +1 -0
- package/.next/standalone/node_modules/styled-jsx/package.json +132 -0
- package/.next/standalone/node_modules/styled-jsx/style.js +1 -0
- package/.next/standalone/package.json +55 -0
- package/.next/standalone/server.js +38 -0
- package/.next/static/BgLP6ChyOyE0k8Ahr8F2H/_buildManifest.js +11 -0
- package/.next/static/BgLP6ChyOyE0k8Ahr8F2H/_clientMiddlewareManifest.js +1 -0
- package/.next/static/BgLP6ChyOyE0k8Ahr8F2H/_ssgManifest.js +1 -0
- package/.next/static/chunks/01xlw8hd842-c.js +1 -0
- package/.next/static/chunks/03~yq9q893hmn.js +1 -0
- package/.next/static/chunks/0bogtdbh.dcu1.js +1 -0
- package/.next/static/chunks/0bzupvr5gt3k9.js +31 -0
- package/.next/static/chunks/0d3shmwh5_nmn.js +1 -0
- package/.next/static/chunks/0iym2_f33sxs7.css +4 -0
- package/.next/static/chunks/0mmpyn9fv2fjf.js +2 -0
- package/.next/static/chunks/0qmupjhwdppg9.js +11 -0
- package/.next/static/chunks/0y3~cortx~or~.js +5 -0
- package/.next/static/chunks/12p3iqtw2ohfq.js +1 -0
- package/.next/static/chunks/turbopack-06dy8k5p5cegf.js +1 -0
- package/.next/static/media/166ab60e98aadb0a-s.p.0mka4ru4_bj1d.woff2 +0 -0
- package/.next/static/media/1bffadaabf893a1e-s.16ipb6fqu393i.woff2 +0 -0
- package/.next/static/media/2bbe8d2671613f1f-s.067x_6k0k23tk.woff2 +0 -0
- package/.next/static/media/2c55a0e60120577a-s.0bjc5tiuqdqro.woff2 +0 -0
- package/.next/static/media/47fe59148dddec23-s.0miki_k4yhs4d.woff2 +0 -0
- package/.next/static/media/4e86c6b06ecb547e-s.0w2c6_8~q7i1~.woff2 +0 -0
- package/.next/static/media/4fa387ec64143e14-s.0q3udbd2bu5yp.woff2 +0 -0
- package/.next/static/media/5476f68d60460930-s.0wxq9webf.ew4.woff2 +0 -0
- package/.next/static/media/63599ae31785f475-s.01zyq0dc2~0hp.woff2 +0 -0
- package/.next/static/media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2 +0 -0
- package/.next/static/media/83afe278b6a6bb3c-s.p.0q-301v4kxxnr.woff2 +0 -0
- package/.next/static/media/8b19d8d892dc610b-s.0.m6yiwn-kka2.woff2 +0 -0
- package/.next/static/media/9c72aa0f40e4eef8-s.0m6w47a4e5dy9.woff2 +0 -0
- package/.next/static/media/ad66f9afd8947f86-s.11u06r12fd6v_.woff2 +0 -0
- package/.next/static/media/bbc41e54d2fcbd21-s.0gw~uztddq1df.woff2 +0 -0
- package/.next/static/media/c5ff0a46612d668f-s.0hhk-7qht1v87.woff2 +0 -0
- package/.next/static/media/f10b37ddd5a9e949-s.15ktajnz8ofs..woff2 +0 -0
- package/.next/static/media/favicon.0x3dzn~oxb6tn.ico +0 -0
- package/README.md +75 -0
- package/bin/miclaw.mjs +99 -0
- package/package.json +55 -0
- package/public/file.svg +1 -0
- package/public/globe.svg +1 -0
- package/public/logo.png +0 -0
- package/public/next.svg +1 -0
- package/public/screenshot.png +0 -0
- package/public/vercel.svg +1 -0
- package/public/window.svg +1 -0
|
@@ -0,0 +1,1672 @@
|
|
|
1
|
+
1:"$Sreact.fragment"
|
|
2
|
+
2:I[22140,["/_next/static/chunks/0mmpyn9fv2fjf.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"Sidebar"]
|
|
3
|
+
3:I[39756,["/_next/static/chunks/0mmpyn9fv2fjf.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
|
|
4
|
+
4:I[37457,["/_next/static/chunks/0mmpyn9fv2fjf.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
|
|
5
|
+
6:I[97367,["/_next/static/chunks/0mmpyn9fv2fjf.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"OutletBoundary"]
|
|
6
|
+
7:"$Sreact.suspense"
|
|
7
|
+
a:I[97367,["/_next/static/chunks/0mmpyn9fv2fjf.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"ViewportBoundary"]
|
|
8
|
+
c:I[97367,["/_next/static/chunks/0mmpyn9fv2fjf.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"MetadataBoundary"]
|
|
9
|
+
e:I[68027,["/_next/static/chunks/0mmpyn9fv2fjf.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default",1]
|
|
10
|
+
:HL["/_next/static/chunks/0iym2_f33sxs7.css","style"]
|
|
11
|
+
:HL["/_next/static/media/166ab60e98aadb0a-s.p.0mka4ru4_bj1d.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
|
12
|
+
:HL["/_next/static/media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
|
13
|
+
:HL["/_next/static/media/83afe278b6a6bb3c-s.p.0q-301v4kxxnr.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
|
14
|
+
0:{"P":null,"c":["","commands"],"q":"","i":false,"f":[[["",{"children":["commands",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",16],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0iym2_f33sxs7.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/0mmpyn9fv2fjf.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/_next/static/chunks/0d3shmwh5_nmn.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","className":"inter_fe8b9d92-module__LINzvG__variable geist_mono_8d43a2aa-module__8Li5zG__variable fira_code_d18ac710-module__OladcG__variable","children":["$","body",null,{"className":"bg-surface text-text font-sans antialiased","children":["$","div",null,{"className":"flex h-screen overflow-hidden","children":[["$","$L2",null,{}],["$","main",null,{"className":"flex-1 overflow-y-auto bg-grid","children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]]}]}]}]]}],{"children":[["$","$1","c",{"children":[null,["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":["$L5",[["$","script","script-0",{"src":"/_next/static/chunks/12p3iqtw2ohfq.js","async":true,"nonce":"$undefined"}]],["$","$L6",null,{"children":["$","$7",null,{"name":"Next.MetadataOutlet","children":"$@8"}]}]]}],{},null,false,null]},null,false,"$@9"]},null,false,null],["$","$1","h",{"children":[null,["$","$La",null,{"children":"$Lb"}],["$","div",null,{"hidden":true,"children":["$","$Lc",null,{"children":["$","$7",null,{"name":"Next.Metadata","children":"$Ld"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],false]],"m":"$undefined","G":["$e",[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0iym2_f33sxs7.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"BgLP6ChyOyE0k8Ahr8F2H"}
|
|
15
|
+
f:[]
|
|
16
|
+
9:"$Wf"
|
|
17
|
+
b:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
|
|
18
|
+
10:I[27201,["/_next/static/chunks/0mmpyn9fv2fjf.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"IconMark"]
|
|
19
|
+
8:null
|
|
20
|
+
d:[["$","title","0",{"children":"MiClaw"}],["$","meta","1",{"name":"description","content":"Claude Code configuration visualizer"}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.0x3dzn~oxb6tn.ico","sizes":"256x256","type":"image/x-icon"}],["$","$L10","3",{}]]
|
|
21
|
+
11:I[22450,["/_next/static/chunks/0mmpyn9fv2fjf.js","/_next/static/chunks/0d3shmwh5_nmn.js","/_next/static/chunks/12p3iqtw2ohfq.js"],"ExpandableBody"]
|
|
22
|
+
12:T1810,# Infrastructure Security Audit
|
|
23
|
+
|
|
24
|
+
Scan all AWS infrastructure modules for security issues across four categories: IAM least-privilege, unprotected API routes, encryption, and factory module bypass.
|
|
25
|
+
|
|
26
|
+
## How This Codebase Works
|
|
27
|
+
|
|
28
|
+
This is an OpenTofu infrastructure codebase. Key facts:
|
|
29
|
+
|
|
30
|
+
- AWS modules live in `modules/aws/`
|
|
31
|
+
- Reusable factory modules enforce security defaults:
|
|
32
|
+
- `private_s3_bucket` — S3 with public access blocked + AES256 encryption
|
|
33
|
+
- `sqs_queue_with_dlq` — SQS with managed SSE + DLQ + CloudWatch alarms
|
|
34
|
+
- `lambda_zip_function` — Lambda with scoped IAM base policy + CloudWatch logs + error/throttle alarms
|
|
35
|
+
- `http_lambda_integration` — API Gateway routes with authorizer wiring
|
|
36
|
+
- IAM policies use `aws_iam_policy_document` data sources with managed policies (not inline)
|
|
37
|
+
- API Gateway routes are defined per-service via `http_lambda_integration`, NOT centralized. Each service module specifies its routes using one of three variables:
|
|
38
|
+
- `api_base_paths` — uses the account authorizer (validates JWT + account membership)
|
|
39
|
+
- `jwt_authorizer_endpoints` — uses JWT-only authorizer (validates JWT, strips account headers)
|
|
40
|
+
- `public_endpoints` — no auth (strips all Bioscope headers)
|
|
41
|
+
|
|
42
|
+
## Your Task
|
|
43
|
+
|
|
44
|
+
### Step 1: Audit factory modules
|
|
45
|
+
|
|
46
|
+
Use the Task tool (subagent_type: "general-purpose") to spin up ONE sub-agent that reads and audits all four factory modules:
|
|
47
|
+
|
|
48
|
+
- `modules/aws/private_s3_bucket/`
|
|
49
|
+
- `modules/aws/sqs_queue_with_dlq/`
|
|
50
|
+
- `modules/aws/lambda_zip_function/`
|
|
51
|
+
- `modules/aws/http_lambda_integration/`
|
|
52
|
+
|
|
53
|
+
This agent should verify the security defaults are sound, write its report to `/tmp/infra-security-audit/factory-modules.md`, and return ONLY a one-line confirmation (e.g., "Wrote report to /tmp/infra-security-audit/factory-modules.md. N findings."). Do NOT return the full report — it's in the file.
|
|
54
|
+
|
|
55
|
+
### Step 2: Audit platform_vpc
|
|
56
|
+
|
|
57
|
+
Spin up ONE sub-agent for `modules/aws/platform_vpc/`. Check:
|
|
58
|
+
|
|
59
|
+
- Security groups: any rules with `0.0.0.0/0` or `::/0` ingress
|
|
60
|
+
- Any public subnets or internet gateways
|
|
61
|
+
- VPC endpoint configuration
|
|
62
|
+
|
|
63
|
+
Write report to `/tmp/infra-security-audit/platform-vpc.md` and return ONLY a one-line confirmation.
|
|
64
|
+
|
|
65
|
+
### Step 3: Audit service modules
|
|
66
|
+
|
|
67
|
+
First, create the output directory: `mkdir -p /tmp/infra-security-audit`
|
|
68
|
+
|
|
69
|
+
Then spin up sub-agents in parallel to scan service modules in batches (~5 modules per agent). Skip the factory modules and `platform_vpc` (already audited). For each module, check:
|
|
70
|
+
|
|
71
|
+
#### IAM Least-Privilege
|
|
72
|
+
|
|
73
|
+
- `resources = ["*"]` on any action EXCEPT where AWS requires it (e.g., Textract, EC2 network interfaces for VPC config). Flag wildcards that could be scoped to specific ARNs.
|
|
74
|
+
- Overly broad actions (e.g., `dynamodb:*` instead of specific operations, `s3:*` instead of specific operations)
|
|
75
|
+
- `Action = "*"` (full admin access) — this would be critical
|
|
76
|
+
|
|
77
|
+
#### Unprotected API Routes
|
|
78
|
+
|
|
79
|
+
- Look for usage of `http_lambda_integration` module. Check which variables are set:
|
|
80
|
+
- `api_base_paths` — good, uses account authorizer
|
|
81
|
+
- `jwt_authorizer_endpoints` — fine for user-centric routes, but flag if the endpoint path suggests it needs account context (e.g., contains `/patients/`, `/accounts/` but not `/me`)
|
|
82
|
+
- `public_endpoints` — flag for review, note what the endpoint does
|
|
83
|
+
- If a service has an API Gateway integration but doesn't use `http_lambda_integration`, flag it
|
|
84
|
+
|
|
85
|
+
#### Encryption & Security Defaults
|
|
86
|
+
|
|
87
|
+
- Any `aws_s3_bucket` created directly (NOT using `private_s3_bucket` module) — check it has public access block and encryption
|
|
88
|
+
- Any `aws_sqs_queue` created directly (NOT using `sqs_queue_with_dlq` module) — check it has `sqs_managed_sse_enabled = true`
|
|
89
|
+
- Any `aws_dynamodb_table` — check if it has `deletion_protection_enabled` on tables that look like they store important data
|
|
90
|
+
- Any SNS topics without encryption
|
|
91
|
+
|
|
92
|
+
#### Factory Module Bypass
|
|
93
|
+
|
|
94
|
+
- Flag any raw `aws_s3_bucket`, `aws_sqs_queue`, or `aws_lambda_function` resources that aren't using the factory modules. These may be intentional (note the context) but should be reviewed.
|
|
95
|
+
|
|
96
|
+
Each sub-agent should write its report to `/tmp/infra-security-audit/batch-<N>.md` and return ONLY a one-line confirmation (e.g., "Wrote report to /tmp/infra-security-audit/batch-1.md. N findings across M modules."). Do NOT return the full report — it's in the file.
|
|
97
|
+
|
|
98
|
+
**IMPORTANT:** When calling the Task tool for each sub-agent, explicitly instruct it to write findings to the file and return only a brief one-line confirmation. The full report must go in the file, NOT in the return message. This prevents the main agent's context from overflowing.
|
|
99
|
+
|
|
100
|
+
### Step 4: Report format
|
|
101
|
+
|
|
102
|
+
Each sub-agent should write its report in this format:
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
## <module-name>
|
|
106
|
+
|
|
107
|
+
### Findings
|
|
108
|
+
|
|
109
|
+
#### <Issue title>
|
|
110
|
+
- **File**: path/to/file.tf:line
|
|
111
|
+
- **Resource**: resource type and name
|
|
112
|
+
- **Issue**: description
|
|
113
|
+
- **Severity**: Critical / High / Medium / Low
|
|
114
|
+
- **Notes**: context (e.g., "wildcard may be required by AWS for this service")
|
|
115
|
+
|
|
116
|
+
### No Issues Found
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Step 5: Aggregate
|
|
120
|
+
|
|
121
|
+
**Important:** Do NOT read the report files yourself — this will overflow your context. Instead, spin up one final sub-agent (subagent_type: "general-purpose") to handle aggregation. This agent should:
|
|
122
|
+
|
|
123
|
+
1. List all files in `/tmp/infra-security-audit/`
|
|
124
|
+
2. Read each file one at a time, extracting only findings (skip "No Issues Found" sections and clean modules)
|
|
125
|
+
3. Write a final summary to `/tmp/infra-security-audit/SUMMARY.md` with:
|
|
126
|
+
- **Executive Summary**: Total modules scanned, total findings by severity
|
|
127
|
+
- **Factory Module Health**: Summary of factory module audit
|
|
128
|
+
- **Findings by Category**: IAM, Routes, Encryption, Factory Bypass
|
|
129
|
+
- **Clean Modules**: List of modules with no findings (names only)
|
|
130
|
+
4. Return a brief summary of the findings to you (just counts and critical items, not the full report)
|
|
131
|
+
|
|
132
|
+
After the aggregation agent completes, tell the user the full report is at `/tmp/infra-security-audit/SUMMARY.md` and output the brief summary.
|
|
133
|
+
|
|
134
|
+
Read the actual .tf files — don't guess based on module names. When a wildcard resource is found, check if it's a known AWS requirement before flagging.5:["$","div",null,{"className":"mx-auto max-w-5xl px-8 py-10","children":[["$","div",null,{"className":"mb-8","children":[["$","div",null,{"className":"flex items-baseline gap-3","children":[["$","h1",null,{"className":"text-2xl font-medium tracking-tight","children":"Commands"}],["$","span",null,{"className":"text-sm text-text-muted","children":12}]]}],["$","p",null,{"className":"mt-1 text-sm text-text-muted","children":"Procedural commands across projects"}]]}],[["$","div","infrastructure",{"className":"mb-8","children":[["$","h2",null,{"className":"text-xs font-medium text-text-dim uppercase tracking-wide mb-3","children":"infrastructure"}],["$","div",null,{"className":"space-y-3","children":[["$","div","/Users/gabry/Desktop/infrastructure/.claude/commands/security-audit.md",{"className":"border border-border rounded-sm p-5 ","children":[["$","div",null,{"className":"flex items-center gap-2","children":[["$","h3",null,{"className":"text-sm font-medium","children":"security-audit"}],["$","span",null,{"className":"inline-flex items-center px-2 py-0.5 text-xs font-medium rounded-sm bg-surface-raised text-text-muted","children":"infrastructure"}]]}],["$","$L11",null,{"content":"$12","previewLines":3}]]}]]}]]}],"$L13","$L14"],false]}]
|
|
135
|
+
15:T368e,# Broken Access Control Scan
|
|
136
|
+
|
|
137
|
+
Scan ALL route handlers and Lambda handlers in platform-services for broken access control vulnerabilities beyond IDOR (which is covered by the separate `idor-scan` command).
|
|
138
|
+
|
|
139
|
+
## How This Codebase Works
|
|
140
|
+
|
|
141
|
+
This is a FastAPI-based backend. Key facts:
|
|
142
|
+
|
|
143
|
+
- Routes live in `packages/*/src/*/routes/*.py`
|
|
144
|
+
- App setup files are at `packages/*/src/*/app.py`
|
|
145
|
+
- Lambda handlers are at `packages/*/src/*/handler.py`
|
|
146
|
+
- Service-specific middleware may be at `packages/*/src/*/middleware.py`
|
|
147
|
+
- Shared middleware is in `packages/shared_middleware/src/shared_middleware/`
|
|
148
|
+
- Most routes are behind an API Gateway account authorizer that validates the JWT and sets trusted headers: `Bioscope-Account-Id`, `Bioscope-User-Id`, `Bioscope-User-Role`, `Bioscope-Is-Demo-User`
|
|
149
|
+
- Some routes use a simpler JWT-only authorizer or no authorizer at all (public endpoints). The authorizer config lives in infrastructure and is not visible from this repo.
|
|
150
|
+
|
|
151
|
+
### Standard Middleware Stack
|
|
152
|
+
|
|
153
|
+
Every FastAPI service should mount these middlewares in this order in `app.py`:
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
app = FastAPI(title="service-name", dependencies=[Depends(enforce_demo_read_only)])
|
|
157
|
+
app.add_middleware(WithExceptionLoggingMiddleware)
|
|
158
|
+
app.add_middleware(WithMetadataLoggingMiddleware)
|
|
159
|
+
app.add_middleware(WithLoggerMiddleware)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
And include routers via `app.include_router(...)`.
|
|
163
|
+
|
|
164
|
+
### Role-Based Access Control
|
|
165
|
+
|
|
166
|
+
The codebase has a single role validation dependency:
|
|
167
|
+
|
|
168
|
+
- `require_owner_role` in `shared_middleware/role_validation.py` — checks `Bioscope-User-Role` header equals `"owner"`, raises 403 otherwise
|
|
169
|
+
- Used as `RequireOwnerRoleDeps = Annotated[None, Depends(require_owner_role)]`
|
|
170
|
+
|
|
171
|
+
Role is set by the API Gateway authorizer from the user's account membership record in DynamoDB.
|
|
172
|
+
|
|
173
|
+
### Demo Mode
|
|
174
|
+
|
|
175
|
+
- `enforce_demo_read_only` is applied as a global FastAPI dependency — blocks all non-GET/HEAD/OPTIONS requests for demo users
|
|
176
|
+
- Routes can opt in to allow demo writes with the `@allow_demo_writes` decorator
|
|
177
|
+
|
|
178
|
+
### Header Dependencies
|
|
179
|
+
|
|
180
|
+
Trusted headers are injected via these typed dependencies (from `shared_middleware/headers.py`):
|
|
181
|
+
|
|
182
|
+
- `BioscopeAccountIdHeaderDeps` — `Bioscope-Account-Id`
|
|
183
|
+
- `BioscopeUserIdHeaderDeps` — `Bioscope-User-Id`
|
|
184
|
+
- `BioscopeUserRoleHeaderDeps` — `Bioscope-User-Role`
|
|
185
|
+
- `BioscopeCorrelationIdHeaderDeps` — `Bioscope-Correlation-Id`
|
|
186
|
+
- `BioscopeInternalApiKeyHeaderDeps` — `Bioscope-Internal-Api-Key`
|
|
187
|
+
- `BioscopeIsDemoUserHeaderDeps` — `Bioscope-Is-Demo-User`
|
|
188
|
+
|
|
189
|
+
## Your Task
|
|
190
|
+
|
|
191
|
+
### Step 1: Discover all services
|
|
192
|
+
|
|
193
|
+
Use glob to find:
|
|
194
|
+
1. All route files: `packages/*/src/*/routes/*.py`
|
|
195
|
+
2. All app files: `packages/*/src/*/app.py`
|
|
196
|
+
3. All handler files: `packages/*/src/*/handler.py`
|
|
197
|
+
4. All handler directories: `packages/*/src/*/handlers/*.py`
|
|
198
|
+
|
|
199
|
+
Group them by service. A service may have routes (FastAPI), handlers (Lambda), or both.
|
|
200
|
+
|
|
201
|
+
### Step 2: Create an output directory and spin up sub-agents
|
|
202
|
+
|
|
203
|
+
First, create an output directory using Bash: `mkdir -p access-control-scan-results` (in the repo root directory).
|
|
204
|
+
|
|
205
|
+
Then, for **every service** (both route-based and handler-only), use the Task tool (subagent_type: "general-purpose") to scan that service.
|
|
206
|
+
|
|
207
|
+
#### Parallelism guidelines
|
|
208
|
+
|
|
209
|
+
**CRITICAL: Do NOT launch all agents at once.** This codebase has many services (typically 50+). Launching too many parallel agents causes resource contention, slow completions, and permission prompt overload.
|
|
210
|
+
|
|
211
|
+
Instead, process services in **batches of 5 agents at a time**:
|
|
212
|
+
|
|
213
|
+
1. **Batch 1**: Launch 5 route-based service agents in parallel (in a single message with 5 Task tool calls). Run them in background (`run_in_background: true`).
|
|
214
|
+
2. **Wait**: After launching a batch, wait for all agents in the batch to complete before launching the next batch. Check completion by reading the output files or using TaskOutput.
|
|
215
|
+
3. **Batch 2**: Launch the next 5 route-based services.
|
|
216
|
+
4. **Continue**: Repeat until all route-based services are scanned, then do the same for handler-only services.
|
|
217
|
+
|
|
218
|
+
For **handler-only services**, you may group 3-5 related services into a single agent (e.g., all `*_event_consumer` services in one agent) since they are simpler to scan. This reduces the total number of agents needed. Each grouped agent should write **separate report files** for each service it scans.
|
|
219
|
+
|
|
220
|
+
#### What each sub-agent should do
|
|
221
|
+
|
|
222
|
+
**For services with route files**, each sub-agent should:
|
|
223
|
+
1. Read ALL route files for that service
|
|
224
|
+
2. Read the service's `app.py` to check middleware mounting and global dependencies
|
|
225
|
+
3. Read any service-specific `middleware.py` if it exists
|
|
226
|
+
4. For each route handler, check for the vulnerabilities listed in Step 3
|
|
227
|
+
5. **Write the report to a file** at `access-control-scan-results/<service-name>.md` (relative to the repo root) using the format in Step 4
|
|
228
|
+
6. **Return ONLY a one-line confirmation** (e.g., "Wrote report to access-control-scan-results/chat_service.md. 2 findings."). Do NOT return the full report — it's in the file.
|
|
229
|
+
|
|
230
|
+
**For handler-only services** (no route files, only `handler.py` and optionally `handlers/*.py`), each sub-agent should:
|
|
231
|
+
1. Read the service's `handler.py` and all files in `handlers/` if present
|
|
232
|
+
2. For each Lambda handler (decorated with `@handler.sqs`, `@handler.sns`, `@handler.direct_invocation`, `@handler.event_bridge`, `@handler.authorizer`), check for the vulnerabilities listed in Step 3 section E
|
|
233
|
+
3. **Write the report to a file** at `access-control-scan-results/<service-name>.md` (relative to the repo root) using the format in Step 4
|
|
234
|
+
4. **Return ONLY a one-line confirmation**
|
|
235
|
+
|
|
236
|
+
**IMPORTANT:** When calling the Task tool for each sub-agent, explicitly instruct it to write findings to the file and return only a brief one-line confirmation. The full report must go in the file, NOT in the return message. This prevents the main agent's context from overflowing.
|
|
237
|
+
|
|
238
|
+
### Step 3: What to check per service and route
|
|
239
|
+
|
|
240
|
+
#### A. Middleware and App-Level Checks
|
|
241
|
+
|
|
242
|
+
For each service's `app.py`, verify:
|
|
243
|
+
|
|
244
|
+
- **Missing standard middleware**: The app MUST mount all three middlewares (`WithExceptionLoggingMiddleware`, `WithMetadataLoggingMiddleware`, `WithLoggerMiddleware`). Flag any that are missing.
|
|
245
|
+
- **Missing demo mode enforcement**: The app MUST have `dependencies=[Depends(enforce_demo_read_only)]` on the `FastAPI()` constructor. Flag if missing.
|
|
246
|
+
- **Non-standard middleware ordering**: Middlewares execute in reverse order of addition (LIFO). `WithLoggerMiddleware` must be added last so it executes first. Flag incorrect ordering.
|
|
247
|
+
- **Routes mounted outside the app**: Check if any route files exist that are NOT included via `app.include_router(...)`. These routes would bypass all app-level middleware and dependencies.
|
|
248
|
+
|
|
249
|
+
#### B. Role-Based Access Control Checks
|
|
250
|
+
|
|
251
|
+
For each route handler, check:
|
|
252
|
+
|
|
253
|
+
- **Sensitive mutations without role checks**: Routes that perform destructive or admin-level operations (DELETE endpoints, account settings changes, user management, billing operations) should use `RequireOwnerRoleDeps` or `Depends(require_owner_role)`. Flag mutation endpoints that handle sensitive operations without any role check. Use your judgment — not every POST/PATCH/DELETE needs a role check, but operations like deleting accounts, managing users, or changing account settings do.
|
|
254
|
+
- **Role from untrusted source**: Any route that reads a role from path params, query params, or request body instead of the `Bioscope-User-Role` header. The role MUST come from the trusted header dependency.
|
|
255
|
+
|
|
256
|
+
#### C. Authentication/Authorization Gaps
|
|
257
|
+
|
|
258
|
+
For each route handler, check:
|
|
259
|
+
|
|
260
|
+
- **Missing identity headers**: Routes that perform any data access or mutation but do NOT inject `BioscopeAccountIdHeaderDeps` or `BioscopeUserIdHeaderDeps`. Every non-public route should use at least the account ID header to scope its operations.
|
|
261
|
+
- **Hardcoded or default account/user IDs**: Any route that uses a hardcoded UUID or default value for account_id or user_id instead of extracting from headers.
|
|
262
|
+
- **Internal API key routes without validation**: Routes that accept `BioscopeInternalApiKeyHeaderDeps` should validate the key value against an expected secret, not just check that the header is present.
|
|
263
|
+
|
|
264
|
+
#### D. Demo Mode Bypass
|
|
265
|
+
|
|
266
|
+
- **Mutation routes with @allow_demo_writes that shouldn't have it**: The `@allow_demo_writes` decorator should only be on routes where demo users legitimately need write access (e.g., creating a chat for a demo walkthrough). Flag any destructive operations (DELETE, account mutations) that have this decorator.
|
|
267
|
+
|
|
268
|
+
#### E. Lambda Handler Checks (for handler-only and hybrid services)
|
|
269
|
+
|
|
270
|
+
Lambda handlers (`@handler.sqs`, `@handler.sns`, `@handler.direct_invocation`, `@handler.event_bridge`) are internal-facing and trust their event sources by design (IAM policies and queue/topic access policies control who can invoke them). The checks below focus on risks that remain even within that trust model.
|
|
271
|
+
|
|
272
|
+
For each Lambda handler, check:
|
|
273
|
+
|
|
274
|
+
- **Unscoped destructive operations**: Direct invocation or event-driven handlers that perform bulk deletes, account mutations, or data purges without scoping to a specific `account_id` or `patient_id` from the event payload. A handler that deletes "all matching records" rather than scoping by the account/patient in the event is dangerous if it ever receives malformed input.
|
|
275
|
+
- **Missing account/patient scoping on queries**: Handlers that query DynamoDB or other data stores without filtering by `account_id` or `patient_id` when the event payload contains those identifiers. The handler should use the event's IDs to scope its operations, not fetch all records globally.
|
|
276
|
+
- **Sensitive operations in direct invocation handlers without caller context**: Direct invocation handlers that perform admin-level operations (creating users, modifying account settings, issuing credentials) should accept and log a `correlation_id` or caller identifier for audit trail. Flag handlers that perform sensitive mutations with no traceability to the original caller.
|
|
277
|
+
- **Event payload used to construct external requests without validation**: Handlers that take URLs, email addresses, or external identifiers from event payloads and pass them directly to external services (HTTP calls, email sends, S3 operations). Validate that the handler sanitizes or validates these inputs rather than blindly trusting them.
|
|
278
|
+
- **Internal API key routes without key validation**: Any HTTP route (in hybrid services that have both routes and handlers) that accepts `BioscopeInternalApiKeyHeaderDeps` should validate the key value against an expected secret, not just check that the header is present.
|
|
279
|
+
|
|
280
|
+
**Important context for sub-agents**: Do NOT flag handler-level findings for the following, as these are expected patterns:
|
|
281
|
+
- Direct invocation handlers that don't have API Gateway-style JWT authorization — they're internal Lambda-to-Lambda calls secured by IAM
|
|
282
|
+
- SQS/SNS handlers that trust `account_id` or `patient_id` from the event body — the event source is trusted
|
|
283
|
+
- Handlers that don't inject `BioscopeAccountIdHeaderDeps` — header dependencies are for HTTP routes only, not Lambda handlers
|
|
284
|
+
|
|
285
|
+
### Step 4: Report format
|
|
286
|
+
|
|
287
|
+
Each sub-agent should write findings in this format:
|
|
288
|
+
|
|
289
|
+
**For services with routes (FastAPI):**
|
|
290
|
+
|
|
291
|
+
```text
|
|
292
|
+
## <service-name>
|
|
293
|
+
|
|
294
|
+
### App-Level Configuration
|
|
295
|
+
- **Middleware**: [All present / Missing: <list>]
|
|
296
|
+
- **Demo mode**: [Enforced / MISSING]
|
|
297
|
+
- **Middleware order**: [Correct / INCORRECT: <details>]
|
|
298
|
+
- **Unmounted routes**: [None / <list>]
|
|
299
|
+
|
|
300
|
+
### Routes Scanned
|
|
301
|
+
- `GET /path` — handler_name (file:line)
|
|
302
|
+
- `POST /path` — handler_name (file:line)
|
|
303
|
+
...
|
|
304
|
+
|
|
305
|
+
### Findings
|
|
306
|
+
|
|
307
|
+
#### Missing role check on sensitive mutation — `DELETE /resource/{id}`
|
|
308
|
+
- **File**: path/to/file.py:123
|
|
309
|
+
- **Handler**: `delete_resource`
|
|
310
|
+
- **Issue**: Destructive operation with no role validation
|
|
311
|
+
- **Confidence**: High / Medium / Low
|
|
312
|
+
- **Notes**: <any relevant context>
|
|
313
|
+
|
|
314
|
+
#### Missing identity headers — `GET /resource`
|
|
315
|
+
...
|
|
316
|
+
|
|
317
|
+
### No Issues Found
|
|
318
|
+
(list routes that were scanned and passed all checks)
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
**For handler-only services (Lambda):**
|
|
322
|
+
|
|
323
|
+
```text
|
|
324
|
+
## <service-name>
|
|
325
|
+
|
|
326
|
+
### Handlers Scanned
|
|
327
|
+
- `@handler.sqs(queue_name="queue-name")` — handler_function (file:line)
|
|
328
|
+
- `@handler.direct_invocation()` — handler_function (file:line)
|
|
329
|
+
- `@handler.event_bridge()` — handler_function (file:line)
|
|
330
|
+
...
|
|
331
|
+
|
|
332
|
+
### Findings
|
|
333
|
+
|
|
334
|
+
#### Unscoped destructive operation — handle_delete_event
|
|
335
|
+
- **File**: path/to/handler.py:45
|
|
336
|
+
- **Handler**: `handle_delete_event`
|
|
337
|
+
- **Decorator**: `@handler.sqs(queue_name="...")`
|
|
338
|
+
- **Issue**: Deletes records without scoping to account_id from event payload
|
|
339
|
+
- **Confidence**: High / Medium / Low
|
|
340
|
+
- **Notes**: <any relevant context>
|
|
341
|
+
|
|
342
|
+
### No Issues Found
|
|
343
|
+
(list handlers that were scanned and passed all checks)
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Step 5: Aggregate
|
|
347
|
+
|
|
348
|
+
After all sub-agents complete, read each file from `access-control-scan-results/` and compile a final summary. To avoid context limits, read one file at a time and extract only the findings (skip the "No Issues Found" and "Routes Scanned" sections for clean services).
|
|
349
|
+
|
|
350
|
+
Write the final report to `access-control-scan-results/SUMMARY.md` with:
|
|
351
|
+
|
|
352
|
+
1. **Executive Summary**: Total services scanned (route-based + handler-only), total routes/handlers scanned, total findings by category
|
|
353
|
+
2. **App-Level Issues**: Any services with middleware or configuration problems
|
|
354
|
+
3. **Route-Level Findings**: All access control vulnerabilities in FastAPI routes, grouped by type
|
|
355
|
+
4. **Handler-Level Findings**: All access control vulnerabilities in Lambda handlers, grouped by type
|
|
356
|
+
5. **Clean Services**: List of services with no findings (names only)
|
|
357
|
+
6. **Per-Service Details**: Full findings for services that had issues
|
|
358
|
+
|
|
359
|
+
Then output the summary to the user.
|
|
360
|
+
|
|
361
|
+
Be thorough. Read the actual code — don't guess based on function names alone. When checking for role validation, trace the full dependency chain. If a role check happens in a called function or middleware rather than at the route level, note it but don't flag it as a vulnerability.13:["$","div","platform-services",{"className":"mb-8","children":[["$","h2",null,{"className":"text-xs font-medium text-text-dim uppercase tracking-wide mb-3","children":"platform-services"}],["$","div",null,{"className":"space-y-3","children":[["$","div","/Users/gabry/Desktop/platform-services/.claude/commands/access-control-scan.md",{"className":"border border-border rounded-sm p-5 ","children":[["$","div",null,{"className":"flex items-center gap-2","children":[["$","h3",null,{"className":"text-sm font-medium","children":"access-control-scan"}],["$","span",null,{"className":"inline-flex items-center px-2 py-0.5 text-xs font-medium rounded-sm bg-surface-raised text-text-muted","children":"platform-services"}]]}],["$","$L11",null,{"content":"$15","previewLines":3}]]}],"$L16","$L17","$L18","$L19","$L1a","$L1b","$L1c","$L1d","$L1e"]}]]}]
|
|
362
|
+
1f:T1605,# Investigate WGS Ingestion Failure
|
|
363
|
+
|
|
364
|
+
You are investigating a WGS ingestion Step Function failure in production. Follow each step. Do NOT ask for user input -- work autonomously.
|
|
365
|
+
|
|
366
|
+
## Input
|
|
367
|
+
|
|
368
|
+
$ARGUMENTS
|
|
369
|
+
|
|
370
|
+
## Step 1: Parse the Alert
|
|
371
|
+
|
|
372
|
+
Extract from the input text: `correlationId`, `wgsIngestionId`, `sfnError`, `sfnStatus`.
|
|
373
|
+
|
|
374
|
+
If the input is missing required fields, write a report noting the parse failure and stop.
|
|
375
|
+
|
|
376
|
+
## Step 2: Query Axiom
|
|
377
|
+
|
|
378
|
+
Use `mcp__axiom__queryDataset` with `startTime` = `now-24h` and `endTime` = `now`.
|
|
379
|
+
|
|
380
|
+
Trace the correlationId:
|
|
381
|
+
|
|
382
|
+
```apl
|
|
383
|
+
['bioscope-prod']
|
|
384
|
+
| where correlationId == "<correlationId>"
|
|
385
|
+
| order by _time asc
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
Search by wgsIngestionId:
|
|
389
|
+
|
|
390
|
+
```apl
|
|
391
|
+
['bioscope-prod']
|
|
392
|
+
| where data.wgsIngestionId == "<wgsIngestionId>" or message contains "<wgsIngestionId>"
|
|
393
|
+
| order by _time asc
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
Focus on ERROR-level entries. Record only the key log lines needed to explain the failure -- not the full trace.
|
|
397
|
+
|
|
398
|
+
## Step 3: Cross-Reference Code
|
|
399
|
+
|
|
400
|
+
Read the `PLATFORM_SERVICES_PATH` and `INFRASTRUCTURE_PATH` environment variables to locate the repos.
|
|
401
|
+
|
|
402
|
+
### Application code (platform-services)
|
|
403
|
+
|
|
404
|
+
1. `$PLATFORM_SERVICES_PATH/packages/wgs_ingestion_service/src/wgs_ingestion_service/handlers/handle_sfn_failure.py`
|
|
405
|
+
2. `$PLATFORM_SERVICES_PATH/packages/wgs_ingestion_service/src/wgs_ingestion_service/handlers/handle_initiate_ingestion.py`
|
|
406
|
+
3. `$PLATFORM_SERVICES_PATH/packages/bioscope_types/src/bioscope_types/dynamodb/wgs_ingestions.py`
|
|
407
|
+
|
|
408
|
+
### Infrastructure (Terraform)
|
|
409
|
+
|
|
410
|
+
If the error points to a Step Function state, Lambda config, IAM permissions, or resource limits, cross-reference these files:
|
|
411
|
+
|
|
412
|
+
1. `$INFRASTRUCTURE_PATH/modules/aws/wgs_ingestion/sfn.tf` -- Step Function state machine definition and pipeline flow
|
|
413
|
+
2. `$INFRASTRUCTURE_PATH/modules/aws/wgs_ingestion/lambda.tf` -- Lambda function configuration (memory, timeout, layers)
|
|
414
|
+
3. `$INFRASTRUCTURE_PATH/modules/aws/wgs_ingestion/iam.tf` -- IAM roles and policies for the pipeline
|
|
415
|
+
4. `$INFRASTRUCTURE_PATH/modules/aws/wgs_ingestion/eventbridge.tf` -- EventBridge rule that triggers on SFN failures
|
|
416
|
+
5. `$INFRASTRUCTURE_PATH/modules/aws/wgs_ingestion/dynamodb.tf` -- DynamoDB table and index definitions
|
|
417
|
+
|
|
418
|
+
The execution name format is `{wgs_ingestion_id}_{kit_id}_{timestamp}`.
|
|
419
|
+
|
|
420
|
+
## Step 4: Classify the Failure
|
|
421
|
+
|
|
422
|
+
**Default to Bug.** Only classify as Transient if you can point to specific evidence (see criteria below).
|
|
423
|
+
|
|
424
|
+
- **Bug**: Code error, unhandled exception, missing IAM permissions, missing config, infrastructure misconfiguration. Requires a code or infra fix. **This is the default classification when the root cause is unclear.**
|
|
425
|
+
- **Transient**: A failure that meets ALL of these criteria:
|
|
426
|
+
1. The error is a network timeout, AWS throttling, or a known transient pattern (see below)
|
|
427
|
+
2. There is no underlying code/config/IAM issue that caused it
|
|
428
|
+
3. A redrive would be expected to succeed WITHOUT any code or infrastructure changes
|
|
429
|
+
- **Data issue**: Bad input, missing files, malformed data. Requires manual intervention.
|
|
430
|
+
|
|
431
|
+
You MUST justify your classification in the Root Cause section. If classifying as Transient, explicitly state why a redrive would fix it without code changes.
|
|
432
|
+
|
|
433
|
+
### Example Transient Errors
|
|
434
|
+
|
|
435
|
+
These LOOK like data issues but are known transient -- classify as **Transient**:
|
|
436
|
+
|
|
437
|
+
- **`INTERSECT_VARIANTS` / `KeyError: 'CHR:POS:A0:A1'` / "No variants in intersection"**: Intermittent failure in `pgsc_calc` during PRS generation. Resolves on redrive.
|
|
438
|
+
|
|
439
|
+
### Example Bug Patterns
|
|
440
|
+
|
|
441
|
+
These may LOOK transient but are bugs -- classify as **Bug**:
|
|
442
|
+
|
|
443
|
+
- **S3 403 Forbidden on HeadObject/GetObject/PutObject**: Usually a missing IAM permission on the task role, not a temporary auth issue. Check the relevant IAM policy in infrastructure. Example: BIOENG-535 where `genomics-bam-subset-processor` was missing `s3:GetObject` on its output bucket.
|
|
444
|
+
- **S3 404 Not Found on expected files**: Could indicate a missing deployment artifact, misconfigured path, or a race condition in the pipeline -- not transient.
|
|
445
|
+
- **Persistent STS/credential errors on FARGATE_SPOT**: If the same error recurs on redrive or appears on non-spot tasks, it is an IAM issue, not credential expiration.
|
|
446
|
+
|
|
447
|
+
## Step 5: Write the Report
|
|
448
|
+
|
|
449
|
+
Write the report file as: `reports/YYYY-MM-DD_<first-8-chars-of-wgsIngestionId>.md`
|
|
450
|
+
|
|
451
|
+
The `reports/` directory is in the current working directory. Verify with `Glob` that the directory exists before writing. If it does not exist, create it.
|
|
452
|
+
|
|
453
|
+
Keep the report concise. Only include log lines that are directly relevant to explaining the failure cause.
|
|
454
|
+
|
|
455
|
+
```
|
|
456
|
+
# WGS Ingestion Failure Report
|
|
457
|
+
|
|
458
|
+
## Summary
|
|
459
|
+
|
|
460
|
+
| Field | Value |
|
|
461
|
+
|-------|-------|
|
|
462
|
+
| Date | YYYY-MM-DD HH:MM UTC |
|
|
463
|
+
| Correlation ID | ... |
|
|
464
|
+
| WGS Ingestion ID | ... |
|
|
465
|
+
| Execution Name | ... |
|
|
466
|
+
| SFN Error | ... |
|
|
467
|
+
| SFN Status | ... |
|
|
468
|
+
|
|
469
|
+
## Key Logs
|
|
470
|
+
|
|
471
|
+
Only the log lines that explain the failure (oldest first):
|
|
472
|
+
|
|
473
|
+
- `TIMESTAMP` [LEVEL] message (logGroup: ...)
|
|
474
|
+
|
|
475
|
+
## Root Cause
|
|
476
|
+
|
|
477
|
+
<1-3 sentences. What failed and why.>
|
|
478
|
+
|
|
479
|
+
## Classification
|
|
480
|
+
|
|
481
|
+
**<Transient | Bug | Data issue>**
|
|
482
|
+
|
|
483
|
+
## Recommended Action
|
|
484
|
+
|
|
485
|
+
<1-2 sentences.>
|
|
486
|
+
|
|
487
|
+
### Redrive JSON
|
|
488
|
+
|
|
489
|
+
If transient, include:
|
|
490
|
+
|
|
491
|
+
{
|
|
492
|
+
"executionIds": ["<execution-name>"]
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
Env-task name: `redrive-wgs-ingestion-execution`
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
## Rules
|
|
499
|
+
|
|
500
|
+
- Do NOT ask for user input. Work fully autonomously.
|
|
501
|
+
- Do NOT include PII/PHI. Only UUIDs, error codes, timestamps, status values.
|
|
502
|
+
- Do NOT use Bash commands. Use only Read, Glob, Grep, Write, and mcp__axiom__queryDataset.
|
|
503
|
+
- If Axiom queries fail, proceed with code analysis and note the gap in the report.14:["$","div","wgs-ingestion-bot",{"className":"mb-8","children":[["$","h2",null,{"className":"text-xs font-medium text-text-dim uppercase tracking-wide mb-3","children":"wgs-ingestion-bot"}],["$","div",null,{"className":"space-y-3","children":[["$","div","/Users/gabry/Desktop/wgs-ingestion-bot/.claude/commands/investigate-wgs-ingestion.md",{"className":"border border-border rounded-sm p-5 ","children":[["$","div",null,{"className":"flex items-center gap-2","children":[["$","h3",null,{"className":"text-sm font-medium","children":"investigate-wgs-ingestion"}],["$","span",null,{"className":"inline-flex items-center px-2 py-0.5 text-xs font-medium rounded-sm bg-surface-raised text-text-muted","children":"wgs-ingestion-bot"}]]}],["$","$L11",null,{"content":"$1f","previewLines":3}]]}]]}]]}]
|
|
504
|
+
20:Tf1d,# Add a New Model to llm-proxy-service
|
|
505
|
+
|
|
506
|
+
Add a new LLM model to `llm-proxy-service`, ensuring accurate cost reporting.
|
|
507
|
+
|
|
508
|
+
## Background
|
|
509
|
+
|
|
510
|
+
- `litellm` contains bundled pricing data in `model_prices_and_context_window.json`
|
|
511
|
+
- We disable litellm's automatic pricing fetch; we ONLY use the bundled pricing
|
|
512
|
+
- If the bundled pricing is wrong or missing for a model, litellm reports $0 cost, which breaks our cost reporting
|
|
513
|
+
- Overrides for incorrect pricing go in `platform-services/packages/llm_proxy_service/src/llm_proxy_service/service.py` via `litellm.register_model()`
|
|
514
|
+
- **IMPORTANT**: Both `llm-proxy-service` and `embedding-service` depend on `litellm`. Their versions must always match. If this skill requires upgrading litellm, update BOTH packages.
|
|
515
|
+
|
|
516
|
+
## Step 1: Gather information
|
|
517
|
+
|
|
518
|
+
Ask the user:
|
|
519
|
+
|
|
520
|
+
1. What model do they want to add? (e.g., `anthropic/claude-opus-4-5-20251101`)
|
|
521
|
+
2. What is the provider's pricing page URL for this model?
|
|
522
|
+
|
|
523
|
+
## Step 2: Determine the current litellm version
|
|
524
|
+
|
|
525
|
+
Read `platform-services/packages/llm_proxy_service/pyproject.toml` to find the currently-used litellm version.
|
|
526
|
+
|
|
527
|
+
## Step 3: Validate pricing in the current litellm version
|
|
528
|
+
|
|
529
|
+
Use `uv run` to check if the model has correct pricing in the bundled litellm data:
|
|
530
|
+
|
|
531
|
+
```bash
|
|
532
|
+
uv run --with litellm==<CURRENT_VERSION> python -c "import litellm, json; print(json.dumps(litellm.model_cost.get('<model_key>', {}), indent=2))"
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
Note: The key in `litellm.model_cost` may not exactly match the model string. If an exact match isn't found, search for partial matches:
|
|
536
|
+
|
|
537
|
+
```bash
|
|
538
|
+
uv run --with litellm==<CURRENT_VERSION> python -c "import litellm; keys = [k for k in litellm.model_cost if '<partial_model_name>' in k]; print('\n'.join(sorted(keys)))"
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
Fetch the provider's pricing page and compare against the litellm pricing. Validate ALL of these fields:
|
|
542
|
+
|
|
543
|
+
- `input_cost_per_token`
|
|
544
|
+
- `output_cost_per_token`
|
|
545
|
+
- `cache_read_input_token_cost` (if applicable)
|
|
546
|
+
- `cache_creation_input_token_cost` (if applicable)
|
|
547
|
+
|
|
548
|
+
Present the comparison to the user.
|
|
549
|
+
|
|
550
|
+
## Step 4: Add the model
|
|
551
|
+
|
|
552
|
+
### 4a. Add to LLMModel type
|
|
553
|
+
|
|
554
|
+
Add the model string to the `LLMModel` Literal type in `platform-services/packages/bioscope_types/src/bioscope_types/services/llm_proxy_service.py`.
|
|
555
|
+
|
|
556
|
+
- Place it in the correct provider group (bedrock, anthropic, vertex_ai, azure, groq)
|
|
557
|
+
- Ensure the provider group has a comment linking to the pricing page (add one if it's a new provider)
|
|
558
|
+
|
|
559
|
+
### 4b. Add pricing override (if needed)
|
|
560
|
+
|
|
561
|
+
If the pricing is incorrect or missing in litellm, add an override in `platform-services/packages/llm_proxy_service/src/llm_proxy_service/service.py`:
|
|
562
|
+
|
|
563
|
+
```python
|
|
564
|
+
litellm.register_model(
|
|
565
|
+
{
|
|
566
|
+
"<model_key>": {
|
|
567
|
+
"input_cost_per_token": <value>, # $X per 1M tokens
|
|
568
|
+
"output_cost_per_token": <value>, # $X per 1M tokens
|
|
569
|
+
"cache_read_input_token_cost": <value>, # $X per 1M tokens (if applicable)
|
|
570
|
+
"cache_creation_input_token_cost": <value>, # $X per 1M tokens (if applicable)
|
|
571
|
+
"litellm_provider": "<provider>",
|
|
572
|
+
"max_input_tokens": <value>,
|
|
573
|
+
"max_output_tokens": <value>,
|
|
574
|
+
"mode": "chat",
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
)
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
Include inline comments showing the human-readable cost (e.g., `# $3.00 per 1M tokens`).
|
|
581
|
+
|
|
582
|
+
### 4c. Add to health check warmup (if needed)
|
|
583
|
+
|
|
584
|
+
If the model requires additional env vars (vertex_ai, groq, or anthropic models), consider adding a `set_additional_env_vars()` call in the health check in `platform-services/packages/llm_proxy_service/src/llm_proxy_service/handler.py`. Only one model per provider prefix is needed for warmup.
|
|
585
|
+
|
|
586
|
+
## Step 5: Validate
|
|
587
|
+
|
|
588
|
+
1. Run `pnpm exec nx run bioscope-types:type-check` to verify the type is valid
|
|
589
|
+
2. Run `pnpm exec nx run llm-proxy-service:test` to verify tests pass
|
|
590
|
+
3. Run `pnpm exec nx run llm-proxy-service:lint` and `pnpm exec nx run llm-proxy-service:type-check`16:["$","div","/Users/gabry/Desktop/platform-services/.claude/commands/add-llm-proxy-service-model.md",{"className":"border border-border rounded-sm p-5 ","children":[["$","div",null,{"className":"flex items-center gap-2","children":[["$","h3",null,{"className":"text-sm font-medium","children":"add-llm-proxy-service-model"}],["$","span",null,{"className":"inline-flex items-center px-2 py-0.5 text-xs font-medium rounded-sm bg-surface-raised text-text-muted","children":"platform-services"}]]}],["$","$L11",null,{"content":"$20","previewLines":3}]]}]
|
|
591
|
+
21:T1c43,# IDOR & Authorization Vulnerability Scan
|
|
592
|
+
|
|
593
|
+
Scan ALL route handlers in platform-services for IDOR (Insecure Direct Object Reference) and authorization vulnerabilities.
|
|
594
|
+
|
|
595
|
+
## How This Codebase Works
|
|
596
|
+
|
|
597
|
+
This is a FastAPI-based backend. Key facts:
|
|
598
|
+
|
|
599
|
+
- Routes *should* live in `packages/*/src/*/routes/*.py` (flag any routes that do not)
|
|
600
|
+
- App setup files are at `packages/*/src/*/app.py`
|
|
601
|
+
- Service-specific middleware may be at `packages/*/src/*/middleware.py`
|
|
602
|
+
- Shared middleware is in `packages/shared_middleware/src/shared_middleware/`
|
|
603
|
+
- Most routes are behind an API Gateway account authorizer that validates the JWT and verifies the user is a member of the account in the `Bioscope-Account-Id` header. For these routes, `account_id`, `user_id`, and `user_role` from headers can be trusted.
|
|
604
|
+
- Some routes use a simpler JWT-only authorizer (e.g. `/accounts/me`, `/users/me`) or no authorizer at all (public endpoints). The authorizer config lives in infrastructure and is not visible from this repo, so don't make assumptions about which authorizer a given route uses — just focus on whether the route handler code itself properly validates ownership.
|
|
605
|
+
- With the above two bullets in mind, `account_id`, `user_id`, and `user_role` can ONLY come from these headers and can NEVER come from path params, query params, request body, etc.
|
|
606
|
+
|
|
607
|
+
### Auth/Authorization Patterns in Route Handlers
|
|
608
|
+
|
|
609
|
+
**Patient validation (cross-service ownership check):**
|
|
610
|
+
Routes with `{patient_id}` in the path MUST use `Depends(validate_patient_account_from_path_as_patient)` (or the factory `get_validate_patient_account`). This calls account-service to verify the patient belongs to the requesting account. A route that takes a patient_id without this dependency is an IDOR unless the route is checking the patient belongs to the account in its internal implementation.
|
|
611
|
+
|
|
612
|
+
**Inline account ownership checks:**
|
|
613
|
+
For non-patient resources (orders, EHR connections, etc.), routes typically fetch the resource and then check `if resource.account_id != account_id`. Missing this check on a resource lookup by ID is a potential IDOR.
|
|
614
|
+
|
|
615
|
+
## Your Task
|
|
616
|
+
|
|
617
|
+
### Step 1: Discover all services with routes
|
|
618
|
+
|
|
619
|
+
Use glob to find all route files matching `packages/*/src/*/routes/*.py`. Group them by service. Also check for any routes that aren't under a `routes` directory and flag them.
|
|
620
|
+
|
|
621
|
+
### Step 2: Create an output directory and spin up sub-agents
|
|
622
|
+
|
|
623
|
+
First, create an output directory using Bash: `mkdir -p /tmp/idor-scan-results`
|
|
624
|
+
|
|
625
|
+
Then, for each service, use the Task tool (subagent_type: "general-purpose") to scan that service's routes. Run these in parallel (include all Task tool calls in a single message). Each sub-agent should:
|
|
626
|
+
|
|
627
|
+
1. Read ALL route files for that service
|
|
628
|
+
2. Read the service's `app.py` to check what global dependencies/middleware are applied
|
|
629
|
+
3. Read any service-specific `middleware.py` if it exists
|
|
630
|
+
4. For each route handler, check for the vulnerabilities listed in Step 3
|
|
631
|
+
5. **Write the report to a file** at `/tmp/idor-scan-results/<service-name>.md` using the format in Step 4
|
|
632
|
+
6. **Return ONLY a one-line confirmation** (e.g., "Wrote report to /tmp/idor-scan-results/chat_service.md. 2 findings."). Do NOT return the full report — it's in the file.
|
|
633
|
+
|
|
634
|
+
**IMPORTANT:** When calling the Task tool for each sub-agent, explicitly instruct it to write findings to the file and return only a brief one-line confirmation. The full report must go in the file, NOT in the return message. This prevents the main agent's context from overflowing.
|
|
635
|
+
|
|
636
|
+
### Step 3: What to check per route
|
|
637
|
+
|
|
638
|
+
For every route handler function, check for these IDOR vulnerabilities:
|
|
639
|
+
|
|
640
|
+
- **Missing patient validation**: Route path contains `{patient_id}` but handler does NOT use `Depends(validate_patient_account_from_path_as_patient)` or equivalent
|
|
641
|
+
- **Patient dependency result discarded**: Route uses `validate_patient_account_from_path_as_patient` but assigns the result to `_` instead of `patient`. The presence of the dependency alone is NOT sufficient — if the route also takes a sub-resource ID (e.g., `{chat_id}`, `{file_id}`, `{order_id}`), the validated `patient.patient_id` MUST be passed to the service layer and checked against the fetched resource's `patient_id`. A discarded `_` is a strong signal that this check is missing. Trace the full call chain to verify.
|
|
642
|
+
- **Missing resource-to-account ownership**: Route takes a resource ID as a path/query/body param, fetches the resource, but does NOT verify `resource.account_id == account_id` before returning or mutating it
|
|
643
|
+
- **Missing resource-to-patient ownership**: Route takes both a `{patient_id}` and another resource ID, fetches the resource, but does NOT verify `resource.patient_id == patient_id`. This applies even if the patient validation dependency is present — the dependency only confirms the patient belongs to the account, NOT that the sub-resource belongs to the patient. You must trace into the service layer to verify this check exists.
|
|
644
|
+
- **Unscoped list/query endpoints**: Route returns a collection of resources (list/search/query) but the underlying query does NOT filter by `account_id` (or `patient_id` where applicable). Follow the call chain into the repository/data access layer to verify the query includes the appropriate scope filter.
|
|
645
|
+
- **Using account, user, or user role not from header**: Route uses account id, user id, or user role from query param, path param, or request body and not from the trusted `Bioscope-Account-Id`, `Bioscope-User-Id`, and `Bioscope-User-Role` headers.
|
|
646
|
+
|
|
647
|
+
### Step 4: Compile the report
|
|
648
|
+
|
|
649
|
+
Each sub-agent should return its findings in this format:
|
|
650
|
+
|
|
651
|
+
```text
|
|
652
|
+
## <service-name>
|
|
653
|
+
|
|
654
|
+
### Routes Scanned
|
|
655
|
+
- `GET /path` — handler_name (file:line)
|
|
656
|
+
- `POST /path` — handler_name (file:line)
|
|
657
|
+
...
|
|
658
|
+
|
|
659
|
+
### Findings
|
|
660
|
+
|
|
661
|
+
#### Missing patient validation — `POST /patients/{patient_id}/resource`
|
|
662
|
+
- **File**: path/to/file.py:123
|
|
663
|
+
- **Handler**: `create_resource`
|
|
664
|
+
- **Issue**: Route includes `{patient_id}` in path but does not use `validate_patient_account_from_path_as_patient`
|
|
665
|
+
- **Confidence**: High / Medium / Low
|
|
666
|
+
- **Notes**: <any relevant context>
|
|
667
|
+
|
|
668
|
+
#### Missing ownership check — `GET /resource/{resource_id}`
|
|
669
|
+
...
|
|
670
|
+
|
|
671
|
+
### No Issues Found
|
|
672
|
+
(list routes that were scanned and passed all checks)
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
### Step 5: Aggregate
|
|
676
|
+
|
|
677
|
+
After all sub-agents complete, read each file from `/tmp/idor-scan-results/` and compile a final summary. To avoid context limits, read one file at a time and extract only the findings (skip the "No Issues Found" and "Routes Scanned" sections for clean services).
|
|
678
|
+
|
|
679
|
+
Write the final report to `/tmp/idor-scan-results/SUMMARY.md` with:
|
|
680
|
+
|
|
681
|
+
1. **Executive Summary**: Total routes scanned, total findings
|
|
682
|
+
2. **Findings**: All IDOR vulnerabilities grouped by type
|
|
683
|
+
3. **Clean Services**: List of services with no findings (names only)
|
|
684
|
+
4. **Per-Service Details**: Full findings for services that had issues
|
|
685
|
+
|
|
686
|
+
Then output the summary to the user.
|
|
687
|
+
|
|
688
|
+
Be thorough. Read the actual code — don't guess based on function names alone. When in doubt about whether a check exists, read the called functions to see if ownership validation happens deeper in the call chain. If validation happens in a called function rather than at the route level, note it but don't flag it as a vulnerability.17:["$","div","/Users/gabry/Desktop/platform-services/.claude/commands/idor-scan.md",{"className":"border border-border rounded-sm p-5 ","children":[["$","div",null,{"className":"flex items-center gap-2","children":[["$","h3",null,{"className":"text-sm font-medium","children":"idor-scan"}],["$","span",null,{"className":"inline-flex items-center px-2 py-0.5 text-xs font-medium rounded-sm bg-surface-raised text-text-muted","children":"platform-services"}]]}],["$","$L11",null,{"content":"$21","previewLines":3}]]}]
|
|
689
|
+
22:T2543,# PHI/PII Data Exposure Scan
|
|
690
|
+
|
|
691
|
+
Scan ALL application code in platform-services for Protected Health Information (PHI) and Personally Identifiable Information (PII) exposure vulnerabilities. This covers logging, error responses, API over-fetching, and any other channel where sensitive data could leak.
|
|
692
|
+
|
|
693
|
+
## What Constitutes PHI/PII in This Codebase
|
|
694
|
+
|
|
695
|
+
### Patient PHI Fields (from `bioscope_types/dynamodb/patients.py`)
|
|
696
|
+
- `first_name`, `last_name` (names)
|
|
697
|
+
- `date_of_birth` (DOB)
|
|
698
|
+
- `sex`
|
|
699
|
+
- `mrn` (medical record number)
|
|
700
|
+
- `address_line_1`, `address_line_2`, `city`, `state`, `zip_code`, `country` (address)
|
|
701
|
+
- `phone_number`
|
|
702
|
+
- `email`
|
|
703
|
+
|
|
704
|
+
### User PII Fields (from `bioscope_types/dynamodb/users.py`)
|
|
705
|
+
- `first_name`, `last_name`
|
|
706
|
+
- `email`
|
|
707
|
+
- `npi_number` (healthcare provider identifier)
|
|
708
|
+
|
|
709
|
+
### Account PII Fields (from `bioscope_types/dynamodb/accounts.py`)
|
|
710
|
+
- Address fields: `address_line_1`, `address_line_2`, `city`, `state`, `zip_code`, `country`
|
|
711
|
+
|
|
712
|
+
### Other PHI Sources
|
|
713
|
+
- FHIR resources (contain full patient demographics, diagnoses, medical history)
|
|
714
|
+
- EHR data (clinical records, lab results, immunizations)
|
|
715
|
+
- Genomic/WGS data and results
|
|
716
|
+
- Chat messages about patients (may contain clinical discussions)
|
|
717
|
+
- File contents (uploaded documents, lab reports)
|
|
718
|
+
|
|
719
|
+
### Safe to Log
|
|
720
|
+
- UUIDs (patient_id, account_id, user_id, order_id, etc.)
|
|
721
|
+
- Timestamps
|
|
722
|
+
- Status values and enums
|
|
723
|
+
- Counts and metrics
|
|
724
|
+
- Operation names and types
|
|
725
|
+
- File IDs (not file contents or names that might contain patient info)
|
|
726
|
+
|
|
727
|
+
## How Logging Works
|
|
728
|
+
|
|
729
|
+
- `BioscopeLogger` (from `bioscope_logger` package) is the standard logger
|
|
730
|
+
- Uses Python's `logging.LoggerAdapter` with JSON formatting
|
|
731
|
+
- Supports `.child()` for adding context fields
|
|
732
|
+
- Extra fields passed via `extra={}` parameter are serialized into the JSON log output
|
|
733
|
+
- Logs go to stdout and optionally CloudWatch — all log output is persisted
|
|
734
|
+
- `BioscopeLoggerDeps` injects the logger into FastAPI routes
|
|
735
|
+
- Lambda handlers receive `logger: BioscopeLogger` via dependency injection
|
|
736
|
+
|
|
737
|
+
## Your Task
|
|
738
|
+
|
|
739
|
+
### Step 1: Discover all scannable code
|
|
740
|
+
|
|
741
|
+
Use glob to find:
|
|
742
|
+
1. All route files: `packages/*/src/*/routes/*.py`
|
|
743
|
+
2. All handler files: `packages/*/src/*/handler.py`
|
|
744
|
+
3. All handlers directories: `packages/*/src/*/handlers/*.py`
|
|
745
|
+
4. All service/business logic files: `packages/*/src/*/*.py` (excluding `__init__.py`, `aws.py`, `app.py`)
|
|
746
|
+
5. Any standalone scripts or local dev files: `packages/*/src/*/local.py`
|
|
747
|
+
|
|
748
|
+
Group them by service/package.
|
|
749
|
+
|
|
750
|
+
### Step 2: Create an output directory and spin up sub-agents
|
|
751
|
+
|
|
752
|
+
First, create an output directory using Bash: `mkdir -p /tmp/phi-exposure-scan-results`
|
|
753
|
+
|
|
754
|
+
Then, for each service/package, use the Task tool (subagent_type: "general-purpose") to scan that package's code. Run these in parallel (include all Task tool calls in a single message). Each sub-agent should:
|
|
755
|
+
|
|
756
|
+
1. Read ALL Python source files for that package (routes, handlers, service modules, utilities)
|
|
757
|
+
2. Check for every vulnerability type listed in Step 3
|
|
758
|
+
3. **Write the report to a file** at `/tmp/phi-exposure-scan-results/<package-name>.md` using the format in Step 4
|
|
759
|
+
4. **Return ONLY a one-line confirmation** (e.g., "Wrote report to /tmp/phi-exposure-scan-results/chat_service.md. 3 findings."). Do NOT return the full report — it's in the file.
|
|
760
|
+
|
|
761
|
+
**IMPORTANT:** When calling the Task tool for each sub-agent, include the full list of PHI/PII fields from the "What Constitutes PHI/PII" section above so the sub-agent knows exactly what to look for. Instruct it to write findings to the file and return only a brief one-line confirmation. The full report must go in the file, NOT in the return message.
|
|
762
|
+
|
|
763
|
+
### Step 3: What to check
|
|
764
|
+
|
|
765
|
+
#### A. PHI/PII in Log Statements (CRITICAL)
|
|
766
|
+
|
|
767
|
+
Search for all `logger.info`, `logger.warning`, `logger.error`, `logger.debug`, `logger.exception`, and `logger.critical` calls. For each, check:
|
|
768
|
+
|
|
769
|
+
- **Full model dumps in logs**: Calls like `logger.info("...", extra={"patient": patient.model_dump()})` or `model_dump_json()` that serialize an entire Pydantic model containing PHI fields. This includes Patient, User, Account, or any FHIR resource model.
|
|
770
|
+
- **PHI field values in log messages**: Direct references to PHI fields in log strings or extra dicts, e.g., `extra={"name": patient.first_name}`, `extra={"email": user.email}`, `extra={"dob": patient.date_of_birth}`.
|
|
771
|
+
- **F-string or format-string PHI**: Log messages that interpolate PHI values, e.g., `logger.info(f"Created patient {patient.first_name} {patient.last_name}")`.
|
|
772
|
+
- **Logging raw request/response bodies**: Logging full HTTP request bodies or response payloads that may contain PHI, e.g., `logger.info("Request", extra={"body": request.body()})`.
|
|
773
|
+
- **Logging full event payloads**: SQS/SNS/EventBridge event payloads logged in full when they may contain PHI fields.
|
|
774
|
+
- **Logging FHIR resources**: Any FHIR Bundle, Patient, Observation, Immunization, or other clinical resource logged in full.
|
|
775
|
+
|
|
776
|
+
#### B. PHI/PII in Error Responses (HIGH)
|
|
777
|
+
|
|
778
|
+
Check all `HTTPException` raises and error response construction:
|
|
779
|
+
|
|
780
|
+
- **PHI in HTTPException detail**: `raise HTTPException(status_code=..., detail=f"Patient {patient.first_name} not found")` — the detail message should never contain PHI, only IDs or generic messages.
|
|
781
|
+
- **PHI in custom error response models**: Any error response class that includes PHI fields.
|
|
782
|
+
- **Full exception messages with PHI**: Exception handlers that return `str(e)` where the exception message might contain PHI from a database query or validation error.
|
|
783
|
+
|
|
784
|
+
#### C. PHI/PII in API Response Over-Fetching (MEDIUM)
|
|
785
|
+
|
|
786
|
+
Check route return values and response models:
|
|
787
|
+
|
|
788
|
+
- **Returning full patient/user records when not needed**: A route that returns a complete Patient object with all fields when the consumer only needs a subset (e.g., patient_id and status).
|
|
789
|
+
|
|
790
|
+
#### D. PHI/PII in URLs and Query Parameters (HIGH)
|
|
791
|
+
|
|
792
|
+
- **Patient data in query strings**: Routes that accept PHI as query parameters (e.g., `?name=John&dob=1990-01-01`). Query strings end up in access logs, browser history, and CDN logs. Only IDs should be in URLs.
|
|
793
|
+
- **PHI in path parameters**: Path params should only contain UUIDs or opaque identifiers, never names, emails, or other PHI.
|
|
794
|
+
|
|
795
|
+
#### E. PHI/PII in Development/Debug Code (MEDIUM)
|
|
796
|
+
|
|
797
|
+
- **Local development files**: Files like `local.py` or scripts that log full records for debugging but exist in the production codebase.
|
|
798
|
+
- **Commented-out debug logging**: Commented code that logs PHI — a developer might uncomment it and forget to remove it.
|
|
799
|
+
- **Print statements with PHI**: Any `print()` calls that output PHI (should use logger instead, but print output also goes to CloudWatch).
|
|
800
|
+
|
|
801
|
+
#### F. Missing Data Sanitization (LOW)
|
|
802
|
+
|
|
803
|
+
- **No redaction utilities**: Note if the codebase lacks any sanitization/redaction utilities for PHI fields. This is an architectural observation, not a per-route vulnerability.
|
|
804
|
+
- **PHI passed through multiple layers without scrubbing**: Trace data flow where PHI enters the system (e.g., from account-service or EHR) and check if it's ever inadvertently logged along the way.
|
|
805
|
+
|
|
806
|
+
### Step 4: Report format
|
|
807
|
+
|
|
808
|
+
Each sub-agent should write findings in this format:
|
|
809
|
+
|
|
810
|
+
```text
|
|
811
|
+
## <package-name>
|
|
812
|
+
|
|
813
|
+
### Files Scanned
|
|
814
|
+
- path/to/file.py
|
|
815
|
+
- path/to/other_file.py
|
|
816
|
+
...
|
|
817
|
+
|
|
818
|
+
### Findings
|
|
819
|
+
|
|
820
|
+
#### [CRITICAL] Full patient model logged — service.py:45
|
|
821
|
+
- **File**: path/to/file.py:45
|
|
822
|
+
- **Code**: `logger.info("Patient: ", extra={"patient": patient.model_dump_json()})`
|
|
823
|
+
- **Category**: PHI in log statements
|
|
824
|
+
- **PHI Fields Exposed**: first_name, last_name, date_of_birth, email, phone_number, address, mrn
|
|
825
|
+
- **Notes**: Logs the entire Patient FHIR resource including all demographics
|
|
826
|
+
|
|
827
|
+
#### [HIGH] PHI in error response — routes/patients.py:78
|
|
828
|
+
- **File**: path/to/file.py:78
|
|
829
|
+
- **Code**: `raise HTTPException(detail=f"Patient {patient.first_name} not found")`
|
|
830
|
+
- **Category**: PHI in error responses
|
|
831
|
+
- **PHI Fields Exposed**: first_name
|
|
832
|
+
- **Notes**: Patient name included in 404 error detail
|
|
833
|
+
|
|
834
|
+
### No Issues Found
|
|
835
|
+
(list files that were scanned and passed all checks)
|
|
836
|
+
```
|
|
837
|
+
|
|
838
|
+
Severity levels:
|
|
839
|
+
- **CRITICAL**: Full model dumps or FHIR resources in logs, multiple PHI fields exposed
|
|
840
|
+
- **HIGH**: Individual PHI fields in logs or error responses, PHI in URLs
|
|
841
|
+
- **MEDIUM**: Over-fetching in API responses, debug/dev code with PHI
|
|
842
|
+
- **LOW**: Architectural observations, missing sanitization utilities
|
|
843
|
+
|
|
844
|
+
### Step 5: Aggregate
|
|
845
|
+
|
|
846
|
+
After all sub-agents complete, read each file from `/tmp/phi-exposure-scan-results/` and compile a final summary. To avoid context limits, read one file at a time and extract only the findings.
|
|
847
|
+
|
|
848
|
+
Write the final report to `/tmp/phi-exposure-scan-results/SUMMARY.md` with:
|
|
849
|
+
|
|
850
|
+
1. **Executive Summary**: Total files scanned, total findings by severity (CRITICAL/HIGH/MEDIUM/LOW)
|
|
851
|
+
2. **CRITICAL Findings**: All critical PHI exposure issues (immediate remediation needed)
|
|
852
|
+
3. **HIGH Findings**: High-severity issues
|
|
853
|
+
4. **MEDIUM Findings**: Medium-severity issues
|
|
854
|
+
5. **LOW Findings & Observations**: Low-severity items and architectural notes
|
|
855
|
+
6. **Clean Packages**: List of packages with no findings (names only)
|
|
856
|
+
7. **Recommendations**: Actionable remediation steps, prioritized by severity
|
|
857
|
+
|
|
858
|
+
Then output the summary to the user.
|
|
859
|
+
|
|
860
|
+
Be thorough. Read the actual code — don't guess based on function names alone. When checking log statements, look at what the `extra` dict actually contains. When checking for model dumps, trace the model class to see what fields it includes. If a model only contains safe fields (IDs, timestamps, statuses), it's not a PHI exposure even if it's logged via `model_dump()`.18:["$","div","/Users/gabry/Desktop/platform-services/.claude/commands/phi-exposure-scan.md",{"className":"border border-border rounded-sm p-5 ","children":[["$","div",null,{"className":"flex items-center gap-2","children":[["$","h3",null,{"className":"text-sm font-medium","children":"phi-exposure-scan"}],["$","span",null,{"className":"inline-flex items-center px-2 py-0.5 text-xs font-medium rounded-sm bg-surface-raised text-text-muted","children":"platform-services"}]]}],["$","$L11",null,{"content":"$22","previewLines":3}]]}]
|
|
861
|
+
23:T1b86,# Upgrade litellm in llm-proxy-service
|
|
862
|
+
|
|
863
|
+
Upgrade the `litellm` dependency in `llm-proxy-service` to a new version, validating that all supported models have correct pricing.
|
|
864
|
+
|
|
865
|
+
## Background
|
|
866
|
+
|
|
867
|
+
- `litellm` contains bundled pricing data in `model_prices_and_context_window.json`
|
|
868
|
+
- We disable litellm's automatic pricing fetch; we ONLY use the bundled pricing
|
|
869
|
+
- If the bundled pricing is wrong or missing for a model, litellm reports $0 cost, which breaks our cost reporting
|
|
870
|
+
- Overrides for incorrect pricing go in `platform-services/packages/llm_proxy_service/src/llm_proxy_service/service.py` via `litellm.register_model()`
|
|
871
|
+
- **IMPORTANT**: Both `llm-proxy-service` and `embedding-service` depend on `litellm`. Their versions must always match. When upgrading, update BOTH `platform-services/packages/llm_proxy_service/pyproject.toml` and `platform-services/packages/embedding_service/pyproject.toml`.
|
|
872
|
+
|
|
873
|
+
## Step 1: Ask the user what version to upgrade to
|
|
874
|
+
|
|
875
|
+
First, read the current litellm version from `platform-services/packages/llm_proxy_service/pyproject.toml`. Then, fetch the latest available versions from PyPI:
|
|
876
|
+
|
|
877
|
+
```bash
|
|
878
|
+
curl -s "https://pypi.org/pypi/litellm/json" | python3 -c "import sys,json; releases=sorted(json.load(sys.stdin)['releases'].keys(), key=lambda v: [int(x) for x in v.split('.')[:3] if x.isdigit()], reverse=True); print('\n'.join(releases[:5]))"
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
Use AskUserQuestion to present the user with a selection of versions. Include the 3-4 most recent versions as options, labeling the latest one with "(Latest)". The user can also type a different version via the "Other" option. Mention the current version in the question text so the user knows what they're upgrading from.
|
|
882
|
+
|
|
883
|
+
## Step 2: Identify all supported models
|
|
884
|
+
|
|
885
|
+
Read the `LLMModel` type definition in `platform-services/packages/bioscope_types/src/bioscope_types/services/llm_proxy_service.py` to get all supported models. Group them by provider:
|
|
886
|
+
|
|
887
|
+
- `bedrock/` models (Anthropic on AWS Bedrock)
|
|
888
|
+
- `anthropic/` models (direct Anthropic API)
|
|
889
|
+
- `vertex_ai/` models (Google Vertex AI)
|
|
890
|
+
- `azure/` models (Azure OpenAI)
|
|
891
|
+
- `groq/` models (Groq)
|
|
892
|
+
- etc.
|
|
893
|
+
|
|
894
|
+
Also read the current litellm version from `platform-services/packages/llm_proxy_service/pyproject.toml`.
|
|
895
|
+
|
|
896
|
+
Also read `platform-services/packages/llm_proxy_service/src/llm_proxy_service/service.py` to identify any existing `litellm.register_model()` overrides.
|
|
897
|
+
|
|
898
|
+
## Step 3: Create output directory and spin up sub-agents per provider
|
|
899
|
+
|
|
900
|
+
First, create an output directory using Bash: `mkdir -p /tmp/litellm-upgrade`
|
|
901
|
+
|
|
902
|
+
Then, for EACH provider (bedrock, anthropic, vertex_ai, azure, groq), spin up a sub-agent using the Task tool (subagent_type: "general-purpose"). Run all provider sub-agents **in parallel** (include all Task tool calls in a single message). **Do NOT run these in the background** — they need to be foreground agents so they can prompt for tool permissions.
|
|
903
|
+
|
|
904
|
+
Each sub-agent should:
|
|
905
|
+
|
|
906
|
+
1. **Check pricing in the NEW version** of litellm for every model belonging to that provider. Use `uv run` to inspect the bundled pricing data:
|
|
907
|
+
|
|
908
|
+
```bash
|
|
909
|
+
uv run --with litellm==<NEW_VERSION> python -c "import litellm, json; print(json.dumps(litellm.model_cost.get('<model_key>', {}), indent=2))"
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
Note: The key in `litellm.model_cost` may not exactly match the model string in `LLMModel`. For example, `bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0` may be keyed as `us.anthropic.claude-sonnet-4-5-20250929-v1:0` or similar. If an exact match isn't found, search for partial matches:
|
|
913
|
+
|
|
914
|
+
```bash
|
|
915
|
+
uv run --with litellm==<NEW_VERSION> python -c "import litellm; keys = [k for k in litellm.model_cost if '<partial_model_name>' in k]; print('\n'.join(sorted(keys)))"
|
|
916
|
+
```
|
|
917
|
+
|
|
918
|
+
2. **Fetch the provider's pricing page** (linked in the `LLMModel` comments) and compare the litellm pricing against the actual provider pricing. Key fields to validate:
|
|
919
|
+
- `input_cost_per_token`
|
|
920
|
+
- `output_cost_per_token`
|
|
921
|
+
- `cache_read_input_token_cost` (if applicable)
|
|
922
|
+
- `cache_creation_input_token_cost` (if applicable)
|
|
923
|
+
|
|
924
|
+
3. **Also check the OLD (current) version** to see if any existing overrides can be removed because the new version has correct pricing:
|
|
925
|
+
|
|
926
|
+
```bash
|
|
927
|
+
uv run --with litellm==<OLD_VERSION> python -c "import litellm, json; print(json.dumps(litellm.model_cost.get('<model_key>', {}), indent=2))"
|
|
928
|
+
```
|
|
929
|
+
|
|
930
|
+
4. **Write findings to a file** at `/tmp/litellm-upgrade/<provider>.md` with this format:
|
|
931
|
+
|
|
932
|
+
```text
|
|
933
|
+
## <provider> Models
|
|
934
|
+
|
|
935
|
+
### <model_name>
|
|
936
|
+
- **Provider pricing page**: <url>
|
|
937
|
+
- **Expected input cost**: $X per 1M tokens
|
|
938
|
+
- **Expected output cost**: $X per 1M tokens
|
|
939
|
+
- **Expected cached input cost**: $X per 1M tokens (if applicable)
|
|
940
|
+
- **litellm (new version) input cost**: $X per 1M tokens
|
|
941
|
+
- **litellm (new version) output cost**: $X per 1M tokens
|
|
942
|
+
- **litellm (new version) cached input cost**: $X per 1M tokens
|
|
943
|
+
- **Status**: CORRECT / INCORRECT / MISSING
|
|
944
|
+
- **Override needed**: Yes (details) / No
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
5. **Return ONLY a single sentence** summarizing findings (e.g., "All 3 Anthropic models have correct pricing in the new version." or "2 of 5 Bedrock models have incorrect cached input pricing."). The full report is in the file — do NOT return it in the response.
|
|
948
|
+
|
|
949
|
+
**IMPORTANT:** When calling the Task tool for each sub-agent, explicitly instruct it to write findings to the file and return only a brief single-sentence confirmation. The full report must go in the file, NOT in the return message. This prevents the main agent's context from overflowing.
|
|
950
|
+
|
|
951
|
+
## Step 4: Spin up a final evaluation sub-agent
|
|
952
|
+
|
|
953
|
+
After all provider sub-agents complete, spin up ONE final sub-agent (subagent_type: "general-purpose") that:
|
|
954
|
+
|
|
955
|
+
1. Reads all files in `/tmp/litellm-upgrade/`
|
|
956
|
+
2. Compiles a summary of which models need overrides and which are correct
|
|
957
|
+
3. Writes a final report to `/tmp/litellm-upgrade/SUMMARY.md`
|
|
958
|
+
4. Returns ONLY a single sentence summary (e.g., "3 models need pricing overrides, 15 are correct. See /tmp/litellm-upgrade/SUMMARY.md for details.")
|
|
959
|
+
|
|
960
|
+
Then read `/tmp/litellm-upgrade/SUMMARY.md` and present the findings to the user.
|
|
961
|
+
|
|
962
|
+
## Step 5: Implement the upgrade
|
|
963
|
+
|
|
964
|
+
After presenting findings to the user and getting their approval:
|
|
965
|
+
|
|
966
|
+
1. Update the litellm version in BOTH:
|
|
967
|
+
- `platform-services/packages/llm_proxy_service/pyproject.toml`
|
|
968
|
+
- `platform-services/packages/embedding_service/pyproject.toml`
|
|
969
|
+
2. Add any needed `litellm.register_model()` overrides in `platform-services/packages/llm_proxy_service/src/llm_proxy_service/service.py`
|
|
970
|
+
3. Remove any existing overrides that are no longer needed (because the new version has correct pricing)
|
|
971
|
+
4. Run `uv sync --all-packages` from the `platform-services/` directory to update the lock file
|
|
972
|
+
5. Run `pnpm exec nx run llm-proxy-service:test` to verify tests pass
|
|
973
|
+
6. Run `pnpm exec nx run llm-proxy-service:lint` and `pnpm exec nx run llm-proxy-service:type-check`
|
|
974
|
+
7. Run `pnpm exec nx run embedding-service:test`, `pnpm exec nx run embedding-service:lint`, and `pnpm exec nx run embedding-service:type-check`19:["$","div","/Users/gabry/Desktop/platform-services/.claude/commands/upgrade-litellm.md",{"className":"border border-border rounded-sm p-5 ","children":[["$","div",null,{"className":"flex items-center gap-2","children":[["$","h3",null,{"className":"text-sm font-medium","children":"upgrade-litellm"}],["$","span",null,{"className":"inline-flex items-center px-2 py-0.5 text-xs font-medium rounded-sm bg-surface-raised text-text-muted","children":"platform-services"}]]}],["$","$L11",null,{"content":"$23","previewLines":3}]]}]
|
|
975
|
+
24:T368e,# Broken Access Control Scan
|
|
976
|
+
|
|
977
|
+
Scan ALL route handlers and Lambda handlers in platform-services for broken access control vulnerabilities beyond IDOR (which is covered by the separate `idor-scan` command).
|
|
978
|
+
|
|
979
|
+
## How This Codebase Works
|
|
980
|
+
|
|
981
|
+
This is a FastAPI-based backend. Key facts:
|
|
982
|
+
|
|
983
|
+
- Routes live in `packages/*/src/*/routes/*.py`
|
|
984
|
+
- App setup files are at `packages/*/src/*/app.py`
|
|
985
|
+
- Lambda handlers are at `packages/*/src/*/handler.py`
|
|
986
|
+
- Service-specific middleware may be at `packages/*/src/*/middleware.py`
|
|
987
|
+
- Shared middleware is in `packages/shared_middleware/src/shared_middleware/`
|
|
988
|
+
- Most routes are behind an API Gateway account authorizer that validates the JWT and sets trusted headers: `Bioscope-Account-Id`, `Bioscope-User-Id`, `Bioscope-User-Role`, `Bioscope-Is-Demo-User`
|
|
989
|
+
- Some routes use a simpler JWT-only authorizer or no authorizer at all (public endpoints). The authorizer config lives in infrastructure and is not visible from this repo.
|
|
990
|
+
|
|
991
|
+
### Standard Middleware Stack
|
|
992
|
+
|
|
993
|
+
Every FastAPI service should mount these middlewares in this order in `app.py`:
|
|
994
|
+
|
|
995
|
+
```python
|
|
996
|
+
app = FastAPI(title="service-name", dependencies=[Depends(enforce_demo_read_only)])
|
|
997
|
+
app.add_middleware(WithExceptionLoggingMiddleware)
|
|
998
|
+
app.add_middleware(WithMetadataLoggingMiddleware)
|
|
999
|
+
app.add_middleware(WithLoggerMiddleware)
|
|
1000
|
+
```
|
|
1001
|
+
|
|
1002
|
+
And include routers via `app.include_router(...)`.
|
|
1003
|
+
|
|
1004
|
+
### Role-Based Access Control
|
|
1005
|
+
|
|
1006
|
+
The codebase has a single role validation dependency:
|
|
1007
|
+
|
|
1008
|
+
- `require_owner_role` in `shared_middleware/role_validation.py` — checks `Bioscope-User-Role` header equals `"owner"`, raises 403 otherwise
|
|
1009
|
+
- Used as `RequireOwnerRoleDeps = Annotated[None, Depends(require_owner_role)]`
|
|
1010
|
+
|
|
1011
|
+
Role is set by the API Gateway authorizer from the user's account membership record in DynamoDB.
|
|
1012
|
+
|
|
1013
|
+
### Demo Mode
|
|
1014
|
+
|
|
1015
|
+
- `enforce_demo_read_only` is applied as a global FastAPI dependency — blocks all non-GET/HEAD/OPTIONS requests for demo users
|
|
1016
|
+
- Routes can opt in to allow demo writes with the `@allow_demo_writes` decorator
|
|
1017
|
+
|
|
1018
|
+
### Header Dependencies
|
|
1019
|
+
|
|
1020
|
+
Trusted headers are injected via these typed dependencies (from `shared_middleware/headers.py`):
|
|
1021
|
+
|
|
1022
|
+
- `BioscopeAccountIdHeaderDeps` — `Bioscope-Account-Id`
|
|
1023
|
+
- `BioscopeUserIdHeaderDeps` — `Bioscope-User-Id`
|
|
1024
|
+
- `BioscopeUserRoleHeaderDeps` — `Bioscope-User-Role`
|
|
1025
|
+
- `BioscopeCorrelationIdHeaderDeps` — `Bioscope-Correlation-Id`
|
|
1026
|
+
- `BioscopeInternalApiKeyHeaderDeps` — `Bioscope-Internal-Api-Key`
|
|
1027
|
+
- `BioscopeIsDemoUserHeaderDeps` — `Bioscope-Is-Demo-User`
|
|
1028
|
+
|
|
1029
|
+
## Your Task
|
|
1030
|
+
|
|
1031
|
+
### Step 1: Discover all services
|
|
1032
|
+
|
|
1033
|
+
Use glob to find:
|
|
1034
|
+
1. All route files: `packages/*/src/*/routes/*.py`
|
|
1035
|
+
2. All app files: `packages/*/src/*/app.py`
|
|
1036
|
+
3. All handler files: `packages/*/src/*/handler.py`
|
|
1037
|
+
4. All handler directories: `packages/*/src/*/handlers/*.py`
|
|
1038
|
+
|
|
1039
|
+
Group them by service. A service may have routes (FastAPI), handlers (Lambda), or both.
|
|
1040
|
+
|
|
1041
|
+
### Step 2: Create an output directory and spin up sub-agents
|
|
1042
|
+
|
|
1043
|
+
First, create an output directory using Bash: `mkdir -p access-control-scan-results` (in the repo root directory).
|
|
1044
|
+
|
|
1045
|
+
Then, for **every service** (both route-based and handler-only), use the Task tool (subagent_type: "general-purpose") to scan that service.
|
|
1046
|
+
|
|
1047
|
+
#### Parallelism guidelines
|
|
1048
|
+
|
|
1049
|
+
**CRITICAL: Do NOT launch all agents at once.** This codebase has many services (typically 50+). Launching too many parallel agents causes resource contention, slow completions, and permission prompt overload.
|
|
1050
|
+
|
|
1051
|
+
Instead, process services in **batches of 5 agents at a time**:
|
|
1052
|
+
|
|
1053
|
+
1. **Batch 1**: Launch 5 route-based service agents in parallel (in a single message with 5 Task tool calls). Run them in background (`run_in_background: true`).
|
|
1054
|
+
2. **Wait**: After launching a batch, wait for all agents in the batch to complete before launching the next batch. Check completion by reading the output files or using TaskOutput.
|
|
1055
|
+
3. **Batch 2**: Launch the next 5 route-based services.
|
|
1056
|
+
4. **Continue**: Repeat until all route-based services are scanned, then do the same for handler-only services.
|
|
1057
|
+
|
|
1058
|
+
For **handler-only services**, you may group 3-5 related services into a single agent (e.g., all `*_event_consumer` services in one agent) since they are simpler to scan. This reduces the total number of agents needed. Each grouped agent should write **separate report files** for each service it scans.
|
|
1059
|
+
|
|
1060
|
+
#### What each sub-agent should do
|
|
1061
|
+
|
|
1062
|
+
**For services with route files**, each sub-agent should:
|
|
1063
|
+
1. Read ALL route files for that service
|
|
1064
|
+
2. Read the service's `app.py` to check middleware mounting and global dependencies
|
|
1065
|
+
3. Read any service-specific `middleware.py` if it exists
|
|
1066
|
+
4. For each route handler, check for the vulnerabilities listed in Step 3
|
|
1067
|
+
5. **Write the report to a file** at `access-control-scan-results/<service-name>.md` (relative to the repo root) using the format in Step 4
|
|
1068
|
+
6. **Return ONLY a one-line confirmation** (e.g., "Wrote report to access-control-scan-results/chat_service.md. 2 findings."). Do NOT return the full report — it's in the file.
|
|
1069
|
+
|
|
1070
|
+
**For handler-only services** (no route files, only `handler.py` and optionally `handlers/*.py`), each sub-agent should:
|
|
1071
|
+
1. Read the service's `handler.py` and all files in `handlers/` if present
|
|
1072
|
+
2. For each Lambda handler (decorated with `@handler.sqs`, `@handler.sns`, `@handler.direct_invocation`, `@handler.event_bridge`, `@handler.authorizer`), check for the vulnerabilities listed in Step 3 section E
|
|
1073
|
+
3. **Write the report to a file** at `access-control-scan-results/<service-name>.md` (relative to the repo root) using the format in Step 4
|
|
1074
|
+
4. **Return ONLY a one-line confirmation**
|
|
1075
|
+
|
|
1076
|
+
**IMPORTANT:** When calling the Task tool for each sub-agent, explicitly instruct it to write findings to the file and return only a brief one-line confirmation. The full report must go in the file, NOT in the return message. This prevents the main agent's context from overflowing.
|
|
1077
|
+
|
|
1078
|
+
### Step 3: What to check per service and route
|
|
1079
|
+
|
|
1080
|
+
#### A. Middleware and App-Level Checks
|
|
1081
|
+
|
|
1082
|
+
For each service's `app.py`, verify:
|
|
1083
|
+
|
|
1084
|
+
- **Missing standard middleware**: The app MUST mount all three middlewares (`WithExceptionLoggingMiddleware`, `WithMetadataLoggingMiddleware`, `WithLoggerMiddleware`). Flag any that are missing.
|
|
1085
|
+
- **Missing demo mode enforcement**: The app MUST have `dependencies=[Depends(enforce_demo_read_only)]` on the `FastAPI()` constructor. Flag if missing.
|
|
1086
|
+
- **Non-standard middleware ordering**: Middlewares execute in reverse order of addition (LIFO). `WithLoggerMiddleware` must be added last so it executes first. Flag incorrect ordering.
|
|
1087
|
+
- **Routes mounted outside the app**: Check if any route files exist that are NOT included via `app.include_router(...)`. These routes would bypass all app-level middleware and dependencies.
|
|
1088
|
+
|
|
1089
|
+
#### B. Role-Based Access Control Checks
|
|
1090
|
+
|
|
1091
|
+
For each route handler, check:
|
|
1092
|
+
|
|
1093
|
+
- **Sensitive mutations without role checks**: Routes that perform destructive or admin-level operations (DELETE endpoints, account settings changes, user management, billing operations) should use `RequireOwnerRoleDeps` or `Depends(require_owner_role)`. Flag mutation endpoints that handle sensitive operations without any role check. Use your judgment — not every POST/PATCH/DELETE needs a role check, but operations like deleting accounts, managing users, or changing account settings do.
|
|
1094
|
+
- **Role from untrusted source**: Any route that reads a role from path params, query params, or request body instead of the `Bioscope-User-Role` header. The role MUST come from the trusted header dependency.
|
|
1095
|
+
|
|
1096
|
+
#### C. Authentication/Authorization Gaps
|
|
1097
|
+
|
|
1098
|
+
For each route handler, check:
|
|
1099
|
+
|
|
1100
|
+
- **Missing identity headers**: Routes that perform any data access or mutation but do NOT inject `BioscopeAccountIdHeaderDeps` or `BioscopeUserIdHeaderDeps`. Every non-public route should use at least the account ID header to scope its operations.
|
|
1101
|
+
- **Hardcoded or default account/user IDs**: Any route that uses a hardcoded UUID or default value for account_id or user_id instead of extracting from headers.
|
|
1102
|
+
- **Internal API key routes without validation**: Routes that accept `BioscopeInternalApiKeyHeaderDeps` should validate the key value against an expected secret, not just check that the header is present.
|
|
1103
|
+
|
|
1104
|
+
#### D. Demo Mode Bypass
|
|
1105
|
+
|
|
1106
|
+
- **Mutation routes with @allow_demo_writes that shouldn't have it**: The `@allow_demo_writes` decorator should only be on routes where demo users legitimately need write access (e.g., creating a chat for a demo walkthrough). Flag any destructive operations (DELETE, account mutations) that have this decorator.
|
|
1107
|
+
|
|
1108
|
+
#### E. Lambda Handler Checks (for handler-only and hybrid services)
|
|
1109
|
+
|
|
1110
|
+
Lambda handlers (`@handler.sqs`, `@handler.sns`, `@handler.direct_invocation`, `@handler.event_bridge`) are internal-facing and trust their event sources by design (IAM policies and queue/topic access policies control who can invoke them). The checks below focus on risks that remain even within that trust model.
|
|
1111
|
+
|
|
1112
|
+
For each Lambda handler, check:
|
|
1113
|
+
|
|
1114
|
+
- **Unscoped destructive operations**: Direct invocation or event-driven handlers that perform bulk deletes, account mutations, or data purges without scoping to a specific `account_id` or `patient_id` from the event payload. A handler that deletes "all matching records" rather than scoping by the account/patient in the event is dangerous if it ever receives malformed input.
|
|
1115
|
+
- **Missing account/patient scoping on queries**: Handlers that query DynamoDB or other data stores without filtering by `account_id` or `patient_id` when the event payload contains those identifiers. The handler should use the event's IDs to scope its operations, not fetch all records globally.
|
|
1116
|
+
- **Sensitive operations in direct invocation handlers without caller context**: Direct invocation handlers that perform admin-level operations (creating users, modifying account settings, issuing credentials) should accept and log a `correlation_id` or caller identifier for audit trail. Flag handlers that perform sensitive mutations with no traceability to the original caller.
|
|
1117
|
+
- **Event payload used to construct external requests without validation**: Handlers that take URLs, email addresses, or external identifiers from event payloads and pass them directly to external services (HTTP calls, email sends, S3 operations). Validate that the handler sanitizes or validates these inputs rather than blindly trusting them.
|
|
1118
|
+
- **Internal API key routes without key validation**: Any HTTP route (in hybrid services that have both routes and handlers) that accepts `BioscopeInternalApiKeyHeaderDeps` should validate the key value against an expected secret, not just check that the header is present.
|
|
1119
|
+
|
|
1120
|
+
**Important context for sub-agents**: Do NOT flag handler-level findings for the following, as these are expected patterns:
|
|
1121
|
+
- Direct invocation handlers that don't have API Gateway-style JWT authorization — they're internal Lambda-to-Lambda calls secured by IAM
|
|
1122
|
+
- SQS/SNS handlers that trust `account_id` or `patient_id` from the event body — the event source is trusted
|
|
1123
|
+
- Handlers that don't inject `BioscopeAccountIdHeaderDeps` — header dependencies are for HTTP routes only, not Lambda handlers
|
|
1124
|
+
|
|
1125
|
+
### Step 4: Report format
|
|
1126
|
+
|
|
1127
|
+
Each sub-agent should write findings in this format:
|
|
1128
|
+
|
|
1129
|
+
**For services with routes (FastAPI):**
|
|
1130
|
+
|
|
1131
|
+
```text
|
|
1132
|
+
## <service-name>
|
|
1133
|
+
|
|
1134
|
+
### App-Level Configuration
|
|
1135
|
+
- **Middleware**: [All present / Missing: <list>]
|
|
1136
|
+
- **Demo mode**: [Enforced / MISSING]
|
|
1137
|
+
- **Middleware order**: [Correct / INCORRECT: <details>]
|
|
1138
|
+
- **Unmounted routes**: [None / <list>]
|
|
1139
|
+
|
|
1140
|
+
### Routes Scanned
|
|
1141
|
+
- `GET /path` — handler_name (file:line)
|
|
1142
|
+
- `POST /path` — handler_name (file:line)
|
|
1143
|
+
...
|
|
1144
|
+
|
|
1145
|
+
### Findings
|
|
1146
|
+
|
|
1147
|
+
#### Missing role check on sensitive mutation — `DELETE /resource/{id}`
|
|
1148
|
+
- **File**: path/to/file.py:123
|
|
1149
|
+
- **Handler**: `delete_resource`
|
|
1150
|
+
- **Issue**: Destructive operation with no role validation
|
|
1151
|
+
- **Confidence**: High / Medium / Low
|
|
1152
|
+
- **Notes**: <any relevant context>
|
|
1153
|
+
|
|
1154
|
+
#### Missing identity headers — `GET /resource`
|
|
1155
|
+
...
|
|
1156
|
+
|
|
1157
|
+
### No Issues Found
|
|
1158
|
+
(list routes that were scanned and passed all checks)
|
|
1159
|
+
```
|
|
1160
|
+
|
|
1161
|
+
**For handler-only services (Lambda):**
|
|
1162
|
+
|
|
1163
|
+
```text
|
|
1164
|
+
## <service-name>
|
|
1165
|
+
|
|
1166
|
+
### Handlers Scanned
|
|
1167
|
+
- `@handler.sqs(queue_name="queue-name")` — handler_function (file:line)
|
|
1168
|
+
- `@handler.direct_invocation()` — handler_function (file:line)
|
|
1169
|
+
- `@handler.event_bridge()` — handler_function (file:line)
|
|
1170
|
+
...
|
|
1171
|
+
|
|
1172
|
+
### Findings
|
|
1173
|
+
|
|
1174
|
+
#### Unscoped destructive operation — handle_delete_event
|
|
1175
|
+
- **File**: path/to/handler.py:45
|
|
1176
|
+
- **Handler**: `handle_delete_event`
|
|
1177
|
+
- **Decorator**: `@handler.sqs(queue_name="...")`
|
|
1178
|
+
- **Issue**: Deletes records without scoping to account_id from event payload
|
|
1179
|
+
- **Confidence**: High / Medium / Low
|
|
1180
|
+
- **Notes**: <any relevant context>
|
|
1181
|
+
|
|
1182
|
+
### No Issues Found
|
|
1183
|
+
(list handlers that were scanned and passed all checks)
|
|
1184
|
+
```
|
|
1185
|
+
|
|
1186
|
+
### Step 5: Aggregate
|
|
1187
|
+
|
|
1188
|
+
After all sub-agents complete, read each file from `access-control-scan-results/` and compile a final summary. To avoid context limits, read one file at a time and extract only the findings (skip the "No Issues Found" and "Routes Scanned" sections for clean services).
|
|
1189
|
+
|
|
1190
|
+
Write the final report to `access-control-scan-results/SUMMARY.md` with:
|
|
1191
|
+
|
|
1192
|
+
1. **Executive Summary**: Total services scanned (route-based + handler-only), total routes/handlers scanned, total findings by category
|
|
1193
|
+
2. **App-Level Issues**: Any services with middleware or configuration problems
|
|
1194
|
+
3. **Route-Level Findings**: All access control vulnerabilities in FastAPI routes, grouped by type
|
|
1195
|
+
4. **Handler-Level Findings**: All access control vulnerabilities in Lambda handlers, grouped by type
|
|
1196
|
+
5. **Clean Services**: List of services with no findings (names only)
|
|
1197
|
+
6. **Per-Service Details**: Full findings for services that had issues
|
|
1198
|
+
|
|
1199
|
+
Then output the summary to the user.
|
|
1200
|
+
|
|
1201
|
+
Be thorough. Read the actual code — don't guess based on function names alone. When checking for role validation, trace the full dependency chain. If a role check happens in a called function or middleware rather than at the route level, note it but don't flag it as a vulnerability.1a:["$","div","/Users/gabry/Desktop/ps-copy/platform-services/.claude/commands/access-control-scan.md",{"className":"border border-border rounded-sm p-5 ","children":[["$","div",null,{"className":"flex items-center gap-2","children":[["$","h3",null,{"className":"text-sm font-medium","children":"access-control-scan"}],["$","span",null,{"className":"inline-flex items-center px-2 py-0.5 text-xs font-medium rounded-sm bg-surface-raised text-text-muted","children":"platform-services"}]]}],["$","$L11",null,{"content":"$24","previewLines":3}]]}]
|
|
1202
|
+
25:Tf1d,# Add a New Model to llm-proxy-service
|
|
1203
|
+
|
|
1204
|
+
Add a new LLM model to `llm-proxy-service`, ensuring accurate cost reporting.
|
|
1205
|
+
|
|
1206
|
+
## Background
|
|
1207
|
+
|
|
1208
|
+
- `litellm` contains bundled pricing data in `model_prices_and_context_window.json`
|
|
1209
|
+
- We disable litellm's automatic pricing fetch; we ONLY use the bundled pricing
|
|
1210
|
+
- If the bundled pricing is wrong or missing for a model, litellm reports $0 cost, which breaks our cost reporting
|
|
1211
|
+
- Overrides for incorrect pricing go in `platform-services/packages/llm_proxy_service/src/llm_proxy_service/service.py` via `litellm.register_model()`
|
|
1212
|
+
- **IMPORTANT**: Both `llm-proxy-service` and `embedding-service` depend on `litellm`. Their versions must always match. If this skill requires upgrading litellm, update BOTH packages.
|
|
1213
|
+
|
|
1214
|
+
## Step 1: Gather information
|
|
1215
|
+
|
|
1216
|
+
Ask the user:
|
|
1217
|
+
|
|
1218
|
+
1. What model do they want to add? (e.g., `anthropic/claude-opus-4-5-20251101`)
|
|
1219
|
+
2. What is the provider's pricing page URL for this model?
|
|
1220
|
+
|
|
1221
|
+
## Step 2: Determine the current litellm version
|
|
1222
|
+
|
|
1223
|
+
Read `platform-services/packages/llm_proxy_service/pyproject.toml` to find the currently-used litellm version.
|
|
1224
|
+
|
|
1225
|
+
## Step 3: Validate pricing in the current litellm version
|
|
1226
|
+
|
|
1227
|
+
Use `uv run` to check if the model has correct pricing in the bundled litellm data:
|
|
1228
|
+
|
|
1229
|
+
```bash
|
|
1230
|
+
uv run --with litellm==<CURRENT_VERSION> python -c "import litellm, json; print(json.dumps(litellm.model_cost.get('<model_key>', {}), indent=2))"
|
|
1231
|
+
```
|
|
1232
|
+
|
|
1233
|
+
Note: The key in `litellm.model_cost` may not exactly match the model string. If an exact match isn't found, search for partial matches:
|
|
1234
|
+
|
|
1235
|
+
```bash
|
|
1236
|
+
uv run --with litellm==<CURRENT_VERSION> python -c "import litellm; keys = [k for k in litellm.model_cost if '<partial_model_name>' in k]; print('\n'.join(sorted(keys)))"
|
|
1237
|
+
```
|
|
1238
|
+
|
|
1239
|
+
Fetch the provider's pricing page and compare against the litellm pricing. Validate ALL of these fields:
|
|
1240
|
+
|
|
1241
|
+
- `input_cost_per_token`
|
|
1242
|
+
- `output_cost_per_token`
|
|
1243
|
+
- `cache_read_input_token_cost` (if applicable)
|
|
1244
|
+
- `cache_creation_input_token_cost` (if applicable)
|
|
1245
|
+
|
|
1246
|
+
Present the comparison to the user.
|
|
1247
|
+
|
|
1248
|
+
## Step 4: Add the model
|
|
1249
|
+
|
|
1250
|
+
### 4a. Add to LLMModel type
|
|
1251
|
+
|
|
1252
|
+
Add the model string to the `LLMModel` Literal type in `platform-services/packages/bioscope_types/src/bioscope_types/services/llm_proxy_service.py`.
|
|
1253
|
+
|
|
1254
|
+
- Place it in the correct provider group (bedrock, anthropic, vertex_ai, azure, groq)
|
|
1255
|
+
- Ensure the provider group has a comment linking to the pricing page (add one if it's a new provider)
|
|
1256
|
+
|
|
1257
|
+
### 4b. Add pricing override (if needed)
|
|
1258
|
+
|
|
1259
|
+
If the pricing is incorrect or missing in litellm, add an override in `platform-services/packages/llm_proxy_service/src/llm_proxy_service/service.py`:
|
|
1260
|
+
|
|
1261
|
+
```python
|
|
1262
|
+
litellm.register_model(
|
|
1263
|
+
{
|
|
1264
|
+
"<model_key>": {
|
|
1265
|
+
"input_cost_per_token": <value>, # $X per 1M tokens
|
|
1266
|
+
"output_cost_per_token": <value>, # $X per 1M tokens
|
|
1267
|
+
"cache_read_input_token_cost": <value>, # $X per 1M tokens (if applicable)
|
|
1268
|
+
"cache_creation_input_token_cost": <value>, # $X per 1M tokens (if applicable)
|
|
1269
|
+
"litellm_provider": "<provider>",
|
|
1270
|
+
"max_input_tokens": <value>,
|
|
1271
|
+
"max_output_tokens": <value>,
|
|
1272
|
+
"mode": "chat",
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
)
|
|
1276
|
+
```
|
|
1277
|
+
|
|
1278
|
+
Include inline comments showing the human-readable cost (e.g., `# $3.00 per 1M tokens`).
|
|
1279
|
+
|
|
1280
|
+
### 4c. Add to health check warmup (if needed)
|
|
1281
|
+
|
|
1282
|
+
If the model requires additional env vars (vertex_ai, groq, or anthropic models), consider adding a `set_additional_env_vars()` call in the health check in `platform-services/packages/llm_proxy_service/src/llm_proxy_service/handler.py`. Only one model per provider prefix is needed for warmup.
|
|
1283
|
+
|
|
1284
|
+
## Step 5: Validate
|
|
1285
|
+
|
|
1286
|
+
1. Run `pnpm exec nx run bioscope-types:type-check` to verify the type is valid
|
|
1287
|
+
2. Run `pnpm exec nx run llm-proxy-service:test` to verify tests pass
|
|
1288
|
+
3. Run `pnpm exec nx run llm-proxy-service:lint` and `pnpm exec nx run llm-proxy-service:type-check`1b:["$","div","/Users/gabry/Desktop/ps-copy/platform-services/.claude/commands/add-llm-proxy-service-model.md",{"className":"border border-border rounded-sm p-5 ","children":[["$","div",null,{"className":"flex items-center gap-2","children":[["$","h3",null,{"className":"text-sm font-medium","children":"add-llm-proxy-service-model"}],["$","span",null,{"className":"inline-flex items-center px-2 py-0.5 text-xs font-medium rounded-sm bg-surface-raised text-text-muted","children":"platform-services"}]]}],["$","$L11",null,{"content":"$25","previewLines":3}]]}]
|
|
1289
|
+
26:T1c43,# IDOR & Authorization Vulnerability Scan
|
|
1290
|
+
|
|
1291
|
+
Scan ALL route handlers in platform-services for IDOR (Insecure Direct Object Reference) and authorization vulnerabilities.
|
|
1292
|
+
|
|
1293
|
+
## How This Codebase Works
|
|
1294
|
+
|
|
1295
|
+
This is a FastAPI-based backend. Key facts:
|
|
1296
|
+
|
|
1297
|
+
- Routes *should* live in `packages/*/src/*/routes/*.py` (flag any routes that do not)
|
|
1298
|
+
- App setup files are at `packages/*/src/*/app.py`
|
|
1299
|
+
- Service-specific middleware may be at `packages/*/src/*/middleware.py`
|
|
1300
|
+
- Shared middleware is in `packages/shared_middleware/src/shared_middleware/`
|
|
1301
|
+
- Most routes are behind an API Gateway account authorizer that validates the JWT and verifies the user is a member of the account in the `Bioscope-Account-Id` header. For these routes, `account_id`, `user_id`, and `user_role` from headers can be trusted.
|
|
1302
|
+
- Some routes use a simpler JWT-only authorizer (e.g. `/accounts/me`, `/users/me`) or no authorizer at all (public endpoints). The authorizer config lives in infrastructure and is not visible from this repo, so don't make assumptions about which authorizer a given route uses — just focus on whether the route handler code itself properly validates ownership.
|
|
1303
|
+
- With the above two bullets in mind, `account_id`, `user_id`, and `user_role` can ONLY come from these headers and can NEVER come from path params, query params, request body, etc.
|
|
1304
|
+
|
|
1305
|
+
### Auth/Authorization Patterns in Route Handlers
|
|
1306
|
+
|
|
1307
|
+
**Patient validation (cross-service ownership check):**
|
|
1308
|
+
Routes with `{patient_id}` in the path MUST use `Depends(validate_patient_account_from_path_as_patient)` (or the factory `get_validate_patient_account`). This calls account-service to verify the patient belongs to the requesting account. A route that takes a patient_id without this dependency is an IDOR unless the route is checking the patient belongs to the account in its internal implementation.
|
|
1309
|
+
|
|
1310
|
+
**Inline account ownership checks:**
|
|
1311
|
+
For non-patient resources (orders, EHR connections, etc.), routes typically fetch the resource and then check `if resource.account_id != account_id`. Missing this check on a resource lookup by ID is a potential IDOR.
|
|
1312
|
+
|
|
1313
|
+
## Your Task
|
|
1314
|
+
|
|
1315
|
+
### Step 1: Discover all services with routes
|
|
1316
|
+
|
|
1317
|
+
Use glob to find all route files matching `packages/*/src/*/routes/*.py`. Group them by service. Also check for any routes that aren't under a `routes` directory and flag them.
|
|
1318
|
+
|
|
1319
|
+
### Step 2: Create an output directory and spin up sub-agents
|
|
1320
|
+
|
|
1321
|
+
First, create an output directory using Bash: `mkdir -p /tmp/idor-scan-results`
|
|
1322
|
+
|
|
1323
|
+
Then, for each service, use the Task tool (subagent_type: "general-purpose") to scan that service's routes. Run these in parallel (include all Task tool calls in a single message). Each sub-agent should:
|
|
1324
|
+
|
|
1325
|
+
1. Read ALL route files for that service
|
|
1326
|
+
2. Read the service's `app.py` to check what global dependencies/middleware are applied
|
|
1327
|
+
3. Read any service-specific `middleware.py` if it exists
|
|
1328
|
+
4. For each route handler, check for the vulnerabilities listed in Step 3
|
|
1329
|
+
5. **Write the report to a file** at `/tmp/idor-scan-results/<service-name>.md` using the format in Step 4
|
|
1330
|
+
6. **Return ONLY a one-line confirmation** (e.g., "Wrote report to /tmp/idor-scan-results/chat_service.md. 2 findings."). Do NOT return the full report — it's in the file.
|
|
1331
|
+
|
|
1332
|
+
**IMPORTANT:** When calling the Task tool for each sub-agent, explicitly instruct it to write findings to the file and return only a brief one-line confirmation. The full report must go in the file, NOT in the return message. This prevents the main agent's context from overflowing.
|
|
1333
|
+
|
|
1334
|
+
### Step 3: What to check per route
|
|
1335
|
+
|
|
1336
|
+
For every route handler function, check for these IDOR vulnerabilities:
|
|
1337
|
+
|
|
1338
|
+
- **Missing patient validation**: Route path contains `{patient_id}` but handler does NOT use `Depends(validate_patient_account_from_path_as_patient)` or equivalent
|
|
1339
|
+
- **Patient dependency result discarded**: Route uses `validate_patient_account_from_path_as_patient` but assigns the result to `_` instead of `patient`. The presence of the dependency alone is NOT sufficient — if the route also takes a sub-resource ID (e.g., `{chat_id}`, `{file_id}`, `{order_id}`), the validated `patient.patient_id` MUST be passed to the service layer and checked against the fetched resource's `patient_id`. A discarded `_` is a strong signal that this check is missing. Trace the full call chain to verify.
|
|
1340
|
+
- **Missing resource-to-account ownership**: Route takes a resource ID as a path/query/body param, fetches the resource, but does NOT verify `resource.account_id == account_id` before returning or mutating it
|
|
1341
|
+
- **Missing resource-to-patient ownership**: Route takes both a `{patient_id}` and another resource ID, fetches the resource, but does NOT verify `resource.patient_id == patient_id`. This applies even if the patient validation dependency is present — the dependency only confirms the patient belongs to the account, NOT that the sub-resource belongs to the patient. You must trace into the service layer to verify this check exists.
|
|
1342
|
+
- **Unscoped list/query endpoints**: Route returns a collection of resources (list/search/query) but the underlying query does NOT filter by `account_id` (or `patient_id` where applicable). Follow the call chain into the repository/data access layer to verify the query includes the appropriate scope filter.
|
|
1343
|
+
- **Using account, user, or user role not from header**: Route uses account id, user id, or user role from query param, path param, or request body and not from the trusted `Bioscope-Account-Id`, `Bioscope-User-Id`, and `Bioscope-User-Role` headers.
|
|
1344
|
+
|
|
1345
|
+
### Step 4: Compile the report
|
|
1346
|
+
|
|
1347
|
+
Each sub-agent should return its findings in this format:
|
|
1348
|
+
|
|
1349
|
+
```text
|
|
1350
|
+
## <service-name>
|
|
1351
|
+
|
|
1352
|
+
### Routes Scanned
|
|
1353
|
+
- `GET /path` — handler_name (file:line)
|
|
1354
|
+
- `POST /path` — handler_name (file:line)
|
|
1355
|
+
...
|
|
1356
|
+
|
|
1357
|
+
### Findings
|
|
1358
|
+
|
|
1359
|
+
#### Missing patient validation — `POST /patients/{patient_id}/resource`
|
|
1360
|
+
- **File**: path/to/file.py:123
|
|
1361
|
+
- **Handler**: `create_resource`
|
|
1362
|
+
- **Issue**: Route includes `{patient_id}` in path but does not use `validate_patient_account_from_path_as_patient`
|
|
1363
|
+
- **Confidence**: High / Medium / Low
|
|
1364
|
+
- **Notes**: <any relevant context>
|
|
1365
|
+
|
|
1366
|
+
#### Missing ownership check — `GET /resource/{resource_id}`
|
|
1367
|
+
...
|
|
1368
|
+
|
|
1369
|
+
### No Issues Found
|
|
1370
|
+
(list routes that were scanned and passed all checks)
|
|
1371
|
+
```
|
|
1372
|
+
|
|
1373
|
+
### Step 5: Aggregate
|
|
1374
|
+
|
|
1375
|
+
After all sub-agents complete, read each file from `/tmp/idor-scan-results/` and compile a final summary. To avoid context limits, read one file at a time and extract only the findings (skip the "No Issues Found" and "Routes Scanned" sections for clean services).
|
|
1376
|
+
|
|
1377
|
+
Write the final report to `/tmp/idor-scan-results/SUMMARY.md` with:
|
|
1378
|
+
|
|
1379
|
+
1. **Executive Summary**: Total routes scanned, total findings
|
|
1380
|
+
2. **Findings**: All IDOR vulnerabilities grouped by type
|
|
1381
|
+
3. **Clean Services**: List of services with no findings (names only)
|
|
1382
|
+
4. **Per-Service Details**: Full findings for services that had issues
|
|
1383
|
+
|
|
1384
|
+
Then output the summary to the user.
|
|
1385
|
+
|
|
1386
|
+
Be thorough. Read the actual code — don't guess based on function names alone. When in doubt about whether a check exists, read the called functions to see if ownership validation happens deeper in the call chain. If validation happens in a called function rather than at the route level, note it but don't flag it as a vulnerability.1c:["$","div","/Users/gabry/Desktop/ps-copy/platform-services/.claude/commands/idor-scan.md",{"className":"border border-border rounded-sm p-5 ","children":[["$","div",null,{"className":"flex items-center gap-2","children":[["$","h3",null,{"className":"text-sm font-medium","children":"idor-scan"}],["$","span",null,{"className":"inline-flex items-center px-2 py-0.5 text-xs font-medium rounded-sm bg-surface-raised text-text-muted","children":"platform-services"}]]}],["$","$L11",null,{"content":"$26","previewLines":3}]]}]
|
|
1387
|
+
27:T2543,# PHI/PII Data Exposure Scan
|
|
1388
|
+
|
|
1389
|
+
Scan ALL application code in platform-services for Protected Health Information (PHI) and Personally Identifiable Information (PII) exposure vulnerabilities. This covers logging, error responses, API over-fetching, and any other channel where sensitive data could leak.
|
|
1390
|
+
|
|
1391
|
+
## What Constitutes PHI/PII in This Codebase
|
|
1392
|
+
|
|
1393
|
+
### Patient PHI Fields (from `bioscope_types/dynamodb/patients.py`)
|
|
1394
|
+
- `first_name`, `last_name` (names)
|
|
1395
|
+
- `date_of_birth` (DOB)
|
|
1396
|
+
- `sex`
|
|
1397
|
+
- `mrn` (medical record number)
|
|
1398
|
+
- `address_line_1`, `address_line_2`, `city`, `state`, `zip_code`, `country` (address)
|
|
1399
|
+
- `phone_number`
|
|
1400
|
+
- `email`
|
|
1401
|
+
|
|
1402
|
+
### User PII Fields (from `bioscope_types/dynamodb/users.py`)
|
|
1403
|
+
- `first_name`, `last_name`
|
|
1404
|
+
- `email`
|
|
1405
|
+
- `npi_number` (healthcare provider identifier)
|
|
1406
|
+
|
|
1407
|
+
### Account PII Fields (from `bioscope_types/dynamodb/accounts.py`)
|
|
1408
|
+
- Address fields: `address_line_1`, `address_line_2`, `city`, `state`, `zip_code`, `country`
|
|
1409
|
+
|
|
1410
|
+
### Other PHI Sources
|
|
1411
|
+
- FHIR resources (contain full patient demographics, diagnoses, medical history)
|
|
1412
|
+
- EHR data (clinical records, lab results, immunizations)
|
|
1413
|
+
- Genomic/WGS data and results
|
|
1414
|
+
- Chat messages about patients (may contain clinical discussions)
|
|
1415
|
+
- File contents (uploaded documents, lab reports)
|
|
1416
|
+
|
|
1417
|
+
### Safe to Log
|
|
1418
|
+
- UUIDs (patient_id, account_id, user_id, order_id, etc.)
|
|
1419
|
+
- Timestamps
|
|
1420
|
+
- Status values and enums
|
|
1421
|
+
- Counts and metrics
|
|
1422
|
+
- Operation names and types
|
|
1423
|
+
- File IDs (not file contents or names that might contain patient info)
|
|
1424
|
+
|
|
1425
|
+
## How Logging Works
|
|
1426
|
+
|
|
1427
|
+
- `BioscopeLogger` (from `bioscope_logger` package) is the standard logger
|
|
1428
|
+
- Uses Python's `logging.LoggerAdapter` with JSON formatting
|
|
1429
|
+
- Supports `.child()` for adding context fields
|
|
1430
|
+
- Extra fields passed via `extra={}` parameter are serialized into the JSON log output
|
|
1431
|
+
- Logs go to stdout and optionally CloudWatch — all log output is persisted
|
|
1432
|
+
- `BioscopeLoggerDeps` injects the logger into FastAPI routes
|
|
1433
|
+
- Lambda handlers receive `logger: BioscopeLogger` via dependency injection
|
|
1434
|
+
|
|
1435
|
+
## Your Task
|
|
1436
|
+
|
|
1437
|
+
### Step 1: Discover all scannable code
|
|
1438
|
+
|
|
1439
|
+
Use glob to find:
|
|
1440
|
+
1. All route files: `packages/*/src/*/routes/*.py`
|
|
1441
|
+
2. All handler files: `packages/*/src/*/handler.py`
|
|
1442
|
+
3. All handlers directories: `packages/*/src/*/handlers/*.py`
|
|
1443
|
+
4. All service/business logic files: `packages/*/src/*/*.py` (excluding `__init__.py`, `aws.py`, `app.py`)
|
|
1444
|
+
5. Any standalone scripts or local dev files: `packages/*/src/*/local.py`
|
|
1445
|
+
|
|
1446
|
+
Group them by service/package.
|
|
1447
|
+
|
|
1448
|
+
### Step 2: Create an output directory and spin up sub-agents
|
|
1449
|
+
|
|
1450
|
+
First, create an output directory using Bash: `mkdir -p /tmp/phi-exposure-scan-results`
|
|
1451
|
+
|
|
1452
|
+
Then, for each service/package, use the Task tool (subagent_type: "general-purpose") to scan that package's code. Run these in parallel (include all Task tool calls in a single message). Each sub-agent should:
|
|
1453
|
+
|
|
1454
|
+
1. Read ALL Python source files for that package (routes, handlers, service modules, utilities)
|
|
1455
|
+
2. Check for every vulnerability type listed in Step 3
|
|
1456
|
+
3. **Write the report to a file** at `/tmp/phi-exposure-scan-results/<package-name>.md` using the format in Step 4
|
|
1457
|
+
4. **Return ONLY a one-line confirmation** (e.g., "Wrote report to /tmp/phi-exposure-scan-results/chat_service.md. 3 findings."). Do NOT return the full report — it's in the file.
|
|
1458
|
+
|
|
1459
|
+
**IMPORTANT:** When calling the Task tool for each sub-agent, include the full list of PHI/PII fields from the "What Constitutes PHI/PII" section above so the sub-agent knows exactly what to look for. Instruct it to write findings to the file and return only a brief one-line confirmation. The full report must go in the file, NOT in the return message.
|
|
1460
|
+
|
|
1461
|
+
### Step 3: What to check
|
|
1462
|
+
|
|
1463
|
+
#### A. PHI/PII in Log Statements (CRITICAL)
|
|
1464
|
+
|
|
1465
|
+
Search for all `logger.info`, `logger.warning`, `logger.error`, `logger.debug`, `logger.exception`, and `logger.critical` calls. For each, check:
|
|
1466
|
+
|
|
1467
|
+
- **Full model dumps in logs**: Calls like `logger.info("...", extra={"patient": patient.model_dump()})` or `model_dump_json()` that serialize an entire Pydantic model containing PHI fields. This includes Patient, User, Account, or any FHIR resource model.
|
|
1468
|
+
- **PHI field values in log messages**: Direct references to PHI fields in log strings or extra dicts, e.g., `extra={"name": patient.first_name}`, `extra={"email": user.email}`, `extra={"dob": patient.date_of_birth}`.
|
|
1469
|
+
- **F-string or format-string PHI**: Log messages that interpolate PHI values, e.g., `logger.info(f"Created patient {patient.first_name} {patient.last_name}")`.
|
|
1470
|
+
- **Logging raw request/response bodies**: Logging full HTTP request bodies or response payloads that may contain PHI, e.g., `logger.info("Request", extra={"body": request.body()})`.
|
|
1471
|
+
- **Logging full event payloads**: SQS/SNS/EventBridge event payloads logged in full when they may contain PHI fields.
|
|
1472
|
+
- **Logging FHIR resources**: Any FHIR Bundle, Patient, Observation, Immunization, or other clinical resource logged in full.
|
|
1473
|
+
|
|
1474
|
+
#### B. PHI/PII in Error Responses (HIGH)
|
|
1475
|
+
|
|
1476
|
+
Check all `HTTPException` raises and error response construction:
|
|
1477
|
+
|
|
1478
|
+
- **PHI in HTTPException detail**: `raise HTTPException(status_code=..., detail=f"Patient {patient.first_name} not found")` — the detail message should never contain PHI, only IDs or generic messages.
|
|
1479
|
+
- **PHI in custom error response models**: Any error response class that includes PHI fields.
|
|
1480
|
+
- **Full exception messages with PHI**: Exception handlers that return `str(e)` where the exception message might contain PHI from a database query or validation error.
|
|
1481
|
+
|
|
1482
|
+
#### C. PHI/PII in API Response Over-Fetching (MEDIUM)
|
|
1483
|
+
|
|
1484
|
+
Check route return values and response models:
|
|
1485
|
+
|
|
1486
|
+
- **Returning full patient/user records when not needed**: A route that returns a complete Patient object with all fields when the consumer only needs a subset (e.g., patient_id and status).
|
|
1487
|
+
|
|
1488
|
+
#### D. PHI/PII in URLs and Query Parameters (HIGH)
|
|
1489
|
+
|
|
1490
|
+
- **Patient data in query strings**: Routes that accept PHI as query parameters (e.g., `?name=John&dob=1990-01-01`). Query strings end up in access logs, browser history, and CDN logs. Only IDs should be in URLs.
|
|
1491
|
+
- **PHI in path parameters**: Path params should only contain UUIDs or opaque identifiers, never names, emails, or other PHI.
|
|
1492
|
+
|
|
1493
|
+
#### E. PHI/PII in Development/Debug Code (MEDIUM)
|
|
1494
|
+
|
|
1495
|
+
- **Local development files**: Files like `local.py` or scripts that log full records for debugging but exist in the production codebase.
|
|
1496
|
+
- **Commented-out debug logging**: Commented code that logs PHI — a developer might uncomment it and forget to remove it.
|
|
1497
|
+
- **Print statements with PHI**: Any `print()` calls that output PHI (should use logger instead, but print output also goes to CloudWatch).
|
|
1498
|
+
|
|
1499
|
+
#### F. Missing Data Sanitization (LOW)
|
|
1500
|
+
|
|
1501
|
+
- **No redaction utilities**: Note if the codebase lacks any sanitization/redaction utilities for PHI fields. This is an architectural observation, not a per-route vulnerability.
|
|
1502
|
+
- **PHI passed through multiple layers without scrubbing**: Trace data flow where PHI enters the system (e.g., from account-service or EHR) and check if it's ever inadvertently logged along the way.
|
|
1503
|
+
|
|
1504
|
+
### Step 4: Report format
|
|
1505
|
+
|
|
1506
|
+
Each sub-agent should write findings in this format:
|
|
1507
|
+
|
|
1508
|
+
```text
|
|
1509
|
+
## <package-name>
|
|
1510
|
+
|
|
1511
|
+
### Files Scanned
|
|
1512
|
+
- path/to/file.py
|
|
1513
|
+
- path/to/other_file.py
|
|
1514
|
+
...
|
|
1515
|
+
|
|
1516
|
+
### Findings
|
|
1517
|
+
|
|
1518
|
+
#### [CRITICAL] Full patient model logged — service.py:45
|
|
1519
|
+
- **File**: path/to/file.py:45
|
|
1520
|
+
- **Code**: `logger.info("Patient: ", extra={"patient": patient.model_dump_json()})`
|
|
1521
|
+
- **Category**: PHI in log statements
|
|
1522
|
+
- **PHI Fields Exposed**: first_name, last_name, date_of_birth, email, phone_number, address, mrn
|
|
1523
|
+
- **Notes**: Logs the entire Patient FHIR resource including all demographics
|
|
1524
|
+
|
|
1525
|
+
#### [HIGH] PHI in error response — routes/patients.py:78
|
|
1526
|
+
- **File**: path/to/file.py:78
|
|
1527
|
+
- **Code**: `raise HTTPException(detail=f"Patient {patient.first_name} not found")`
|
|
1528
|
+
- **Category**: PHI in error responses
|
|
1529
|
+
- **PHI Fields Exposed**: first_name
|
|
1530
|
+
- **Notes**: Patient name included in 404 error detail
|
|
1531
|
+
|
|
1532
|
+
### No Issues Found
|
|
1533
|
+
(list files that were scanned and passed all checks)
|
|
1534
|
+
```
|
|
1535
|
+
|
|
1536
|
+
Severity levels:
|
|
1537
|
+
- **CRITICAL**: Full model dumps or FHIR resources in logs, multiple PHI fields exposed
|
|
1538
|
+
- **HIGH**: Individual PHI fields in logs or error responses, PHI in URLs
|
|
1539
|
+
- **MEDIUM**: Over-fetching in API responses, debug/dev code with PHI
|
|
1540
|
+
- **LOW**: Architectural observations, missing sanitization utilities
|
|
1541
|
+
|
|
1542
|
+
### Step 5: Aggregate
|
|
1543
|
+
|
|
1544
|
+
After all sub-agents complete, read each file from `/tmp/phi-exposure-scan-results/` and compile a final summary. To avoid context limits, read one file at a time and extract only the findings.
|
|
1545
|
+
|
|
1546
|
+
Write the final report to `/tmp/phi-exposure-scan-results/SUMMARY.md` with:
|
|
1547
|
+
|
|
1548
|
+
1. **Executive Summary**: Total files scanned, total findings by severity (CRITICAL/HIGH/MEDIUM/LOW)
|
|
1549
|
+
2. **CRITICAL Findings**: All critical PHI exposure issues (immediate remediation needed)
|
|
1550
|
+
3. **HIGH Findings**: High-severity issues
|
|
1551
|
+
4. **MEDIUM Findings**: Medium-severity issues
|
|
1552
|
+
5. **LOW Findings & Observations**: Low-severity items and architectural notes
|
|
1553
|
+
6. **Clean Packages**: List of packages with no findings (names only)
|
|
1554
|
+
7. **Recommendations**: Actionable remediation steps, prioritized by severity
|
|
1555
|
+
|
|
1556
|
+
Then output the summary to the user.
|
|
1557
|
+
|
|
1558
|
+
Be thorough. Read the actual code — don't guess based on function names alone. When checking log statements, look at what the `extra` dict actually contains. When checking for model dumps, trace the model class to see what fields it includes. If a model only contains safe fields (IDs, timestamps, statuses), it's not a PHI exposure even if it's logged via `model_dump()`.1d:["$","div","/Users/gabry/Desktop/ps-copy/platform-services/.claude/commands/phi-exposure-scan.md",{"className":"border border-border rounded-sm p-5 ","children":[["$","div",null,{"className":"flex items-center gap-2","children":[["$","h3",null,{"className":"text-sm font-medium","children":"phi-exposure-scan"}],["$","span",null,{"className":"inline-flex items-center px-2 py-0.5 text-xs font-medium rounded-sm bg-surface-raised text-text-muted","children":"platform-services"}]]}],["$","$L11",null,{"content":"$27","previewLines":3}]]}]
|
|
1559
|
+
28:T1b86,# Upgrade litellm in llm-proxy-service
|
|
1560
|
+
|
|
1561
|
+
Upgrade the `litellm` dependency in `llm-proxy-service` to a new version, validating that all supported models have correct pricing.
|
|
1562
|
+
|
|
1563
|
+
## Background
|
|
1564
|
+
|
|
1565
|
+
- `litellm` contains bundled pricing data in `model_prices_and_context_window.json`
|
|
1566
|
+
- We disable litellm's automatic pricing fetch; we ONLY use the bundled pricing
|
|
1567
|
+
- If the bundled pricing is wrong or missing for a model, litellm reports $0 cost, which breaks our cost reporting
|
|
1568
|
+
- Overrides for incorrect pricing go in `platform-services/packages/llm_proxy_service/src/llm_proxy_service/service.py` via `litellm.register_model()`
|
|
1569
|
+
- **IMPORTANT**: Both `llm-proxy-service` and `embedding-service` depend on `litellm`. Their versions must always match. When upgrading, update BOTH `platform-services/packages/llm_proxy_service/pyproject.toml` and `platform-services/packages/embedding_service/pyproject.toml`.
|
|
1570
|
+
|
|
1571
|
+
## Step 1: Ask the user what version to upgrade to
|
|
1572
|
+
|
|
1573
|
+
First, read the current litellm version from `platform-services/packages/llm_proxy_service/pyproject.toml`. Then, fetch the latest available versions from PyPI:
|
|
1574
|
+
|
|
1575
|
+
```bash
|
|
1576
|
+
curl -s "https://pypi.org/pypi/litellm/json" | python3 -c "import sys,json; releases=sorted(json.load(sys.stdin)['releases'].keys(), key=lambda v: [int(x) for x in v.split('.')[:3] if x.isdigit()], reverse=True); print('\n'.join(releases[:5]))"
|
|
1577
|
+
```
|
|
1578
|
+
|
|
1579
|
+
Use AskUserQuestion to present the user with a selection of versions. Include the 3-4 most recent versions as options, labeling the latest one with "(Latest)". The user can also type a different version via the "Other" option. Mention the current version in the question text so the user knows what they're upgrading from.
|
|
1580
|
+
|
|
1581
|
+
## Step 2: Identify all supported models
|
|
1582
|
+
|
|
1583
|
+
Read the `LLMModel` type definition in `platform-services/packages/bioscope_types/src/bioscope_types/services/llm_proxy_service.py` to get all supported models. Group them by provider:
|
|
1584
|
+
|
|
1585
|
+
- `bedrock/` models (Anthropic on AWS Bedrock)
|
|
1586
|
+
- `anthropic/` models (direct Anthropic API)
|
|
1587
|
+
- `vertex_ai/` models (Google Vertex AI)
|
|
1588
|
+
- `azure/` models (Azure OpenAI)
|
|
1589
|
+
- `groq/` models (Groq)
|
|
1590
|
+
- etc.
|
|
1591
|
+
|
|
1592
|
+
Also read the current litellm version from `platform-services/packages/llm_proxy_service/pyproject.toml`.
|
|
1593
|
+
|
|
1594
|
+
Also read `platform-services/packages/llm_proxy_service/src/llm_proxy_service/service.py` to identify any existing `litellm.register_model()` overrides.
|
|
1595
|
+
|
|
1596
|
+
## Step 3: Create output directory and spin up sub-agents per provider
|
|
1597
|
+
|
|
1598
|
+
First, create an output directory using Bash: `mkdir -p /tmp/litellm-upgrade`
|
|
1599
|
+
|
|
1600
|
+
Then, for EACH provider (bedrock, anthropic, vertex_ai, azure, groq), spin up a sub-agent using the Task tool (subagent_type: "general-purpose"). Run all provider sub-agents **in parallel** (include all Task tool calls in a single message). **Do NOT run these in the background** — they need to be foreground agents so they can prompt for tool permissions.
|
|
1601
|
+
|
|
1602
|
+
Each sub-agent should:
|
|
1603
|
+
|
|
1604
|
+
1. **Check pricing in the NEW version** of litellm for every model belonging to that provider. Use `uv run` to inspect the bundled pricing data:
|
|
1605
|
+
|
|
1606
|
+
```bash
|
|
1607
|
+
uv run --with litellm==<NEW_VERSION> python -c "import litellm, json; print(json.dumps(litellm.model_cost.get('<model_key>', {}), indent=2))"
|
|
1608
|
+
```
|
|
1609
|
+
|
|
1610
|
+
Note: The key in `litellm.model_cost` may not exactly match the model string in `LLMModel`. For example, `bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0` may be keyed as `us.anthropic.claude-sonnet-4-5-20250929-v1:0` or similar. If an exact match isn't found, search for partial matches:
|
|
1611
|
+
|
|
1612
|
+
```bash
|
|
1613
|
+
uv run --with litellm==<NEW_VERSION> python -c "import litellm; keys = [k for k in litellm.model_cost if '<partial_model_name>' in k]; print('\n'.join(sorted(keys)))"
|
|
1614
|
+
```
|
|
1615
|
+
|
|
1616
|
+
2. **Fetch the provider's pricing page** (linked in the `LLMModel` comments) and compare the litellm pricing against the actual provider pricing. Key fields to validate:
|
|
1617
|
+
- `input_cost_per_token`
|
|
1618
|
+
- `output_cost_per_token`
|
|
1619
|
+
- `cache_read_input_token_cost` (if applicable)
|
|
1620
|
+
- `cache_creation_input_token_cost` (if applicable)
|
|
1621
|
+
|
|
1622
|
+
3. **Also check the OLD (current) version** to see if any existing overrides can be removed because the new version has correct pricing:
|
|
1623
|
+
|
|
1624
|
+
```bash
|
|
1625
|
+
uv run --with litellm==<OLD_VERSION> python -c "import litellm, json; print(json.dumps(litellm.model_cost.get('<model_key>', {}), indent=2))"
|
|
1626
|
+
```
|
|
1627
|
+
|
|
1628
|
+
4. **Write findings to a file** at `/tmp/litellm-upgrade/<provider>.md` with this format:
|
|
1629
|
+
|
|
1630
|
+
```text
|
|
1631
|
+
## <provider> Models
|
|
1632
|
+
|
|
1633
|
+
### <model_name>
|
|
1634
|
+
- **Provider pricing page**: <url>
|
|
1635
|
+
- **Expected input cost**: $X per 1M tokens
|
|
1636
|
+
- **Expected output cost**: $X per 1M tokens
|
|
1637
|
+
- **Expected cached input cost**: $X per 1M tokens (if applicable)
|
|
1638
|
+
- **litellm (new version) input cost**: $X per 1M tokens
|
|
1639
|
+
- **litellm (new version) output cost**: $X per 1M tokens
|
|
1640
|
+
- **litellm (new version) cached input cost**: $X per 1M tokens
|
|
1641
|
+
- **Status**: CORRECT / INCORRECT / MISSING
|
|
1642
|
+
- **Override needed**: Yes (details) / No
|
|
1643
|
+
```
|
|
1644
|
+
|
|
1645
|
+
5. **Return ONLY a single sentence** summarizing findings (e.g., "All 3 Anthropic models have correct pricing in the new version." or "2 of 5 Bedrock models have incorrect cached input pricing."). The full report is in the file — do NOT return it in the response.
|
|
1646
|
+
|
|
1647
|
+
**IMPORTANT:** When calling the Task tool for each sub-agent, explicitly instruct it to write findings to the file and return only a brief single-sentence confirmation. The full report must go in the file, NOT in the return message. This prevents the main agent's context from overflowing.
|
|
1648
|
+
|
|
1649
|
+
## Step 4: Spin up a final evaluation sub-agent
|
|
1650
|
+
|
|
1651
|
+
After all provider sub-agents complete, spin up ONE final sub-agent (subagent_type: "general-purpose") that:
|
|
1652
|
+
|
|
1653
|
+
1. Reads all files in `/tmp/litellm-upgrade/`
|
|
1654
|
+
2. Compiles a summary of which models need overrides and which are correct
|
|
1655
|
+
3. Writes a final report to `/tmp/litellm-upgrade/SUMMARY.md`
|
|
1656
|
+
4. Returns ONLY a single sentence summary (e.g., "3 models need pricing overrides, 15 are correct. See /tmp/litellm-upgrade/SUMMARY.md for details.")
|
|
1657
|
+
|
|
1658
|
+
Then read `/tmp/litellm-upgrade/SUMMARY.md` and present the findings to the user.
|
|
1659
|
+
|
|
1660
|
+
## Step 5: Implement the upgrade
|
|
1661
|
+
|
|
1662
|
+
After presenting findings to the user and getting their approval:
|
|
1663
|
+
|
|
1664
|
+
1. Update the litellm version in BOTH:
|
|
1665
|
+
- `platform-services/packages/llm_proxy_service/pyproject.toml`
|
|
1666
|
+
- `platform-services/packages/embedding_service/pyproject.toml`
|
|
1667
|
+
2. Add any needed `litellm.register_model()` overrides in `platform-services/packages/llm_proxy_service/src/llm_proxy_service/service.py`
|
|
1668
|
+
3. Remove any existing overrides that are no longer needed (because the new version has correct pricing)
|
|
1669
|
+
4. Run `uv sync --all-packages` from the `platform-services/` directory to update the lock file
|
|
1670
|
+
5. Run `pnpm exec nx run llm-proxy-service:test` to verify tests pass
|
|
1671
|
+
6. Run `pnpm exec nx run llm-proxy-service:lint` and `pnpm exec nx run llm-proxy-service:type-check`
|
|
1672
|
+
7. Run `pnpm exec nx run embedding-service:test`, `pnpm exec nx run embedding-service:lint`, and `pnpm exec nx run embedding-service:type-check`1e:["$","div","/Users/gabry/Desktop/ps-copy/platform-services/.claude/commands/upgrade-litellm.md",{"className":"border border-border rounded-sm p-5 ","children":[["$","div",null,{"className":"flex items-center gap-2","children":[["$","h3",null,{"className":"text-sm font-medium","children":"upgrade-litellm"}],["$","span",null,{"className":"inline-flex items-center px-2 py-0.5 text-xs font-medium rounded-sm bg-surface-raised text-text-muted","children":"platform-services"}]]}],["$","$L11",null,{"content":"$28","previewLines":3}]]}]
|