@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,641 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildChildEnvironment = buildChildEnvironment;
|
|
4
|
+
exports.validateHermesManifest = validateHermesManifest;
|
|
5
|
+
exports.resolveHermesCommand = resolveHermesCommand;
|
|
6
|
+
exports.installHermes = installHermes;
|
|
7
|
+
const node_crypto_1 = require("node:crypto");
|
|
8
|
+
const node_child_process_1 = require("node:child_process");
|
|
9
|
+
const node_fs_1 = require("node:fs");
|
|
10
|
+
const node_os_1 = require("node:os");
|
|
11
|
+
const node_path_1 = require("node:path");
|
|
12
|
+
const OFFICIAL_INSTALLER_PATHS = {
|
|
13
|
+
windows: 'scripts/install.ps1',
|
|
14
|
+
posix: 'scripts/install.sh',
|
|
15
|
+
};
|
|
16
|
+
const OFFICIAL_HERMES_REPOSITORY = 'https://github.com/NousResearch/hermes-agent.git';
|
|
17
|
+
const USER_MEMORY_LIMIT = 1_375;
|
|
18
|
+
const AGENT_MEMORY_LIMIT = 2_200;
|
|
19
|
+
const PROJECT_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9-]{0,127}$/;
|
|
20
|
+
const PROFILE_PATTERN = /^[a-z][a-z0-9_-]{0,62}$/;
|
|
21
|
+
const SHA256_PATTERN = /^[a-f0-9]{64}$/;
|
|
22
|
+
const COMMIT_PATTERN = /^[a-f0-9]{40}$/;
|
|
23
|
+
const REQUIRED_DISTRIBUTION_FILES = new Set(['distribution.yaml', 'SOUL.md', 'config.yaml', 'README.md']);
|
|
24
|
+
const SECRET_PATTERNS = [
|
|
25
|
+
{ label: 'private key', pattern: /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/ },
|
|
26
|
+
{ label: 'provider token', pattern: /\b(?:sk|ghp|github_pat|xox[baprs])-[-A-Za-z0-9_]{16,}\b/ },
|
|
27
|
+
{
|
|
28
|
+
label: 'credential assignment',
|
|
29
|
+
pattern: /\b(?:api[_-]?key|access[_-]?token|password|client[_-]?secret)\s*[:=]\s*["']?(?!redacted\b|placeholder\b|your[_-])[A-Za-z0-9_./+=-]{12,}/i,
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
function buildChildEnvironment(base, overlay = {}, unset = [], platform = process.platform) {
|
|
33
|
+
const childEnv = { ...base, ...overlay };
|
|
34
|
+
const removed = new Set(unset.map((key) => platform === 'win32' ? key.toUpperCase() : key));
|
|
35
|
+
for (const key of Object.keys(childEnv)) {
|
|
36
|
+
if (removed.has(platform === 'win32' ? key.toUpperCase() : key))
|
|
37
|
+
delete childEnv[key];
|
|
38
|
+
}
|
|
39
|
+
return childEnv;
|
|
40
|
+
}
|
|
41
|
+
const defaultRuntime = {
|
|
42
|
+
platform: process.platform,
|
|
43
|
+
arch: process.arch,
|
|
44
|
+
homeDir: (0, node_os_1.homedir)(),
|
|
45
|
+
localAppData: process.env.LOCALAPPDATA,
|
|
46
|
+
tempDir: (0, node_os_1.tmpdir)(),
|
|
47
|
+
now: () => new Date(),
|
|
48
|
+
log: (message) => console.log(message),
|
|
49
|
+
async download(url) {
|
|
50
|
+
const response = await fetch(url, { redirect: 'error' });
|
|
51
|
+
if (!response.ok)
|
|
52
|
+
throw new Error(`Official Hermes installer download failed (HTTP ${response.status}).`);
|
|
53
|
+
return Buffer.from(await response.arrayBuffer());
|
|
54
|
+
},
|
|
55
|
+
run(command, args, options) {
|
|
56
|
+
const childEnv = buildChildEnvironment(process.env, options?.env, options?.unsetEnv);
|
|
57
|
+
const result = (0, node_child_process_1.spawnSync)(command, args, {
|
|
58
|
+
stdio: options?.quiet ? ['ignore', 'pipe', 'pipe'] : 'inherit',
|
|
59
|
+
shell: false,
|
|
60
|
+
env: childEnv,
|
|
61
|
+
encoding: 'utf8',
|
|
62
|
+
timeout: options?.timeoutMs,
|
|
63
|
+
});
|
|
64
|
+
return {
|
|
65
|
+
status: result.status,
|
|
66
|
+
error: result.error,
|
|
67
|
+
stdout: typeof result.stdout === 'string' ? result.stdout : undefined,
|
|
68
|
+
stderr: typeof result.stderr === 'string' ? result.stderr : undefined,
|
|
69
|
+
};
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
function assertPlainObject(value, label) {
|
|
73
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
74
|
+
throw new Error(`${label} must be an object.`);
|
|
75
|
+
}
|
|
76
|
+
function parseJsonWithOptionalBom(value, label) {
|
|
77
|
+
try {
|
|
78
|
+
return JSON.parse(value.startsWith('\uFEFF') ? value.slice(1) : value);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
throw new Error(`${label} is not valid JSON: ${error.message}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function assertDate(value, label) {
|
|
85
|
+
if (typeof value !== 'string' || !value || Number.isNaN(Date.parse(value)))
|
|
86
|
+
throw new Error(`${label} must be an ISO date.`);
|
|
87
|
+
}
|
|
88
|
+
function characterCount(value) {
|
|
89
|
+
return Array.from(value).length;
|
|
90
|
+
}
|
|
91
|
+
function assertNoSecret(content, filePath) {
|
|
92
|
+
for (const candidate of SECRET_PATTERNS) {
|
|
93
|
+
if (candidate.pattern.test(content)) {
|
|
94
|
+
throw new Error(`Hermes manifest ${filePath} appears to contain a ${candidate.label}. Enter credentials only in official Hermes setup.`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function safeDistributionPath(filePath) {
|
|
99
|
+
const normalized = filePath.replace(/\\/g, '/').replace(/^\.\//, '');
|
|
100
|
+
if (!normalized || (0, node_path_1.isAbsolute)(filePath) || normalized.split('/').some((part) => !part || part === '..' || part === '.')) {
|
|
101
|
+
throw new Error(`Unsafe Hermes distribution path: ${filePath}`);
|
|
102
|
+
}
|
|
103
|
+
if (REQUIRED_DISTRIBUTION_FILES.has(normalized))
|
|
104
|
+
return normalized;
|
|
105
|
+
if (/^skills\/[a-z0-9][a-z0-9-]{0,62}\/SKILL\.md$/.test(normalized))
|
|
106
|
+
return normalized;
|
|
107
|
+
throw new Error(`Hermes distribution path is not allowed: ${filePath}`);
|
|
108
|
+
}
|
|
109
|
+
function safeSeedPath(filePath) {
|
|
110
|
+
if (filePath !== 'memories/USER.md' && filePath !== 'memories/MEMORY.md') {
|
|
111
|
+
throw new Error(`Hermes seed path is not allowed: ${filePath}`);
|
|
112
|
+
}
|
|
113
|
+
return filePath;
|
|
114
|
+
}
|
|
115
|
+
function validateHermesManifest(manifest) {
|
|
116
|
+
assertPlainObject(manifest, 'Hermes manifest');
|
|
117
|
+
if (manifest.schemaVersion !== 2)
|
|
118
|
+
throw new Error('Unsupported agent installer manifest. Update the Lattice CLI and try again.');
|
|
119
|
+
assertPlainObject(manifest.project, 'Hermes project');
|
|
120
|
+
if (!PROJECT_ID_PATTERN.test(manifest.project.id || ''))
|
|
121
|
+
throw new Error('Hermes installer manifest has an invalid project ID.');
|
|
122
|
+
if (typeof manifest.project.name !== 'string' || !manifest.project.name.trim())
|
|
123
|
+
throw new Error('Hermes installer manifest has an invalid project name.');
|
|
124
|
+
assertDate(manifest.project.createdAt, 'Hermes project createdAt');
|
|
125
|
+
assertPlainObject(manifest.install, 'Hermes install payload');
|
|
126
|
+
if (manifest.install.productType !== 'agent_setup' || manifest.install.runtime !== 'hermes') {
|
|
127
|
+
throw new Error('This project is not a Hermes agent setup. Use `lattice agent install --id <project-id>` to select its runtime automatically.');
|
|
128
|
+
}
|
|
129
|
+
assertPlainObject(manifest.install.release, 'Hermes release pin');
|
|
130
|
+
const release = manifest.install.release;
|
|
131
|
+
if (typeof release.tag !== 'string' || !/^v?[A-Za-z0-9][A-Za-z0-9.+-]{0,63}$/.test(release.tag))
|
|
132
|
+
throw new Error('Hermes release tag is invalid.');
|
|
133
|
+
if (release.packageVersion !== null && (typeof release.packageVersion !== 'string' || !/^\d+\.\d+\.\d+(?:[-+][A-Za-z0-9.-]+)?$/.test(release.packageVersion))) {
|
|
134
|
+
throw new Error('Hermes package version is invalid.');
|
|
135
|
+
}
|
|
136
|
+
if (!COMMIT_PATTERN.test(release.commitSha))
|
|
137
|
+
throw new Error('Hermes release commit must be a full lowercase SHA.');
|
|
138
|
+
assertDate(release.publishedAt, 'Hermes release publishedAt');
|
|
139
|
+
assertDate(release.reviewedAt, 'Hermes release reviewedAt');
|
|
140
|
+
assertPlainObject(release.installScriptSha256, 'Hermes installer hashes');
|
|
141
|
+
if (!SHA256_PATTERN.test(release.installScriptSha256.windows) || !SHA256_PATTERN.test(release.installScriptSha256.posix)) {
|
|
142
|
+
throw new Error('Hermes installer hashes must be lowercase SHA-256 values.');
|
|
143
|
+
}
|
|
144
|
+
if (!PROFILE_PATTERN.test(manifest.install.profileName) || manifest.install.profileName === 'default') {
|
|
145
|
+
throw new Error('Hermes profile name must start with a lowercase letter, contain only lowercase letters, numbers, hyphens, or underscores, and cannot be "default".');
|
|
146
|
+
}
|
|
147
|
+
assertPlainObject(manifest.install.distributionFiles, 'Hermes distribution files');
|
|
148
|
+
for (const required of ['distribution.yaml', 'SOUL.md', 'config.yaml', 'README.md']) {
|
|
149
|
+
if (typeof manifest.install.distributionFiles[required] !== 'string')
|
|
150
|
+
throw new Error(`Hermes manifest is missing ${required}.`);
|
|
151
|
+
}
|
|
152
|
+
for (const [filePath, content] of Object.entries(manifest.install.distributionFiles)) {
|
|
153
|
+
safeDistributionPath(filePath);
|
|
154
|
+
if (typeof content !== 'string')
|
|
155
|
+
throw new Error(`Hermes distribution file is not text: ${filePath}`);
|
|
156
|
+
assertNoSecret(content, filePath);
|
|
157
|
+
}
|
|
158
|
+
assertPlainObject(manifest.install.localSeedFiles, 'Hermes local seed files');
|
|
159
|
+
for (const [filePath, content] of Object.entries(manifest.install.localSeedFiles)) {
|
|
160
|
+
safeSeedPath(filePath);
|
|
161
|
+
if (typeof content !== 'string')
|
|
162
|
+
throw new Error(`Hermes seed file is not text: ${filePath}`);
|
|
163
|
+
const limit = filePath === 'memories/USER.md' ? USER_MEMORY_LIMIT : AGENT_MEMORY_LIMIT;
|
|
164
|
+
if (characterCount(content) > limit)
|
|
165
|
+
throw new Error(`${filePath} exceeds Hermes' ${limit.toLocaleString('en-US')}-character limit.`);
|
|
166
|
+
assertNoSecret(content, filePath);
|
|
167
|
+
}
|
|
168
|
+
if (!Array.isArray(manifest.install.selectedChannels) || manifest.install.selectedChannels.some((item) => typeof item !== 'string' || !/^[a-z0-9_-]{1,40}$/.test(item))) {
|
|
169
|
+
throw new Error('Hermes selected channels are invalid.');
|
|
170
|
+
}
|
|
171
|
+
if (!['portal', 'byok', 'local', 'during_setup'].includes(manifest.install.providerSetup))
|
|
172
|
+
throw new Error('Hermes provider setup choice is invalid.');
|
|
173
|
+
if (!['local', 'docker', 'ssh', 'during_setup'].includes(manifest.install.terminalBackend))
|
|
174
|
+
throw new Error('Hermes terminal backend is invalid.');
|
|
175
|
+
if (typeof manifest.install.requestedGatewaySetup !== 'boolean')
|
|
176
|
+
throw new Error('Hermes gateway setup choice is invalid.');
|
|
177
|
+
}
|
|
178
|
+
function assertSupportedPlatform(runtime) {
|
|
179
|
+
if (!['win32', 'darwin', 'linux'].includes(runtime.platform)) {
|
|
180
|
+
throw new Error(`Hermes installation is not supported on ${runtime.platform}/${runtime.arch}. Use Windows 10/11, macOS, Linux, or WSL2.`);
|
|
181
|
+
}
|
|
182
|
+
if (!['x64', 'arm64'].includes(runtime.arch)) {
|
|
183
|
+
throw new Error(`Hermes installation is not supported on ${runtime.platform}/${runtime.arch}. Use an x64 or arm64 machine.`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function resolveInside(root, relativePath) {
|
|
187
|
+
const target = (0, node_path_1.resolve)(root, relativePath);
|
|
188
|
+
const rel = (0, node_path_1.relative)((0, node_path_1.resolve)(root), target);
|
|
189
|
+
if (rel.startsWith('..') || (0, node_path_1.isAbsolute)(rel))
|
|
190
|
+
throw new Error(`Path escapes the managed directory: ${relativePath}`);
|
|
191
|
+
return target;
|
|
192
|
+
}
|
|
193
|
+
async function pathExists(filePath) {
|
|
194
|
+
try {
|
|
195
|
+
await node_fs_1.promises.lstat(filePath);
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
if (error.code === 'ENOENT')
|
|
200
|
+
return false;
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
async function assertNoSymlinkPath(root, relativePath) {
|
|
205
|
+
let current = (0, node_path_1.resolve)(root);
|
|
206
|
+
for (const part of relativePath.replace(/\\/g, '/').split('/')) {
|
|
207
|
+
current = (0, node_path_1.join)(current, part);
|
|
208
|
+
try {
|
|
209
|
+
if ((await node_fs_1.promises.lstat(current)).isSymbolicLink())
|
|
210
|
+
throw new Error(`Refusing to write through symbolic link: ${current}`);
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
if (error.code === 'ENOENT')
|
|
214
|
+
return;
|
|
215
|
+
throw error;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
async function assertManagedPathHasNoSymlinks(root, target) {
|
|
220
|
+
const resolvedRoot = (0, node_path_1.resolve)(root);
|
|
221
|
+
const resolvedTarget = (0, node_path_1.resolve)(target);
|
|
222
|
+
const relativeTarget = (0, node_path_1.relative)(resolvedRoot, resolvedTarget);
|
|
223
|
+
if (relativeTarget.startsWith('..') || (0, node_path_1.isAbsolute)(relativeTarget)) {
|
|
224
|
+
throw new Error(`Managed target escapes its root: ${target}`);
|
|
225
|
+
}
|
|
226
|
+
try {
|
|
227
|
+
if ((await node_fs_1.promises.lstat(resolvedRoot)).isSymbolicLink()) {
|
|
228
|
+
throw new Error(`Refusing to use symbolic-link root: ${resolvedRoot}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
if (error.code !== 'ENOENT')
|
|
233
|
+
throw error;
|
|
234
|
+
}
|
|
235
|
+
await assertNoSymlinkPath(resolvedRoot, relativeTarget);
|
|
236
|
+
}
|
|
237
|
+
async function atomicWrite(filePath, content, mode = 0o600) {
|
|
238
|
+
await node_fs_1.promises.mkdir((0, node_path_1.dirname)(filePath), { recursive: true, mode: 0o700 });
|
|
239
|
+
const temporary = `${filePath}.lattice-${process.pid}-${Date.now()}.tmp`;
|
|
240
|
+
await node_fs_1.promises.writeFile(temporary, content, { mode });
|
|
241
|
+
await node_fs_1.promises.rename(temporary, filePath);
|
|
242
|
+
}
|
|
243
|
+
async function writeExclusive(filePath, content, mode = 0o600) {
|
|
244
|
+
await node_fs_1.promises.mkdir((0, node_path_1.dirname)(filePath), { recursive: true, mode: 0o700 });
|
|
245
|
+
const handle = await node_fs_1.promises.open(filePath, 'wx', mode);
|
|
246
|
+
try {
|
|
247
|
+
await handle.writeFile(content);
|
|
248
|
+
await handle.sync();
|
|
249
|
+
}
|
|
250
|
+
finally {
|
|
251
|
+
await handle.close();
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
async function snapshotFiles(root, paths, backupRoot) {
|
|
255
|
+
const existed = new Map();
|
|
256
|
+
for (const filePath of paths) {
|
|
257
|
+
await assertNoSymlinkPath(root, filePath);
|
|
258
|
+
const target = resolveInside(root, filePath);
|
|
259
|
+
const exists = await pathExists(target);
|
|
260
|
+
existed.set(filePath, exists);
|
|
261
|
+
if (exists) {
|
|
262
|
+
const backup = resolveInside(backupRoot, filePath);
|
|
263
|
+
await node_fs_1.promises.mkdir((0, node_path_1.dirname)(backup), { recursive: true, mode: 0o700 });
|
|
264
|
+
await node_fs_1.promises.copyFile(target, backup);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return { root, backupRoot, existed };
|
|
268
|
+
}
|
|
269
|
+
async function restoreSnapshot(snapshot) {
|
|
270
|
+
for (const [filePath, existed] of [...snapshot.existed.entries()].reverse()) {
|
|
271
|
+
const target = resolveInside(snapshot.root, filePath);
|
|
272
|
+
if (existed) {
|
|
273
|
+
await node_fs_1.promises.mkdir((0, node_path_1.dirname)(target), { recursive: true, mode: 0o700 });
|
|
274
|
+
await node_fs_1.promises.copyFile(resolveInside(snapshot.backupRoot, filePath), target);
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
await node_fs_1.promises.rm(target, { force: true });
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
function sanitizeCommandDiagnostic(value) {
|
|
282
|
+
return String(value || '')
|
|
283
|
+
.replace(/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g, '[redacted private key]')
|
|
284
|
+
.replace(/\b(Bearer\s+)[^\s]+/gi, '$1[redacted]')
|
|
285
|
+
.replace(/\b((?:api[_-]?key|access[_-]?token|password|client[_-]?secret|authorization)\s*[:=]\s*)["']?[^\s"']+/gi, '$1[redacted]')
|
|
286
|
+
.replace(/\b(?:sk|ghp|github_pat|xox[baprs])-[-A-Za-z0-9_]{12,}\b/g, '[redacted token]')
|
|
287
|
+
.trim()
|
|
288
|
+
.slice(-2_000);
|
|
289
|
+
}
|
|
290
|
+
function requireSuccess(runtime, command, args, label, quiet = false, env, controls) {
|
|
291
|
+
const result = runtime.run(command, args, { quiet, env, ...controls });
|
|
292
|
+
if (result.status !== 0) {
|
|
293
|
+
const detail = sanitizeCommandDiagnostic([result.error?.message, result.stderr].filter(Boolean).join('\n'));
|
|
294
|
+
const status = result.status === null ? '' : ` (exit ${result.status})`;
|
|
295
|
+
throw new Error(`${label} failed${status}${detail ? `: ${detail}` : ''}.`);
|
|
296
|
+
}
|
|
297
|
+
return { stdout: result.stdout, stderr: result.stderr };
|
|
298
|
+
}
|
|
299
|
+
function hermesVersionsFromOfficialHeaders(value) {
|
|
300
|
+
const versions = [];
|
|
301
|
+
for (const line of String(value || '').split(/\r?\n/)) {
|
|
302
|
+
const match = line.match(/^Hermes Agent v(\d+\.\d+\.\d+(?:[-+][A-Za-z0-9.-]+)?)(?=$|[\s(·])/);
|
|
303
|
+
if (match)
|
|
304
|
+
versions.push(match[1]);
|
|
305
|
+
}
|
|
306
|
+
return versions;
|
|
307
|
+
}
|
|
308
|
+
function formatHermesVersionStream(label, value) {
|
|
309
|
+
const detail = sanitizeCommandDiagnostic(value);
|
|
310
|
+
return `${label}: ${detail || '(empty)'}`;
|
|
311
|
+
}
|
|
312
|
+
async function resolveInstalledHermesGit(hermesHome, platform) {
|
|
313
|
+
if (platform !== 'win32')
|
|
314
|
+
return 'git';
|
|
315
|
+
const toolsDirectory = (0, node_path_1.join)(hermesHome, 'tools');
|
|
316
|
+
try {
|
|
317
|
+
const facts = parseJsonWithOptionalBom(await node_fs_1.promises.readFile((0, node_path_1.join)(toolsDirectory, 'facts.json'), 'utf8'), 'Hermes tool facts');
|
|
318
|
+
assertPlainObject(facts, 'Hermes tool facts');
|
|
319
|
+
assertPlainObject(facts.packages, 'Hermes tool packages');
|
|
320
|
+
const git = facts.packages.git;
|
|
321
|
+
if (git && typeof git === 'object' && !Array.isArray(git)) {
|
|
322
|
+
const entry = git.entry;
|
|
323
|
+
if (typeof entry === 'string' && entry) {
|
|
324
|
+
const managedGit = resolveInside(toolsDirectory, (0, node_path_1.join)(entry, 'cmd', 'git.exe'));
|
|
325
|
+
await assertManagedPathHasNoSymlinks(hermesHome, managedGit);
|
|
326
|
+
await node_fs_1.promises.access(managedGit, node_fs_1.constants.X_OK);
|
|
327
|
+
return managedGit;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
catch (error) {
|
|
332
|
+
if (error.code !== 'ENOENT') {
|
|
333
|
+
throw new Error(`Hermes installed Git metadata is invalid: ${error.message}`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return 'git';
|
|
337
|
+
}
|
|
338
|
+
async function resolveVerifiedHermesCommand(hermesHome, platform) {
|
|
339
|
+
const installDirectory = (0, node_path_1.join)(hermesHome, 'hermes-agent');
|
|
340
|
+
const managedCommand = (0, node_path_1.join)(installDirectory, '.hermes', 'bin', platform === 'win32' ? 'hermes.exe' : 'hermes');
|
|
341
|
+
await assertManagedPathHasNoSymlinks(installDirectory, managedCommand);
|
|
342
|
+
try {
|
|
343
|
+
const entry = await node_fs_1.promises.lstat(managedCommand);
|
|
344
|
+
if (!entry.isFile())
|
|
345
|
+
throw new Error(`Managed Hermes launcher is not a regular file: ${managedCommand}.`);
|
|
346
|
+
await node_fs_1.promises.access(managedCommand, node_fs_1.constants.X_OK);
|
|
347
|
+
return managedCommand;
|
|
348
|
+
}
|
|
349
|
+
catch (error) {
|
|
350
|
+
if (error.code === 'ENOENT') {
|
|
351
|
+
throw new Error(`Official Hermes installation did not publish its managed launcher: ${managedCommand}.`);
|
|
352
|
+
}
|
|
353
|
+
throw error;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
const GIT_PROVENANCE_ENV_KEYS = ['GIT_DIR', 'GIT_WORK_TREE', 'GIT_INDEX_FILE'];
|
|
357
|
+
const GIT_METADATA_TIMEOUT_MS = 15_000;
|
|
358
|
+
const GIT_FETCH_TIMEOUT_MS = 90_000;
|
|
359
|
+
// A fresh managed Python environment can take longer to initialize on native CI.
|
|
360
|
+
const HERMES_VERSION_TIMEOUT_MS = 60_000;
|
|
361
|
+
function requireExactGitOutput(runtime, gitCommand, installDirectory, args, expected, label, env) {
|
|
362
|
+
const output = requireSuccess(runtime, gitCommand, ['-C', installDirectory, ...args], label, true, { ...env, GIT_TERMINAL_PROMPT: '0' }, { timeoutMs: GIT_METADATA_TIMEOUT_MS, unsetEnv: [...GIT_PROVENANCE_ENV_KEYS] });
|
|
363
|
+
const observed = String(output.stdout || '').trim().toLowerCase();
|
|
364
|
+
if (observed !== expected.toLowerCase()) {
|
|
365
|
+
throw new Error(`${label} returned ${sanitizeCommandDiagnostic(observed) || '(empty)'}; expected ${expected}.`);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
async function reconcileInstalledHermesRelease(release, hermesHome, setupRoot, backupDirectory, runtime, env) {
|
|
369
|
+
const installDirectory = (0, node_path_1.join)(hermesHome, 'hermes-agent');
|
|
370
|
+
await assertManagedPathHasNoSymlinks(hermesHome, installDirectory);
|
|
371
|
+
await assertNoSymlinkPath(installDirectory, 'install-stamp.json');
|
|
372
|
+
const gitCommand = await resolveInstalledHermesGit(hermesHome, runtime.platform);
|
|
373
|
+
const pinnedCommit = release.commitSha.toLowerCase();
|
|
374
|
+
requireExactGitOutput(runtime, gitCommand, installDirectory, ['rev-parse', '--verify', 'HEAD^{commit}'], pinnedCommit, 'Hermes checkout verification', env);
|
|
375
|
+
const gitEnv = { ...env, GIT_TERMINAL_PROMPT: '0' };
|
|
376
|
+
const metadataControls = { timeoutMs: GIT_METADATA_TIMEOUT_MS, unsetEnv: [...GIT_PROVENANCE_ENV_KEYS] };
|
|
377
|
+
requireSuccess(runtime, gitCommand, ['-C', installDirectory, 'diff', '--quiet', '--no-ext-diff', 'HEAD', '--'], 'Hermes tracked-source verification', true, gitEnv, metadataControls);
|
|
378
|
+
requireSuccess(runtime, gitCommand, ['-C', installDirectory, 'diff', '--cached', '--quiet', '--no-ext-diff', '--'], 'Hermes staged-source verification', true, gitEnv, metadataControls);
|
|
379
|
+
requireSuccess(runtime, gitCommand, [
|
|
380
|
+
'-C', installDirectory, 'fetch', '--no-tags', OFFICIAL_HERMES_REPOSITORY,
|
|
381
|
+
`refs/tags/${release.tag}:refs/tags/${release.tag}`,
|
|
382
|
+
], 'Official Hermes release tag fetch', true, gitEnv, {
|
|
383
|
+
timeoutMs: GIT_FETCH_TIMEOUT_MS,
|
|
384
|
+
unsetEnv: [...GIT_PROVENANCE_ENV_KEYS],
|
|
385
|
+
});
|
|
386
|
+
requireExactGitOutput(runtime, gitCommand, installDirectory, ['rev-parse', '--verify', `refs/tags/${release.tag}^{commit}`], pinnedCommit, 'Hermes release tag verification', env);
|
|
387
|
+
requireExactGitOutput(runtime, gitCommand, installDirectory, ['rev-parse', '--verify', 'HEAD^{commit}'], pinnedCommit, 'Hermes checkout re-verification', env);
|
|
388
|
+
const stampPath = (0, node_path_1.join)(installDirectory, 'install-stamp.json');
|
|
389
|
+
let stamp;
|
|
390
|
+
let stampBytes;
|
|
391
|
+
try {
|
|
392
|
+
stampBytes = await node_fs_1.promises.readFile(stampPath);
|
|
393
|
+
const parsed = parseJsonWithOptionalBom(stampBytes.toString('utf8'), 'Hermes install stamp');
|
|
394
|
+
assertPlainObject(parsed, 'Hermes install stamp');
|
|
395
|
+
stamp = parsed;
|
|
396
|
+
}
|
|
397
|
+
catch (error) {
|
|
398
|
+
if (error.code === 'ENOENT')
|
|
399
|
+
return null;
|
|
400
|
+
throw new Error(`Hermes install stamp is invalid: ${error.message}`);
|
|
401
|
+
}
|
|
402
|
+
if (String(stamp.commit || '').toLowerCase() !== pinnedCommit || stamp.source !== 'git' || stamp.updateMechanism !== 'self') {
|
|
403
|
+
throw new Error('Hermes install stamp does not describe the verified source checkout.');
|
|
404
|
+
}
|
|
405
|
+
if (stamp.schemaVersion !== 2 || stamp.payload !== 'bootstrap' || stamp.distribution !== null || stamp.tag !== null) {
|
|
406
|
+
throw new Error('Hermes install stamp is not a recognized source-generated identity.');
|
|
407
|
+
}
|
|
408
|
+
if (release.packageVersion && (stamp.baseVersion !== release.packageVersion
|
|
409
|
+
|| stamp.displayVersion !== release.packageVersion
|
|
410
|
+
|| stamp.distance !== 0)) {
|
|
411
|
+
const backupPath = (0, node_path_1.join)(backupDirectory, 'runtime-identity', 'install-stamp.json');
|
|
412
|
+
await assertManagedPathHasNoSymlinks(setupRoot, backupPath);
|
|
413
|
+
await writeExclusive(backupPath, stampBytes);
|
|
414
|
+
await node_fs_1.promises.rm(stampPath);
|
|
415
|
+
runtime.log(`Reconciled Hermes ${release.tag} source identity from its verified official tag.`);
|
|
416
|
+
return backupPath;
|
|
417
|
+
}
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
420
|
+
async function resolveHermesCommand(hermesHome, platform, explicitCommand) {
|
|
421
|
+
if (explicitCommand)
|
|
422
|
+
return explicitCommand;
|
|
423
|
+
const installDirectory = (0, node_path_1.join)(hermesHome, 'hermes-agent');
|
|
424
|
+
const candidates = platform === 'win32'
|
|
425
|
+
? [
|
|
426
|
+
(0, node_path_1.join)(installDirectory, '.hermes', 'bin', 'hermes.exe'),
|
|
427
|
+
(0, node_path_1.join)(hermesHome, 'bin', 'hermes.exe'),
|
|
428
|
+
(0, node_path_1.join)(installDirectory, 'venv', 'Scripts', 'hermes.exe'),
|
|
429
|
+
]
|
|
430
|
+
: [
|
|
431
|
+
(0, node_path_1.join)(installDirectory, '.hermes', 'bin', 'hermes'),
|
|
432
|
+
(0, node_path_1.join)(hermesHome, 'bin', 'hermes'),
|
|
433
|
+
(0, node_path_1.join)(installDirectory, 'venv', 'bin', 'hermes'),
|
|
434
|
+
];
|
|
435
|
+
for (const candidate of candidates) {
|
|
436
|
+
try {
|
|
437
|
+
await node_fs_1.promises.access(candidate, node_fs_1.constants.X_OK);
|
|
438
|
+
return candidate;
|
|
439
|
+
}
|
|
440
|
+
catch {
|
|
441
|
+
// Continue through the bounded official managed and legacy layouts.
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
throw new Error(`Hermes command was not published under the requested Hermes home: ${hermesHome}.`);
|
|
445
|
+
}
|
|
446
|
+
function buildResumeCommand(projectId, profileName) {
|
|
447
|
+
return `npx --yes latticeai@latest hermes install --id ${projectId} --profile-name ${profileName} --update-existing-profile`;
|
|
448
|
+
}
|
|
449
|
+
function sanitizeFailureStage(value) {
|
|
450
|
+
return value.replace(/[^a-z0-9_-]/gi, '-').slice(0, 80);
|
|
451
|
+
}
|
|
452
|
+
async function installHermes(manifest, options = {}, runtime = defaultRuntime) {
|
|
453
|
+
validateHermesManifest(manifest);
|
|
454
|
+
assertSupportedPlatform(runtime);
|
|
455
|
+
if (!options.dryRun && !options.skipHermesInstall && options.hermesCommand) {
|
|
456
|
+
throw new Error('An explicit Hermes command requires --skip-hermes-install; a managed official install must verify its own launcher.');
|
|
457
|
+
}
|
|
458
|
+
const profileName = options.profileName || manifest.install.profileName;
|
|
459
|
+
if (!PROFILE_PATTERN.test(profileName) || profileName === 'default')
|
|
460
|
+
throw new Error(`Unsafe Hermes profile name: ${profileName}`);
|
|
461
|
+
const hermesHome = (0, node_path_1.resolve)(options.hermesHome || process.env.HERMES_HOME || (runtime.platform === 'win32'
|
|
462
|
+
? (0, node_path_1.join)(runtime.localAppData || (0, node_path_1.join)(runtime.homeDir, 'AppData', 'Local'), 'hermes')
|
|
463
|
+
: (0, node_path_1.join)(runtime.homeDir, '.hermes')));
|
|
464
|
+
const hermesEnv = { HERMES_HOME: hermesHome };
|
|
465
|
+
const setupRoot = (0, node_path_1.resolve)(runtime.homeDir, '.lattice', 'agent-setups', manifest.project.id);
|
|
466
|
+
const distributionDirectory = (0, node_path_1.join)(setupRoot, 'hermes-distribution');
|
|
467
|
+
const profileDirectory = (0, node_path_1.join)(hermesHome, 'profiles', profileName);
|
|
468
|
+
const timestamp = runtime.now().toISOString().replace(/[:.]/g, '-');
|
|
469
|
+
const backupDirectory = (0, node_path_1.join)(setupRoot, 'backups', timestamp);
|
|
470
|
+
const distributionFiles = Object.keys(manifest.install.distributionFiles).map(safeDistributionPath).sort();
|
|
471
|
+
const seedFiles = Object.keys(manifest.install.localSeedFiles).map(safeSeedPath).sort();
|
|
472
|
+
const resumeCommand = buildResumeCommand(manifest.project.id, profileName);
|
|
473
|
+
const receiptPath = (0, node_path_1.join)(setupRoot, 'receipt.json');
|
|
474
|
+
const receipt = {
|
|
475
|
+
schemaVersion: 1,
|
|
476
|
+
projectId: manifest.project.id,
|
|
477
|
+
runtime: 'hermes',
|
|
478
|
+
stage: options.dryRun ? 'planned' : 'installed',
|
|
479
|
+
release: {
|
|
480
|
+
tag: manifest.install.release.tag,
|
|
481
|
+
packageVersion: manifest.install.release.packageVersion,
|
|
482
|
+
commitSha: manifest.install.release.commitSha,
|
|
483
|
+
},
|
|
484
|
+
profileName,
|
|
485
|
+
distributionDirectory,
|
|
486
|
+
profileDirectory,
|
|
487
|
+
backupDirectory: options.dryRun ? null : backupDirectory,
|
|
488
|
+
runtimeIdentityBackup: null,
|
|
489
|
+
filesApplied: distributionFiles,
|
|
490
|
+
seedFilesApplied: seedFiles,
|
|
491
|
+
selectedChannels: [...manifest.install.selectedChannels],
|
|
492
|
+
dryRun: !!options.dryRun,
|
|
493
|
+
setupRequired: !!options.skipSetup,
|
|
494
|
+
modelCheckRequired: !!options.skipSetup || !!options.skipModelCheck,
|
|
495
|
+
gatewaySetupRequired: manifest.install.requestedGatewaySetup && (!!options.skipSetup || !!options.skipModelCheck || !!options.skipGatewaySetup),
|
|
496
|
+
resumeCommand,
|
|
497
|
+
completedAt: null,
|
|
498
|
+
};
|
|
499
|
+
if (options.dryRun) {
|
|
500
|
+
runtime.log(`Dry run: would install Hermes ${manifest.install.release.tag}, create profile ${profileName}, write ${distributionFiles.length} distribution files and ${seedFiles.length} local seed files.`);
|
|
501
|
+
return receipt;
|
|
502
|
+
}
|
|
503
|
+
await node_fs_1.promises.mkdir(setupRoot, { recursive: true, mode: 0o700 });
|
|
504
|
+
await atomicWrite(receiptPath, JSON.stringify(receipt, null, 2) + '\n');
|
|
505
|
+
const snapshots = [];
|
|
506
|
+
let failedStage = 'runtime-install';
|
|
507
|
+
let temporaryScript;
|
|
508
|
+
let verifiedHermesCommand;
|
|
509
|
+
try {
|
|
510
|
+
if (!options.skipHermesInstall) {
|
|
511
|
+
const isWindows = runtime.platform === 'win32';
|
|
512
|
+
const installerPath = isWindows ? OFFICIAL_INSTALLER_PATHS.windows : OFFICIAL_INSTALLER_PATHS.posix;
|
|
513
|
+
const url = `https://raw.githubusercontent.com/NousResearch/hermes-agent/${manifest.install.release.commitSha}/${installerPath}`;
|
|
514
|
+
const expectedHash = isWindows
|
|
515
|
+
? manifest.install.release.installScriptSha256.windows
|
|
516
|
+
: manifest.install.release.installScriptSha256.posix;
|
|
517
|
+
const installer = await runtime.download(url);
|
|
518
|
+
const actualHash = (0, node_crypto_1.createHash)('sha256').update(installer).digest('hex');
|
|
519
|
+
if (actualHash !== expectedHash)
|
|
520
|
+
throw new Error(`Hermes installer integrity check failed. Expected ${expectedHash}, received ${actualHash}. The script was not executed.`);
|
|
521
|
+
const scriptDirectory = (0, node_path_1.join)(runtime.tempDir, `lattice-hermes-${manifest.project.id}-${timestamp}`);
|
|
522
|
+
temporaryScript = (0, node_path_1.join)(scriptDirectory, isWindows ? 'install.ps1' : 'install.sh');
|
|
523
|
+
await atomicWrite(temporaryScript, installer, isWindows ? 0o600 : 0o700);
|
|
524
|
+
if (isWindows) {
|
|
525
|
+
requireSuccess(runtime, 'powershell.exe', [
|
|
526
|
+
'-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', temporaryScript,
|
|
527
|
+
'-Commit', manifest.install.release.commitSha, '-NonInteractive', '-SkipSetup',
|
|
528
|
+
'-HermesHome', hermesHome, '-InstallDir', (0, node_path_1.join)(hermesHome, 'hermes-agent'),
|
|
529
|
+
], 'Official Hermes installation', false, hermesEnv);
|
|
530
|
+
}
|
|
531
|
+
else {
|
|
532
|
+
requireSuccess(runtime, 'bash', [
|
|
533
|
+
temporaryScript, '--commit', manifest.install.release.commitSha,
|
|
534
|
+
'--non-interactive', '--skip-setup', '--hermes-home', hermesHome,
|
|
535
|
+
'--dir', (0, node_path_1.join)(hermesHome, 'hermes-agent'),
|
|
536
|
+
], 'Official Hermes installation', false, hermesEnv);
|
|
537
|
+
}
|
|
538
|
+
failedStage = 'runtime-provenance';
|
|
539
|
+
receipt.runtimeIdentityBackup = await reconcileInstalledHermesRelease(manifest.install.release, hermesHome, setupRoot, backupDirectory, runtime, hermesEnv);
|
|
540
|
+
verifiedHermesCommand = await resolveVerifiedHermesCommand(hermesHome, runtime.platform);
|
|
541
|
+
}
|
|
542
|
+
failedStage = 'runtime-command';
|
|
543
|
+
const hermesCommand = verifiedHermesCommand
|
|
544
|
+
|| await resolveHermesCommand(hermesHome, runtime.platform, options.hermesCommand);
|
|
545
|
+
failedStage = 'runtime-version';
|
|
546
|
+
const versionOutput = requireSuccess(runtime, hermesCommand, ['--version'], 'Hermes version check', true, hermesEnv, { timeoutMs: HERMES_VERSION_TIMEOUT_MS, unsetEnv: [...GIT_PROVENANCE_ENV_KEYS] });
|
|
547
|
+
const expectedVersion = manifest.install.release.packageVersion;
|
|
548
|
+
if (expectedVersion) {
|
|
549
|
+
const observedVersions = new Set([
|
|
550
|
+
...hermesVersionsFromOfficialHeaders(versionOutput.stdout),
|
|
551
|
+
...hermesVersionsFromOfficialHeaders(versionOutput.stderr),
|
|
552
|
+
]);
|
|
553
|
+
if (observedVersions.size !== 1 || !observedVersions.has(expectedVersion)) {
|
|
554
|
+
const diagnostics = [
|
|
555
|
+
formatHermesVersionStream('stdout', versionOutput.stdout),
|
|
556
|
+
formatHermesVersionStream('stderr', versionOutput.stderr),
|
|
557
|
+
].join('\n');
|
|
558
|
+
throw new Error(`Hermes version check returned an unexpected release. Expected ${expectedVersion}.\n${diagnostics}`);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
failedStage = 'profile-conflict';
|
|
562
|
+
const existingProfile = runtime.run(hermesCommand, ['profile', 'show', profileName], { quiet: true, env: hermesEnv }).status === 0;
|
|
563
|
+
if (existingProfile && !options.updateExistingProfile) {
|
|
564
|
+
throw new Error(`Hermes profile "${profileName}" already exists. Re-run with --profile-name <new-name>, or review the generated files and explicitly use --update-existing-profile.`);
|
|
565
|
+
}
|
|
566
|
+
failedStage = 'backup';
|
|
567
|
+
await assertManagedPathHasNoSymlinks(setupRoot, distributionDirectory);
|
|
568
|
+
await assertManagedPathHasNoSymlinks(hermesHome, profileDirectory);
|
|
569
|
+
snapshots.push(await snapshotFiles(distributionDirectory, distributionFiles, (0, node_path_1.join)(backupDirectory, 'distribution')));
|
|
570
|
+
snapshots.push(await snapshotFiles(profileDirectory, [...distributionFiles, ...seedFiles], (0, node_path_1.join)(backupDirectory, 'profile')));
|
|
571
|
+
failedStage = 'distribution-write';
|
|
572
|
+
for (const filePath of distributionFiles) {
|
|
573
|
+
await atomicWrite(resolveInside(distributionDirectory, filePath), manifest.install.distributionFiles[filePath]);
|
|
574
|
+
runtime.log(`Prepared ${filePath}`);
|
|
575
|
+
}
|
|
576
|
+
failedStage = 'profile-install';
|
|
577
|
+
const profileArgs = ['profile', 'install', distributionDirectory, '--name', profileName, '--alias', '--yes'];
|
|
578
|
+
if (existingProfile && options.updateExistingProfile)
|
|
579
|
+
profileArgs.push('--force');
|
|
580
|
+
requireSuccess(runtime, hermesCommand, profileArgs, 'Hermes profile installation', false, hermesEnv);
|
|
581
|
+
failedStage = 'seed-files';
|
|
582
|
+
for (const filePath of seedFiles) {
|
|
583
|
+
await atomicWrite(resolveInside(profileDirectory, filePath), manifest.install.localSeedFiles[filePath]);
|
|
584
|
+
runtime.log(`Applied local ${filePath}`);
|
|
585
|
+
}
|
|
586
|
+
failedStage = 'config-check';
|
|
587
|
+
requireSuccess(runtime, hermesCommand, ['-p', profileName, 'config', 'check'], 'Hermes configuration check', false, hermesEnv);
|
|
588
|
+
if (!options.skipSetup) {
|
|
589
|
+
failedStage = 'provider-setup';
|
|
590
|
+
const setupArgs = ['-p', profileName, 'setup'];
|
|
591
|
+
if (manifest.install.providerSetup === 'portal')
|
|
592
|
+
setupArgs.push('--portal');
|
|
593
|
+
requireSuccess(runtime, hermesCommand, setupArgs, 'Official Hermes provider setup', false, hermesEnv);
|
|
594
|
+
receipt.stage = 'configured';
|
|
595
|
+
receipt.setupRequired = false;
|
|
596
|
+
if (!options.skipModelCheck) {
|
|
597
|
+
failedStage = 'model-check';
|
|
598
|
+
runtime.log('Running one brief Hermes model check. This may use a small amount of your selected provider quota.');
|
|
599
|
+
requireSuccess(runtime, hermesCommand, ['-p', profileName, 'chat', '-q', 'Reply with READY.'], 'Hermes model check', false, hermesEnv);
|
|
600
|
+
receipt.modelCheckRequired = false;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
if (manifest.install.requestedGatewaySetup && !receipt.setupRequired && !receipt.modelCheckRequired && !options.skipGatewaySetup) {
|
|
604
|
+
failedStage = 'gateway-setup';
|
|
605
|
+
requireSuccess(runtime, hermesCommand, ['-p', profileName, 'gateway', 'setup'], 'Official Hermes gateway setup', false, hermesEnv);
|
|
606
|
+
requireSuccess(runtime, hermesCommand, ['-p', profileName, 'gateway', 'status'], 'Hermes gateway status', false, hermesEnv);
|
|
607
|
+
receipt.stage = 'connected';
|
|
608
|
+
receipt.gatewaySetupRequired = false;
|
|
609
|
+
}
|
|
610
|
+
// Doctor includes credential and provider checks. A deliberately staged
|
|
611
|
+
// installation must retain its valid profile and report the remaining work.
|
|
612
|
+
if (!receipt.setupRequired && !receipt.modelCheckRequired && !receipt.gatewaySetupRequired) {
|
|
613
|
+
failedStage = 'doctor';
|
|
614
|
+
requireSuccess(runtime, hermesCommand, ['doctor'], 'Hermes doctor', false, hermesEnv);
|
|
615
|
+
}
|
|
616
|
+
else {
|
|
617
|
+
runtime.log('Profile installed and configuration checked. Complete the remaining provider/model/gateway setup, then run hermes doctor. This setup is not yet verified.');
|
|
618
|
+
}
|
|
619
|
+
requireSuccess(runtime, hermesCommand, ['profile', 'show', profileName], 'Hermes profile verification', false, hermesEnv);
|
|
620
|
+
if (!receipt.setupRequired && !receipt.modelCheckRequired && !receipt.gatewaySetupRequired)
|
|
621
|
+
receipt.stage = 'verified';
|
|
622
|
+
receipt.completedAt = runtime.now().toISOString();
|
|
623
|
+
await atomicWrite(receiptPath, JSON.stringify(receipt, null, 2) + '\n');
|
|
624
|
+
return receipt;
|
|
625
|
+
}
|
|
626
|
+
catch (error) {
|
|
627
|
+
for (const snapshot of [...snapshots].reverse())
|
|
628
|
+
await restoreSnapshot(snapshot);
|
|
629
|
+
receipt.stage = 'failed';
|
|
630
|
+
receipt.failedStage = sanitizeFailureStage(failedStage);
|
|
631
|
+
receipt.completedAt = runtime.now().toISOString();
|
|
632
|
+
await atomicWrite(receiptPath, JSON.stringify(receipt, null, 2) + '\n');
|
|
633
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
634
|
+
throw new Error(`${message} Lattice-owned distribution and seed files were restored to their pre-install state. Hermes runtime installation, profile registration or alias changes, provider or credential setup, model usage, and gateway or service changes are not automatically reverted; review them before retrying. Backup: ${backupDirectory}. Resume with: ${resumeCommand}`);
|
|
635
|
+
}
|
|
636
|
+
finally {
|
|
637
|
+
if (temporaryScript)
|
|
638
|
+
await node_fs_1.promises.rm((0, node_path_1.dirname)(temporaryScript), { recursive: true, force: true });
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
//# sourceMappingURL=hermes-install.js.map
|