sandstream-kit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +617 -0
- package/dist/adapters/api-key-adapter.d.ts +35 -0
- package/dist/adapters/api-key-adapter.js +46 -0
- package/dist/adapters/api-key-adapter.js.map +1 -0
- package/dist/adapters/clerk-auth.d.ts +6 -0
- package/dist/adapters/clerk-auth.js +20 -0
- package/dist/adapters/clerk-auth.js.map +1 -0
- package/dist/adapters/cloudflare-r2.d.ts +6 -0
- package/dist/adapters/cloudflare-r2.js +136 -0
- package/dist/adapters/cloudflare-r2.js.map +1 -0
- package/dist/adapters/expo-eas.d.ts +6 -0
- package/dist/adapters/expo-eas.js +129 -0
- package/dist/adapters/expo-eas.js.map +1 -0
- package/dist/adapters/flagsmith-flags.d.ts +5 -0
- package/dist/adapters/flagsmith-flags.js +20 -0
- package/dist/adapters/flagsmith-flags.js.map +1 -0
- package/dist/adapters/flyio-hosting.d.ts +2 -0
- package/dist/adapters/flyio-hosting.js +143 -0
- package/dist/adapters/flyio-hosting.js.map +1 -0
- package/dist/adapters/index.d.ts +6 -0
- package/dist/adapters/index.js +48 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/inngest-background.d.ts +5 -0
- package/dist/adapters/inngest-background.js +19 -0
- package/dist/adapters/inngest-background.js.map +1 -0
- package/dist/adapters/liveblocks-realtime.d.ts +11 -0
- package/dist/adapters/liveblocks-realtime.js +62 -0
- package/dist/adapters/liveblocks-realtime.js.map +1 -0
- package/dist/adapters/loops-email.d.ts +6 -0
- package/dist/adapters/loops-email.js +18 -0
- package/dist/adapters/loops-email.js.map +1 -0
- package/dist/adapters/neon-db.d.ts +10 -0
- package/dist/adapters/neon-db.js +94 -0
- package/dist/adapters/neon-db.js.map +1 -0
- package/dist/adapters/planetscale-db.d.ts +11 -0
- package/dist/adapters/planetscale-db.js +134 -0
- package/dist/adapters/planetscale-db.js.map +1 -0
- package/dist/adapters/posthog-analytics.d.ts +6 -0
- package/dist/adapters/posthog-analytics.js +22 -0
- package/dist/adapters/posthog-analytics.js.map +1 -0
- package/dist/adapters/railway-hosting.d.ts +2 -0
- package/dist/adapters/railway-hosting.js +136 -0
- package/dist/adapters/railway-hosting.js.map +1 -0
- package/dist/adapters/resend-email.d.ts +35 -0
- package/dist/adapters/resend-email.js +109 -0
- package/dist/adapters/resend-email.js.map +1 -0
- package/dist/adapters/searxng-instance.d.ts +6 -0
- package/dist/adapters/searxng-instance.js +240 -0
- package/dist/adapters/searxng-instance.js.map +1 -0
- package/dist/adapters/sentry-monitoring.d.ts +7 -0
- package/dist/adapters/sentry-monitoring.js +27 -0
- package/dist/adapters/sentry-monitoring.js.map +1 -0
- package/dist/adapters/stripe-payments.d.ts +6 -0
- package/dist/adapters/stripe-payments.js +134 -0
- package/dist/adapters/stripe-payments.js.map +1 -0
- package/dist/adapters/supabase-db.d.ts +6 -0
- package/dist/adapters/supabase-db.js +130 -0
- package/dist/adapters/supabase-db.js.map +1 -0
- package/dist/adapters/tinybird-analytics.d.ts +5 -0
- package/dist/adapters/tinybird-analytics.js +20 -0
- package/dist/adapters/tinybird-analytics.js.map +1 -0
- package/dist/adapters/trigger-background.d.ts +6 -0
- package/dist/adapters/trigger-background.js +20 -0
- package/dist/adapters/trigger-background.js.map +1 -0
- package/dist/adapters/types.d.ts +7 -0
- package/dist/adapters/types.js +2 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/adapters/upstash-redis.d.ts +6 -0
- package/dist/adapters/upstash-redis.js +88 -0
- package/dist/adapters/upstash-redis.js.map +1 -0
- package/dist/adapters/vercel-hosting.d.ts +6 -0
- package/dist/adapters/vercel-hosting.js +112 -0
- package/dist/adapters/vercel-hosting.js.map +1 -0
- package/dist/agent-adapter-model.d.ts +108 -0
- package/dist/agent-adapter-model.js +6 -0
- package/dist/agent-adapter-model.js.map +1 -0
- package/dist/agent-adapter-service.d.ts +67 -0
- package/dist/agent-adapter-service.js +299 -0
- package/dist/agent-adapter-service.js.map +1 -0
- package/dist/agent-config.d.ts +56 -0
- package/dist/agent-config.js +129 -0
- package/dist/agent-config.js.map +1 -0
- package/dist/agent-governance-model.d.ts +128 -0
- package/dist/agent-governance-model.js +6 -0
- package/dist/agent-governance-model.js.map +1 -0
- package/dist/agent-governance-service.d.ts +101 -0
- package/dist/agent-governance-service.js +319 -0
- package/dist/agent-governance-service.js.map +1 -0
- package/dist/alert-rules-engine.d.ts +102 -0
- package/dist/alert-rules-engine.js +210 -0
- package/dist/alert-rules-engine.js.map +1 -0
- package/dist/analytics-service.d.ts +126 -0
- package/dist/analytics-service.js +318 -0
- package/dist/analytics-service.js.map +1 -0
- package/dist/analyze.d.ts +19 -0
- package/dist/analyze.js +311 -0
- package/dist/analyze.js.map +1 -0
- package/dist/apm-instrumentor.d.ts +119 -0
- package/dist/apm-instrumentor.js +225 -0
- package/dist/apm-instrumentor.js.map +1 -0
- package/dist/approval-model.d.ts +82 -0
- package/dist/approval-model.js +6 -0
- package/dist/approval-model.js.map +1 -0
- package/dist/approval-service.d.ts +39 -0
- package/dist/approval-service.js +236 -0
- package/dist/approval-service.js.map +1 -0
- package/dist/approval.d.ts +22 -0
- package/dist/approval.js +148 -0
- package/dist/approval.js.map +1 -0
- package/dist/audit-logging-model.d.ts +157 -0
- package/dist/audit-logging-model.js +6 -0
- package/dist/audit-logging-model.js.map +1 -0
- package/dist/audit-logging-service.d.ts +89 -0
- package/dist/audit-logging-service.js +367 -0
- package/dist/audit-logging-service.js.map +1 -0
- package/dist/audit-secrets.d.ts +42 -0
- package/dist/audit-secrets.js +126 -0
- package/dist/audit-secrets.js.map +1 -0
- package/dist/audit.d.ts +43 -0
- package/dist/audit.js +286 -0
- package/dist/audit.js.map +1 -0
- package/dist/author-dashboard.d.ts +84 -0
- package/dist/author-dashboard.js +204 -0
- package/dist/author-dashboard.js.map +1 -0
- package/dist/author-notifications.d.ts +130 -0
- package/dist/author-notifications.js +261 -0
- package/dist/author-notifications.js.map +1 -0
- package/dist/author-verification.d.ts +79 -0
- package/dist/author-verification.js +257 -0
- package/dist/author-verification.js.map +1 -0
- package/dist/autonomous-setup-model.d.ts +117 -0
- package/dist/autonomous-setup-model.js +6 -0
- package/dist/autonomous-setup-model.js.map +1 -0
- package/dist/autonomous-setup-service.d.ts +74 -0
- package/dist/autonomous-setup-service.js +325 -0
- package/dist/autonomous-setup-service.js.map +1 -0
- package/dist/badge-system.d.ts +70 -0
- package/dist/badge-system.js +210 -0
- package/dist/badge-system.js.map +1 -0
- package/dist/baseline.d.ts +34 -0
- package/dist/baseline.js +78 -0
- package/dist/baseline.js.map +1 -0
- package/dist/beta-program-service.d.ts +112 -0
- package/dist/beta-program-service.js +240 -0
- package/dist/beta-program-service.js.map +1 -0
- package/dist/budget.d.ts +34 -0
- package/dist/budget.js +159 -0
- package/dist/budget.js.map +1 -0
- package/dist/bumblebee.d.ts +143 -0
- package/dist/bumblebee.js +384 -0
- package/dist/bumblebee.js.map +1 -0
- package/dist/cache-manager.d.ts +97 -0
- package/dist/cache-manager.js +244 -0
- package/dist/cache-manager.js.map +1 -0
- package/dist/cdn-adapter.d.ts +64 -0
- package/dist/cdn-adapter.js +263 -0
- package/dist/cdn-adapter.js.map +1 -0
- package/dist/certification-workflow-model.d.ts +95 -0
- package/dist/certification-workflow-model.js +6 -0
- package/dist/certification-workflow-model.js.map +1 -0
- package/dist/certification-workflow-service.d.ts +72 -0
- package/dist/certification-workflow-service.js +305 -0
- package/dist/certification-workflow-service.js.map +1 -0
- package/dist/check-design.d.ts +38 -0
- package/dist/check-design.js +256 -0
- package/dist/check-design.js.map +1 -0
- package/dist/check-gitignore.d.ts +39 -0
- package/dist/check-gitignore.js +156 -0
- package/dist/check-gitignore.js.map +1 -0
- package/dist/check-hooks.d.ts +15 -0
- package/dist/check-hooks.js +72 -0
- package/dist/check-hooks.js.map +1 -0
- package/dist/check-lock.d.ts +16 -0
- package/dist/check-lock.js +94 -0
- package/dist/check-lock.js.map +1 -0
- package/dist/check-secrets.d.ts +11 -0
- package/dist/check-secrets.js +320 -0
- package/dist/check-secrets.js.map +1 -0
- package/dist/check-security.d.ts +13 -0
- package/dist/check-security.js +887 -0
- package/dist/check-security.js.map +1 -0
- package/dist/check-services.d.ts +10 -0
- package/dist/check-services.js +44 -0
- package/dist/check-services.js.map +1 -0
- package/dist/check-skills.d.ts +8 -0
- package/dist/check-skills.js +26 -0
- package/dist/check-skills.js.map +1 -0
- package/dist/check-tests.d.ts +43 -0
- package/dist/check-tests.js +175 -0
- package/dist/check-tests.js.map +1 -0
- package/dist/check-tools.d.ts +8 -0
- package/dist/check-tools.js +42 -0
- package/dist/check-tools.js.map +1 -0
- package/dist/check-web-search.d.ts +12 -0
- package/dist/check-web-search.js +168 -0
- package/dist/check-web-search.js.map +1 -0
- package/dist/ci-cd-publisher.d.ts +162 -0
- package/dist/ci-cd-publisher.js +319 -0
- package/dist/ci-cd-publisher.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +4074 -0
- package/dist/cli.js.map +1 -0
- package/dist/clone.d.ts +25 -0
- package/dist/clone.js +73 -0
- package/dist/clone.js.map +1 -0
- package/dist/completions.d.ts +8 -0
- package/dist/completions.js +250 -0
- package/dist/completions.js.map +1 -0
- package/dist/compression-manager.d.ts +107 -0
- package/dist/compression-manager.js +250 -0
- package/dist/compression-manager.js.map +1 -0
- package/dist/config.d.ts +233 -0
- package/dist/config.js +255 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +38 -0
- package/dist/context.js +86 -0
- package/dist/context.js.map +1 -0
- package/dist/cost-monitor.d.ts +72 -0
- package/dist/cost-monitor.js +218 -0
- package/dist/cost-monitor.js.map +1 -0
- package/dist/create-plugin.d.ts +22 -0
- package/dist/create-plugin.js +266 -0
- package/dist/create-plugin.js.map +1 -0
- package/dist/database.d.ts +123 -0
- package/dist/database.js +354 -0
- package/dist/database.js.map +1 -0
- package/dist/datadog-adapter.d.ts +60 -0
- package/dist/datadog-adapter.js +245 -0
- package/dist/datadog-adapter.js.map +1 -0
- package/dist/doctor.d.ts +15 -0
- package/dist/doctor.js +131 -0
- package/dist/doctor.js.map +1 -0
- package/dist/documentation-generator.d.ts +226 -0
- package/dist/documentation-generator.js +348 -0
- package/dist/documentation-generator.js.map +1 -0
- package/dist/elevation-scopes.d.ts +40 -0
- package/dist/elevation-scopes.js +110 -0
- package/dist/elevation-scopes.js.map +1 -0
- package/dist/elevation.d.ts +102 -0
- package/dist/elevation.js +449 -0
- package/dist/elevation.js.map +1 -0
- package/dist/env-diff.d.ts +27 -0
- package/dist/env-diff.js +104 -0
- package/dist/env-diff.js.map +1 -0
- package/dist/env-inspect.d.ts +28 -0
- package/dist/env-inspect.js +81 -0
- package/dist/env-inspect.js.map +1 -0
- package/dist/env-switch.d.ts +37 -0
- package/dist/env-switch.js +102 -0
- package/dist/env-switch.js.map +1 -0
- package/dist/environment.d.ts +27 -0
- package/dist/environment.js +148 -0
- package/dist/environment.js.map +1 -0
- package/dist/error-tracker.d.ts +92 -0
- package/dist/error-tracker.js +206 -0
- package/dist/error-tracker.js.map +1 -0
- package/dist/escalate.d.ts +11 -0
- package/dist/escalate.js +73 -0
- package/dist/escalate.js.map +1 -0
- package/dist/event-stream.d.ts +81 -0
- package/dist/event-stream.js +161 -0
- package/dist/event-stream.js.map +1 -0
- package/dist/fix.d.ts +42 -0
- package/dist/fix.js +419 -0
- package/dist/fix.js.map +1 -0
- package/dist/governance-middleware.d.ts +22 -0
- package/dist/governance-middleware.js +173 -0
- package/dist/governance-middleware.js.map +1 -0
- package/dist/governance.d.ts +44 -0
- package/dist/governance.js +236 -0
- package/dist/governance.js.map +1 -0
- package/dist/hooks.d.ts +25 -0
- package/dist/hooks.js +281 -0
- package/dist/hooks.js.map +1 -0
- package/dist/id-generator.d.ts +43 -0
- package/dist/id-generator.js +47 -0
- package/dist/id-generator.js.map +1 -0
- package/dist/image-optimizer.d.ts +92 -0
- package/dist/image-optimizer.js +202 -0
- package/dist/image-optimizer.js.map +1 -0
- package/dist/install.d.ts +15 -0
- package/dist/install.js +59 -0
- package/dist/install.js.map +1 -0
- package/dist/lock.d.ts +82 -0
- package/dist/lock.js +264 -0
- package/dist/lock.js.map +1 -0
- package/dist/login.d.ts +23 -0
- package/dist/login.js +132 -0
- package/dist/login.js.map +1 -0
- package/dist/mcp-kit-tools-model.d.ts +195 -0
- package/dist/mcp-kit-tools-model.js +6 -0
- package/dist/mcp-kit-tools-model.js.map +1 -0
- package/dist/mcp-kit-tools-service.d.ts +127 -0
- package/dist/mcp-kit-tools-service.js +943 -0
- package/dist/mcp-kit-tools-service.js.map +1 -0
- package/dist/mcp-orchestrator.d.ts +70 -0
- package/dist/mcp-orchestrator.js +175 -0
- package/dist/mcp-orchestrator.js.map +1 -0
- package/dist/mcp-server.d.ts +3 -0
- package/dist/mcp-server.js +722 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/middleware/rate-limiter.d.ts +74 -0
- package/dist/middleware/rate-limiter.js +342 -0
- package/dist/middleware/rate-limiter.js.map +1 -0
- package/dist/migration-runner.d.ts +66 -0
- package/dist/migration-runner.js +192 -0
- package/dist/migration-runner.js.map +1 -0
- package/dist/migrations.d.ts +25 -0
- package/dist/migrations.js +530 -0
- package/dist/migrations.js.map +1 -0
- package/dist/moderation-system.d.ts +153 -0
- package/dist/moderation-system.js +338 -0
- package/dist/moderation-system.js.map +1 -0
- package/dist/multi-agent-workflow-model.d.ts +125 -0
- package/dist/multi-agent-workflow-model.js +6 -0
- package/dist/multi-agent-workflow-model.js.map +1 -0
- package/dist/multi-agent-workflow-service.d.ts +102 -0
- package/dist/multi-agent-workflow-service.js +452 -0
- package/dist/multi-agent-workflow-service.js.map +1 -0
- package/dist/onepassword.d.ts +75 -0
- package/dist/onepassword.js +140 -0
- package/dist/onepassword.js.map +1 -0
- package/dist/open.d.ts +30 -0
- package/dist/open.js +166 -0
- package/dist/open.js.map +1 -0
- package/dist/output.d.ts +32 -0
- package/dist/output.js +295 -0
- package/dist/output.js.map +1 -0
- package/dist/partner-service.d.ts +101 -0
- package/dist/partner-service.js +191 -0
- package/dist/partner-service.js.map +1 -0
- package/dist/payout-service.d.ts +136 -0
- package/dist/payout-service.js +293 -0
- package/dist/payout-service.js.map +1 -0
- package/dist/pkg.d.ts +30 -0
- package/dist/pkg.js +162 -0
- package/dist/pkg.js.map +1 -0
- package/dist/plugin-loader.d.ts +16 -0
- package/dist/plugin-loader.js +124 -0
- package/dist/plugin-loader.js.map +1 -0
- package/dist/plugin-registry-model.d.ts +133 -0
- package/dist/plugin-registry-model.js +6 -0
- package/dist/plugin-registry-model.js.map +1 -0
- package/dist/plugin-registry-service.d.ts +109 -0
- package/dist/plugin-registry-service.js +361 -0
- package/dist/plugin-registry-service.js.map +1 -0
- package/dist/plugin-registry.d.ts +58 -0
- package/dist/plugin-registry.js +108 -0
- package/dist/plugin-registry.js.map +1 -0
- package/dist/plugin-updates.d.ts +135 -0
- package/dist/plugin-updates.js +326 -0
- package/dist/plugin-updates.js.map +1 -0
- package/dist/plugins-cli.d.ts +7 -0
- package/dist/plugins-cli.js +157 -0
- package/dist/plugins-cli.js.map +1 -0
- package/dist/plugins.d.ts +88 -0
- package/dist/plugins.js +251 -0
- package/dist/plugins.js.map +1 -0
- package/dist/policy.d.ts +66 -0
- package/dist/policy.js +160 -0
- package/dist/policy.js.map +1 -0
- package/dist/post-pull-audit.d.ts +39 -0
- package/dist/post-pull-audit.js +151 -0
- package/dist/post-pull-audit.js.map +1 -0
- package/dist/provision.d.ts +17 -0
- package/dist/provision.js +147 -0
- package/dist/provision.js.map +1 -0
- package/dist/query-optimizer.d.ts +102 -0
- package/dist/query-optimizer.js +199 -0
- package/dist/query-optimizer.js.map +1 -0
- package/dist/read-only-mode.d.ts +46 -0
- package/dist/read-only-mode.js +71 -0
- package/dist/read-only-mode.js.map +1 -0
- package/dist/redis-adapter.d.ts +71 -0
- package/dist/redis-adapter.js +278 -0
- package/dist/redis-adapter.js.map +1 -0
- package/dist/resilience-tests.d.ts +120 -0
- package/dist/resilience-tests.js +293 -0
- package/dist/resilience-tests.js.map +1 -0
- package/dist/revocation.d.ts +22 -0
- package/dist/revocation.js +100 -0
- package/dist/revocation.js.map +1 -0
- package/dist/run.d.ts +21 -0
- package/dist/run.js +80 -0
- package/dist/run.js.map +1 -0
- package/dist/scan-build.d.ts +18 -0
- package/dist/scan-build.js +100 -0
- package/dist/scan-build.js.map +1 -0
- package/dist/scan-plaintext.d.ts +24 -0
- package/dist/scan-plaintext.js +147 -0
- package/dist/scan-plaintext.js.map +1 -0
- package/dist/scan-staged.d.ts +15 -0
- package/dist/scan-staged.js +70 -0
- package/dist/scan-staged.js.map +1 -0
- package/dist/scan-transcripts.d.ts +23 -0
- package/dist/scan-transcripts.js +93 -0
- package/dist/scan-transcripts.js.map +1 -0
- package/dist/secret-backends.d.ts +50 -0
- package/dist/secret-backends.js +510 -0
- package/dist/secret-backends.js.map +1 -0
- package/dist/secret-expiration.d.ts +46 -0
- package/dist/secret-expiration.js +172 -0
- package/dist/secret-expiration.js.map +1 -0
- package/dist/secrets-migrate.d.ts +75 -0
- package/dist/secrets-migrate.js +185 -0
- package/dist/secrets-migrate.js.map +1 -0
- package/dist/secrets-model.d.ts +77 -0
- package/dist/secrets-model.js +6 -0
- package/dist/secrets-model.js.map +1 -0
- package/dist/secrets-onecli.d.ts +65 -0
- package/dist/secrets-onecli.js +113 -0
- package/dist/secrets-onecli.js.map +1 -0
- package/dist/secrets-propagate.d.ts +48 -0
- package/dist/secrets-propagate.js +201 -0
- package/dist/secrets-propagate.js.map +1 -0
- package/dist/secrets-pull.d.ts +34 -0
- package/dist/secrets-pull.js +118 -0
- package/dist/secrets-pull.js.map +1 -0
- package/dist/secrets-purge-history.d.ts +53 -0
- package/dist/secrets-purge-history.js +144 -0
- package/dist/secrets-purge-history.js.map +1 -0
- package/dist/secrets-rotate-cli.d.ts +54 -0
- package/dist/secrets-rotate-cli.js +438 -0
- package/dist/secrets-rotate-cli.js.map +1 -0
- package/dist/secrets-rotate.d.ts +38 -0
- package/dist/secrets-rotate.js +65 -0
- package/dist/secrets-rotate.js.map +1 -0
- package/dist/secrets-service.d.ts +73 -0
- package/dist/secrets-service.js +283 -0
- package/dist/secrets-service.js.map +1 -0
- package/dist/secrets-set.d.ts +25 -0
- package/dist/secrets-set.js +33 -0
- package/dist/secrets-set.js.map +1 -0
- package/dist/secrets-sync.d.ts +21 -0
- package/dist/secrets-sync.js +215 -0
- package/dist/secrets-sync.js.map +1 -0
- package/dist/secrets-validate.d.ts +41 -0
- package/dist/secrets-validate.js +126 -0
- package/dist/secrets-validate.js.map +1 -0
- package/dist/secrets-vault-migrate.d.ts +71 -0
- package/dist/secrets-vault-migrate.js +258 -0
- package/dist/secrets-vault-migrate.js.map +1 -0
- package/dist/secrets.d.ts +16 -0
- package/dist/secrets.js +72 -0
- package/dist/secrets.js.map +1 -0
- package/dist/security-hardening.d.ts +150 -0
- package/dist/security-hardening.js +275 -0
- package/dist/security-hardening.js.map +1 -0
- package/dist/security-policy.d.ts +89 -0
- package/dist/security-policy.js +174 -0
- package/dist/security-policy.js.map +1 -0
- package/dist/security-prescan.d.ts +117 -0
- package/dist/security-prescan.js +566 -0
- package/dist/security-prescan.js.map +1 -0
- package/dist/sentry-adapter.d.ts +49 -0
- package/dist/sentry-adapter.js +227 -0
- package/dist/sentry-adapter.js.map +1 -0
- package/dist/service-adapter.d.ts +94 -0
- package/dist/service-adapter.js +162 -0
- package/dist/service-adapter.js.map +1 -0
- package/dist/skills.d.ts +13 -0
- package/dist/skills.js +17 -0
- package/dist/skills.js.map +1 -0
- package/dist/sla-monitor.d.ts +107 -0
- package/dist/sla-monitor.js +233 -0
- package/dist/sla-monitor.js.map +1 -0
- package/dist/stack-detector.d.ts +12 -0
- package/dist/stack-detector.js +251 -0
- package/dist/stack-detector.js.map +1 -0
- package/dist/team-model.d.ts +58 -0
- package/dist/team-model.js +83 -0
- package/dist/team-model.js.map +1 -0
- package/dist/team-service.d.ts +54 -0
- package/dist/team-service.js +206 -0
- package/dist/team-service.js.map +1 -0
- package/dist/toml-generator.d.ts +8 -0
- package/dist/toml-generator.js +223 -0
- package/dist/toml-generator.js.map +1 -0
- package/dist/triage-sandbox.d.ts +34 -0
- package/dist/triage-sandbox.js +167 -0
- package/dist/triage-sandbox.js.map +1 -0
- package/dist/triage.d.ts +30 -0
- package/dist/triage.js +79 -0
- package/dist/triage.js.map +1 -0
- package/dist/update-check.d.ts +13 -0
- package/dist/update-check.js +91 -0
- package/dist/update-check.js.map +1 -0
- package/dist/utils/colors.d.ts +14 -0
- package/dist/utils/colors.js +15 -0
- package/dist/utils/colors.js.map +1 -0
- package/dist/utils/didYouMean.d.ts +15 -0
- package/dist/utils/didYouMean.js +47 -0
- package/dist/utils/didYouMean.js.map +1 -0
- package/dist/utils/exec.d.ts +21 -0
- package/dist/utils/exec.js +23 -0
- package/dist/utils/exec.js.map +1 -0
- package/dist/utils/execFileNoThrow.d.ts +14 -0
- package/dist/utils/execFileNoThrow.js +29 -0
- package/dist/utils/execFileNoThrow.js.map +1 -0
- package/dist/utils/flags.d.ts +19 -0
- package/dist/utils/flags.js +36 -0
- package/dist/utils/flags.js.map +1 -0
- package/dist/utils/parseCommand.d.ts +16 -0
- package/dist/utils/parseCommand.js +13 -0
- package/dist/utils/parseCommand.js.map +1 -0
- package/dist/utils/prompt.d.ts +13 -0
- package/dist/utils/prompt.js +35 -0
- package/dist/utils/prompt.js.map +1 -0
- package/dist/utils/promptSelect.d.ts +19 -0
- package/dist/utils/promptSelect.js +89 -0
- package/dist/utils/promptSelect.js.map +1 -0
- package/dist/utils/redactSecrets.d.ts +24 -0
- package/dist/utils/redactSecrets.js +134 -0
- package/dist/utils/redactSecrets.js.map +1 -0
- package/dist/validation/dynamic-schema.d.ts +29 -0
- package/dist/validation/dynamic-schema.js +76 -0
- package/dist/validation/dynamic-schema.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Elevation gate for destructive secret operations.
|
|
3
|
+
*
|
|
4
|
+
* User requirement: agents (or unauthorized humans) must not be able to
|
|
5
|
+
* rotate / migrate / propagate / register-fake a key without an explicit
|
|
6
|
+
* human-loop confirmation. This module provides:
|
|
7
|
+
*
|
|
8
|
+
* 1. A short-lived elevation marker (`.kit/elevation.json`) with TTL,
|
|
9
|
+
* created by `kit auth elevate`.
|
|
10
|
+
* 2. Optional TOTP (RFC 6238) verification when `KIT_TOTP_SECRET` is set.
|
|
11
|
+
* Without TOTP, falls back to a plain interactive "YES" prompt.
|
|
12
|
+
* 3. A `requireElevation()` check that destructive ops call before running.
|
|
13
|
+
* In non-interactive / agent contexts: fails closed unless
|
|
14
|
+
* `KIT_ELEVATED=1` is set (CI escape hatch — gets audit-logged loudly
|
|
15
|
+
* so a leaked CI env doesn't silently bypass).
|
|
16
|
+
*/
|
|
17
|
+
import { readFile, writeFile, mkdir, access } from "node:fs/promises";
|
|
18
|
+
import { resolve, dirname } from "node:path";
|
|
19
|
+
import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
|
|
20
|
+
import { appendAuditEventDirect } from "./audit.js";
|
|
21
|
+
const ELEVATION_FILE = ".kit/elevation.json";
|
|
22
|
+
const DEFAULT_TTL_MINUTES = 15;
|
|
23
|
+
/**
|
|
24
|
+
* Scopes that, when granted, MUST be consumed (atomically deleted) on use.
|
|
25
|
+
* One elevation = one destructive operation. Rotation modes that need a
|
|
26
|
+
* follow-up rollback path (scoped-key-mint) are intentionally absent — they
|
|
27
|
+
* retain the standard 15-min TTL because the rollback re-uses the marker.
|
|
28
|
+
*/
|
|
29
|
+
const ONE_SHOT_SCOPES = new Set([
|
|
30
|
+
"jwt-secret-roll",
|
|
31
|
+
"purge-history",
|
|
32
|
+
"onecli-register",
|
|
33
|
+
]);
|
|
34
|
+
export function isOneShotScope(scope) {
|
|
35
|
+
return ONE_SHOT_SCOPES.has(scope);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Loud one-time stderr warning for the CI escape hatch. Emitted once per
|
|
39
|
+
* process so a single `kit secrets rotate ... ` invocation doesn't spam,
|
|
40
|
+
* but the operator sees it on stderr even when stdout is captured.
|
|
41
|
+
*/
|
|
42
|
+
let warnedAboutCiBypass = false;
|
|
43
|
+
function warnCiBypassOnce(operation) {
|
|
44
|
+
if (warnedAboutCiBypass)
|
|
45
|
+
return;
|
|
46
|
+
warnedAboutCiBypass = true;
|
|
47
|
+
console.error(`[kit] WARNING: KIT_ELEVATED=1 is bypassing the TTY elevation gate for "${operation}". This is logged to .kit-audit.jsonl.`);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Records every elevation decision — granted or refused — to the local
|
|
51
|
+
* audit log. Returns true on success; false means the audit-log itself
|
|
52
|
+
* couldn't be written, which the caller treats as a refusal-to-elevate.
|
|
53
|
+
*
|
|
54
|
+
* Audit-log write must succeed before destructive ops proceed. The
|
|
55
|
+
* "always-allow if audit-log down" pattern is exactly the silent-bypass
|
|
56
|
+
* we're closing.
|
|
57
|
+
*/
|
|
58
|
+
async function auditElevationDecision(operation, granted, reason, method, cwd) {
|
|
59
|
+
return appendAuditEventDirect({
|
|
60
|
+
operation: "elevation-check",
|
|
61
|
+
environment: process.env.KIT_ENV ?? process.env.NODE_ENV ?? "unknown",
|
|
62
|
+
success: granted,
|
|
63
|
+
metadata: {
|
|
64
|
+
requested_scope: operation,
|
|
65
|
+
method,
|
|
66
|
+
reason,
|
|
67
|
+
granter: process.env.USER ?? "unknown",
|
|
68
|
+
},
|
|
69
|
+
}, { cwd });
|
|
70
|
+
}
|
|
71
|
+
// ── Marker signing ───────────────────────────────────────────────────────────
|
|
72
|
+
//
|
|
73
|
+
// The elevation marker lives in the PROJECT dir (.kit/elevation.json). Without
|
|
74
|
+
// a signature, any process that can write that file could forge elevation and
|
|
75
|
+
// bypass the TOTP/human gate entirely. We HMAC-sign the marker with a key kept
|
|
76
|
+
// OUTSIDE the project, in ~/.kit/elevation.key (0600). A process sandboxed to
|
|
77
|
+
// the project (the agent threat model) can write the marker but cannot read the
|
|
78
|
+
// key, so it cannot produce a valid signature.
|
|
79
|
+
const ELEVATION_KEY_REL = ".kit/elevation.key";
|
|
80
|
+
function elevationKeyPath() {
|
|
81
|
+
return `${_homedir()}/${ELEVATION_KEY_REL}`;
|
|
82
|
+
}
|
|
83
|
+
/** Machine-local HMAC key, created once (0600). Create is atomic (flag "wx"):
|
|
84
|
+
* on a lost create race the winner's key is re-read, so all callers agree. */
|
|
85
|
+
async function getElevationSigningKey() {
|
|
86
|
+
const keyPath = elevationKeyPath();
|
|
87
|
+
try {
|
|
88
|
+
const hex = (await readFile(keyPath, "utf-8")).trim();
|
|
89
|
+
if (hex.length >= 64)
|
|
90
|
+
return Buffer.from(hex, "hex");
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
/* fall through to create */
|
|
94
|
+
}
|
|
95
|
+
const key = randomBytes(32);
|
|
96
|
+
await mkdir(dirname(keyPath), { recursive: true });
|
|
97
|
+
try {
|
|
98
|
+
await writeFile(keyPath, key.toString("hex") + "\n", { encoding: "utf-8", mode: 0o600, flag: "wx" });
|
|
99
|
+
return key;
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
const hex = (await readFile(keyPath, "utf-8")).trim();
|
|
103
|
+
return Buffer.from(hex, "hex");
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/** Canonical signed form — stable field order, excludes the signature itself. */
|
|
107
|
+
function elevationPayload(state) {
|
|
108
|
+
return JSON.stringify({
|
|
109
|
+
expiresAt: state.expiresAt,
|
|
110
|
+
scope: state.scope,
|
|
111
|
+
granter: state.granter,
|
|
112
|
+
method: state.method,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
async function signElevation(state) {
|
|
116
|
+
const key = await getElevationSigningKey();
|
|
117
|
+
return createHmac("sha256", key).update(elevationPayload(state)).digest("hex");
|
|
118
|
+
}
|
|
119
|
+
async function verifyElevationSig(state, sig) {
|
|
120
|
+
if (!sig)
|
|
121
|
+
return false;
|
|
122
|
+
const expected = Buffer.from(await signElevation(state), "hex");
|
|
123
|
+
let actual;
|
|
124
|
+
try {
|
|
125
|
+
actual = Buffer.from(sig, "hex");
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
return expected.length === actual.length && timingSafeEqual(expected, actual);
|
|
131
|
+
}
|
|
132
|
+
export async function readElevation(cwd = process.cwd()) {
|
|
133
|
+
const path = resolve(cwd, ELEVATION_FILE);
|
|
134
|
+
try {
|
|
135
|
+
await access(path);
|
|
136
|
+
const text = await readFile(path, "utf-8");
|
|
137
|
+
const parsed = JSON.parse(text);
|
|
138
|
+
if (!parsed.expiresAt || !parsed.scope)
|
|
139
|
+
return null;
|
|
140
|
+
const state = {
|
|
141
|
+
expiresAt: parsed.expiresAt,
|
|
142
|
+
scope: parsed.scope,
|
|
143
|
+
granter: parsed.granter ?? "unknown",
|
|
144
|
+
method: parsed.method ?? "yes-prompt",
|
|
145
|
+
};
|
|
146
|
+
// Reject unsigned / tampered / forged markers — only an HMAC signed with the
|
|
147
|
+
// machine-local key is honored. This is what makes the gate unforgeable.
|
|
148
|
+
if (!(await verifyElevationSig(state, parsed.sig ?? "")))
|
|
149
|
+
return null;
|
|
150
|
+
return state;
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
export async function writeElevation(state, cwd = process.cwd()) {
|
|
157
|
+
const path = resolve(cwd, ELEVATION_FILE);
|
|
158
|
+
await mkdir(dirname(path), { recursive: true });
|
|
159
|
+
const sig = await signElevation(state);
|
|
160
|
+
await writeFile(path, JSON.stringify({ ...state, sig }, null, 2) + "\n", "utf-8");
|
|
161
|
+
}
|
|
162
|
+
export async function clearElevation(cwd = process.cwd()) {
|
|
163
|
+
const path = resolve(cwd, ELEVATION_FILE);
|
|
164
|
+
try {
|
|
165
|
+
const { rm } = await import("node:fs/promises");
|
|
166
|
+
await rm(path);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
/* nothing to clear */
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Returns true if an unexpired elevation marker exists that covers the
|
|
174
|
+
* requested operation scope.
|
|
175
|
+
*/
|
|
176
|
+
export async function isElevated(operation, cwd = process.cwd()) {
|
|
177
|
+
const state = await readElevation(cwd);
|
|
178
|
+
if (!state)
|
|
179
|
+
return false;
|
|
180
|
+
const expires = Date.parse(state.expiresAt);
|
|
181
|
+
if (!Number.isFinite(expires) || expires < Date.now()) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
return state.scope === "all" || state.scope === operation;
|
|
185
|
+
}
|
|
186
|
+
export function elevationTtlMinutes() {
|
|
187
|
+
const env = process.env.KIT_ELEVATION_TTL_MINUTES;
|
|
188
|
+
if (env) {
|
|
189
|
+
const n = parseInt(env, 10);
|
|
190
|
+
if (Number.isFinite(n) && n > 0 && n <= 240)
|
|
191
|
+
return n;
|
|
192
|
+
}
|
|
193
|
+
return DEFAULT_TTL_MINUTES;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Mints a fresh elevation marker covering `scope` for the configured TTL.
|
|
197
|
+
* Caller is responsible for prompting / verifying the user before calling.
|
|
198
|
+
*/
|
|
199
|
+
export async function grantElevation(scope, method, cwd = process.cwd(), granter = process.env.USER || "unknown") {
|
|
200
|
+
// Read-only mode: refuse before writing the elevation marker. Granting
|
|
201
|
+
// elevation IS a write — without this gate a read-only session could
|
|
202
|
+
// still mint a marker for a subsequent destructive op.
|
|
203
|
+
const { isReadOnlyMode, refuseWrite } = await import("./read-only-mode.js");
|
|
204
|
+
if (isReadOnlyMode()) {
|
|
205
|
+
const refusal = await refuseWrite("grant-elevation", { scope, method });
|
|
206
|
+
throw new Error(refusal.reason);
|
|
207
|
+
}
|
|
208
|
+
const expiresAt = new Date(Date.now() + elevationTtlMinutes() * 60_000).toISOString();
|
|
209
|
+
const state = { expiresAt, scope, granter, method };
|
|
210
|
+
await writeElevation(state, cwd);
|
|
211
|
+
return state;
|
|
212
|
+
}
|
|
213
|
+
// ── TOTP enrollment ─────────────────────────────────────────────────────────
|
|
214
|
+
//
|
|
215
|
+
// `kit auth setup-totp` generates a fresh base32 secret, writes it to
|
|
216
|
+
// ~/.kit/totp-secret (chmod 0o600 so other users can't read it), and
|
|
217
|
+
// prints the otpauth provisioning URI for the user's authenticator app.
|
|
218
|
+
// The secret only ever exists on disk in that one file; the elevation
|
|
219
|
+
// flow reads it via `KIT_TOTP_SECRET` env var (or the new helper that
|
|
220
|
+
// reads the file when the env var is unset).
|
|
221
|
+
import { homedir as _homedir } from "node:os";
|
|
222
|
+
const TOTP_FILE_REL = ".kit/totp-secret";
|
|
223
|
+
function totpFilePath() {
|
|
224
|
+
return `${_homedir()}/${TOTP_FILE_REL}`;
|
|
225
|
+
}
|
|
226
|
+
export function generateBase32Secret(byteLength = 20) {
|
|
227
|
+
// ESM-friendly — reuse the top-level import.
|
|
228
|
+
const bytes = randomBytes(byteLength);
|
|
229
|
+
// RFC 4648 base32 (no padding) — same alphabet TOTP libs expect.
|
|
230
|
+
let bits = "";
|
|
231
|
+
for (const b of bytes)
|
|
232
|
+
bits += b.toString(2).padStart(8, "0");
|
|
233
|
+
let out = "";
|
|
234
|
+
for (let i = 0; i + 5 <= bits.length; i += 5) {
|
|
235
|
+
out += BASE32_ALPHABET[parseInt(bits.slice(i, i + 5), 2)];
|
|
236
|
+
}
|
|
237
|
+
return out;
|
|
238
|
+
}
|
|
239
|
+
export function buildOtpAuthUri(input) {
|
|
240
|
+
const issuer = input.issuer ?? "kit";
|
|
241
|
+
const label = `${encodeURIComponent(issuer)}:${encodeURIComponent(input.accountName)}`;
|
|
242
|
+
const params = new URLSearchParams({
|
|
243
|
+
secret: input.secret,
|
|
244
|
+
issuer,
|
|
245
|
+
algorithm: "SHA1",
|
|
246
|
+
digits: "6",
|
|
247
|
+
period: "30",
|
|
248
|
+
});
|
|
249
|
+
return `otpauth://totp/${label}?${params.toString()}`;
|
|
250
|
+
}
|
|
251
|
+
export async function enrollTotp(opts) {
|
|
252
|
+
const { writeFile, mkdir, access } = await import("node:fs/promises");
|
|
253
|
+
const { dirname } = await import("node:path");
|
|
254
|
+
const filePath = totpFilePath();
|
|
255
|
+
// Guard against silently overwriting an existing enrollment — that
|
|
256
|
+
// would invalidate the user's already-registered authenticator entry.
|
|
257
|
+
let exists = false;
|
|
258
|
+
try {
|
|
259
|
+
await access(filePath);
|
|
260
|
+
exists = true;
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
exists = false;
|
|
264
|
+
}
|
|
265
|
+
if (exists && !opts.overwrite) {
|
|
266
|
+
throw new Error(`TOTP secret already enrolled at ${filePath}. Pass overwrite=true to replace it (your old authenticator entry will stop working).`);
|
|
267
|
+
}
|
|
268
|
+
const secret = generateBase32Secret(20);
|
|
269
|
+
const uri = buildOtpAuthUri({
|
|
270
|
+
accountName: opts.accountName,
|
|
271
|
+
issuer: opts.issuer,
|
|
272
|
+
secret,
|
|
273
|
+
});
|
|
274
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
275
|
+
await writeFile(filePath, secret + "\n", { encoding: "utf-8", mode: 0o600 });
|
|
276
|
+
return {
|
|
277
|
+
secret,
|
|
278
|
+
filePath,
|
|
279
|
+
uri,
|
|
280
|
+
currentCode: generateTotp(secret),
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Resolves the TOTP secret in priority order:
|
|
285
|
+
* 1. `KIT_TOTP_SECRET` env var (overrides everything; useful for CI)
|
|
286
|
+
* 2. `~/.kit/totp-secret` file (created by `kit auth setup-totp`)
|
|
287
|
+
* 3. undefined — caller falls back to yes-prompt
|
|
288
|
+
*/
|
|
289
|
+
export async function resolveTotpSecret() {
|
|
290
|
+
if (process.env.KIT_TOTP_SECRET)
|
|
291
|
+
return process.env.KIT_TOTP_SECRET;
|
|
292
|
+
try {
|
|
293
|
+
const { readFile } = await import("node:fs/promises");
|
|
294
|
+
const content = await readFile(totpFilePath(), "utf-8");
|
|
295
|
+
return content.trim() || undefined;
|
|
296
|
+
}
|
|
297
|
+
catch {
|
|
298
|
+
return undefined;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// ── TOTP (RFC 6238) ─────────────────────────────────────────────────────────
|
|
302
|
+
//
|
|
303
|
+
// Minimal implementation so we don't add an npm dep for a 30-line algorithm.
|
|
304
|
+
// Accepts base32-encoded secret in `KIT_TOTP_SECRET`. 6-digit codes,
|
|
305
|
+
// 30-second period, SHA-1 — matches Google Authenticator / 1Password / Authy.
|
|
306
|
+
const BASE32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
|
307
|
+
function base32Decode(input) {
|
|
308
|
+
const cleaned = input.toUpperCase().replace(/=+$/, "").replace(/\s+/g, "");
|
|
309
|
+
let bits = "";
|
|
310
|
+
for (const ch of cleaned) {
|
|
311
|
+
const idx = BASE32_ALPHABET.indexOf(ch);
|
|
312
|
+
if (idx < 0)
|
|
313
|
+
throw new Error(`invalid base32 char: ${ch}`);
|
|
314
|
+
bits += idx.toString(2).padStart(5, "0");
|
|
315
|
+
}
|
|
316
|
+
const bytes = [];
|
|
317
|
+
for (let i = 0; i + 8 <= bits.length; i += 8) {
|
|
318
|
+
bytes.push(parseInt(bits.slice(i, i + 8), 2));
|
|
319
|
+
}
|
|
320
|
+
return Buffer.from(bytes);
|
|
321
|
+
}
|
|
322
|
+
export function generateTotp(secretBase32, step = Math.floor(Date.now() / 1000 / 30)) {
|
|
323
|
+
const secret = base32Decode(secretBase32);
|
|
324
|
+
const counter = Buffer.alloc(8);
|
|
325
|
+
// Big-endian uint64. step fits in uint32 for the next ~136 years, so write
|
|
326
|
+
// the high word as zero.
|
|
327
|
+
counter.writeUInt32BE(0, 0);
|
|
328
|
+
counter.writeUInt32BE(step >>> 0, 4);
|
|
329
|
+
const hmac = createHmac("sha1", secret).update(counter).digest();
|
|
330
|
+
const offset = hmac[hmac.length - 1] & 0x0f;
|
|
331
|
+
const bin = ((hmac[offset] & 0x7f) << 24) |
|
|
332
|
+
((hmac[offset + 1] & 0xff) << 16) |
|
|
333
|
+
((hmac[offset + 2] & 0xff) << 8) |
|
|
334
|
+
(hmac[offset + 3] & 0xff);
|
|
335
|
+
return (bin % 1_000_000).toString().padStart(6, "0");
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Verifies a user-supplied TOTP. Accepts the current step ± 1 (handles minor
|
|
339
|
+
* clock skew, ±30s window). Uses timingSafeEqual for the digit comparison —
|
|
340
|
+
* both sides are fixed 6-ASCII-digit strings, so lengths always match.
|
|
341
|
+
*/
|
|
342
|
+
export function verifyTotp(code, secretBase32, windowSteps = 1) {
|
|
343
|
+
if (!/^\d{6}$/.test(code))
|
|
344
|
+
return false;
|
|
345
|
+
const codeBuf = Buffer.from(code, "ascii");
|
|
346
|
+
const now = Math.floor(Date.now() / 1000 / 30);
|
|
347
|
+
for (let delta = -windowSteps; delta <= windowSteps; delta++) {
|
|
348
|
+
const expected = Buffer.from(generateTotp(secretBase32, now + delta), "ascii");
|
|
349
|
+
if (expected.length === codeBuf.length && timingSafeEqual(expected, codeBuf))
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Throws (or returns false in nice mode) when the active context isn't
|
|
356
|
+
* elevated for `operation`. Used by every destructive secrets-* command.
|
|
357
|
+
*
|
|
358
|
+
* Order of resolution:
|
|
359
|
+
* 1. `KIT_ELEVATED=1` env var (CI escape hatch).
|
|
360
|
+
* 2. A live elevation marker covering the operation.
|
|
361
|
+
* 3. Otherwise: not elevated.
|
|
362
|
+
*
|
|
363
|
+
* Every decision — granted or refused — emits an audit-log entry before
|
|
364
|
+
* returning. If the audit-log write itself fails, the call returns
|
|
365
|
+
* `{ ok: false }` even if the credential would otherwise be granted. The
|
|
366
|
+
* intent is: a code path that runs destructive ops must always leave a
|
|
367
|
+
* forensic trail; "audit-log down" is treated identically to "elevation
|
|
368
|
+
* refused" so the silent-bypass property is eliminated.
|
|
369
|
+
*/
|
|
370
|
+
export async function requireElevation(operation, cwd = process.cwd()) {
|
|
371
|
+
const decide = async (ok, reason, method) => {
|
|
372
|
+
const audited = await auditElevationDecision(operation, ok, reason, method, cwd);
|
|
373
|
+
if (ok && !audited) {
|
|
374
|
+
return {
|
|
375
|
+
ok: false,
|
|
376
|
+
reason: "audit-log unavailable; refusing elevation (fail-closed)",
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
return { ok, reason };
|
|
380
|
+
};
|
|
381
|
+
if (process.env.KIT_ELEVATED === "1") {
|
|
382
|
+
warnCiBypassOnce(operation);
|
|
383
|
+
return decide(true, "KIT_ELEVATED=1 (CI escape hatch)", "ci-env");
|
|
384
|
+
}
|
|
385
|
+
const state = await readElevation(cwd);
|
|
386
|
+
if (!state) {
|
|
387
|
+
return decide(false, `No elevation marker. Run 'kit auth elevate --scope ${operation}' first.`, "none");
|
|
388
|
+
}
|
|
389
|
+
const expires = Date.parse(state.expiresAt);
|
|
390
|
+
if (!Number.isFinite(expires) || expires < Date.now()) {
|
|
391
|
+
return decide(false, "Elevation marker expired. Run 'kit auth elevate' again.", state.method);
|
|
392
|
+
}
|
|
393
|
+
if (state.scope !== "all" && state.scope !== operation) {
|
|
394
|
+
return decide(false, `Elevation covers scope="${state.scope}" but operation requires "${operation}".`, state.method);
|
|
395
|
+
}
|
|
396
|
+
return decide(true, `Elevated by ${state.granter} via ${state.method} until ${state.expiresAt}`, state.method);
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* One-shot elevation: same gate as `requireElevation`, but the underlying
|
|
400
|
+
* marker is **deleted** immediately on successful use. Used for scopes that
|
|
401
|
+
* must not be reusable within their TTL window (jwt-secret-roll, etc).
|
|
402
|
+
*
|
|
403
|
+
* The KIT_ELEVATED=1 escape hatch is allowed once per process — after
|
|
404
|
+
* the first consume call the module-scoped `consumedInProcess` flag prevents
|
|
405
|
+
* the same env var from re-grant the same scope on a subsequent call in the
|
|
406
|
+
* same invocation. This matches the "one auth, one destructive op" intent.
|
|
407
|
+
*/
|
|
408
|
+
const consumedInProcess = new Set();
|
|
409
|
+
export async function consumeElevation(operation, cwd = process.cwd()) {
|
|
410
|
+
if (consumedInProcess.has(operation)) {
|
|
411
|
+
const reason = `Elevation for "${operation}" already consumed in this process. Re-run 'kit auth elevate' for another one-shot op.`;
|
|
412
|
+
await auditElevationDecision(operation, false, reason, "none", cwd);
|
|
413
|
+
return { ok: false, reason };
|
|
414
|
+
}
|
|
415
|
+
const result = await requireElevation(operation, cwd);
|
|
416
|
+
if (!result.ok)
|
|
417
|
+
return result;
|
|
418
|
+
// Atomic cross-process claim: rename the marker so exactly one caller wins.
|
|
419
|
+
// Two concurrent invocations can both pass requireElevation (read), but only
|
|
420
|
+
// one rename succeeds — the loser finds the marker gone and is refused, so one
|
|
421
|
+
// human elevation authorizes exactly one one-shot op. Env-var (KIT_ELEVATED)
|
|
422
|
+
// grants have no marker file; the rename fails and is allowed (explicit CI
|
|
423
|
+
// escape hatch).
|
|
424
|
+
const markerPath = resolve(cwd, ELEVATION_FILE);
|
|
425
|
+
try {
|
|
426
|
+
const { rename, rm } = await import("node:fs/promises");
|
|
427
|
+
await rename(markerPath, `${markerPath}.consumed`);
|
|
428
|
+
await rm(`${markerPath}.consumed`).catch(() => { });
|
|
429
|
+
}
|
|
430
|
+
catch {
|
|
431
|
+
if (process.env.KIT_ELEVATED !== "1") {
|
|
432
|
+
const reason = `Elevation for "${operation}" was already consumed by a concurrent process.`;
|
|
433
|
+
await auditElevationDecision(operation, false, reason, "none", cwd);
|
|
434
|
+
return { ok: false, reason };
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
consumedInProcess.add(operation);
|
|
438
|
+
return result;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Test-only: reset the in-process consumed-scope set. Public so tests can
|
|
442
|
+
* exercise the one-shot semantics deterministically without spawning new
|
|
443
|
+
* processes.
|
|
444
|
+
*/
|
|
445
|
+
export function _resetConsumedElevationForTests() {
|
|
446
|
+
consumedInProcess.clear();
|
|
447
|
+
warnedAboutCiBypass = false;
|
|
448
|
+
}
|
|
449
|
+
//# sourceMappingURL=elevation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"elevation.js","sourceRoot":"","sources":["../src/elevation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compare two .env-style files (or local vs vault state) and surface drift.
|
|
3
|
+
*
|
|
4
|
+
* Used by `kit env diff --compare staging` to spot when a developer's
|
|
5
|
+
* local .env.local has drifted from .env.staging — common cause of bugs
|
|
6
|
+
* that only reproduce in one environment.
|
|
7
|
+
*
|
|
8
|
+
* Reads via the existing planMigration() path so we honor the same KEY=VALUE
|
|
9
|
+
* parsing (quote-stripping, comment skipping, validation). Output is a
|
|
10
|
+
* diff-summary: only-in-A, only-in-B, value-different-keys. Values
|
|
11
|
+
* themselves are NEVER printed — only key-presence + a hash-prefix to
|
|
12
|
+
* confirm they differ.
|
|
13
|
+
*/
|
|
14
|
+
export interface EnvDiffResult {
|
|
15
|
+
onlyInA: string[];
|
|
16
|
+
onlyInB: string[];
|
|
17
|
+
/** Keys present in both with different values. */
|
|
18
|
+
changed: Array<{
|
|
19
|
+
key: string;
|
|
20
|
+
aHash: string;
|
|
21
|
+
bHash: string;
|
|
22
|
+
}>;
|
|
23
|
+
/** Keys with identical values (rendered only as count). */
|
|
24
|
+
identicalCount: number;
|
|
25
|
+
}
|
|
26
|
+
export declare function diffEnvFiles(pathA: string, pathB: string, cwd?: string): Promise<EnvDiffResult>;
|
|
27
|
+
export declare function formatEnvDiff(diff: EnvDiffResult, labelA: string, labelB: string): string;
|
package/dist/env-diff.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compare two .env-style files (or local vs vault state) and surface drift.
|
|
3
|
+
*
|
|
4
|
+
* Used by `kit env diff --compare staging` to spot when a developer's
|
|
5
|
+
* local .env.local has drifted from .env.staging — common cause of bugs
|
|
6
|
+
* that only reproduce in one environment.
|
|
7
|
+
*
|
|
8
|
+
* Reads via the existing planMigration() path so we honor the same KEY=VALUE
|
|
9
|
+
* parsing (quote-stripping, comment skipping, validation). Output is a
|
|
10
|
+
* diff-summary: only-in-A, only-in-B, value-different-keys. Values
|
|
11
|
+
* themselves are NEVER printed — only key-presence + a hash-prefix to
|
|
12
|
+
* confirm they differ.
|
|
13
|
+
*/
|
|
14
|
+
import { readFile } from "node:fs/promises";
|
|
15
|
+
import { resolve } from "node:path";
|
|
16
|
+
import { createHash } from "node:crypto";
|
|
17
|
+
import { isValidKeyName } from "./secrets-migrate.js";
|
|
18
|
+
async function parseEnvFile(path) {
|
|
19
|
+
const out = new Map();
|
|
20
|
+
let text;
|
|
21
|
+
try {
|
|
22
|
+
text = await readFile(path, "utf-8");
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
for (const rawLine of text.split("\n")) {
|
|
28
|
+
const line = rawLine.trim();
|
|
29
|
+
if (!line || line.startsWith("#"))
|
|
30
|
+
continue;
|
|
31
|
+
const eq = line.indexOf("=");
|
|
32
|
+
if (eq <= 0)
|
|
33
|
+
continue;
|
|
34
|
+
const key = line.slice(0, eq).trim();
|
|
35
|
+
let value = line.slice(eq + 1).trim();
|
|
36
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
37
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
38
|
+
value = value.slice(1, -1);
|
|
39
|
+
}
|
|
40
|
+
if (!isValidKeyName(key))
|
|
41
|
+
continue;
|
|
42
|
+
out.set(key, value);
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
function hashPrefix(value) {
|
|
47
|
+
return createHash("sha256").update(value).digest("hex").slice(0, 8);
|
|
48
|
+
}
|
|
49
|
+
export async function diffEnvFiles(pathA, pathB, cwd = process.cwd()) {
|
|
50
|
+
const a = await parseEnvFile(resolve(cwd, pathA));
|
|
51
|
+
const b = await parseEnvFile(resolve(cwd, pathB));
|
|
52
|
+
const onlyInA = [];
|
|
53
|
+
const onlyInB = [];
|
|
54
|
+
const changed = [];
|
|
55
|
+
let identicalCount = 0;
|
|
56
|
+
for (const [k, vA] of a) {
|
|
57
|
+
if (!b.has(k)) {
|
|
58
|
+
onlyInA.push(k);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
const vB = b.get(k);
|
|
62
|
+
if (vA === vB)
|
|
63
|
+
identicalCount++;
|
|
64
|
+
else
|
|
65
|
+
changed.push({ key: k, aHash: hashPrefix(vA), bHash: hashPrefix(vB) });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
for (const k of b.keys()) {
|
|
69
|
+
if (!a.has(k))
|
|
70
|
+
onlyInB.push(k);
|
|
71
|
+
}
|
|
72
|
+
onlyInA.sort();
|
|
73
|
+
onlyInB.sort();
|
|
74
|
+
changed.sort((x, y) => x.key.localeCompare(y.key));
|
|
75
|
+
return { onlyInA, onlyInB, changed, identicalCount };
|
|
76
|
+
}
|
|
77
|
+
export function formatEnvDiff(diff, labelA, labelB) {
|
|
78
|
+
const lines = [];
|
|
79
|
+
lines.push(`env-diff ${labelA} vs ${labelB}`);
|
|
80
|
+
lines.push("─".repeat(50));
|
|
81
|
+
lines.push("");
|
|
82
|
+
if (diff.changed.length > 0) {
|
|
83
|
+
lines.push(`Changed (${diff.changed.length}):`);
|
|
84
|
+
for (const c of diff.changed) {
|
|
85
|
+
lines.push(` ⚠ ${c.key} ${labelA}=${c.aHash}… ${labelB}=${c.bHash}…`);
|
|
86
|
+
}
|
|
87
|
+
lines.push("");
|
|
88
|
+
}
|
|
89
|
+
if (diff.onlyInA.length > 0) {
|
|
90
|
+
lines.push(`Only in ${labelA} (${diff.onlyInA.length}):`);
|
|
91
|
+
for (const k of diff.onlyInA)
|
|
92
|
+
lines.push(` + ${k}`);
|
|
93
|
+
lines.push("");
|
|
94
|
+
}
|
|
95
|
+
if (diff.onlyInB.length > 0) {
|
|
96
|
+
lines.push(`Only in ${labelB} (${diff.onlyInB.length}):`);
|
|
97
|
+
for (const k of diff.onlyInB)
|
|
98
|
+
lines.push(` - ${k}`);
|
|
99
|
+
lines.push("");
|
|
100
|
+
}
|
|
101
|
+
lines.push(`Identical keys: ${diff.identicalCount}`);
|
|
102
|
+
return lines.join("\n");
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=env-diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-diff.js","sourceRoot":"","sources":["../src/env-diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { kitConfig } from "./config.js";
|
|
2
|
+
export interface EnvKeyStatus {
|
|
3
|
+
name: string;
|
|
4
|
+
set: boolean;
|
|
5
|
+
value?: string;
|
|
6
|
+
redacted?: string;
|
|
7
|
+
source: string;
|
|
8
|
+
}
|
|
9
|
+
export interface EnvInspectResult {
|
|
10
|
+
ok: boolean;
|
|
11
|
+
keys: EnvKeyStatus[];
|
|
12
|
+
envLocalExists: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface InspectOptions {
|
|
15
|
+
showValues?: boolean;
|
|
16
|
+
missingOnly?: boolean;
|
|
17
|
+
cwd?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Parse a .env file into a key-value record.
|
|
21
|
+
* Handles blank lines, comments (#), and quoted values.
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseEnvFile(content: string): Record<string, string>;
|
|
24
|
+
/**
|
|
25
|
+
* Redact a secret value: show first 4 chars + ****
|
|
26
|
+
*/
|
|
27
|
+
export declare function redactValue(value: string): string;
|
|
28
|
+
export declare function inspectEnv(config: kitConfig, options?: InspectOptions): Promise<EnvInspectResult>;
|