@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,45 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { UsageError } from '../core/errors.mjs';
|
|
4
|
+
import { packageRoot } from '../core/paths.mjs';
|
|
5
|
+
import { readLatticeArtifact } from './artifact.mjs';
|
|
6
|
+
|
|
7
|
+
const ARTIFACT_MARKERS = Object.freeze([
|
|
8
|
+
'artifact-manifest.json',
|
|
9
|
+
'lattice-runtime.mjs',
|
|
10
|
+
'lattice-catalog.json',
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
const MISSING_COMMERCIAL_COVERAGE = Object.freeze([
|
|
14
|
+
'commercial_component_rights_not_cleared',
|
|
15
|
+
'third_party_attribution_catalog_incomplete',
|
|
16
|
+
'replacement_rule_coverage_not_approved',
|
|
17
|
+
'artifact_release_approval_missing',
|
|
18
|
+
]);
|
|
19
|
+
|
|
20
|
+
function markerPresent(marker) {
|
|
21
|
+
try {
|
|
22
|
+
fs.lstatSync(path.join(packageRoot, marker));
|
|
23
|
+
return true;
|
|
24
|
+
} catch (error) {
|
|
25
|
+
if (error?.code === 'ENOENT') return false;
|
|
26
|
+
throw new UsageError(`[commercial_artifact_unavailable] cannot inspect runtime marker ${marker} (${error?.code ?? 'filesystem_error'}).`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Refuses scanner/setup execution from an identifiable candidate or partial artifact. */
|
|
31
|
+
export function assertStandaloneExecution({ allowQualification = false } = {}) {
|
|
32
|
+
const present = ARTIFACT_MARKERS.filter(markerPresent);
|
|
33
|
+
if (!present.length) return;
|
|
34
|
+
if (present.length === ARTIFACT_MARKERS.length) {
|
|
35
|
+
try {
|
|
36
|
+
const manifest = readLatticeArtifact({ artifactRoot: packageRoot });
|
|
37
|
+
if (manifest.releaseEligibility?.status === 'approved') return;
|
|
38
|
+
if (manifest.releaseEligibility?.status === 'blocked'
|
|
39
|
+
&& allowQualification && process.env.VSG_COMMERCIAL_QUALIFICATION === '1'
|
|
40
|
+
&& JSON.stringify(manifest.releaseEligibility.blockers) === JSON.stringify(MISSING_COMMERCIAL_COVERAGE)) return;
|
|
41
|
+
} catch { /* use the fixed denial below */ }
|
|
42
|
+
}
|
|
43
|
+
throw new UsageError(`[commercial_artifact_unavailable] candidate artifact execution is blocked; missing commercial coverage: ${MISSING_COMMERCIAL_COVERAGE.join(', ')}; runtime markers present: ${present.join(', ')}.`);
|
|
44
|
+
}
|
|
45
|
+
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { captureReviewContext } from '../core/pipeline.mjs';
|
|
4
|
+
import { readLatticeArtifact } from './artifact.mjs';
|
|
5
|
+
import { captureRuntimeProvenance } from './provenance.mjs';
|
|
6
|
+
|
|
7
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
8
|
+
const SHA256 = /^[0-9a-f]{64}$/;
|
|
9
|
+
const SHA1 = /^[0-9a-f]{40}$/;
|
|
10
|
+
const AUDIT_MODES = ['scan', 'deep', 'release'];
|
|
11
|
+
const MODES = [...AUDIT_MODES, 'report'];
|
|
12
|
+
const CONFIDENCES = new Set(['confirmed', 'high', 'medium', 'low']);
|
|
13
|
+
const SEVERITIES = new Set(['critical', 'high', 'medium', 'low', 'info']);
|
|
14
|
+
const PUBLIC_ID = /^[A-Za-z0-9][A-Za-z0-9._:/@+-]*$/;
|
|
15
|
+
const SENSITIVE = /-----BEGIN [A-Z ]*PRIVATE KEY-----|\bAKIA[0-9A-Z]{16}\b|\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{30,}\b|\bgithub_pat_[A-Za-z0-9_]{30,}\b|\b(?:sk|rk|pk)_(?:live|test)_[A-Za-z0-9]{16,}\b|\bxox[abprs]-[A-Za-z0-9-]{10,}\b|\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/;
|
|
16
|
+
|
|
17
|
+
export class LatticeReportError extends Error {
|
|
18
|
+
constructor(message, code = 'invalid_report') {
|
|
19
|
+
super(`Lattice report rejected: ${message}`);
|
|
20
|
+
this.name = 'LatticeReportError';
|
|
21
|
+
this.code = code;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function fail(message, code = 'invalid_report') {
|
|
26
|
+
throw new LatticeReportError(message, code);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function readJson(file, label) {
|
|
30
|
+
try { return JSON.parse(fs.readFileSync(file, 'utf8')); } catch (error) { fail(`${label} is missing or invalid (${error.message}).`); }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const canonical = (value) => {
|
|
34
|
+
if (value === null || typeof value !== 'object') return JSON.stringify(value);
|
|
35
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(',')}]`;
|
|
36
|
+
return `{${Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([key, item]) => `${JSON.stringify(key)}:${canonical(item)}`).join(',')}}`;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
function validateRepositoryIdentity(value) {
|
|
40
|
+
if (typeof value !== 'string' || value.length === 0 || value.length > 512 || SENSITIVE.test(value) || /^[A-Za-z]:|^\/|\\|\.\.|@|[?#]|[\u0000-\u001f]/.test(value)) fail('repositoryIdentity must be a canonical public repository identity.');
|
|
41
|
+
const parts = value.split('/');
|
|
42
|
+
if (parts.length < 3 || !parts[0].includes('.') || parts.some((part) => !/^[A-Za-z0-9_.-]+$/.test(part)) || /^(?:localhost|0\.0\.0\.0|127\.|10\.|192\.168\.|169\.254\.|172\.(?:1[6-9]|2[0-9]|3[01])\.)/i.test(parts[0])) fail('repositoryIdentity must name a public host, owner, and repository.');
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function validateSnapshot(snapshot) {
|
|
47
|
+
if (!snapshot || snapshot.schemaVersion !== 1 || !snapshot.start || !snapshot.end) fail('scan start/end source evidence is missing.');
|
|
48
|
+
for (const [name, item] of Object.entries({ start: snapshot.start, end: snapshot.end })) {
|
|
49
|
+
if (item.schemaVersion !== 1 || typeof item.runId !== 'string' || !item.runId || typeof item.repo !== 'string' || !path.isAbsolute(item.repo)
|
|
50
|
+
|| !SHA256.test(item.sourceHash ?? '') || !Number.isSafeInteger(item.fileCount) || item.fileCount < 0
|
|
51
|
+
|| (item.commitSha !== null && !SHA1.test(item.commitSha ?? '')) || typeof item.dirty !== 'boolean') {
|
|
52
|
+
fail(`scan ${name} source evidence is invalid.`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (canonical(snapshot.start) !== canonical(snapshot.end)) fail('repository source changed while the scan was running.', 'source_changed');
|
|
56
|
+
return snapshot.start;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function validateRuntimeSnapshot(snapshot, artifact, artifactRoot) {
|
|
60
|
+
if (!snapshot || snapshot.schemaVersion !== 1 || !snapshot.start || !snapshot.end) fail('scan start/end runtime evidence is missing.');
|
|
61
|
+
if (canonical(snapshot.start) !== canonical(snapshot.end)) fail('executing VSG runtime changed while the scan was running.');
|
|
62
|
+
if (snapshot.start.kind !== 'lattice-artifact') fail('scan was not executed by the verified Lattice artifact entrypoint.');
|
|
63
|
+
const expected = captureRuntimeProvenance({ runtimeRoot: artifactRoot, entrypoint: path.join(artifactRoot, ...artifact.entryPoint.split('/')) });
|
|
64
|
+
if (canonical(snapshot.start) !== canonical(expected)) fail('originating VSG runtime does not match the supplied artifact.');
|
|
65
|
+
return snapshot.start;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function normalizedCheck(check, index) {
|
|
69
|
+
if (!check || typeof check.id !== 'string' || !check.id || check.id.length > 128 || !PUBLIC_ID.test(check.id) || SENSITIVE.test(check.id)) fail(`check ${index} has an invalid id.`);
|
|
70
|
+
const statuses = { ran: 'ran', not_run: 'missing', not_applicable: 'not_applicable' };
|
|
71
|
+
const status = statuses[check.status];
|
|
72
|
+
if (!status) fail(`check ${check.id} has an unsupported status.`);
|
|
73
|
+
const coverageStatus = /^degraded:/.test(check.reason ?? '') ? `${check.status}_degraded` : check.status;
|
|
74
|
+
return {
|
|
75
|
+
id: check.id,
|
|
76
|
+
status,
|
|
77
|
+
required: check.required === true,
|
|
78
|
+
coverageCodes: [`vsg.${check.id}.${coverageStatus}`],
|
|
79
|
+
attributionIds: [],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function ruleIdOf(finding) {
|
|
84
|
+
const value = finding.sources?.find((source) => typeof source?.ruleId === 'string' && source.ruleId)?.ruleId ?? finding.check;
|
|
85
|
+
if (typeof value !== 'string' || !value || value.length > 160 || !PUBLIC_ID.test(value) || SENSITIVE.test(value)) fail(`finding ${finding.fingerprint ?? '?'} has no bounded public rule identity.`);
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function advisoryIdsOf(finding) {
|
|
90
|
+
const values = [];
|
|
91
|
+
const add = (value) => {
|
|
92
|
+
for (const match of String(value ?? '').matchAll(/\b(?:CVE-\d{4}-\d{4,}|GHSA-[23456789cfghjmpqrvwx]{4}-[23456789cfghjmpqrvwx]{4}-[23456789cfghjmpqrvwx]{4}|OSV-[A-Za-z0-9._-]+)\b/gi)) values.push(match[0].toUpperCase());
|
|
93
|
+
};
|
|
94
|
+
for (const source of finding.sources ?? []) add(source.ruleId);
|
|
95
|
+
for (const ref of finding.refs ?? []) add(ref);
|
|
96
|
+
return [...new Set(values)].slice(0, 50);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function packageRefOf(location) {
|
|
100
|
+
if (!location?.package) return null;
|
|
101
|
+
const ecosystem = String(location.ecosystem ?? 'package').replace(/[^A-Za-z0-9._-]/g, '').slice(0, 64) || 'package';
|
|
102
|
+
const name = String(location.package).replace(/[\u0000-\u001f]/g, '').slice(0, 160);
|
|
103
|
+
const version = location.version == null ? '' : `@${String(location.version).replace(/[\u0000-\u001f]/g, '').slice(0, 80)}`;
|
|
104
|
+
const value = `${ecosystem}:${name}${version}`;
|
|
105
|
+
if (value.length > 300 || !PUBLIC_ID.test(value) || SENSITIVE.test(value)) fail('finding package reference is invalid or contains sensitive data.');
|
|
106
|
+
return value;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function locationOf(location, fingerprint) {
|
|
110
|
+
if (!location?.file) return null;
|
|
111
|
+
const value = String(location.file).replace(/\\/g, '/');
|
|
112
|
+
if (!value || value.length > 512 || /[\u0000-\u001f\u007f]/.test(value) || SENSITIVE.test(value) || value.startsWith('/') || /^[A-Za-z]:/.test(value) || value.includes('://') || value.split('/').some((part) => !part || part === '.' || part === '..')) fail(`finding ${fingerprint} contains a non-relative or sensitive source path.`);
|
|
113
|
+
const line = location.line == null ? null : Number(location.line);
|
|
114
|
+
if (line !== null && (!Number.isSafeInteger(line) || line < 1 || line > 10_000_000)) fail(`finding ${fingerprint} has an invalid line.`);
|
|
115
|
+
return { path: value, line, column: null };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function cweIdsOf(finding, ruleId, catalog) {
|
|
119
|
+
const values = [
|
|
120
|
+
...[].concat(finding.cweIds ?? []),
|
|
121
|
+
...[].concat(finding.cwe ?? []),
|
|
122
|
+
...[].concat(catalog.provenance?.rules?.[ruleId]?.cweIds ?? []),
|
|
123
|
+
];
|
|
124
|
+
const normalized = values.map((value) => {
|
|
125
|
+
const text = String(value).trim().toUpperCase();
|
|
126
|
+
const number = /^(?:CWE-)?([1-9][0-9]{0,5})$/.exec(text)?.[1];
|
|
127
|
+
if (!number) fail(`finding ${finding.fingerprint ?? '?'} contains an invalid CWE identity.`);
|
|
128
|
+
return `CWE-${Number(number)}`;
|
|
129
|
+
});
|
|
130
|
+
return [...new Set(normalized)].sort((a, b) => Number(a.slice(4)) - Number(b.slice(4)));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function normalizedFinding(finding, index, catalog) {
|
|
134
|
+
if (!finding || !SHA256.test(finding.fingerprint ?? '')) fail(`finding ${index} has an invalid fingerprint.`);
|
|
135
|
+
if (!SEVERITIES.has(finding.severity)) fail(`finding ${finding.fingerprint} has an invalid severity.`);
|
|
136
|
+
if (!CONFIDENCES.has(finding.confidence)) fail(`finding ${finding.fingerprint} has an invalid confidence.`);
|
|
137
|
+
if (typeof finding.category !== 'string' || !finding.category || finding.category.length > 128) fail(`finding ${finding.fingerprint} has an invalid category.`);
|
|
138
|
+
if (!finding.exploited || typeof finding.exploited.kev !== 'boolean' || typeof finding.fix !== 'string') fail(`finding ${finding.fingerprint} lacks normalized policy inputs.`);
|
|
139
|
+
const ruleId = ruleIdOf(finding);
|
|
140
|
+
const trustedRule = catalog.rules?.[ruleId];
|
|
141
|
+
return {
|
|
142
|
+
fingerprint: finding.fingerprint,
|
|
143
|
+
severity: finding.severity,
|
|
144
|
+
category: finding.category,
|
|
145
|
+
confidence: finding.confidence,
|
|
146
|
+
status: finding.status === 'accepted' ? 'accepted' : 'open',
|
|
147
|
+
ruleId,
|
|
148
|
+
cweIds: cweIdsOf(finding, ruleId, catalog),
|
|
149
|
+
location: locationOf(finding.location, finding.fingerprint),
|
|
150
|
+
packageRef: packageRefOf(finding.location),
|
|
151
|
+
advisoryIds: advisoryIdsOf(finding),
|
|
152
|
+
attributionIds: trustedRule ? [...trustedRule.attributionIds] : [],
|
|
153
|
+
policyInputs: {
|
|
154
|
+
knownExploited: finding.exploited.kev,
|
|
155
|
+
fixAvailable: finding.fix.trim().length > 0,
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** Produces the strict semantic 1.1 publication DTO from one retained VSG run. */
|
|
161
|
+
export function exportLatticeReport({ repo, outDir, runId, mode, artifactRoot, repositoryIdentity }) {
|
|
162
|
+
repo = fs.realpathSync(path.resolve(repo));
|
|
163
|
+
outDir = path.resolve(outDir);
|
|
164
|
+
if (!UUID.test(runId ?? '')) fail('runId must be a UUID.');
|
|
165
|
+
if (!MODES.includes(mode)) fail('mode is unsupported.');
|
|
166
|
+
repositoryIdentity = validateRepositoryIdentity(repositoryIdentity);
|
|
167
|
+
const artifact = readLatticeArtifact({ artifactRoot });
|
|
168
|
+
const catalog = readJson(path.join(artifactRoot, 'lattice-catalog.json'), 'lattice-catalog.json');
|
|
169
|
+
const findingsDoc = readJson(path.join(outDir, 'findings.json'), 'findings.json');
|
|
170
|
+
const coverageDoc = readJson(path.join(outDir, 'coverage.json'), 'coverage.json');
|
|
171
|
+
if (!Array.isArray(findingsDoc.findings) || !Array.isArray(findingsDoc.checks) || !Array.isArray(coverageDoc.checks)) fail('retained output is not a complete VSG run.');
|
|
172
|
+
if (findingsDoc.findings.length > 5_000 || findingsDoc.checks.length > 100) fail('retained output exceeds the report collection limits.');
|
|
173
|
+
if (canonical(findingsDoc.checks) !== canonical(coverageDoc.checks)) fail('findings and coverage check evidence does not match.');
|
|
174
|
+
if (canonical(findingsDoc.sourceSnapshot) !== canonical(coverageDoc.sourceSnapshot)) fail('findings and coverage source evidence was tampered with.');
|
|
175
|
+
if (canonical(findingsDoc.runtimeSnapshot) !== canonical(coverageDoc.runtimeSnapshot)) fail('findings and coverage runtime evidence was tampered with.');
|
|
176
|
+
const source = validateSnapshot(findingsDoc.sourceSnapshot);
|
|
177
|
+
validateRuntimeSnapshot(findingsDoc.runtimeSnapshot, artifact, path.resolve(artifactRoot));
|
|
178
|
+
if (findingsDoc.vsgVersion !== artifact.identity.vsgVersion) fail('originating VSG version does not match the supplied artifact.');
|
|
179
|
+
if (path.resolve(source.repo) !== repo) fail('retained evidence belongs to a different repository.', 'source_changed');
|
|
180
|
+
const current = captureReviewContext(repo, source.runId, outDir);
|
|
181
|
+
if (canonical(current) !== canonical(source)) fail('retained evidence is stale for the current repository source.', 'source_changed');
|
|
182
|
+
|
|
183
|
+
let auditMode;
|
|
184
|
+
if (mode === 'report') {
|
|
185
|
+
if (!['deep', 'release'].includes(findingsDoc.mode)) fail('report publication must retain a deep or release parent audit mode.');
|
|
186
|
+
auditMode = findingsDoc.mode;
|
|
187
|
+
} else {
|
|
188
|
+
if (findingsDoc.mode !== mode) fail('requested mode does not match the originating audit mode.');
|
|
189
|
+
auditMode = mode;
|
|
190
|
+
}
|
|
191
|
+
const startedAt = findingsDoc.startedAt;
|
|
192
|
+
const completedAt = findingsDoc.finishedAt;
|
|
193
|
+
if (typeof startedAt !== 'string' || typeof completedAt !== 'string' || Number.isNaN(Date.parse(startedAt)) || Number.isNaN(Date.parse(completedAt)) || new Date(startedAt).toISOString() !== startedAt || new Date(completedAt).toISOString() !== completedAt) fail('run timestamps are missing or invalid.');
|
|
194
|
+
const checks = findingsDoc.checks.map(normalizedCheck);
|
|
195
|
+
if (new Set(checks.map((check) => check.id)).size !== checks.length) fail('duplicate check ids are forbidden.');
|
|
196
|
+
const findings = findingsDoc.findings.map((finding, index) => normalizedFinding(finding, index, catalog));
|
|
197
|
+
if (new Set(findings.map((finding) => finding.fingerprint)).size !== findings.length) fail('duplicate finding fingerprints are forbidden.');
|
|
198
|
+
return {
|
|
199
|
+
schemaVersion: '1.1',
|
|
200
|
+
runId,
|
|
201
|
+
mode,
|
|
202
|
+
auditMode,
|
|
203
|
+
startedAt,
|
|
204
|
+
completedAt,
|
|
205
|
+
source: {
|
|
206
|
+
repositoryIdentity,
|
|
207
|
+
commitSha: source.commitSha,
|
|
208
|
+
contentHash: source.sourceHash,
|
|
209
|
+
dirty: source.dirty,
|
|
210
|
+
},
|
|
211
|
+
runtime: artifact.identity,
|
|
212
|
+
checks,
|
|
213
|
+
findings,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { readLatticeArtifact } from './artifact.mjs';
|
|
5
|
+
|
|
6
|
+
const sha256 = (bytes) => crypto.createHash('sha256').update(bytes).digest('hex');
|
|
7
|
+
|
|
8
|
+
function hashTree(root) {
|
|
9
|
+
const hash = crypto.createHash('sha256');
|
|
10
|
+
const walk = (dir, rel = '') => {
|
|
11
|
+
if (!fs.existsSync(dir)) return;
|
|
12
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
13
|
+
const childRel = rel ? `${rel}/${entry.name}` : entry.name;
|
|
14
|
+
const child = path.join(dir, entry.name);
|
|
15
|
+
const stat = fs.lstatSync(child);
|
|
16
|
+
if (stat.isSymbolicLink()) throw new Error(`Runtime provenance rejected linked path ${childRel}.`);
|
|
17
|
+
if (entry.isDirectory()) walk(child, childRel);
|
|
18
|
+
else if (entry.isFile()) {
|
|
19
|
+
hash.update(childRel);
|
|
20
|
+
hash.update('\0');
|
|
21
|
+
hash.update(fs.readFileSync(child));
|
|
22
|
+
hash.update('\0');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
walk(root);
|
|
27
|
+
return hash.digest('hex');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function fileDigest(file) {
|
|
31
|
+
return fs.existsSync(file) && fs.statSync(file).isFile() ? sha256(fs.readFileSync(file)) : null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Captures the immutable VSG package that is actually executing the scan. */
|
|
35
|
+
export function captureRuntimeProvenance({ runtimeRoot, entrypoint = process.argv[1] }) {
|
|
36
|
+
runtimeRoot = fs.realpathSync(path.resolve(runtimeRoot));
|
|
37
|
+
const manifestPath = path.join(runtimeRoot, 'artifact-manifest.json');
|
|
38
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(runtimeRoot, 'package.json'), 'utf8'));
|
|
39
|
+
if (fs.existsSync(manifestPath)) {
|
|
40
|
+
const manifest = readLatticeArtifact({ artifactRoot: runtimeRoot });
|
|
41
|
+
const expectedEntrypoint = fs.realpathSync(path.join(runtimeRoot, ...manifest.entryPoint.split('/')));
|
|
42
|
+
let actualEntrypoint;
|
|
43
|
+
try { actualEntrypoint = fs.realpathSync(path.resolve(entrypoint)); } catch { throw new Error('Lattice runtime provenance requires its exact verified artifact entrypoint.'); }
|
|
44
|
+
if (actualEntrypoint !== expectedEntrypoint) throw new Error('Lattice runtime provenance requires its exact verified artifact entrypoint.');
|
|
45
|
+
return {
|
|
46
|
+
schemaVersion: 1,
|
|
47
|
+
kind: 'lattice-artifact',
|
|
48
|
+
vsgVersion: manifest.identity.vsgVersion,
|
|
49
|
+
entrypointSha256: fileDigest(expectedEntrypoint),
|
|
50
|
+
rulesDigest: manifest.identity.rulesDigest,
|
|
51
|
+
registryDigest: manifest.identity.registryDigest,
|
|
52
|
+
commercialManifestDigest: manifest.identity.commercialManifestDigest,
|
|
53
|
+
artifactManifestSha256: sha256(fs.readFileSync(manifestPath)),
|
|
54
|
+
artifactIdentity: manifest.identity,
|
|
55
|
+
artifactSourceCommit: manifest.sourceCommit,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
schemaVersion: 1,
|
|
60
|
+
kind: 'source-checkout',
|
|
61
|
+
vsgVersion: packageJson.version,
|
|
62
|
+
entrypointSha256: fileDigest(path.join(runtimeRoot, 'bin', 'vsg.mjs')),
|
|
63
|
+
rulesDigest: hashTree(path.join(runtimeRoot, 'rules')),
|
|
64
|
+
registryDigest: hashTree(path.join(runtimeRoot, 'tools', 'registry')),
|
|
65
|
+
commercialManifestDigest: fileDigest(path.join(runtimeRoot, 'licensing', 'commercial-components.json')),
|
|
66
|
+
artifactManifestSha256: null,
|
|
67
|
+
artifactIdentity: null,
|
|
68
|
+
artifactSourceCommit: null,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import { applyPolicy, requiredFor } from '../core/gate.mjs';
|
|
3
|
+
import { CATEGORIES, CONFIDENCES, SEVERITIES } from '../core/findings.mjs';
|
|
4
|
+
|
|
5
|
+
const STATUSES = ['open', 'accepted'];
|
|
6
|
+
const POLICY_CONFIDENCES = [...CONFIDENCES, 'unknown'];
|
|
7
|
+
const AUDIT_MODES = ['scan', 'deep', 'release'];
|
|
8
|
+
const FIXED_DETECTION = { workflows: ['.github/workflows'], lockfiles: ['package-lock.json'], supabase: true };
|
|
9
|
+
|
|
10
|
+
const canonical = (value) => {
|
|
11
|
+
if (value === null || typeof value !== 'object') return JSON.stringify(value);
|
|
12
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(',')}]`;
|
|
13
|
+
return `{${Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([key, item]) => `${JSON.stringify(key)}:${canonical(item)}`).join(',')}}`;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const sha256 = (value) => crypto.createHash('sha256').update(value).digest('hex');
|
|
17
|
+
|
|
18
|
+
function blockingTable() {
|
|
19
|
+
const table = {};
|
|
20
|
+
for (const category of CATEGORIES) {
|
|
21
|
+
for (const severity of SEVERITIES) {
|
|
22
|
+
for (const confidence of POLICY_CONFIDENCES) {
|
|
23
|
+
for (const status of STATUSES) {
|
|
24
|
+
for (const knownExploited of [false, true]) {
|
|
25
|
+
for (const fixAvailable of [false, true]) {
|
|
26
|
+
const finding = {
|
|
27
|
+
category, severity, confidence, status,
|
|
28
|
+
exploited: { kev: knownExploited },
|
|
29
|
+
fix: fixAvailable ? 'available' : '',
|
|
30
|
+
blocking: false,
|
|
31
|
+
blockReason: '',
|
|
32
|
+
};
|
|
33
|
+
applyPolicy([finding]);
|
|
34
|
+
if (finding.blocking) {
|
|
35
|
+
table[[category, severity, confidence, status, Number(knownExploited), Number(fixAvailable)].join('|')] = finding.blockReason;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return table;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function requiredProfiles() {
|
|
47
|
+
return Object.fromEntries(AUDIT_MODES.map((mode) => [
|
|
48
|
+
mode,
|
|
49
|
+
requiredFor(mode, FIXED_DETECTION, { config: { requiredChecks: { remove: [] } } }).required,
|
|
50
|
+
]));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Builds the dependency-free object-expression module loaded by the Lattice website. */
|
|
54
|
+
export function buildLatticeRuntimeSource({ identity, catalog, releaseEligibility }) {
|
|
55
|
+
const policy = blockingTable();
|
|
56
|
+
const profiles = requiredProfiles();
|
|
57
|
+
const evaluatorMaterial = { policy, profiles, severities: SEVERITIES };
|
|
58
|
+
const evaluatorDigest = sha256(canonical(evaluatorMaterial));
|
|
59
|
+
const catalogDigest = sha256(canonical(catalog));
|
|
60
|
+
const manifest = {
|
|
61
|
+
format: 'lattice-security-runtime-v1',
|
|
62
|
+
...identity,
|
|
63
|
+
evaluatorDigest,
|
|
64
|
+
catalogDigest,
|
|
65
|
+
releaseEligibility,
|
|
66
|
+
};
|
|
67
|
+
const source = `export default ${`{manifest: ${JSON.stringify(manifest)},
|
|
68
|
+
evaluate(report) {
|
|
69
|
+
const policy = ${JSON.stringify(policy)};
|
|
70
|
+
const profiles = ${JSON.stringify(profiles)};
|
|
71
|
+
const severities = ${JSON.stringify(SEVERITIES)};
|
|
72
|
+
if (!report || typeof report !== 'object' || !Array.isArray(report.findings) || !Array.isArray(report.checks)) throw new Error('Invalid security report.');
|
|
73
|
+
const auditMode = report.mode === 'report' ? report.auditMode : report.mode;
|
|
74
|
+
const required = profiles[auditMode];
|
|
75
|
+
if (!required) throw new Error('Unsupported audit mode.');
|
|
76
|
+
const checks = new Map(report.checks.map((check) => [check.id, check]));
|
|
77
|
+
const missingRequiredChecks = required.filter((id) => {
|
|
78
|
+
const status = checks.get(id)?.status;
|
|
79
|
+
return status !== 'ran' && status !== 'not_applicable';
|
|
80
|
+
}).length;
|
|
81
|
+
const counts = Object.fromEntries(severities.map((severity) => [severity, 0]));
|
|
82
|
+
let blocking = 0;
|
|
83
|
+
for (const finding of report.findings) {
|
|
84
|
+
if (!severities.includes(finding.severity)) throw new Error('Unsupported finding severity.');
|
|
85
|
+
counts[finding.severity]++;
|
|
86
|
+
const inputs = finding.policyInputs;
|
|
87
|
+
if (!inputs || typeof inputs.knownExploited !== 'boolean' || typeof inputs.fixAvailable !== 'boolean') throw new Error('Missing finding policy inputs.');
|
|
88
|
+
const key = [finding.category, finding.severity, finding.confidence, finding.status, Number(inputs.knownExploited), Number(inputs.fixAvailable)].join('|');
|
|
89
|
+
if (policy[key]) blocking++;
|
|
90
|
+
}
|
|
91
|
+
const verdict = blocking > 0 ? 'BLOCKED' : missingRequiredChecks > 0 ? 'INCOMPLETE' : 'PASS';
|
|
92
|
+
const coverageCodes = [...new Set(report.checks.flatMap((check) => Array.isArray(check.coverageCodes) ? check.coverageCodes : []))].sort();
|
|
93
|
+
return {
|
|
94
|
+
verdict,
|
|
95
|
+
counts: {
|
|
96
|
+
...counts,
|
|
97
|
+
requiredChecks: required.length,
|
|
98
|
+
completedRequiredChecks: required.length - missingRequiredChecks,
|
|
99
|
+
missingRequiredChecks,
|
|
100
|
+
},
|
|
101
|
+
coverageCodes,
|
|
102
|
+
evaluatorDigest: ${JSON.stringify(evaluatorDigest)},
|
|
103
|
+
catalogDigest: ${JSON.stringify(catalogDigest)},
|
|
104
|
+
};
|
|
105
|
+
},
|
|
106
|
+
present(report, baseline) {
|
|
107
|
+
const catalog = ${JSON.stringify(catalog)};
|
|
108
|
+
const profiles = ${JSON.stringify(profiles)};
|
|
109
|
+
const ruleIds = [...new Set(report.findings.map((finding) => finding.ruleId))];
|
|
110
|
+
const trustedId = (id) => {
|
|
111
|
+
if (catalog.rules[id]) return id;
|
|
112
|
+
const selectedYara = /^forge[0-9]+:([A-Za-z0-9_]+)$/.exec(id);
|
|
113
|
+
return selectedYara && catalog.rules[selectedYara[1]] ? selectedYara[1] : null;
|
|
114
|
+
};
|
|
115
|
+
const resolvedRuleIds = ruleIds.map((id) => [id, trustedId(id)]);
|
|
116
|
+
for (const [, id] of resolvedRuleIds) if (!id) throw new Error('Missing trusted rule presentation.');
|
|
117
|
+
const rules = resolvedRuleIds.map(([reportRuleId, id]) => ({
|
|
118
|
+
...catalog.rules[id],
|
|
119
|
+
ruleId: reportRuleId,
|
|
120
|
+
reportRuleId,
|
|
121
|
+
catalogRuleId: id,
|
|
122
|
+
}));
|
|
123
|
+
const attributionIds = [...new Set([
|
|
124
|
+
...report.findings.flatMap((finding) => finding.attributionIds || []),
|
|
125
|
+
...rules.flatMap((rule) => rule.attributionIds || []),
|
|
126
|
+
])];
|
|
127
|
+
for (const id of attributionIds) if (!catalog.credits[id]) throw new Error('Missing trusted attribution credit.');
|
|
128
|
+
const credits = attributionIds.map((id) => catalog.credits[id]);
|
|
129
|
+
let comparison = null;
|
|
130
|
+
if (baseline) {
|
|
131
|
+
const reasons = [];
|
|
132
|
+
if (report.source?.dirty || baseline.source?.dirty) reasons.push('dirty_source');
|
|
133
|
+
const missing = (value) => {
|
|
134
|
+
const auditMode = value.mode === 'report' ? value.auditMode : value.mode;
|
|
135
|
+
const checks = new Map(value.checks.map((check) => [check.id, check.status]));
|
|
136
|
+
return !profiles[auditMode] || profiles[auditMode].some((id) => !['ran', 'not_applicable'].includes(checks.get(id)));
|
|
137
|
+
};
|
|
138
|
+
if (missing(report) || missing(baseline)) reasons.push('incomplete_checks');
|
|
139
|
+
if (report.runtime?.profileId !== baseline.runtime?.profileId || report.runtime?.profileVersion !== baseline.runtime?.profileVersion) reasons.push('profile_changed');
|
|
140
|
+
if (JSON.stringify(report.runtime) !== JSON.stringify(baseline.runtime)) reasons.push('runtime_identity_changed');
|
|
141
|
+
if (report.source?.repositoryIdentity !== baseline.source?.repositoryIdentity) reasons.push('source_identity_changed');
|
|
142
|
+
const current = new Set(report.findings.map((finding) => finding.fingerprint));
|
|
143
|
+
const prior = new Set(baseline.findings.map((finding) => finding.fingerprint));
|
|
144
|
+
comparison = {
|
|
145
|
+
baselineRunId: baseline.runId,
|
|
146
|
+
currentRunId: report.runId,
|
|
147
|
+
comparable: reasons.length === 0,
|
|
148
|
+
unverifiedReasons: [...new Set(reasons)],
|
|
149
|
+
fixedFindingFingerprints: [...prior].filter((id) => !current.has(id)).sort(),
|
|
150
|
+
newFindingFingerprints: [...current].filter((id) => !prior.has(id)).sort(),
|
|
151
|
+
persistentFindingFingerprints: [...current].filter((id) => prior.has(id)).sort(),
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
return { rules, credits, comparison };
|
|
155
|
+
},
|
|
156
|
+
}`};\n`;
|
|
157
|
+
return { source, manifest, evaluatorDigest, catalogDigest };
|
|
158
|
+
}
|