@m2-ai/lattice-cli 0.0.0-stage → 0.8.7
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/DISCLOSURE +1 -0
- package/README.md +118 -2
- package/bundles/expo-mobile/.agents/skills/lattice-feature-handoff/SKILL.md +31 -0
- package/bundles/expo-mobile/.agents/skills/lattice-release-manager/SKILL.md +29 -0
- package/bundles/expo-mobile/.agents/skills/lattice-verify/SKILL.md +27 -0
- package/bundles/expo-mobile/.claude/agents/lattice-feature-agent.md +10 -0
- package/bundles/expo-mobile/.claude/agents/lattice-release-manager.md +9 -0
- package/bundles/expo-mobile/.claude/hooks/README.md +9 -0
- package/bundles/expo-mobile/.claude/hooks/pre-commit-verify.mjs +10 -0
- package/bundles/expo-mobile/.claude/hooks/pre-tool-use.mjs +51 -0
- package/bundles/expo-mobile/.claude/rules/lattice-core.md +20 -0
- package/bundles/expo-mobile/.claude/settings.json +38 -0
- package/bundles/expo-mobile/.claude/skills/lattice-verify/SKILL.md +27 -0
- package/bundles/expo-mobile/.codex/agents/lattice-feature-agent.toml +9 -0
- package/bundles/expo-mobile/.codex/agents/lattice-release-manager.toml +9 -0
- package/bundles/expo-mobile/.cursor/mcp.json +34 -0
- package/bundles/expo-mobile/.cursor/rules/lattice-core.mdc +35 -0
- package/bundles/expo-mobile/.cursor/rules.md +94 -0
- package/bundles/expo-mobile/.env.example +19 -0
- package/bundles/expo-mobile/.github/PULL_REQUEST_TEMPLATE.md +42 -0
- package/bundles/expo-mobile/.github/agents/lattice-feature-agent.agent.md +7 -0
- package/bundles/expo-mobile/.github/agents/lattice-release-manager.agent.md +7 -0
- package/bundles/expo-mobile/.github/copilot-instructions.md +37 -0
- package/bundles/expo-mobile/.github/instructions/lattice-core.instructions.md +11 -0
- package/bundles/expo-mobile/.github/workflows/ci.yml +26 -0
- package/bundles/expo-mobile/.gitmessage +24 -0
- package/bundles/expo-mobile/.lattice/config.json +9 -0
- package/bundles/expo-mobile/.lattice/dependency-security.json +91 -0
- package/bundles/expo-mobile/.lattice/prompts/01-feature.md +36 -0
- package/bundles/expo-mobile/.lattice/prompts/02-bugfix.md +32 -0
- package/bundles/expo-mobile/.lattice/prompts/03-refactor.md +30 -0
- package/bundles/expo-mobile/.lattice/prompts/04-test.md +31 -0
- package/bundles/expo-mobile/.lattice/prompts/05-polish.md +38 -0
- package/bundles/expo-mobile/.lattice/prompts/06-security.md +32 -0
- package/bundles/expo-mobile/.lattice/release-workflow.json +55 -0
- package/bundles/expo-mobile/.lattice/schemas/feature-handoff.schema.json +264 -0
- package/bundles/expo-mobile/.lattice/templates/feature-handoff.json +52 -0
- package/bundles/expo-mobile/.mcp.json +35 -0
- package/bundles/expo-mobile/AGENTS.md +58 -0
- package/bundles/expo-mobile/CLAUDE.md +75 -0
- package/bundles/expo-mobile/PROJECT_GUIDE.md +299 -0
- package/bundles/expo-mobile/README.md +39 -0
- package/bundles/expo-mobile/__tests__/home.test.tsx +22 -0
- package/bundles/expo-mobile/app/_layout.tsx +20 -0
- package/bundles/expo-mobile/app/index.tsx +72 -0
- package/bundles/expo-mobile/app.json +33 -0
- package/bundles/expo-mobile/components/ui/Button.tsx +75 -0
- package/bundles/expo-mobile/components/ui/Input.tsx +50 -0
- package/bundles/expo-mobile/components/ui/index.ts +2 -0
- package/bundles/expo-mobile/docs/LATTICE_RELEASE_WORKFLOW.md +53 -0
- package/bundles/expo-mobile/docs/rules/codex.md +62 -0
- package/bundles/expo-mobile/eslint.config.js +7 -0
- package/bundles/expo-mobile/lib/supabase/client.ts +22 -0
- package/bundles/expo-mobile/lib/supabase/realtime.ts +10 -0
- package/bundles/expo-mobile/lib/supabase/storage.ts +6 -0
- package/bundles/expo-mobile/package.json +65 -0
- package/bundles/expo-mobile/plugins/with-lattice-commons-io.cjs +42 -0
- package/bundles/expo-mobile/prompts/01-feature-implementation.md +48 -0
- package/bundles/expo-mobile/prompts/02-bug-fix.md +43 -0
- package/bundles/expo-mobile/prompts/03-safe-refactor.md +38 -0
- package/bundles/expo-mobile/prompts/04-test-first.md +41 -0
- package/bundles/expo-mobile/prompts/05-ui-polish.md +44 -0
- package/bundles/expo-mobile/prompts/06-security-review.md +39 -0
- package/bundles/expo-mobile/prompts/quality.md +143 -0
- package/bundles/expo-mobile/supabase/migrations/001_initial_schema.sql +66 -0
- package/bundles/expo-mobile/tsconfig.json +21 -0
- package/bundles/expo-mobile/types/database.types.ts +76 -0
- package/bundles/expo-mobile/vendor/m2ai-braces-3.0.3-m2ai.1.tar +0 -0
- package/bundles/expo-supabase/.agents/skills/lattice-feature-handoff/SKILL.md +31 -0
- package/bundles/expo-supabase/.agents/skills/lattice-release-manager/SKILL.md +29 -0
- package/bundles/expo-supabase/.agents/skills/lattice-verify/SKILL.md +27 -0
- package/bundles/expo-supabase/.claude/agents/lattice-feature-agent.md +10 -0
- package/bundles/expo-supabase/.claude/agents/lattice-release-manager.md +9 -0
- package/bundles/expo-supabase/.claude/hooks/README.md +9 -0
- package/bundles/expo-supabase/.claude/hooks/pre-commit-verify.mjs +10 -0
- package/bundles/expo-supabase/.claude/hooks/pre-tool-use.mjs +51 -0
- package/bundles/expo-supabase/.claude/rules/lattice-core.md +20 -0
- package/bundles/expo-supabase/.claude/settings.json +38 -0
- package/bundles/expo-supabase/.claude/skills/lattice-verify/SKILL.md +27 -0
- package/bundles/expo-supabase/.codex/agents/lattice-feature-agent.toml +9 -0
- package/bundles/expo-supabase/.codex/agents/lattice-release-manager.toml +9 -0
- package/bundles/expo-supabase/.cursor/mcp.json +34 -0
- package/bundles/expo-supabase/.cursor/rules/lattice-core.mdc +35 -0
- package/bundles/expo-supabase/.cursor/rules.md +94 -0
- package/bundles/expo-supabase/.env.example +12 -0
- package/bundles/expo-supabase/.github/PULL_REQUEST_TEMPLATE.md +42 -0
- package/bundles/expo-supabase/.github/agents/lattice-feature-agent.agent.md +7 -0
- package/bundles/expo-supabase/.github/agents/lattice-release-manager.agent.md +7 -0
- package/bundles/expo-supabase/.github/copilot-instructions.md +37 -0
- package/bundles/expo-supabase/.github/instructions/lattice-core.instructions.md +11 -0
- package/bundles/expo-supabase/.github/workflows/ci.yml +26 -0
- package/bundles/expo-supabase/.gitmessage +24 -0
- package/bundles/expo-supabase/.lattice/config.json +9 -0
- package/bundles/expo-supabase/.lattice/dependency-security.json +91 -0
- package/bundles/expo-supabase/.lattice/prompts/01-feature.md +36 -0
- package/bundles/expo-supabase/.lattice/prompts/02-bugfix.md +32 -0
- package/bundles/expo-supabase/.lattice/prompts/03-refactor.md +30 -0
- package/bundles/expo-supabase/.lattice/prompts/04-test.md +31 -0
- package/bundles/expo-supabase/.lattice/prompts/05-polish.md +38 -0
- package/bundles/expo-supabase/.lattice/prompts/06-security.md +32 -0
- package/bundles/expo-supabase/.lattice/release-workflow.json +55 -0
- package/bundles/expo-supabase/.lattice/schemas/feature-handoff.schema.json +264 -0
- package/bundles/expo-supabase/.lattice/templates/feature-handoff.json +52 -0
- package/bundles/expo-supabase/.mcp.json +35 -0
- package/bundles/expo-supabase/AGENTS.md +58 -0
- package/bundles/expo-supabase/CLAUDE.md +75 -0
- package/bundles/expo-supabase/PROJECT_GUIDE.md +201 -0
- package/bundles/expo-supabase/README.md +38 -0
- package/bundles/expo-supabase/__tests__/home.test.tsx +22 -0
- package/bundles/expo-supabase/app/_layout.tsx +14 -0
- package/bundles/expo-supabase/app/index.tsx +72 -0
- package/bundles/expo-supabase/app.json +33 -0
- package/bundles/expo-supabase/components/ui/Button.tsx +75 -0
- package/bundles/expo-supabase/components/ui/Input.tsx +50 -0
- package/bundles/expo-supabase/components/ui/index.ts +2 -0
- package/bundles/expo-supabase/docs/LATTICE_RELEASE_WORKFLOW.md +53 -0
- package/bundles/expo-supabase/docs/rules/codex.md +62 -0
- package/bundles/expo-supabase/eslint.config.js +7 -0
- package/bundles/expo-supabase/lib/supabase/client.ts +22 -0
- package/bundles/expo-supabase/lib/supabase/realtime.ts +10 -0
- package/bundles/expo-supabase/lib/supabase/storage.ts +6 -0
- package/bundles/expo-supabase/package.json +60 -0
- package/bundles/expo-supabase/plugins/with-lattice-commons-io.cjs +42 -0
- package/bundles/expo-supabase/prompts/01-feature-implementation.md +8 -0
- package/bundles/expo-supabase/prompts/02-bug-fix.md +9 -0
- package/bundles/expo-supabase/prompts/03-safe-refactor.md +8 -0
- package/bundles/expo-supabase/prompts/04-test-first.md +7 -0
- package/bundles/expo-supabase/prompts/05-ui-polish.md +7 -0
- package/bundles/expo-supabase/prompts/06-security-review.md +7 -0
- package/bundles/expo-supabase/prompts/quality.md +143 -0
- package/bundles/expo-supabase/supabase/migrations/001_initial_schema.sql +66 -0
- package/bundles/expo-supabase/tsconfig.json +21 -0
- package/bundles/expo-supabase/types/database.types.ts +76 -0
- package/bundles/expo-supabase/vendor/m2ai-braces-3.0.3-m2ai.1.tar +0 -0
- package/bundles/nextjs-landing/.agents/skills/lattice-feature-handoff/SKILL.md +31 -0
- package/bundles/nextjs-landing/.agents/skills/lattice-release-manager/SKILL.md +29 -0
- package/bundles/nextjs-landing/.agents/skills/lattice-verify/SKILL.md +27 -0
- package/bundles/nextjs-landing/.claude/agents/lattice-feature-agent.md +10 -0
- package/bundles/nextjs-landing/.claude/agents/lattice-release-manager.md +9 -0
- package/bundles/nextjs-landing/.claude/hooks/README.md +9 -0
- package/bundles/nextjs-landing/.claude/hooks/pre-commit-verify.mjs +10 -0
- package/bundles/nextjs-landing/.claude/hooks/pre-tool-use.mjs +51 -0
- package/bundles/nextjs-landing/.claude/rules/lattice-core.md +20 -0
- package/bundles/nextjs-landing/.claude/settings.json +38 -0
- package/bundles/nextjs-landing/.claude/skills/lattice-verify/SKILL.md +27 -0
- package/bundles/nextjs-landing/.codex/agents/lattice-feature-agent.toml +9 -0
- package/bundles/nextjs-landing/.codex/agents/lattice-release-manager.toml +9 -0
- package/bundles/nextjs-landing/.cursor/mcp.json +34 -0
- package/bundles/nextjs-landing/.cursor/rules/lattice-core.mdc +35 -0
- package/bundles/nextjs-landing/.cursor/rules.md +95 -0
- package/bundles/nextjs-landing/.env.example +24 -0
- package/bundles/nextjs-landing/.github/PULL_REQUEST_TEMPLATE.md +42 -0
- package/bundles/nextjs-landing/.github/agents/lattice-feature-agent.agent.md +7 -0
- package/bundles/nextjs-landing/.github/agents/lattice-release-manager.agent.md +7 -0
- package/bundles/nextjs-landing/.github/copilot-instructions.md +37 -0
- package/bundles/nextjs-landing/.github/instructions/lattice-core.instructions.md +11 -0
- package/bundles/nextjs-landing/.github/workflows/ci.yml +26 -0
- package/bundles/nextjs-landing/.gitmessage +24 -0
- package/bundles/nextjs-landing/.lattice/config.json +9 -0
- package/bundles/nextjs-landing/.lattice/dependency-security.json +46 -0
- package/bundles/nextjs-landing/.lattice/prompts/01-feature.md +36 -0
- package/bundles/nextjs-landing/.lattice/prompts/02-bugfix.md +32 -0
- package/bundles/nextjs-landing/.lattice/prompts/03-refactor.md +30 -0
- package/bundles/nextjs-landing/.lattice/prompts/04-test.md +31 -0
- package/bundles/nextjs-landing/.lattice/prompts/05-polish.md +38 -0
- package/bundles/nextjs-landing/.lattice/prompts/06-security.md +32 -0
- package/bundles/nextjs-landing/.lattice/release-workflow.json +55 -0
- package/bundles/nextjs-landing/.lattice/schemas/feature-handoff.schema.json +264 -0
- package/bundles/nextjs-landing/.lattice/templates/feature-handoff.json +52 -0
- package/bundles/nextjs-landing/.mcp.json +35 -0
- package/bundles/nextjs-landing/AGENTS.md +58 -0
- package/bundles/nextjs-landing/CLAUDE.md +76 -0
- package/bundles/nextjs-landing/PROJECT_GUIDE.md +216 -0
- package/bundles/nextjs-landing/README.md +39 -0
- package/bundles/nextjs-landing/app/api/example/[id]/route.ts +34 -0
- package/bundles/nextjs-landing/app/api/example/route.ts +24 -0
- package/bundles/nextjs-landing/app/api/health/route.ts +8 -0
- package/bundles/nextjs-landing/app/global-error.tsx +17 -0
- package/bundles/nextjs-landing/app/globals.css +55 -0
- package/bundles/nextjs-landing/app/layout.tsx +22 -0
- package/bundles/nextjs-landing/app/page.tsx +42 -0
- package/bundles/nextjs-landing/components/ui/button.tsx +39 -0
- package/bundles/nextjs-landing/components/ui/card.tsx +53 -0
- package/bundles/nextjs-landing/components/ui/index.ts +4 -0
- package/bundles/nextjs-landing/components/ui/input.tsx +23 -0
- package/bundles/nextjs-landing/components/ui/spinner.tsx +22 -0
- package/bundles/nextjs-landing/docs/LATTICE_RELEASE_WORKFLOW.md +53 -0
- package/bundles/nextjs-landing/docs/rules/codex.md +62 -0
- package/bundles/nextjs-landing/eslint.config.mjs +16 -0
- package/bundles/nextjs-landing/instrumentation-client.ts +30 -0
- package/bundles/nextjs-landing/instrumentation.ts +12 -0
- package/bundles/nextjs-landing/jest.config.mjs +16 -0
- package/bundles/nextjs-landing/jest.setup.js +1 -0
- package/bundles/nextjs-landing/lib/utils.ts +6 -0
- package/bundles/nextjs-landing/next-env.d.ts +5 -0
- package/bundles/nextjs-landing/next.config.ts +15 -0
- package/bundles/nextjs-landing/package.json +48 -0
- package/bundles/nextjs-landing/postcss.config.mjs +7 -0
- package/bundles/nextjs-landing/prompts/01-feature-implementation.md +9 -0
- package/bundles/nextjs-landing/prompts/02-bug-fix.md +10 -0
- package/bundles/nextjs-landing/prompts/03-safe-refactor.md +8 -0
- package/bundles/nextjs-landing/prompts/04-test-first.md +8 -0
- package/bundles/nextjs-landing/prompts/05-ui-polish.md +8 -0
- package/bundles/nextjs-landing/prompts/06-security-review.md +7 -0
- package/bundles/nextjs-landing/prompts/quality.md +269 -0
- package/bundles/nextjs-landing/sentry.edge.config.ts +15 -0
- package/bundles/nextjs-landing/sentry.server.config.ts +15 -0
- package/bundles/nextjs-landing/tsconfig.json +42 -0
- package/bundles/nextjs-landing/vendor/m2ai-braces-3.0.3-m2ai.1.tar +0 -0
- package/bundles/nextjs-saas/.agents/skills/lattice-feature-handoff/SKILL.md +31 -0
- package/bundles/nextjs-saas/.agents/skills/lattice-release-manager/SKILL.md +29 -0
- package/bundles/nextjs-saas/.agents/skills/lattice-verify/SKILL.md +27 -0
- package/bundles/nextjs-saas/.claude/agents/lattice-feature-agent.md +10 -0
- package/bundles/nextjs-saas/.claude/agents/lattice-release-manager.md +9 -0
- package/bundles/nextjs-saas/.claude/hooks/README.md +9 -0
- package/bundles/nextjs-saas/.claude/hooks/pre-commit-verify.mjs +10 -0
- package/bundles/nextjs-saas/.claude/hooks/pre-tool-use.mjs +51 -0
- package/bundles/nextjs-saas/.claude/rules/lattice-core.md +20 -0
- package/bundles/nextjs-saas/.claude/settings.json +38 -0
- package/bundles/nextjs-saas/.claude/skills/lattice-verify/SKILL.md +27 -0
- package/bundles/nextjs-saas/.codex/agents/lattice-feature-agent.toml +9 -0
- package/bundles/nextjs-saas/.codex/agents/lattice-release-manager.toml +9 -0
- package/bundles/nextjs-saas/.cursor/mcp.json +34 -0
- package/bundles/nextjs-saas/.cursor/rules/lattice-core.mdc +35 -0
- package/bundles/nextjs-saas/.cursor/rules.md +95 -0
- package/bundles/nextjs-saas/.env.example +48 -0
- package/bundles/nextjs-saas/.github/PULL_REQUEST_TEMPLATE.md +42 -0
- package/bundles/nextjs-saas/.github/agents/lattice-feature-agent.agent.md +7 -0
- package/bundles/nextjs-saas/.github/agents/lattice-release-manager.agent.md +7 -0
- package/bundles/nextjs-saas/.github/copilot-instructions.md +37 -0
- package/bundles/nextjs-saas/.github/instructions/lattice-core.instructions.md +11 -0
- package/bundles/nextjs-saas/.github/workflows/ci.yml +26 -0
- package/bundles/nextjs-saas/.gitmessage +24 -0
- package/bundles/nextjs-saas/.lattice/config.json +9 -0
- package/bundles/nextjs-saas/.lattice/dependency-security.json +46 -0
- package/bundles/nextjs-saas/.lattice/prompts/01-feature.md +36 -0
- package/bundles/nextjs-saas/.lattice/prompts/02-bugfix.md +32 -0
- package/bundles/nextjs-saas/.lattice/prompts/03-refactor.md +30 -0
- package/bundles/nextjs-saas/.lattice/prompts/04-test.md +31 -0
- package/bundles/nextjs-saas/.lattice/prompts/05-polish.md +38 -0
- package/bundles/nextjs-saas/.lattice/prompts/06-security.md +32 -0
- package/bundles/nextjs-saas/.lattice/prompts/quality.md +269 -0
- package/bundles/nextjs-saas/.lattice/release-workflow.json +55 -0
- package/bundles/nextjs-saas/.lattice/schemas/feature-handoff.schema.json +264 -0
- package/bundles/nextjs-saas/.lattice/templates/feature-handoff.json +52 -0
- package/bundles/nextjs-saas/.mcp.json +35 -0
- package/bundles/nextjs-saas/AGENTS.md +58 -0
- package/bundles/nextjs-saas/CLAUDE.md +76 -0
- package/bundles/nextjs-saas/PROJECT_GUIDE.md +279 -0
- package/bundles/nextjs-saas/README.md +42 -0
- package/bundles/nextjs-saas/app/(auth)/forgot-password/page.tsx +101 -0
- package/bundles/nextjs-saas/app/(auth)/layout.tsx +7 -0
- package/bundles/nextjs-saas/app/(auth)/login/page.tsx +108 -0
- package/bundles/nextjs-saas/app/(auth)/reset-password/page.tsx +135 -0
- package/bundles/nextjs-saas/app/(auth)/signup/page.tsx +144 -0
- package/bundles/nextjs-saas/app/(dashboard)/dashboard/page.tsx +80 -0
- package/bundles/nextjs-saas/app/(dashboard)/layout.tsx +49 -0
- package/bundles/nextjs-saas/app/api/billing/checkout/route.ts +47 -0
- package/bundles/nextjs-saas/app/api/billing/portal/route.ts +29 -0
- package/bundles/nextjs-saas/app/api/example/[id]/route.ts +93 -0
- package/bundles/nextjs-saas/app/api/example/route.ts +61 -0
- package/bundles/nextjs-saas/app/api/health/route.ts +8 -0
- package/bundles/nextjs-saas/app/api/stripe/webhook/route.ts +57 -0
- package/bundles/nextjs-saas/app/api/user/route.ts +49 -0
- package/bundles/nextjs-saas/app/auth/callback/route.ts +16 -0
- package/bundles/nextjs-saas/app/auth/signout/route.ts +10 -0
- package/bundles/nextjs-saas/app/global-error.tsx +17 -0
- package/bundles/nextjs-saas/app/globals.css +55 -0
- package/bundles/nextjs-saas/app/layout.tsx +22 -0
- package/bundles/nextjs-saas/app/page.tsx +84 -0
- package/bundles/nextjs-saas/components/ui/button.tsx +39 -0
- package/bundles/nextjs-saas/components/ui/card.tsx +53 -0
- package/bundles/nextjs-saas/components/ui/index.ts +4 -0
- package/bundles/nextjs-saas/components/ui/input.tsx +23 -0
- package/bundles/nextjs-saas/components/ui/spinner.tsx +22 -0
- package/bundles/nextjs-saas/docs/LATTICE_RELEASE_WORKFLOW.md +53 -0
- package/bundles/nextjs-saas/docs/rules/codex.md +62 -0
- package/bundles/nextjs-saas/eslint.config.mjs +16 -0
- package/bundles/nextjs-saas/instrumentation-client.ts +30 -0
- package/bundles/nextjs-saas/instrumentation.ts +12 -0
- package/bundles/nextjs-saas/jest.config.mjs +16 -0
- package/bundles/nextjs-saas/jest.setup.js +1 -0
- package/bundles/nextjs-saas/lib/auth/password-recovery.ts +94 -0
- package/bundles/nextjs-saas/lib/stripe.ts +10 -0
- package/bundles/nextjs-saas/lib/supabase/admin.ts +14 -0
- package/bundles/nextjs-saas/lib/supabase/client.ts +8 -0
- package/bundles/nextjs-saas/lib/supabase/server.ts +27 -0
- package/bundles/nextjs-saas/lib/utils.ts +6 -0
- package/bundles/nextjs-saas/next-env.d.ts +5 -0
- package/bundles/nextjs-saas/next.config.ts +15 -0
- package/bundles/nextjs-saas/package.json +50 -0
- package/bundles/nextjs-saas/postcss.config.mjs +7 -0
- package/bundles/nextjs-saas/prompts/01-feature-implementation.md +92 -0
- package/bundles/nextjs-saas/prompts/02-bug-fix.md +78 -0
- package/bundles/nextjs-saas/prompts/03-safe-refactor.md +82 -0
- package/bundles/nextjs-saas/prompts/04-test-first.md +80 -0
- package/bundles/nextjs-saas/prompts/05-ui-polish.md +82 -0
- package/bundles/nextjs-saas/prompts/06-security-review.md +74 -0
- package/bundles/nextjs-saas/proxy.ts +61 -0
- package/bundles/nextjs-saas/sentry.edge.config.ts +15 -0
- package/bundles/nextjs-saas/sentry.server.config.ts +15 -0
- package/bundles/nextjs-saas/supabase/migrations/001_initial_schema.sql +66 -0
- package/bundles/nextjs-saas/supabase/migrations/002_billing.sql +17 -0
- package/bundles/nextjs-saas/tsconfig.json +42 -0
- package/bundles/nextjs-saas/types/database.types.ts +76 -0
- package/bundles/nextjs-saas/vendor/m2ai-braces-3.0.3-m2ai.1.tar +0 -0
- package/bundles/nextjs-trpc/.agents/skills/lattice-feature-handoff/SKILL.md +31 -0
- package/bundles/nextjs-trpc/.agents/skills/lattice-release-manager/SKILL.md +29 -0
- package/bundles/nextjs-trpc/.agents/skills/lattice-verify/SKILL.md +27 -0
- package/bundles/nextjs-trpc/.claude/agents/lattice-feature-agent.md +10 -0
- package/bundles/nextjs-trpc/.claude/agents/lattice-release-manager.md +9 -0
- package/bundles/nextjs-trpc/.claude/hooks/README.md +9 -0
- package/bundles/nextjs-trpc/.claude/hooks/pre-commit-verify.mjs +10 -0
- package/bundles/nextjs-trpc/.claude/hooks/pre-tool-use.mjs +51 -0
- package/bundles/nextjs-trpc/.claude/rules/lattice-core.md +20 -0
- package/bundles/nextjs-trpc/.claude/settings.json +38 -0
- package/bundles/nextjs-trpc/.claude/skills/lattice-verify/SKILL.md +27 -0
- package/bundles/nextjs-trpc/.codex/agents/lattice-feature-agent.toml +9 -0
- package/bundles/nextjs-trpc/.codex/agents/lattice-release-manager.toml +9 -0
- package/bundles/nextjs-trpc/.cursor/mcp.json +34 -0
- package/bundles/nextjs-trpc/.cursor/rules/lattice-core.mdc +35 -0
- package/bundles/nextjs-trpc/.cursor/rules.md +95 -0
- package/bundles/nextjs-trpc/.env.example +21 -0
- package/bundles/nextjs-trpc/.github/PULL_REQUEST_TEMPLATE.md +42 -0
- package/bundles/nextjs-trpc/.github/agents/lattice-feature-agent.agent.md +7 -0
- package/bundles/nextjs-trpc/.github/agents/lattice-release-manager.agent.md +7 -0
- package/bundles/nextjs-trpc/.github/copilot-instructions.md +37 -0
- package/bundles/nextjs-trpc/.github/instructions/lattice-core.instructions.md +11 -0
- package/bundles/nextjs-trpc/.github/workflows/ci.yml +26 -0
- package/bundles/nextjs-trpc/.gitmessage +24 -0
- package/bundles/nextjs-trpc/.lattice/config.json +9 -0
- package/bundles/nextjs-trpc/.lattice/dependency-security.json +46 -0
- package/bundles/nextjs-trpc/.lattice/prompts/01-feature.md +36 -0
- package/bundles/nextjs-trpc/.lattice/prompts/02-bugfix.md +32 -0
- package/bundles/nextjs-trpc/.lattice/prompts/03-refactor.md +30 -0
- package/bundles/nextjs-trpc/.lattice/prompts/04-test.md +31 -0
- package/bundles/nextjs-trpc/.lattice/prompts/05-polish.md +38 -0
- package/bundles/nextjs-trpc/.lattice/prompts/06-security.md +32 -0
- package/bundles/nextjs-trpc/.lattice/release-workflow.json +55 -0
- package/bundles/nextjs-trpc/.lattice/schemas/feature-handoff.schema.json +264 -0
- package/bundles/nextjs-trpc/.lattice/templates/feature-handoff.json +52 -0
- package/bundles/nextjs-trpc/.mcp.json +35 -0
- package/bundles/nextjs-trpc/AGENTS.md +58 -0
- package/bundles/nextjs-trpc/CLAUDE.md +76 -0
- package/bundles/nextjs-trpc/PROJECT_GUIDE.md +187 -0
- package/bundles/nextjs-trpc/README.md +49 -0
- package/bundles/nextjs-trpc/app/api/trpc/[trpc]/route.ts +12 -0
- package/bundles/nextjs-trpc/app/global-error.tsx +17 -0
- package/bundles/nextjs-trpc/app/globals.css +55 -0
- package/bundles/nextjs-trpc/app/layout.tsx +19 -0
- package/bundles/nextjs-trpc/app/page.tsx +16 -0
- package/bundles/nextjs-trpc/app/providers.tsx +24 -0
- package/bundles/nextjs-trpc/components/ui/button.tsx +39 -0
- package/bundles/nextjs-trpc/components/ui/card.tsx +53 -0
- package/bundles/nextjs-trpc/components/ui/index.ts +4 -0
- package/bundles/nextjs-trpc/components/ui/input.tsx +23 -0
- package/bundles/nextjs-trpc/components/ui/spinner.tsx +22 -0
- package/bundles/nextjs-trpc/components/user-list.tsx +17 -0
- package/bundles/nextjs-trpc/docs/LATTICE_RELEASE_WORKFLOW.md +53 -0
- package/bundles/nextjs-trpc/docs/rules/codex.md +62 -0
- package/bundles/nextjs-trpc/eslint.config.mjs +16 -0
- package/bundles/nextjs-trpc/instrumentation-client.ts +20 -0
- package/bundles/nextjs-trpc/instrumentation.ts +12 -0
- package/bundles/nextjs-trpc/jest.config.mjs +16 -0
- package/bundles/nextjs-trpc/jest.setup.js +1 -0
- package/bundles/nextjs-trpc/lib/db.ts +17 -0
- package/bundles/nextjs-trpc/lib/trpc/react.tsx +7 -0
- package/bundles/nextjs-trpc/lib/utils.ts +6 -0
- package/bundles/nextjs-trpc/next-env.d.ts +5 -0
- package/bundles/nextjs-trpc/next.config.ts +15 -0
- package/bundles/nextjs-trpc/package.json +62 -0
- package/bundles/nextjs-trpc/postcss.config.mjs +7 -0
- package/bundles/nextjs-trpc/prisma/schema.prisma +41 -0
- package/bundles/nextjs-trpc/prisma.config.ts +10 -0
- package/bundles/nextjs-trpc/prompts/01-feature-implementation.md +9 -0
- package/bundles/nextjs-trpc/prompts/02-bug-fix.md +9 -0
- package/bundles/nextjs-trpc/prompts/03-safe-refactor.md +8 -0
- package/bundles/nextjs-trpc/prompts/04-test-first.md +8 -0
- package/bundles/nextjs-trpc/prompts/05-ui-polish.md +7 -0
- package/bundles/nextjs-trpc/prompts/06-security-review.md +7 -0
- package/bundles/nextjs-trpc/prompts/quality.md +269 -0
- package/bundles/nextjs-trpc/sentry.edge.config.ts +15 -0
- package/bundles/nextjs-trpc/sentry.server.config.ts +15 -0
- package/bundles/nextjs-trpc/server/routers/_app.test.ts +60 -0
- package/bundles/nextjs-trpc/server/routers/_app.ts +25 -0
- package/bundles/nextjs-trpc/server/trpc.ts +12 -0
- package/bundles/nextjs-trpc/tsconfig.json +42 -0
- package/bundles/nextjs-trpc/vendor/m2ai-braces-3.0.3-m2ai.1.tar +0 -0
- package/dist/agent-install-session.d.ts +17 -0
- package/dist/agent-install-session.d.ts.map +1 -0
- package/dist/agent-install-session.js +106 -0
- package/dist/agent-install-session.js.map +1 -0
- package/dist/agent-install-session.test.d.ts +2 -0
- package/dist/agent-install-session.test.d.ts.map +1 -0
- package/dist/agent-install-session.test.js +62 -0
- package/dist/agent-install-session.test.js.map +1 -0
- package/dist/agent-install.d.ts +41 -0
- package/dist/agent-install.d.ts.map +1 -0
- package/dist/agent-install.js +42 -0
- package/dist/agent-install.js.map +1 -0
- package/dist/agent-install.test.d.ts +2 -0
- package/dist/agent-install.test.d.ts.map +1 -0
- package/dist/agent-install.test.js +58 -0
- package/dist/agent-install.test.js.map +1 -0
- package/dist/apply-merge.test.d.ts +2 -0
- package/dist/apply-merge.test.d.ts.map +1 -0
- package/dist/apply-merge.test.js +123 -0
- package/dist/apply-merge.test.js.map +1 -0
- package/dist/bundle-download.d.ts +23 -0
- package/dist/bundle-download.d.ts.map +1 -0
- package/dist/bundle-download.js +180 -0
- package/dist/bundle-download.js.map +1 -0
- package/dist/bundle-download.test.d.ts +2 -0
- package/dist/bundle-download.test.d.ts.map +1 -0
- package/dist/bundle-download.test.js +200 -0
- package/dist/bundle-download.test.js.map +1 -0
- package/dist/bundle-rollback.test.d.ts +2 -0
- package/dist/bundle-rollback.test.d.ts.map +1 -0
- package/dist/bundle-rollback.test.js +127 -0
- package/dist/bundle-rollback.test.js.map +1 -0
- package/dist/bundle-scaffold.test.d.ts +2 -0
- package/dist/bundle-scaffold.test.d.ts.map +1 -0
- package/dist/bundle-scaffold.test.js +105 -0
- package/dist/bundle-scaffold.test.js.map +1 -0
- package/dist/commands.d.ts +132 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +2012 -0
- package/dist/commands.js.map +1 -0
- package/dist/credential-store.d.ts +27 -0
- package/dist/credential-store.d.ts.map +1 -0
- package/dist/credential-store.js +48 -0
- package/dist/credential-store.js.map +1 -0
- package/dist/credential-store.test.d.ts +2 -0
- package/dist/credential-store.test.d.ts.map +1 -0
- package/dist/credential-store.test.js +80 -0
- package/dist/credential-store.test.js.map +1 -0
- package/dist/delivered-project-files.d.ts +31 -0
- package/dist/delivered-project-files.d.ts.map +1 -0
- package/dist/delivered-project-files.js +158 -0
- package/dist/delivered-project-files.js.map +1 -0
- package/dist/delivered-project-files.test.d.ts +2 -0
- package/dist/delivered-project-files.test.d.ts.map +1 -0
- package/dist/delivered-project-files.test.js +107 -0
- package/dist/delivered-project-files.test.js.map +1 -0
- package/dist/doctor-agents.test.d.ts +2 -0
- package/dist/doctor-agents.test.d.ts.map +1 -0
- package/dist/doctor-agents.test.js +65 -0
- package/dist/doctor-agents.test.js.map +1 -0
- package/dist/hermes-install.d.ts +102 -0
- package/dist/hermes-install.d.ts.map +1 -0
- package/dist/hermes-install.js +641 -0
- package/dist/hermes-install.js.map +1 -0
- package/dist/hermes-install.test.d.ts +2 -0
- package/dist/hermes-install.test.d.ts.map +1 -0
- package/dist/hermes-install.test.js +866 -0
- package/dist/hermes-install.test.js.map +1 -0
- package/dist/index.d.ts +115 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5311 -0
- package/dist/index.js.map +1 -0
- package/dist/openclaw-install.d.ts +67 -0
- package/dist/openclaw-install.d.ts.map +1 -0
- package/dist/openclaw-install.js +358 -0
- package/dist/openclaw-install.js.map +1 -0
- package/dist/openclaw-install.test.d.ts +2 -0
- package/dist/openclaw-install.test.d.ts.map +1 -0
- package/dist/openclaw-install.test.js +296 -0
- package/dist/openclaw-install.test.js.map +1 -0
- package/dist/password-recovery-bundle.test.d.ts +2 -0
- package/dist/password-recovery-bundle.test.d.ts.map +1 -0
- package/dist/password-recovery-bundle.test.js +132 -0
- package/dist/password-recovery-bundle.test.js.map +1 -0
- package/dist/project-bundle-env.d.ts +19 -0
- package/dist/project-bundle-env.d.ts.map +1 -0
- package/dist/project-bundle-env.js +111 -0
- package/dist/project-bundle-env.js.map +1 -0
- package/dist/project-bundle-env.test.d.ts +2 -0
- package/dist/project-bundle-env.test.d.ts.map +1 -0
- package/dist/project-bundle-env.test.js +93 -0
- package/dist/project-bundle-env.test.js.map +1 -0
- package/dist/project-path-confinement.test.d.ts +2 -0
- package/dist/project-path-confinement.test.d.ts.map +1 -0
- package/dist/project-path-confinement.test.js +222 -0
- package/dist/project-path-confinement.test.js.map +1 -0
- package/dist/security/api.d.ts +18 -0
- package/dist/security/api.d.ts.map +1 -0
- package/dist/security/api.js +238 -0
- package/dist/security/api.js.map +1 -0
- package/dist/security/api.test.d.ts +2 -0
- package/dist/security/api.test.d.ts.map +1 -0
- package/dist/security/api.test.js +220 -0
- package/dist/security/api.test.js.map +1 -0
- package/dist/security/artifact.d.ts +10 -0
- package/dist/security/artifact.d.ts.map +1 -0
- package/dist/security/artifact.js +283 -0
- package/dist/security/artifact.js.map +1 -0
- package/dist/security/artifact.test.d.ts +2 -0
- package/dist/security/artifact.test.d.ts.map +1 -0
- package/dist/security/artifact.test.js +229 -0
- package/dist/security/artifact.test.js.map +1 -0
- package/dist/security/commands.d.ts +42 -0
- package/dist/security/commands.d.ts.map +1 -0
- package/dist/security/commands.js +825 -0
- package/dist/security/commands.js.map +1 -0
- package/dist/security/commands.test.d.ts +2 -0
- package/dist/security/commands.test.d.ts.map +1 -0
- package/dist/security/commands.test.js +1051 -0
- package/dist/security/commands.test.js.map +1 -0
- package/dist/security/connection.d.ts +19 -0
- package/dist/security/connection.d.ts.map +1 -0
- package/dist/security/connection.js +145 -0
- package/dist/security/connection.js.map +1 -0
- package/dist/security/connection.test.d.ts +2 -0
- package/dist/security/connection.test.d.ts.map +1 -0
- package/dist/security/connection.test.js +62 -0
- package/dist/security/connection.test.js.map +1 -0
- package/dist/security/index-routing.test.d.ts +2 -0
- package/dist/security/index-routing.test.d.ts.map +1 -0
- package/dist/security/index-routing.test.js +169 -0
- package/dist/security/index-routing.test.js.map +1 -0
- package/dist/security/journal.d.ts +26 -0
- package/dist/security/journal.d.ts.map +1 -0
- package/dist/security/journal.js +441 -0
- package/dist/security/journal.js.map +1 -0
- package/dist/security/journal.test.d.ts +2 -0
- package/dist/security/journal.test.d.ts.map +1 -0
- package/dist/security/journal.test.js +226 -0
- package/dist/security/journal.test.js.map +1 -0
- package/dist/security/package-verifier.d.ts +15 -0
- package/dist/security/package-verifier.d.ts.map +1 -0
- package/dist/security/package-verifier.js +65 -0
- package/dist/security/package-verifier.js.map +1 -0
- package/dist/security/package-verifier.test.d.ts +2 -0
- package/dist/security/package-verifier.test.d.ts.map +1 -0
- package/dist/security/package-verifier.test.js +57 -0
- package/dist/security/package-verifier.test.js.map +1 -0
- package/dist/security/runtime.d.ts +43 -0
- package/dist/security/runtime.d.ts.map +1 -0
- package/dist/security/runtime.js +81 -0
- package/dist/security/runtime.js.map +1 -0
- package/dist/security/runtime.test.d.ts +2 -0
- package/dist/security/runtime.test.d.ts.map +1 -0
- package/dist/security/runtime.test.js +88 -0
- package/dist/security/runtime.test.js.map +1 -0
- package/dist/security/types.d.ts +169 -0
- package/dist/security/types.d.ts.map +1 -0
- package/dist/security/types.js +3 -0
- package/dist/security/types.js.map +1 -0
- package/dist/security-runtime/LICENSE +202 -0
- package/dist/security-runtime/NOTICE +16 -0
- package/dist/security-runtime/artifact-manifest.json +960 -0
- package/dist/security-runtime/bin/vsg.mjs +5 -0
- package/dist/security-runtime/lattice-catalog.json +176585 -0
- package/dist/security-runtime/lattice-runtime.mjs +90 -0
- package/dist/security-runtime/licensing/candidates/apache-source-license-evidence.json +478 -0
- package/dist/security-runtime/licensing/candidates/betterleaks-generic-api-key.json +76 -0
- package/dist/security-runtime/licensing/candidates/betterleaks-jwt.json +74 -0
- package/dist/security-runtime/licensing/candidates/blackberry-additional-source-declaration-evidence.json +276 -0
- package/dist/security-runtime/licensing/candidates/blackberry-source-declaration-evidence.json +369 -0
- package/dist/security-runtime/licensing/candidates/cado-source-declaration-evidence.json +283 -0
- package/dist/security-runtime/licensing/candidates/commercial-rule-candidate.json +280 -0
- package/dist/security-runtime/licensing/candidates/commercial-runtime-release.json +389 -0
- package/dist/security-runtime/licensing/candidates/data-feed-evidence.json +259 -0
- package/dist/security-runtime/licensing/candidates/gitlab-sast-rule-identities.json +178 -0
- package/dist/security-runtime/licensing/candidates/gitlab-sast-source-evidence.json +1824 -0
- package/dist/security-runtime/licensing/candidates/gitlab-sast-source-notice-bundle.json +45 -0
- package/dist/security-runtime/licensing/candidates/malpedia-source-license-evidence.json +41 -0
- package/dist/security-runtime/licensing/candidates/rule-license-evidence.json +376 -0
- package/dist/security-runtime/licensing/candidates/runner-image-composition.json +1500 -0
- package/dist/security-runtime/licensing/candidates/selected-runtime-coverage.json +91 -0
- package/dist/security-runtime/licensing/candidates/yara-forge-20260927.json +58502 -0
- package/dist/security-runtime/licensing/commercial-components.json +379 -0
- package/dist/security-runtime/licensing/notices/betterleaks-1.9.0-MIT.txt +21 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/28a9529c7d0bb4dc51f4bf5c116a3d16ef247a052f7591466768ddf563fd1cf5.txt +428 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/33acf42afdd03163d75fe856cb431e70710e0b5deede3362e6d1c4697cfe1c6a.txt +28 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/3972dc9744f6499f0f9b2dbf76696f2ae7ad8af9b23dde66d6af86c9dfb36986.txt +674 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/4fecb8fcaf80fd9a6315bca5225ee43377015b46a0459c2925495be885cab19a.txt +21 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/811515f8723aa4007de2fbb75a364127fdec51cda534b87a7ea8f2fef2f96dd7.txt +24 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/814442c3987a2c0411171ad8ad43118e8c08f85c9c5d1dcdecc9787c7ca8689b.txt +664 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/8a959b2413d0c83ca1b3ce9153076c649abf2e4bbfebbb493fb24c2074a1eb8a.txt +38 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/995182e185856186fbbe49f150409ae026aa4cda7e94f83c6ed737cbb77fa9c7.txt +23 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/9b8e1305e46d1dd4011b6ed933c9f6223e08c9c4625001c5fd75a34fa930f616.txt +202 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/a01f1a28424bfe7f49a23d339a01847cfa9ace3864d5e7295051772a4bae2271.txt +38 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/a5681bf9b05db14d86776930017c647ad9e6e56ff6bbcfdf21e5848288dfaf1b.txt +165 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/a5b8bd9ae96c630bbf229d61c5c5def20274e00be39abfd2fab4d7879ceab462.txt +24 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/ada32b3747ce108d5e8bab7918af94abbd03f2fe2a46304f74c6333bbfd914ed.txt +8 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4.txt +201 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/c738ae413cf561f174e34f6961f8ca458aae2369a73640dda6234c629b98bcc4.txt +2732 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/ce41c9a2c986277f7f9ab146a2195c1888a5d8da062e22d7c9c88666bb7c38cd.txt +17 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/d5f4c36a0528e01cfdd9e4fc60879201d3af49b41c520200643d321fe53da5f9.txt +17 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/e08c368ccd455f85c7fb9e04830e730f26e9dbb5c0f77bc88e09a5b0cb37df5b.txt +38 -0
- package/dist/security-runtime/licensing/notices/candidate-sources/sha256/e9efb2f7daf11bb6379c06c16b870dddcecc4a10f8704bb8aad807529c8b3c97.txt +8 -0
- package/dist/security-runtime/licensing/notices/gitleaks-generic-origin-782f3104-MIT.txt +21 -0
- package/dist/security-runtime/package.json +17 -0
- package/dist/security-runtime/playbook/README.md +76 -0
- package/dist/security-runtime/playbook/access-control.md +56 -0
- package/dist/security-runtime/playbook/ai-features.md +53 -0
- package/dist/security-runtime/playbook/desktop-python.md +59 -0
- package/dist/security-runtime/playbook/input-handling.md +59 -0
- package/dist/security-runtime/playbook/mobile-expo.md +59 -0
- package/dist/security-runtime/playbook/payments.md +53 -0
- package/dist/security-runtime/playbook/privacy-account-recovery.md +59 -0
- package/dist/security-runtime/playbook/secrets-config.md +47 -0
- package/dist/security-runtime/playbook/supabase.md +48 -0
- package/dist/security-runtime/playbook/supply-chain.md +62 -0
- package/dist/security-runtime/playbook/webhooks-integrations.md +52 -0
- package/dist/security-runtime/rules/vsg-ai-key-in-client.yaml +41 -0
- package/dist/security-runtime/rules/vsg-ai-output-raw-html.yaml +35 -0
- package/dist/security-runtime/rules/vsg-angular-sanitizer-bypass.yaml +23 -0
- package/dist/security-runtime/rules/vsg-expo-token-in-asyncstorage.yaml +22 -0
- package/dist/security-runtime/rules/vsg-flask-public-bind.yaml +32 -0
- package/dist/security-runtime/rules/vsg-nextjs-action-write-no-auth.yaml +144 -0
- package/dist/security-runtime/rules/vsg-nextjs-inline-action-write-no-auth.yaml +161 -0
- package/dist/security-runtime/rules/vsg-nextjs-route-write-no-auth.yaml +193 -0
- package/dist/security-runtime/rules/vsg-nosql-where-injection.yaml +36 -0
- package/dist/security-runtime/rules/vsg-python-pickle-load.yaml +26 -0
- package/dist/security-runtime/rules/vsg-python-requests-verify-false.yaml +34 -0
- package/dist/security-runtime/rules/vsg-python-subprocess-shell.yaml +23 -0
- package/dist/security-runtime/rules/vsg-stripe-client-price.yaml +51 -0
- package/dist/security-runtime/rules/vsg-stripe-webhook-no-signature.yaml +31 -0
- package/dist/security-runtime/rules/vsg-stripe-webhook-pages-no-signature.yaml +51 -0
- package/dist/security-runtime/rules/vsg-supabase-service-role-in-client.yaml +27 -0
- package/dist/security-runtime/rules/vsg-supabase-service-role-public-env.yaml +24 -0
- package/dist/security-runtime/rules/vsg-xml-external-entities.yaml +19 -0
- package/dist/security-runtime/src/agent/brief.mjs +95 -0
- package/dist/security-runtime/src/agent/discover.mjs +108 -0
- package/dist/security-runtime/src/agent/exec.mjs +64 -0
- package/dist/security-runtime/src/agent/ingest.mjs +213 -0
- package/dist/security-runtime/src/agent/report.mjs +94 -0
- package/dist/security-runtime/src/agent/schema.mjs +62 -0
- package/dist/security-runtime/src/agent/tokenize.mjs +38 -0
- package/dist/security-runtime/src/checks/README.md +8 -0
- package/dist/security-runtime/src/checks/_lib/gitfiles.mjs +35 -0
- package/dist/security-runtime/src/checks/_lib/lockfiles.mjs +135 -0
- package/dist/security-runtime/src/checks/_lib/osv.mjs +6 -0
- package/dist/security-runtime/src/checks/_lib/secrets.mjs +381 -0
- package/dist/security-runtime/src/checks/_lib/targets.mjs +79 -0
- package/dist/security-runtime/src/checks/agent-review/index.mjs +52 -0
- package/dist/security-runtime/src/checks/agent-surface/config.mjs +223 -0
- package/dist/security-runtime/src/checks/agent-surface/index.mjs +113 -0
- package/dist/security-runtime/src/checks/agent-surface/instructions.mjs +87 -0
- package/dist/security-runtime/src/checks/agent-surface/patterns.mjs +68 -0
- package/dist/security-runtime/src/checks/agent-surface/unicode.mjs +88 -0
- package/dist/security-runtime/src/checks/code/auth-helpers.mjs +659 -0
- package/dist/security-runtime/src/checks/code/index.mjs +617 -0
- package/dist/security-runtime/src/checks/code/opengrep-container.mjs +85 -0
- package/dist/security-runtime/src/checks/code/opengrep-runner.mjs +86 -0
- package/dist/security-runtime/src/checks/code/selected-opengrep-runner.mjs +112 -0
- package/dist/security-runtime/src/checks/dep-change/guarddog.mjs +142 -0
- package/dist/security-runtime/src/checks/dep-change/index.mjs +316 -0
- package/dist/security-runtime/src/checks/dep-change/registries.mjs +199 -0
- package/dist/security-runtime/src/checks/deps-vuln/index.mjs +305 -0
- package/dist/security-runtime/src/checks/desktop-config/index.mjs +112 -0
- package/dist/security-runtime/src/checks/dns-mail/index.mjs +71 -0
- package/dist/security-runtime/src/checks/iac/index.mjs +83 -0
- package/dist/security-runtime/src/checks/install-posture/index.mjs +123 -0
- package/dist/security-runtime/src/checks/licenses/index.mjs +143 -0
- package/dist/security-runtime/src/checks/live-basic/index.mjs +77 -0
- package/dist/security-runtime/src/checks/live-js-secrets/index.mjs +100 -0
- package/dist/security-runtime/src/checks/malware/clamav.mjs +17 -0
- package/dist/security-runtime/src/checks/malware/defender.mjs +43 -0
- package/dist/security-runtime/src/checks/malware/index.mjs +186 -0
- package/dist/security-runtime/src/checks/malware/targets.mjs +147 -0
- package/dist/security-runtime/src/checks/malware/yara-runner.mjs +201 -0
- package/dist/security-runtime/src/checks/malware/yara.mjs +124 -0
- package/dist/security-runtime/src/checks/mobile-config/index.mjs +173 -0
- package/dist/security-runtime/src/checks/mobile-config/mobsf.mjs +105 -0
- package/dist/security-runtime/src/checks/posture/index.mjs +133 -0
- package/dist/security-runtime/src/checks/project-scripts/index.mjs +187 -0
- package/dist/security-runtime/src/checks/sbom/index.mjs +98 -0
- package/dist/security-runtime/src/checks/secrets-build/index.mjs +63 -0
- package/dist/security-runtime/src/checks/secrets-history/index.mjs +112 -0
- package/dist/security-runtime/src/checks/secrets-tree/env.mjs +120 -0
- package/dist/security-runtime/src/checks/secrets-tree/index.mjs +73 -0
- package/dist/security-runtime/src/checks/supabase-static/index.mjs +240 -0
- package/dist/security-runtime/src/checks/supabase-static/sql.mjs +557 -0
- package/dist/security-runtime/src/checks/workflows/index.mjs +93 -0
- package/dist/security-runtime/src/cli/deep.mjs +13 -0
- package/dist/security-runtime/src/cli/doctor.mjs +82 -0
- package/dist/security-runtime/src/cli/index.mjs +60 -0
- package/dist/security-runtime/src/cli/live-common.mjs +27 -0
- package/dist/security-runtime/src/cli/parse.mjs +56 -0
- package/dist/security-runtime/src/cli/portfolio.mjs +34 -0
- package/dist/security-runtime/src/cli/release.mjs +28 -0
- package/dist/security-runtime/src/cli/report.mjs +18 -0
- package/dist/security-runtime/src/cli/run-common.mjs +54 -0
- package/dist/security-runtime/src/cli/scan.mjs +12 -0
- package/dist/security-runtime/src/cli/setup.mjs +59 -0
- package/dist/security-runtime/src/cli/url.mjs +38 -0
- package/dist/security-runtime/src/core/accept.mjs +141 -0
- package/dist/security-runtime/src/core/archive.mjs +114 -0
- package/dist/security-runtime/src/core/base-ref.mjs +43 -0
- package/dist/security-runtime/src/core/checks.mjs +39 -0
- package/dist/security-runtime/src/core/detect.mjs +90 -0
- package/dist/security-runtime/src/core/errors.mjs +5 -0
- package/dist/security-runtime/src/core/fetch.mjs +139 -0
- package/dist/security-runtime/src/core/findings.mjs +177 -0
- package/dist/security-runtime/src/core/gate.mjs +131 -0
- package/dist/security-runtime/src/core/installer.mjs +255 -0
- package/dist/security-runtime/src/core/lock.mjs +38 -0
- package/dist/security-runtime/src/core/nested.mjs +107 -0
- package/dist/security-runtime/src/core/paths.mjs +20 -0
- package/dist/security-runtime/src/core/pipeline.mjs +196 -0
- package/dist/security-runtime/src/core/registry.mjs +81 -0
- package/dist/security-runtime/src/core/report.mjs +128 -0
- package/dist/security-runtime/src/core/runner.mjs +86 -0
- package/dist/security-runtime/src/core/sarif.mjs +141 -0
- package/dist/security-runtime/src/lattice/artifact.mjs +1201 -0
- package/dist/security-runtime/src/lattice/execution.mjs +45 -0
- package/dist/security-runtime/src/lattice/export.mjs +215 -0
- package/dist/security-runtime/src/lattice/provenance.mjs +70 -0
- package/dist/security-runtime/src/lattice/runtime.mjs +158 -0
- package/dist/security-runtime/src/lattice/selected-runtime.mjs +189 -0
- package/dist/security-runtime/src/lattice/source-acquirer.mjs +51 -0
- package/dist/security-runtime/src/lattice/source-fetcher.mjs +88 -0
- package/dist/security-runtime/src/lattice/transport.mjs +232 -0
- package/dist/security-runtime/src/live/analyze.mjs +101 -0
- package/dist/security-runtime/src/live/exposure.mjs +79 -0
- package/dist/security-runtime/src/live/secrets.mjs +31 -0
- package/dist/security-runtime/src/live/session.mjs +98 -0
- package/dist/security-runtime/src/live/targets.mjs +81 -0
- package/dist/security-runtime/src/portfolio/index.mjs +116 -0
- package/dist/security-runtime/tools/registry/betterleaks.json +29 -0
- package/dist/security-runtime/tools/registry/guarddog.json +9 -0
- package/dist/security-runtime/tools/registry/mobsf.json +10 -0
- package/dist/security-runtime/tools/registry/opengrep.json +28 -0
- package/dist/security-runtime/tools/registry/osv-scanner.json +14 -0
- package/dist/security-runtime/tools/registry/semgrep-rules.json +21 -0
- package/dist/security-runtime/tools/registry/trivy.json +30 -0
- package/dist/security-runtime/tools/registry/yara-forge-exclusions.json +14 -0
- package/dist/security-runtime/tools/registry/yara-forge.json +22 -0
- package/dist/security-runtime/tools/registry/yara-runner.json +10 -0
- package/dist/security-runtime/tools/registry/yara-x.json +24 -0
- package/dist/security-runtime/tools/registry/zizmor.json +30 -0
- package/dist/spinner.d.ts +16 -0
- package/dist/spinner.d.ts.map +1 -0
- package/dist/spinner.js +72 -0
- package/dist/spinner.js.map +1 -0
- package/dist/verify.test.d.ts +2 -0
- package/dist/verify.test.d.ts.map +1 -0
- package/dist/verify.test.js +98 -0
- package/dist/verify.test.js.map +1 -0
- package/package.json +73 -4
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// secrets-tree (REQ-012): Betterleaks over the working tree (respecting .gitignore), plus public-prefix env exposure and committed .env files.
|
|
2
|
+
// In deep and release runs found credentials are validated against their issuers unless --no-validate is passed.
|
|
3
|
+
// Bundled single-file blobs (*.wasm.js and *.min.js over 1 MB) are not scanned for secrets (REQ-037): they are base64 or minified data that
|
|
4
|
+
// produces false matches. They still get malware scanning.
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { scanTargetsWithIgnored } from '../_lib/targets.mjs';
|
|
8
|
+
import { demoJwtFinding, gitState, hitToFinding, ignoredPaths, repoFiles, ROTATE, runBetterleaks, skipPatterns, supabasePublicKeyFinding } from '../_lib/secrets.mjs';
|
|
9
|
+
import { envExposure } from './env.mjs';
|
|
10
|
+
|
|
11
|
+
export const id = 'secrets-tree';
|
|
12
|
+
export const title = 'Secrets in the working tree';
|
|
13
|
+
export const modes = ['scan', 'deep', 'release'];
|
|
14
|
+
export const requiredIn = ['scan', 'deep', 'release'];
|
|
15
|
+
export const timeoutSec = 900;
|
|
16
|
+
|
|
17
|
+
export const applies = () => true;
|
|
18
|
+
|
|
19
|
+
export const shouldValidate = (ctx) => ['deep', 'release'].includes(ctx.mode) && !ctx.flags?.noValidate;
|
|
20
|
+
|
|
21
|
+
export const LARGE_BUNDLE = /\.(?:wasm|min)\.js$/i;
|
|
22
|
+
export const LARGE_BUNDLE_BYTES = 1024 * 1024;
|
|
23
|
+
|
|
24
|
+
/** Generated single-file bundles over 1 MB: [{ file, bytes }]. */
|
|
25
|
+
export function largeBundles(repo, files) {
|
|
26
|
+
const out = [];
|
|
27
|
+
for (const file of files) {
|
|
28
|
+
if (!LARGE_BUNDLE.test(file)) continue;
|
|
29
|
+
try {
|
|
30
|
+
const bytes = fs.statSync(path.join(repo, file)).size;
|
|
31
|
+
if (bytes > LARGE_BUNDLE_BYTES) out.push({ file, bytes });
|
|
32
|
+
} catch { /* unreadable: leave it to the scanner */ }
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function run(ctx) {
|
|
38
|
+
const state = await gitState(ctx);
|
|
39
|
+
const ignored = state.usable ? await ignoredPaths(ctx) : [];
|
|
40
|
+
const validate = shouldValidate(ctx);
|
|
41
|
+
const { files, tracked, git } = await repoFiles(ctx, state);
|
|
42
|
+
const bundles = largeBundles(ctx.repo, files);
|
|
43
|
+
// With nested checkouts present, hand Betterleaks explicit paths: it still walks a directory it is told to skip (see _lib/targets.mjs).
|
|
44
|
+
const nested = (ctx.nestedRepos ?? []).map((n) => n.path);
|
|
45
|
+
const { targets: paths } = scanTargetsWithIgnored(ctx.repo, nested, ['node_modules', '.git', '.venv', 'venv', '__pycache__', '.pnpm-store', '.vsg'], nested.length > 0);
|
|
46
|
+
const scan = await runBetterleaks(ctx, { kind: 'dir', paths, validate, skip: skipPatterns(ignored, bundles.map((b) => b.file)) });
|
|
47
|
+
if (scan.status !== 'ran') return { status: 'not_run', reason: scan.reason };
|
|
48
|
+
|
|
49
|
+
const demo = demoJwtFinding(scan.demoJwts, { where: 'in the working tree' });
|
|
50
|
+
const publicKey = supabasePublicKeyFinding(scan.publicKeys, { where: 'in the working tree' });
|
|
51
|
+
const findings = [
|
|
52
|
+
...scan.hits.map((h) => hitToFinding(h, {
|
|
53
|
+
category: 'secret', severity: 'critical', where: 'in the working tree',
|
|
54
|
+
fix: `${ROTATE} If the file is committed, the value also stays in git history, so rotation is required, not optional.`,
|
|
55
|
+
})),
|
|
56
|
+
...(demo ? [demo] : []),
|
|
57
|
+
...(publicKey ? [publicKey] : []),
|
|
58
|
+
...envExposure(ctx.repo, files, tracked),
|
|
59
|
+
];
|
|
60
|
+
return {
|
|
61
|
+
status: 'ran',
|
|
62
|
+
reason: validate ? '' : (['deep', 'release'].includes(ctx.mode) ? 'credential validation was disabled by --no-validate' : ''),
|
|
63
|
+
findings,
|
|
64
|
+
toolVersion: ctx.registry?.get('betterleaks')?.version ?? null,
|
|
65
|
+
evidence: {
|
|
66
|
+
hits: scan.hits.length, filteredLocalizationNoise: scan.filtered, suppressed: scan.suppressed,
|
|
67
|
+
skippedLargeBundles: bundles.map((b) => `${b.file} (${b.bytes} bytes)`),
|
|
68
|
+
validated: validate, gitignoreRespected: state.usable, ignoredPaths: ignored.length, filesChecked: files.length, git,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export default { id, title, modes, requiredIn, timeoutSec, applies, run };
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
// supabase-static (REQ-014): static analysis of supabase/migrations/*.sql (final state across migrations) plus an optional
|
|
2
|
+
// import of the Supabase security advisors. Pure Node: no external tool. Reads the repository only.
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { listFiles } from '../../core/detect.mjs';
|
|
6
|
+
import { scrubText } from '../../core/findings.mjs';
|
|
7
|
+
import { applyMigration, isTrueExpr, newState } from './sql.mjs';
|
|
8
|
+
|
|
9
|
+
export const id = 'supabase-static';
|
|
10
|
+
export const title = 'Supabase migrations: RLS, policies, definer functions, views and storage buckets';
|
|
11
|
+
export const modes = ['scan', 'deep', 'release'];
|
|
12
|
+
export const requiredIn = ['deep', 'release'];
|
|
13
|
+
export const timeoutSec = 300;
|
|
14
|
+
|
|
15
|
+
export const ADVISOR_URL = (ref) => `https://api.supabase.com/v1/projects/${ref}/advisors/security`;
|
|
16
|
+
const MIGRATION = /(^|\/)supabase\/migrations\/[^/]+\.sql$/;
|
|
17
|
+
const REF = /^[A-Za-z0-9_-]{6,64}$/;
|
|
18
|
+
/** A migrations folder under docs/, examples/, reference/ or a *-reference folder is a copy for reading, not the project's own schema (REQ-037). */
|
|
19
|
+
const REFERENCE_SEGMENT = /^(?:docs|examples|reference|.+-reference)$/i;
|
|
20
|
+
export const isReferenceCopy = (dir) => dir.split('/').slice(0, -2).some((seg) => REFERENCE_SEGMENT.test(seg));
|
|
21
|
+
const DOCS = 'https://supabase.com/docs/guides/database/postgres/row-level-security';
|
|
22
|
+
const EXPOSED = new Set(['anon', 'authenticated', 'public']);
|
|
23
|
+
|
|
24
|
+
export function applies(ctx) {
|
|
25
|
+
return ctx.detection.supabase ? true : { applies: false, reason: 'Supabase is not used in this repository' };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// ---- rendering helpers ----
|
|
29
|
+
const qi = (n) => (/^[a-z_][a-z0-9_$]*$/.test(n) ? n : `"${String(n).replace(/"/g, '""')}"`);
|
|
30
|
+
const qt = (schema, name) => `${qi(schema)}.${qi(name)}`;
|
|
31
|
+
const lit = (s) => `'${String(s).replace(/'/g, "''")}'`;
|
|
32
|
+
const where = (o) => ({ file: o.file, line: o.line });
|
|
33
|
+
const evidenceOf = (o) => `${o.file}:${o.line}: ${o.text}`;
|
|
34
|
+
|
|
35
|
+
// ---- final-state findings ----
|
|
36
|
+
function stateFindings(state, publicTables) {
|
|
37
|
+
const out = [];
|
|
38
|
+
const listed = (schema, name) => publicTables.has(name.toLowerCase()) || publicTables.has(`${schema}.${name}`.toLowerCase());
|
|
39
|
+
const dynamic = state.dynamicRls.length
|
|
40
|
+
? ` Note: a DO block at ${state.dynamicRls.map((d) => `${d.file}:${d.line}`).join(', ')} mentions row level security; dynamic SQL is not analyzed, so check whether it already covers this table.`
|
|
41
|
+
: '';
|
|
42
|
+
|
|
43
|
+
for (const t of state.tables.values()) {
|
|
44
|
+
if (t.schema !== 'public' || t.rls || (!t.anonOpen && !t.authOpen)) continue;
|
|
45
|
+
const tbl = qt(t.schema, t.name);
|
|
46
|
+
out.push({
|
|
47
|
+
category: 'supabase', severity: 'high', confidence: 'high', key: `rls-disabled:${t.schema}.${t.name}`, tool: 'vsg', ruleId: 'supabase-rls-disabled', cwe: ['CWE-862'],
|
|
48
|
+
location: where(t), refs: [DOCS],
|
|
49
|
+
title: `Table ${tbl} has row level security disabled`,
|
|
50
|
+
description: `Every table in the public schema is reachable through the Supabase API with the public (anon) key. Without RLS, anyone who has the key can read, change and delete every row of ${tbl}. A table listed in publicTables is still writable by anyone while RLS is off.${dynamic}`,
|
|
51
|
+
evidence: evidenceOf(t),
|
|
52
|
+
fix: `alter table ${tbl} enable row level security;\n-- Then add the policies the app needs (with RLS on and no policy, access is denied), for example:\n-- create policy "Users read own rows" on ${tbl} for select to authenticated using ((select auth.uid()) = user_id);`,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
for (const p of state.policies) {
|
|
57
|
+
if (p.restrictive || !(p.using || p.check)) continue;
|
|
58
|
+
const exposed = p.roles.length === 0 || p.roles.some((r) => EXPOSED.has(r));
|
|
59
|
+
const open = (p.using && isTrueExpr(p.using)) || (p.check && isTrueExpr(p.check));
|
|
60
|
+
if (!exposed || !open) continue;
|
|
61
|
+
const who = p.roles.length ? p.roles.join(', ') : 'everyone (no TO clause means public)';
|
|
62
|
+
const tbl = qt(p.schema, p.tableName);
|
|
63
|
+
if (p.schema === 'storage' && p.tableName === 'objects') {
|
|
64
|
+
out.push({
|
|
65
|
+
category: 'supabase', severity: 'medium', confidence: 'high', key: `storage-open-policy:${p.name}`, tool: 'vsg', ruleId: 'supabase-storage-policy-open',
|
|
66
|
+
location: where(p), refs: ['https://supabase.com/docs/guides/storage/security/access-control'],
|
|
67
|
+
title: `Storage policy "${p.name}" gives ${who} access to every object in every bucket`,
|
|
68
|
+
description: `This policy on storage.objects is literally true, so it does not restrict by bucket or owner.`,
|
|
69
|
+
evidence: evidenceOf(p),
|
|
70
|
+
fix: `drop policy ${qi(p.name)} on storage.objects;\ncreate policy ${qi(p.name)} on storage.objects for ${p.cmd === 'all' ? 'select' : p.cmd} to authenticated using (bucket_id = 'your-bucket' and (select auth.uid())::text = (storage.foldername(name))[1]);`,
|
|
71
|
+
});
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const owner = '(select auth.uid()) = user_id';
|
|
75
|
+
const clause = p.cmd === 'insert' ? `with check (${owner})` : p.cmd === 'select' || p.cmd === 'delete' ? `using (${owner})` : `using (${owner}) with check (${owner})`;
|
|
76
|
+
const publicRead =listed(p.schema, p.tableName) && p.cmd === 'select';
|
|
77
|
+
if (publicRead) continue;
|
|
78
|
+
out.push({
|
|
79
|
+
category: 'supabase', severity: 'high', confidence: 'high', key: `open-policy:${p.schema}.${p.tableName}:${p.name}`, tool: 'vsg', ruleId: 'supabase-policy-unconditional', cwe: ['CWE-862'],
|
|
80
|
+
location: where(p), refs: [DOCS],
|
|
81
|
+
title: `Policy "${p.name}" on ${tbl} lets ${who} access every row`,
|
|
82
|
+
description: `The ${p.cmd === 'all' ? 'ALL commands' : p.cmd.toUpperCase()} policy's USING or WITH CHECK is literally true, so it does not restrict rows.${listed(p.schema, p.tableName) ? ` ${tbl} is in publicTables, but only SELECT is allowed to be unconditional.` : ` ${tbl} is not listed in publicTables in vsg.config.json.`}`,
|
|
83
|
+
evidence: evidenceOf(p),
|
|
84
|
+
fix: `drop policy ${qi(p.name)} on ${tbl};\ncreate policy ${qi(p.name)} on ${tbl} for ${p.cmd} to authenticated ${clause};\n-- If ${tbl} is meant to be world-readable, list it in publicTables in vsg.config.json and keep the policy SELECT-only.`,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
for (const f of state.functions.values()) {
|
|
89
|
+
if (!f.definer || f.searchPath) continue;
|
|
90
|
+
out.push({
|
|
91
|
+
category: 'supabase', severity: 'medium', confidence: 'high', key: `definer-no-search-path:${f.schema}.${f.name}`, tool: 'vsg', ruleId: 'supabase-definer-search-path', cwe: ['CWE-427'],
|
|
92
|
+
location: where(f), refs: ['https://supabase.com/docs/guides/database/database-advisors?lint=0011_function_search_path_mutable'],
|
|
93
|
+
title: `security definer function ${qt(f.schema, f.name)} has no fixed search_path`,
|
|
94
|
+
description: 'A security definer function runs with its owner\'s privileges. Without a fixed search_path, a caller who can create objects in a schema earlier on the path can make the function run their code with those privileges.',
|
|
95
|
+
evidence: evidenceOf(f),
|
|
96
|
+
fix: `alter function ${qt(f.schema, f.name)}(${f.args}) set search_path = '';\n-- Then schema-qualify every table, function and operator the body uses (public.my_table).`,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
for (const v of state.views.values()) {
|
|
101
|
+
if (v.schema !== 'public' || v.invoker) continue;
|
|
102
|
+
out.push({
|
|
103
|
+
category: 'supabase', severity: 'medium', confidence: 'high', key: `view-no-invoker:${v.schema}.${v.name}`, tool: 'vsg', ruleId: 'supabase-view-security-invoker',
|
|
104
|
+
location: where(v), refs: ['https://supabase.com/docs/guides/database/database-advisors?lint=0010_security_definer_view'],
|
|
105
|
+
title: `View ${qt(v.schema, v.name)} bypasses row level security`,
|
|
106
|
+
description: 'A view runs with its owner\'s privileges unless security_invoker is set, so it can expose rows that RLS hides from the caller on the underlying tables. security_invoker needs Postgres 15 or later.',
|
|
107
|
+
evidence: evidenceOf(v),
|
|
108
|
+
fix: `alter view ${qt(v.schema, v.name)} set (security_invoker = true);`,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
for (const b of state.buckets.values()) {
|
|
113
|
+
if (!b.public) continue;
|
|
114
|
+
out.push({
|
|
115
|
+
category: 'supabase', severity: 'medium', confidence: 'high', key: `public-bucket:${b.id}`, tool: 'vsg', ruleId: 'supabase-public-bucket',
|
|
116
|
+
location: where(b), refs: ['https://supabase.com/docs/guides/storage/buckets/fundamentals'],
|
|
117
|
+
title: `Storage bucket ${lit(b.id)} is public`,
|
|
118
|
+
description: 'Anyone with an object URL can download files from a public bucket without signing in, and file names in it are easy to guess or enumerate. That is fine for genuinely public assets and wrong for anything user-specific.',
|
|
119
|
+
evidence: evidenceOf(b),
|
|
120
|
+
fix: `update storage.buckets set public = false where id = ${lit(b.id)};\n-- Serve files with signed URLs (createSignedUrl) or add storage.objects policies scoped to the owner. If the bucket really is public, accept this finding with a reason.`,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return out;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ---- advisor import ----
|
|
127
|
+
const LEVELS = { ERROR: 'high', WARN: 'medium', INFO: 'info' };
|
|
128
|
+
|
|
129
|
+
/** Maps advisor lints (shape tolerant: the endpoint is experimental) to raw findings. */
|
|
130
|
+
export function mapAdvisorLints(lints) {
|
|
131
|
+
const findings = [];
|
|
132
|
+
let unreadable = 0;
|
|
133
|
+
for (const l of lints) {
|
|
134
|
+
if (!l || typeof l !== 'object' || typeof l.name !== 'string') { unreadable++; continue; }
|
|
135
|
+
const meta = l.metadata && typeof l.metadata === 'object' ? l.metadata : {};
|
|
136
|
+
const object = [meta.schema, meta.name].filter((x) => typeof x === 'string' && x).join('.');
|
|
137
|
+
const level = String(l.level ?? '').toUpperCase();
|
|
138
|
+
const text = (x) => (typeof x === 'string' ? x : '');
|
|
139
|
+
const remediation = text(l.remediation);
|
|
140
|
+
const sql = l.name === 'rls_disabled_in_public' && meta.schema && meta.name ? `alter table ${qt(meta.schema, meta.name)} enable row level security;` : '';
|
|
141
|
+
findings.push({
|
|
142
|
+
category: 'supabase', severity: LEVELS[level] ?? 'info', confidence: 'high', tool: 'supabase-advisor', ruleId: l.name,
|
|
143
|
+
key: `advisor:${l.name}:${text(l.cache_key) || object || text(l.detail).slice(0, 80)}`,
|
|
144
|
+
location: {}, refs: /^https?:\/\//.test(remediation) ? [remediation] : [],
|
|
145
|
+
title: `Supabase advisor: ${text(l.title) || l.name}${object ? ` (${object})` : ''}`,
|
|
146
|
+
description: [text(l.detail), text(l.description)].filter(Boolean).join(' ') || `Supabase advisor lint ${l.name}.`,
|
|
147
|
+
evidence: `lint ${l.name}, level ${level || 'unknown'}${object ? `, object ${object}` : ''}${meta.type ? `, type ${meta.type}` : ''}`,
|
|
148
|
+
fix: sql || (remediation ? `Follow the Supabase remediation: ${remediation}` : ''),
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return { findings, unreadable };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function projectRef(ctx, dirs) {
|
|
155
|
+
const fromConfig = ctx.config?.supabase?.projectRef;
|
|
156
|
+
if (fromConfig) return REF.test(fromConfig) ? fromConfig : null;
|
|
157
|
+
const candidates = [path.join(ctx.repo, 'supabase', '.temp', 'project-ref'), ...dirs.map((d) => path.join(ctx.repo, d, '..', '.temp', 'project-ref'))];
|
|
158
|
+
for (const f of candidates) {
|
|
159
|
+
try {
|
|
160
|
+
const ref = fs.readFileSync(f, 'utf8').trim();
|
|
161
|
+
if (REF.test(ref)) return ref;
|
|
162
|
+
} catch { /* no linked project in this location */ }
|
|
163
|
+
}
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async function importAdvisors(ctx, dirs) {
|
|
168
|
+
const token = process.env.SUPABASE_ACCESS_TOKEN;
|
|
169
|
+
if (!token) return { status: 'skipped', reason: 'SUPABASE_ACCESS_TOKEN is not set, so the security advisors were not imported.' };
|
|
170
|
+
const ref = projectRef(ctx, dirs);
|
|
171
|
+
if (!ref) return { status: 'skipped', reason: 'No Supabase project ref is known (set supabase.projectRef in vsg.config.json or link the project), so the security advisors were not imported.' };
|
|
172
|
+
const fail = (why) => ({ status: 'failed', reason: scrubText(`Security advisor import failed: ${why}`, [token]) });
|
|
173
|
+
try {
|
|
174
|
+
const res = await ctx.fetch(ADVISOR_URL(ref), { headers: { Authorization: `Bearer ${token}`, Accept: 'application/json' }, timeoutMs: 30_000 });
|
|
175
|
+
if (res.status === 401 || res.status === 403) return fail(`HTTP ${res.status} (the token was rejected or lacks access to the project).`);
|
|
176
|
+
if (!res.ok) return fail(`HTTP ${res.status}.`);
|
|
177
|
+
let body;
|
|
178
|
+
try { body = JSON.parse(res.body.toString('utf8')); } catch { return fail('the response was not JSON.'); }
|
|
179
|
+
const lints = Array.isArray(body) ? body : (body?.lints ?? body?.data?.lints ?? body?.result?.lints);
|
|
180
|
+
if (!Array.isArray(lints)) return fail('the response had no list of lints (the endpoint is experimental and its shape may have changed).');
|
|
181
|
+
const { findings, unreadable } = mapAdvisorLints(lints);
|
|
182
|
+
return { status: 'imported', reason: '', ref, count: lints.length, unreadable, findings, lints: lints.slice(0, 500) };
|
|
183
|
+
} catch (e) {
|
|
184
|
+
return fail(e.message);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ---- run ----
|
|
189
|
+
export async function run(ctx) {
|
|
190
|
+
const publicTables = new Set((ctx.config?.publicTables ?? []).map((s) => s.toLowerCase()));
|
|
191
|
+
const byDir = new Map();
|
|
192
|
+
for (const f of listFiles(ctx.repo).filter((x) => MIGRATION.test(x))) {
|
|
193
|
+
const dir = f.slice(0, f.lastIndexOf('/'));
|
|
194
|
+
if (!byDir.has(dir)) byDir.set(dir, []);
|
|
195
|
+
byDir.get(dir).push(f);
|
|
196
|
+
}
|
|
197
|
+
const findings = [];
|
|
198
|
+
const evidence = { migrationDirs: [], referenceCopies: [], statements: 0, skippedStatements: 0, skipped: [] };
|
|
199
|
+
for (const [dir, files] of [...byDir].sort(([a], [b]) => (a < b ? -1 : 1))) {
|
|
200
|
+
files.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)); // filename order is the order Supabase applies migrations
|
|
201
|
+
const state = newState();
|
|
202
|
+
for (const f of files) {
|
|
203
|
+
let src;
|
|
204
|
+
try { src = fs.readFileSync(path.join(ctx.repo, f), 'utf8'); } catch (e) { state.skipped.push({ file: f, line: 0, reason: `unreadable file: ${e.message}`, text: '' }); continue; }
|
|
205
|
+
applyMigration(state, f, (src.charCodeAt(0) === 0xfeff ? src.slice(1) : src));
|
|
206
|
+
}
|
|
207
|
+
const dirFindings = stateFindings(state, publicTables);
|
|
208
|
+
if (isReferenceCopy(dir)) {
|
|
209
|
+
for (const f of dirFindings) {
|
|
210
|
+
f.severity = 'medium';
|
|
211
|
+
f.title = `${f.title} (reference copy)`;
|
|
212
|
+
f.description = `Reference copy: this migration folder (${dir}) is outside the project's own supabase/migrations, so it is reported but does not block. The SQL is real if anyone copies it into a live project. ${f.description}`;
|
|
213
|
+
}
|
|
214
|
+
evidence.referenceCopies.push({ dir, findings: dirFindings.length });
|
|
215
|
+
}
|
|
216
|
+
findings.push(...dirFindings);
|
|
217
|
+
evidence.migrationDirs.push({ dir, files: files.length, tables: state.tables.size, policies: state.policies.length, functions: state.functions.size, views: state.views.size, buckets: state.buckets.size, rlsEnabledByDoBlock: state.dynamicRlsApplied });
|
|
218
|
+
evidence.statements += state.statements;
|
|
219
|
+
evidence.skippedStatements += state.skipped.length;
|
|
220
|
+
evidence.skipped.push(...state.skipped.slice(0, 20));
|
|
221
|
+
}
|
|
222
|
+
evidence.skipped = evidence.skipped.slice(0, 20);
|
|
223
|
+
|
|
224
|
+
const advisor = await importAdvisors(ctx, [...byDir.keys()]);
|
|
225
|
+
evidence.advisor = { status: advisor.status, reason: advisor.reason, ref: advisor.ref ?? null, count: advisor.count ?? 0, unreadable: advisor.unreadable ?? 0 };
|
|
226
|
+
if (advisor.findings) findings.push(...advisor.findings);
|
|
227
|
+
|
|
228
|
+
const notes = [];
|
|
229
|
+
if (!byDir.size) notes.push('No supabase/migrations/*.sql files were found, so the static analysis did not run.');
|
|
230
|
+
if (evidence.skippedStatements) notes.push(`${evidence.skippedStatements} SQL statement(s) could not be parsed and were skipped (see evidence).`);
|
|
231
|
+
if (advisor.status === 'failed') notes.push(advisor.reason);
|
|
232
|
+
if (!byDir.size && advisor.status !== 'imported') {
|
|
233
|
+
return { status: 'not_run', reason: `${notes[0]} ${advisor.reason || ''} Provide migrations, or set SUPABASE_ACCESS_TOKEN and supabase.projectRef so the security advisors can be imported.`.replace(/\s+/g, ' ').trim() };
|
|
234
|
+
}
|
|
235
|
+
const files = { 'summary.json': JSON.stringify(evidence, null, 2) }; // raw evidence is { filename: text }
|
|
236
|
+
if (advisor.lints) files['advisor-lints.json'] = JSON.stringify(advisor.lints, null, 2);
|
|
237
|
+
return { status: 'ran', reason: notes.join(' '), findings, evidence: files };
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export default { id, title, modes, requiredIn, timeoutSec, applies, run };
|