vibecheck-ai 2.0.1 ā 5.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/bin/.generated +25 -0
- package/bin/_deprecations.js +463 -0
- package/bin/_router.js +46 -0
- package/bin/cli-hygiene.js +241 -0
- package/bin/dev/run-v2-torture.js +30 -0
- package/bin/registry.js +656 -0
- package/bin/runners/CLI_REFACTOR_SUMMARY.md +229 -0
- package/bin/runners/ENHANCEMENT_GUIDE.md +121 -0
- package/bin/runners/REPORT_AUDIT.md +64 -0
- package/bin/runners/cli-utils.js +1070 -0
- package/bin/runners/context/ai-task-decomposer.js +337 -0
- package/bin/runners/context/analyzer.js +513 -0
- package/bin/runners/context/api-contracts.js +427 -0
- package/bin/runners/context/context-diff.js +342 -0
- package/bin/runners/context/context-pruner.js +291 -0
- package/bin/runners/context/dependency-graph.js +414 -0
- package/bin/runners/context/generators/claude.js +107 -0
- package/bin/runners/context/generators/codex.js +108 -0
- package/bin/runners/context/generators/copilot.js +119 -0
- package/bin/runners/context/generators/cursor-enhanced.js +2525 -0
- package/bin/runners/context/generators/cursor.js +514 -0
- package/bin/runners/context/generators/mcp.js +169 -0
- package/bin/runners/context/generators/windsurf.js +180 -0
- package/bin/runners/context/git-context.js +304 -0
- package/bin/runners/context/index.js +1110 -0
- package/bin/runners/context/insights.js +173 -0
- package/bin/runners/context/mcp-server/generate-rules.js +337 -0
- package/bin/runners/context/mcp-server/index.js +1176 -0
- package/bin/runners/context/mcp-server/package.json +24 -0
- package/bin/runners/context/memory.js +200 -0
- package/bin/runners/context/monorepo.js +215 -0
- package/bin/runners/context/multi-repo-federation.js +404 -0
- package/bin/runners/context/patterns.js +253 -0
- package/bin/runners/context/proof-context.js +1264 -0
- package/bin/runners/context/security-scanner.js +541 -0
- package/bin/runners/context/semantic-search.js +350 -0
- package/bin/runners/context/shared.js +264 -0
- package/bin/runners/context/team-conventions.js +336 -0
- package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -0
- package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +474 -0
- package/bin/runners/lib/agent-firewall/change-packet/builder.js +488 -0
- package/bin/runners/lib/agent-firewall/change-packet/schema.json +228 -0
- package/bin/runners/lib/agent-firewall/change-packet/store.js +200 -0
- package/bin/runners/lib/agent-firewall/claims/claim-types.js +21 -0
- package/bin/runners/lib/agent-firewall/claims/extractor.js +303 -0
- package/bin/runners/lib/agent-firewall/claims/patterns.js +24 -0
- package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
- package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
- package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
- package/bin/runners/lib/agent-firewall/enforcement/gateway.js +1059 -0
- package/bin/runners/lib/agent-firewall/enforcement/index.js +98 -0
- package/bin/runners/lib/agent-firewall/enforcement/mode.js +318 -0
- package/bin/runners/lib/agent-firewall/enforcement/orchestrator.js +484 -0
- package/bin/runners/lib/agent-firewall/enforcement/proof-artifact.js +418 -0
- package/bin/runners/lib/agent-firewall/enforcement/schemas/change-event.schema.json +173 -0
- package/bin/runners/lib/agent-firewall/enforcement/schemas/intent.schema.json +181 -0
- package/bin/runners/lib/agent-firewall/enforcement/schemas/verdict.schema.json +222 -0
- package/bin/runners/lib/agent-firewall/enforcement/verdict-v2.js +333 -0
- package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +88 -0
- package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +75 -0
- package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +127 -0
- package/bin/runners/lib/agent-firewall/evidence/resolver.js +102 -0
- package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +213 -0
- package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +145 -0
- package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +19 -0
- package/bin/runners/lib/agent-firewall/fs-hook/installer.js +87 -0
- package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +184 -0
- package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +163 -0
- package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +107 -0
- package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +68 -0
- package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +66 -0
- package/bin/runners/lib/agent-firewall/index.js +200 -0
- package/bin/runners/lib/agent-firewall/integration/index.js +20 -0
- package/bin/runners/lib/agent-firewall/integration/ship-gate.js +437 -0
- package/bin/runners/lib/agent-firewall/intent/alignment-engine.js +634 -0
- package/bin/runners/lib/agent-firewall/intent/auto-detect.js +426 -0
- package/bin/runners/lib/agent-firewall/intent/index.js +102 -0
- package/bin/runners/lib/agent-firewall/intent/schema.js +352 -0
- package/bin/runners/lib/agent-firewall/intent/store.js +283 -0
- package/bin/runners/lib/agent-firewall/interception/fs-interceptor.js +502 -0
- package/bin/runners/lib/agent-firewall/interception/index.js +23 -0
- package/bin/runners/lib/agent-firewall/interceptor/base.js +308 -0
- package/bin/runners/lib/agent-firewall/interceptor/cursor.js +35 -0
- package/bin/runners/lib/agent-firewall/interceptor/vscode.js +35 -0
- package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +34 -0
- package/bin/runners/lib/agent-firewall/lawbook/distributor.js +465 -0
- package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
- package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
- package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
- package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
- package/bin/runners/lib/agent-firewall/logger.js +141 -0
- package/bin/runners/lib/agent-firewall/policy/default-policy.json +90 -0
- package/bin/runners/lib/agent-firewall/policy/engine.js +103 -0
- package/bin/runners/lib/agent-firewall/policy/loader.js +451 -0
- package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +50 -0
- package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +50 -0
- package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +79 -0
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +227 -0
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +191 -0
- package/bin/runners/lib/agent-firewall/policy/rules/scope.js +93 -0
- package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +57 -0
- package/bin/runners/lib/agent-firewall/policy/schema.json +183 -0
- package/bin/runners/lib/agent-firewall/policy/verdict.js +54 -0
- package/bin/runners/lib/agent-firewall/proposal/extractor.js +394 -0
- package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
- package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
- package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
- package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
- package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
- package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
- package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
- package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
- package/bin/runners/lib/agent-firewall/risk/thresholds.js +322 -0
- package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
- package/bin/runners/lib/agent-firewall/session/collector.js +451 -0
- package/bin/runners/lib/agent-firewall/session/index.js +26 -0
- package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
- package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
- package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
- package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
- package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
- package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
- package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
- package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
- package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
- package/bin/runners/lib/agent-firewall/truthpack/index.js +67 -0
- package/bin/runners/lib/agent-firewall/truthpack/loader.js +137 -0
- package/bin/runners/lib/agent-firewall/unblock/planner.js +337 -0
- package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +118 -0
- package/bin/runners/lib/ai-bridge.js +416 -0
- package/bin/runners/lib/analysis-core.js +309 -0
- package/bin/runners/lib/analyzers.js +2500 -0
- package/bin/runners/lib/api-client.js +269 -0
- package/bin/runners/lib/approve-output.js +235 -0
- package/bin/runners/lib/artifact-envelope.js +540 -0
- package/bin/runners/lib/assets/vibecheck-logo.png +0 -0
- package/bin/runners/lib/audit-bridge.js +391 -0
- package/bin/runners/lib/auth-shared.js +977 -0
- package/bin/runners/lib/auth-truth.js +193 -0
- package/bin/runners/lib/auth.js +215 -0
- package/bin/runners/lib/authority-badge.js +425 -0
- package/bin/runners/lib/backup.js +62 -0
- package/bin/runners/lib/billing.js +107 -0
- package/bin/runners/lib/checkpoint.js +941 -0
- package/bin/runners/lib/claims.js +118 -0
- package/bin/runners/lib/classify-output.js +204 -0
- package/bin/runners/lib/cleanup/engine.js +571 -0
- package/bin/runners/lib/cleanup/index.js +53 -0
- package/bin/runners/lib/cleanup/output.js +375 -0
- package/bin/runners/lib/cleanup/rules.js +1060 -0
- package/bin/runners/lib/cli-output.js +400 -0
- package/bin/runners/lib/cli-ui.js +540 -0
- package/bin/runners/lib/compliance-bridge-new.js +0 -0
- package/bin/runners/lib/compliance-bridge.js +165 -0
- package/bin/runners/lib/contracts/auth-contract.js +202 -0
- package/bin/runners/lib/contracts/env-contract.js +181 -0
- package/bin/runners/lib/contracts/external-contract.js +206 -0
- package/bin/runners/lib/contracts/guard.js +168 -0
- package/bin/runners/lib/contracts/index.js +89 -0
- package/bin/runners/lib/contracts/plan-validator.js +311 -0
- package/bin/runners/lib/contracts/route-contract.js +199 -0
- package/bin/runners/lib/contracts.js +804 -0
- package/bin/runners/lib/default-config.js +127 -0
- package/bin/runners/lib/detect.js +89 -0
- package/bin/runners/lib/detectors-v2.js +622 -0
- package/bin/runners/lib/doctor/autofix.js +254 -0
- package/bin/runners/lib/doctor/diagnosis-receipt.js +454 -0
- package/bin/runners/lib/doctor/failure-signatures.js +526 -0
- package/bin/runners/lib/doctor/fix-script.js +336 -0
- package/bin/runners/lib/doctor/index.js +37 -0
- package/bin/runners/lib/doctor/modules/build-tools.js +453 -0
- package/bin/runners/lib/doctor/modules/dependencies.js +325 -0
- package/bin/runners/lib/doctor/modules/index.js +105 -0
- package/bin/runners/lib/doctor/modules/network.js +250 -0
- package/bin/runners/lib/doctor/modules/os-quirks.js +706 -0
- package/bin/runners/lib/doctor/modules/project.js +312 -0
- package/bin/runners/lib/doctor/modules/repo-integrity.js +485 -0
- package/bin/runners/lib/doctor/modules/runtime.js +224 -0
- package/bin/runners/lib/doctor/modules/security.js +350 -0
- package/bin/runners/lib/doctor/modules/system.js +213 -0
- package/bin/runners/lib/doctor/modules/vibecheck.js +394 -0
- package/bin/runners/lib/doctor/reporter.js +262 -0
- package/bin/runners/lib/doctor/safe-repair.js +384 -0
- package/bin/runners/lib/doctor/service.js +262 -0
- package/bin/runners/lib/doctor/types.js +113 -0
- package/bin/runners/lib/doctor/ui.js +263 -0
- package/bin/runners/lib/doctor-enhanced.js +233 -0
- package/bin/runners/lib/doctor-output.js +226 -0
- package/bin/runners/lib/doctor-v2.js +608 -0
- package/bin/runners/lib/drift.js +425 -0
- package/bin/runners/lib/enforcement.js +72 -0
- package/bin/runners/lib/engine/ast-cache.js +210 -0
- package/bin/runners/lib/engine/auth-extractor.js +211 -0
- package/bin/runners/lib/engine/billing-extractor.js +112 -0
- package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
- package/bin/runners/lib/engine/env-extractor.js +207 -0
- package/bin/runners/lib/engine/express-extractor.js +208 -0
- package/bin/runners/lib/engine/extractors.js +849 -0
- package/bin/runners/lib/engine/index.js +207 -0
- package/bin/runners/lib/engine/repo-index.js +514 -0
- package/bin/runners/lib/engine/types.js +124 -0
- package/bin/runners/lib/engines/accessibility-engine.js +190 -0
- package/bin/runners/lib/engines/api-consistency-engine.js +162 -0
- package/bin/runners/lib/engines/ast-cache.js +99 -0
- package/bin/runners/lib/engines/attack-detector.js +1192 -0
- package/bin/runners/lib/engines/code-quality-engine.js +255 -0
- package/bin/runners/lib/engines/console-logs-engine.js +115 -0
- package/bin/runners/lib/engines/cross-file-analysis-engine.js +268 -0
- package/bin/runners/lib/engines/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/deprecated-api-engine.js +226 -0
- package/bin/runners/lib/engines/empty-catch-engine.js +150 -0
- package/bin/runners/lib/engines/file-filter.js +131 -0
- package/bin/runners/lib/engines/hardcoded-secrets-engine.js +251 -0
- package/bin/runners/lib/engines/mock-data-engine.js +272 -0
- package/bin/runners/lib/engines/parallel-processor.js +71 -0
- package/bin/runners/lib/engines/performance-issues-engine.js +265 -0
- package/bin/runners/lib/engines/security-vulnerabilities-engine.js +243 -0
- package/bin/runners/lib/engines/todo-fixme-engine.js +115 -0
- package/bin/runners/lib/engines/type-aware-engine.js +152 -0
- package/bin/runners/lib/engines/unsafe-regex-engine.js +225 -0
- package/bin/runners/lib/engines/vibecheck-engines/README.md +53 -0
- package/bin/runners/lib/engines/vibecheck-engines/index.js +15 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +139 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
- package/bin/runners/lib/engines/vibecheck-engines/package.json +13 -0
- package/bin/runners/lib/enterprise-detect.js +603 -0
- package/bin/runners/lib/enterprise-init.js +942 -0
- package/bin/runners/lib/entitlements-v2.js +265 -0
- package/bin/runners/lib/entitlements.generated.js +0 -0
- package/bin/runners/lib/entitlements.js +340 -0
- package/bin/runners/lib/env-resolver.js +417 -0
- package/bin/runners/lib/env-template.js +66 -0
- package/bin/runners/lib/env.js +189 -0
- package/bin/runners/lib/error-handler.js +368 -0
- package/bin/runners/lib/error-messages.js +289 -0
- package/bin/runners/lib/evidence-pack.js +684 -0
- package/bin/runners/lib/exit-codes.js +275 -0
- package/bin/runners/lib/extractors/client-calls.js +990 -0
- package/bin/runners/lib/extractors/fastify-route-dump.js +573 -0
- package/bin/runners/lib/extractors/fastify-routes.js +426 -0
- package/bin/runners/lib/extractors/index.js +363 -0
- package/bin/runners/lib/extractors/next-routes.js +524 -0
- package/bin/runners/lib/extractors/proof-graph.js +431 -0
- package/bin/runners/lib/extractors/route-matcher.js +451 -0
- package/bin/runners/lib/extractors/truthpack-v2.js +377 -0
- package/bin/runners/lib/extractors/ui-bindings.js +547 -0
- package/bin/runners/lib/finding-id.js +69 -0
- package/bin/runners/lib/finding-sorter.js +89 -0
- package/bin/runners/lib/findings-schema.js +281 -0
- package/bin/runners/lib/fingerprint.js +377 -0
- package/bin/runners/lib/firewall-prompt.js +50 -0
- package/bin/runners/lib/fix-output.js +228 -0
- package/bin/runners/lib/global-flags.js +250 -0
- package/bin/runners/lib/graph/graph-builder.js +265 -0
- package/bin/runners/lib/graph/html-renderer.js +413 -0
- package/bin/runners/lib/graph/index.js +32 -0
- package/bin/runners/lib/graph/runtime-collector.js +215 -0
- package/bin/runners/lib/graph/static-extractor.js +518 -0
- package/bin/runners/lib/help-formatter.js +413 -0
- package/bin/runners/lib/html-proof-report.js +913 -0
- package/bin/runners/lib/html-report.js +650 -0
- package/bin/runners/lib/init-wizard.js +601 -0
- package/bin/runners/lib/interactive-menu.js +1496 -0
- package/bin/runners/lib/json-output.js +76 -0
- package/bin/runners/lib/llm.js +75 -0
- package/bin/runners/lib/logger.js +38 -0
- package/bin/runners/lib/meter.js +61 -0
- package/bin/runners/lib/missions/briefing.js +427 -0
- package/bin/runners/lib/missions/checkpoint.js +753 -0
- package/bin/runners/lib/missions/evidence.js +126 -0
- package/bin/runners/lib/missions/hardening.js +851 -0
- package/bin/runners/lib/missions/plan.js +648 -0
- package/bin/runners/lib/missions/safety-gates.js +645 -0
- package/bin/runners/lib/missions/schema.js +478 -0
- package/bin/runners/lib/missions/templates.js +317 -0
- package/bin/runners/lib/next-action.js +560 -0
- package/bin/runners/lib/packs/bundle.js +675 -0
- package/bin/runners/lib/packs/evidence-pack.js +671 -0
- package/bin/runners/lib/packs/pack-factory.js +837 -0
- package/bin/runners/lib/packs/permissions-pack.js +686 -0
- package/bin/runners/lib/packs/proof-graph-pack.js +779 -0
- package/bin/runners/lib/patch.js +40 -0
- package/bin/runners/lib/permissions/auth-model.js +213 -0
- package/bin/runners/lib/permissions/idor-prover.js +205 -0
- package/bin/runners/lib/permissions/index.js +45 -0
- package/bin/runners/lib/permissions/matrix-builder.js +198 -0
- package/bin/runners/lib/pkgjson.js +28 -0
- package/bin/runners/lib/policy.js +295 -0
- package/bin/runners/lib/polish/accessibility.js +62 -0
- package/bin/runners/lib/polish/analyzer.js +93 -0
- package/bin/runners/lib/polish/backend.js +87 -0
- package/bin/runners/lib/polish/configuration.js +83 -0
- package/bin/runners/lib/polish/documentation.js +83 -0
- package/bin/runners/lib/polish/frontend.js +817 -0
- package/bin/runners/lib/polish/index.js +27 -0
- package/bin/runners/lib/polish/infrastructure.js +80 -0
- package/bin/runners/lib/polish/internationalization.js +85 -0
- package/bin/runners/lib/polish/libraries.js +180 -0
- package/bin/runners/lib/polish/observability.js +75 -0
- package/bin/runners/lib/polish/performance.js +64 -0
- package/bin/runners/lib/polish/privacy.js +110 -0
- package/bin/runners/lib/polish/resilience.js +92 -0
- package/bin/runners/lib/polish/security.js +78 -0
- package/bin/runners/lib/polish/seo.js +71 -0
- package/bin/runners/lib/polish/styles.js +62 -0
- package/bin/runners/lib/polish/utils.js +104 -0
- package/bin/runners/lib/preflight.js +142 -0
- package/bin/runners/lib/prerequisites.js +149 -0
- package/bin/runners/lib/prove-output.js +220 -0
- package/bin/runners/lib/reality/correlation-detectors.js +359 -0
- package/bin/runners/lib/reality/index.js +318 -0
- package/bin/runners/lib/reality/request-hashing.js +416 -0
- package/bin/runners/lib/reality/request-mapper.js +453 -0
- package/bin/runners/lib/reality/safety-rails.js +463 -0
- package/bin/runners/lib/reality/semantic-snapshot.js +408 -0
- package/bin/runners/lib/reality/toast-detector.js +393 -0
- package/bin/runners/lib/reality-findings.js +84 -0
- package/bin/runners/lib/reality-output.js +231 -0
- package/bin/runners/lib/receipts.js +179 -0
- package/bin/runners/lib/redact.js +29 -0
- package/bin/runners/lib/replay/capsule-manager.js +154 -0
- package/bin/runners/lib/replay/index.js +263 -0
- package/bin/runners/lib/replay/player.js +348 -0
- package/bin/runners/lib/replay/recorder.js +331 -0
- package/bin/runners/lib/report-engine.js +626 -0
- package/bin/runners/lib/report-html.js +1233 -0
- package/bin/runners/lib/report-output.js +366 -0
- package/bin/runners/lib/report-templates.js +967 -0
- package/bin/runners/lib/report.js +135 -0
- package/bin/runners/lib/route-detection.js +1209 -0
- package/bin/runners/lib/route-truth.js +1322 -0
- package/bin/runners/lib/safelist/index.js +96 -0
- package/bin/runners/lib/safelist/integration.js +334 -0
- package/bin/runners/lib/safelist/matcher.js +696 -0
- package/bin/runners/lib/safelist/schema.js +948 -0
- package/bin/runners/lib/safelist/store.js +438 -0
- package/bin/runners/lib/sandbox/index.js +59 -0
- package/bin/runners/lib/sandbox/proof-chain.js +399 -0
- package/bin/runners/lib/sandbox/sandbox-runner.js +205 -0
- package/bin/runners/lib/sandbox/worktree.js +174 -0
- package/bin/runners/lib/scan-cache.js +330 -0
- package/bin/runners/lib/scan-output-schema.js +344 -0
- package/bin/runners/lib/scan-output.js +631 -0
- package/bin/runners/lib/scan-runner.js +135 -0
- package/bin/runners/lib/schema-validator.js +350 -0
- package/bin/runners/lib/schemas/ajv-validator.js +464 -0
- package/bin/runners/lib/schemas/contracts.schema.json +160 -0
- package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
- package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
- package/bin/runners/lib/schemas/finding.schema.json +100 -0
- package/bin/runners/lib/schemas/mission-pack.schema.json +206 -0
- package/bin/runners/lib/schemas/proof-graph.schema.json +176 -0
- package/bin/runners/lib/schemas/reality-report.schema.json +162 -0
- package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
- package/bin/runners/lib/schemas/run-request.schema.json +108 -0
- package/bin/runners/lib/schemas/share-pack.schema.json +180 -0
- package/bin/runners/lib/schemas/ship-manifest.schema.json +251 -0
- package/bin/runners/lib/schemas/ship-report.schema.json +117 -0
- package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -0
- package/bin/runners/lib/schemas/validator.js +465 -0
- package/bin/runners/lib/schemas/verdict.schema.json +140 -0
- package/bin/runners/lib/score-history.js +282 -0
- package/bin/runners/lib/security-bridge.js +249 -0
- package/bin/runners/lib/server-usage.js +513 -0
- package/bin/runners/lib/share-pack.js +239 -0
- package/bin/runners/lib/ship-gate.js +832 -0
- package/bin/runners/lib/ship-manifest.js +1153 -0
- package/bin/runners/lib/ship-output-enterprise.js +239 -0
- package/bin/runners/lib/ship-output.js +1128 -0
- package/bin/runners/lib/snippets.js +67 -0
- package/bin/runners/lib/status-output.js +340 -0
- package/bin/runners/lib/terminal-ui.js +356 -0
- package/bin/runners/lib/truth.js +1691 -0
- package/bin/runners/lib/ui.js +562 -0
- package/bin/runners/lib/unified-cli-output.js +947 -0
- package/bin/runners/lib/unified-output.js +197 -0
- package/bin/runners/lib/upsell.js +410 -0
- package/bin/runners/lib/usage.js +153 -0
- package/bin/runners/lib/validate-patch.js +156 -0
- package/bin/runners/lib/verdict-engine.js +628 -0
- package/bin/runners/lib/verification.js +345 -0
- package/bin/runners/lib/why-tree.js +650 -0
- package/bin/runners/reality/engine.js +917 -0
- package/bin/runners/reality/flows.js +122 -0
- package/bin/runners/reality/report.js +378 -0
- package/bin/runners/reality/session.js +193 -0
- package/bin/runners/runAIAgent.js +229 -0
- package/bin/runners/runAgent.d.ts +5 -0
- package/bin/runners/runAgent.js +161 -0
- package/bin/runners/runAllowlist.js +418 -0
- package/bin/runners/runApprove.js +320 -0
- package/bin/runners/runAudit.js +692 -0
- package/bin/runners/runAuth.js +731 -0
- package/bin/runners/runCI.js +353 -0
- package/bin/runners/runCheckpoint.js +530 -0
- package/bin/runners/runClassify.js +928 -0
- package/bin/runners/runCleanup.js +343 -0
- package/bin/runners/runContext.d.ts +4 -0
- package/bin/runners/runContext.js +175 -0
- package/bin/runners/runDoctor.js +877 -0
- package/bin/runners/runEvidencePack.js +362 -0
- package/bin/runners/runFirewall.d.ts +5 -0
- package/bin/runners/runFirewall.js +134 -0
- package/bin/runners/runFirewallHook.d.ts +5 -0
- package/bin/runners/runFirewallHook.js +56 -0
- package/bin/runners/runFix.js +1355 -0
- package/bin/runners/runForge.js +451 -0
- package/bin/runners/runGuard.js +262 -0
- package/bin/runners/runInit.js +1927 -0
- package/bin/runners/runIntent.js +906 -0
- package/bin/runners/runKickoff.js +878 -0
- package/bin/runners/runLabs.js +424 -0
- package/bin/runners/runLaunch.js +2000 -0
- package/bin/runners/runLink.js +785 -0
- package/bin/runners/runMcp.js +1875 -0
- package/bin/runners/runPacks.js +2089 -0
- package/bin/runners/runPolish.d.ts +4 -0
- package/bin/runners/runPolish.js +390 -0
- package/bin/runners/runPromptFirewall.js +211 -0
- package/bin/runners/runProve.js +1411 -0
- package/bin/runners/runQuickstart.js +531 -0
- package/bin/runners/runReality.js +2260 -0
- package/bin/runners/runReport.js +726 -0
- package/bin/runners/runRuntime.js +110 -0
- package/bin/runners/runSafelist.js +1190 -0
- package/bin/runners/runScan.js +688 -0
- package/bin/runners/runShield.js +1282 -0
- package/bin/runners/runShip.js +1660 -0
- package/bin/runners/runTruth.d.ts +5 -0
- package/bin/runners/runTruth.js +101 -0
- package/bin/runners/runValidate.js +179 -0
- package/bin/runners/runWatch.js +478 -0
- package/bin/runners/utils.js +360 -0
- package/bin/scan.js +617 -0
- package/bin/vibecheck.js +1617 -0
- package/dist/guardrail/index.d.ts +2405 -0
- package/dist/guardrail/index.js +9747 -0
- package/dist/guardrail/index.js.map +1 -0
- package/dist/scanner/index.d.ts +282 -0
- package/dist/scanner/index.js +3395 -0
- package/dist/scanner/index.js.map +1 -0
- package/package.json +123 -104
- package/README.md +0 -491
- package/dist/index.js +0 -99711
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,804 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contracts Generator + Drift Detector v2
|
|
3
|
+
*
|
|
4
|
+
* Generates contracts from truthpack and detects drift between runs.
|
|
5
|
+
* The hallucination stopper - AI can't invent endpoints, env vars, or auth.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
"use strict";
|
|
9
|
+
|
|
10
|
+
const fs = require("fs");
|
|
11
|
+
const path = require("path");
|
|
12
|
+
const crypto = require("crypto");
|
|
13
|
+
|
|
14
|
+
const { createFinding, getSeverity } = require("./schemas/validator");
|
|
15
|
+
|
|
16
|
+
// =============================================================================
|
|
17
|
+
// CONTRACT TYPES
|
|
18
|
+
// =============================================================================
|
|
19
|
+
|
|
20
|
+
const CONTRACT_TYPES = {
|
|
21
|
+
ROUTES: "routes",
|
|
22
|
+
ENV: "env",
|
|
23
|
+
AUTH: "auth",
|
|
24
|
+
EXTERNAL: "external",
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// =============================================================================
|
|
28
|
+
// CONTRACT GENERATION
|
|
29
|
+
// =============================================================================
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Generate all contracts from truthpack
|
|
33
|
+
*/
|
|
34
|
+
function generateContracts(truthpack, options = {}) {
|
|
35
|
+
const { includeInternal = false } = options;
|
|
36
|
+
|
|
37
|
+
const contracts = {
|
|
38
|
+
meta: {
|
|
39
|
+
version: "2.0.0",
|
|
40
|
+
generatedAt: new Date().toISOString(),
|
|
41
|
+
truthpackHash: computeHash(JSON.stringify(truthpack)),
|
|
42
|
+
},
|
|
43
|
+
routes: generateRouteContract(truthpack),
|
|
44
|
+
env: generateEnvContract(truthpack),
|
|
45
|
+
auth: generateAuthContract(truthpack),
|
|
46
|
+
external: generateExternalContract(truthpack),
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// Compute contract hashes
|
|
50
|
+
contracts.hashes = {
|
|
51
|
+
routes: computeHash(JSON.stringify(contracts.routes)),
|
|
52
|
+
env: computeHash(JSON.stringify(contracts.env)),
|
|
53
|
+
auth: computeHash(JSON.stringify(contracts.auth)),
|
|
54
|
+
external: computeHash(JSON.stringify(contracts.external)),
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
return contracts;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Generate route contract
|
|
62
|
+
*/
|
|
63
|
+
function generateRouteContract(truthpack) {
|
|
64
|
+
const routes = truthpack?.routes?.server || [];
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
endpoints: routes.map(r => ({
|
|
68
|
+
method: r.method,
|
|
69
|
+
path: r.path,
|
|
70
|
+
file: r.file,
|
|
71
|
+
confidence: r.confidence,
|
|
72
|
+
authRequired: r.authRequired || false,
|
|
73
|
+
paidOnly: r.paidOnly || false,
|
|
74
|
+
})),
|
|
75
|
+
count: routes.length,
|
|
76
|
+
byMethod: countByField(routes, "method"),
|
|
77
|
+
byConfidence: countByField(routes, "confidence"),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Generate env contract
|
|
83
|
+
*/
|
|
84
|
+
function generateEnvContract(truthpack) {
|
|
85
|
+
const env = truthpack?.env || {};
|
|
86
|
+
const vars = env.vars || [];
|
|
87
|
+
const declared = env.declared || [];
|
|
88
|
+
|
|
89
|
+
// Classify vars by prefix
|
|
90
|
+
const classified = {
|
|
91
|
+
public: vars.filter(v => v.name.startsWith("NEXT_PUBLIC_") || v.name.startsWith("VITE_")),
|
|
92
|
+
server: vars.filter(v => !v.name.startsWith("NEXT_PUBLIC_") && !v.name.startsWith("VITE_")),
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// Required vs optional (heuristic: used in multiple files = required)
|
|
96
|
+
const required = vars.filter(v => v.usageCount > 1 || v.required);
|
|
97
|
+
const optional = vars.filter(v => v.usageCount <= 1 && !v.required);
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
variables: vars.map(v => ({
|
|
101
|
+
name: v.name,
|
|
102
|
+
required: v.required || v.usageCount > 1,
|
|
103
|
+
public: v.name.startsWith("NEXT_PUBLIC_") || v.name.startsWith("VITE_"),
|
|
104
|
+
declaredIn: declared.includes(v.name) ? ".env.example" : null,
|
|
105
|
+
usageCount: v.usageCount || 1,
|
|
106
|
+
})),
|
|
107
|
+
count: vars.length,
|
|
108
|
+
requiredCount: required.length,
|
|
109
|
+
publicCount: classified.public.length,
|
|
110
|
+
declared: declared,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Generate auth contract
|
|
116
|
+
*/
|
|
117
|
+
function generateAuthContract(truthpack) {
|
|
118
|
+
const auth = truthpack?.auth || {};
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
providers: auth.providers || [],
|
|
122
|
+
protectedPatterns: auth.nextMatcherPatterns || [],
|
|
123
|
+
middleware: {
|
|
124
|
+
next: auth.nextMiddleware?.length > 0,
|
|
125
|
+
fastify: auth.fastify?.preHandlerHooks?.length > 0,
|
|
126
|
+
},
|
|
127
|
+
rbacDetected: auth.rbacPatterns?.length > 0,
|
|
128
|
+
signals: {
|
|
129
|
+
sessionChecks: auth.sessionChecks || [],
|
|
130
|
+
redirects: auth.redirects || [],
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Generate external services contract
|
|
137
|
+
*/
|
|
138
|
+
function generateExternalContract(truthpack) {
|
|
139
|
+
const billing = truthpack?.billing || {};
|
|
140
|
+
const integrations = truthpack?.integrations || [];
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
stripe: {
|
|
144
|
+
detected: billing.stripeDetected || false,
|
|
145
|
+
webhookVerified: billing.webhookSignatureVerification || false,
|
|
146
|
+
products: billing.products || [],
|
|
147
|
+
},
|
|
148
|
+
services: integrations.map(i => ({
|
|
149
|
+
name: i.name,
|
|
150
|
+
type: i.type,
|
|
151
|
+
envVars: i.envVars || [],
|
|
152
|
+
})),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// =============================================================================
|
|
157
|
+
// DRIFT DETECTION
|
|
158
|
+
// =============================================================================
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Detect drift between two contract sets
|
|
162
|
+
*/
|
|
163
|
+
function detectDrift(currentContracts, previousContracts, options = {}) {
|
|
164
|
+
const { strict = false } = options;
|
|
165
|
+
|
|
166
|
+
const findings = [];
|
|
167
|
+
|
|
168
|
+
// Route drift
|
|
169
|
+
const routeDrift = detectRouteDrift(
|
|
170
|
+
currentContracts.routes,
|
|
171
|
+
previousContracts.routes,
|
|
172
|
+
{ strict }
|
|
173
|
+
);
|
|
174
|
+
findings.push(...routeDrift);
|
|
175
|
+
|
|
176
|
+
// Env drift
|
|
177
|
+
const envDrift = detectEnvDrift(
|
|
178
|
+
currentContracts.env,
|
|
179
|
+
previousContracts.env,
|
|
180
|
+
{ strict }
|
|
181
|
+
);
|
|
182
|
+
findings.push(...envDrift);
|
|
183
|
+
|
|
184
|
+
// Auth drift
|
|
185
|
+
const authDrift = detectAuthDrift(
|
|
186
|
+
currentContracts.auth,
|
|
187
|
+
previousContracts.auth,
|
|
188
|
+
{ strict }
|
|
189
|
+
);
|
|
190
|
+
findings.push(...authDrift);
|
|
191
|
+
|
|
192
|
+
// External drift
|
|
193
|
+
const externalDrift = detectExternalDrift(
|
|
194
|
+
currentContracts.external,
|
|
195
|
+
previousContracts.external,
|
|
196
|
+
{ strict }
|
|
197
|
+
);
|
|
198
|
+
findings.push(...externalDrift);
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
hasDrift: findings.length > 0,
|
|
202
|
+
findings,
|
|
203
|
+
summary: {
|
|
204
|
+
routes: routeDrift.length,
|
|
205
|
+
env: envDrift.length,
|
|
206
|
+
auth: authDrift.length,
|
|
207
|
+
external: externalDrift.length,
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Detect route drift
|
|
214
|
+
*/
|
|
215
|
+
function detectRouteDrift(current, previous, options = {}) {
|
|
216
|
+
const findings = [];
|
|
217
|
+
const { strict } = options;
|
|
218
|
+
|
|
219
|
+
const currentPaths = new Set(current.endpoints.map(e => `${e.method}:${e.path}`));
|
|
220
|
+
const previousPaths = new Set(previous.endpoints.map(e => `${e.method}:${e.path}`));
|
|
221
|
+
|
|
222
|
+
// New routes (not in previous)
|
|
223
|
+
for (const ep of current.endpoints) {
|
|
224
|
+
const key = `${ep.method}:${ep.path}`;
|
|
225
|
+
if (!previousPaths.has(key)) {
|
|
226
|
+
findings.push(createFinding({
|
|
227
|
+
detectorId: "D_DRIFT_ROUTE_NEW",
|
|
228
|
+
severity: "INFO",
|
|
229
|
+
category: "ContractDrift",
|
|
230
|
+
scope: "contracts",
|
|
231
|
+
title: `New route added: ${ep.method} ${ep.path}`,
|
|
232
|
+
why: "Route was added since last contract sync",
|
|
233
|
+
confidence: "high",
|
|
234
|
+
path: ep.path,
|
|
235
|
+
method: ep.method,
|
|
236
|
+
evidence: [{
|
|
237
|
+
kind: "file",
|
|
238
|
+
file: ep.file,
|
|
239
|
+
reason: "New route definition",
|
|
240
|
+
}],
|
|
241
|
+
}));
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Removed routes (in previous but not current)
|
|
246
|
+
for (const ep of previous.endpoints) {
|
|
247
|
+
const key = `${ep.method}:${ep.path}`;
|
|
248
|
+
if (!currentPaths.has(key)) {
|
|
249
|
+
findings.push(createFinding({
|
|
250
|
+
detectorId: "D_DRIFT_ROUTE_REMOVED",
|
|
251
|
+
severity: strict ? "BLOCK" : "WARN",
|
|
252
|
+
category: "ContractDrift",
|
|
253
|
+
scope: "contracts",
|
|
254
|
+
title: `Route removed: ${ep.method} ${ep.path}`,
|
|
255
|
+
why: "Route existed in previous contract but is now missing",
|
|
256
|
+
confidence: "high",
|
|
257
|
+
path: ep.path,
|
|
258
|
+
method: ep.method,
|
|
259
|
+
evidence: [{
|
|
260
|
+
kind: "file",
|
|
261
|
+
file: ep.file,
|
|
262
|
+
reason: "Route no longer exists",
|
|
263
|
+
}],
|
|
264
|
+
}));
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Auth requirement changes
|
|
269
|
+
for (const ep of current.endpoints) {
|
|
270
|
+
const key = `${ep.method}:${ep.path}`;
|
|
271
|
+
const prev = previous.endpoints.find(p => `${p.method}:${p.path}` === key);
|
|
272
|
+
|
|
273
|
+
if (prev && prev.authRequired && !ep.authRequired) {
|
|
274
|
+
findings.push(createFinding({
|
|
275
|
+
detectorId: "D_DRIFT_AUTH_REMOVED",
|
|
276
|
+
severity: "BLOCK",
|
|
277
|
+
category: "ContractDrift",
|
|
278
|
+
scope: "contracts",
|
|
279
|
+
title: `Auth removed from route: ${ep.method} ${ep.path}`,
|
|
280
|
+
why: "Route previously required auth but no longer does",
|
|
281
|
+
confidence: "high",
|
|
282
|
+
path: ep.path,
|
|
283
|
+
method: ep.method,
|
|
284
|
+
evidence: [{
|
|
285
|
+
kind: "file",
|
|
286
|
+
file: ep.file,
|
|
287
|
+
reason: "Auth requirement removed",
|
|
288
|
+
}],
|
|
289
|
+
}));
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return findings;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Detect env drift
|
|
298
|
+
*/
|
|
299
|
+
function detectEnvDrift(current, previous, options = {}) {
|
|
300
|
+
const findings = [];
|
|
301
|
+
const { strict } = options;
|
|
302
|
+
|
|
303
|
+
const currentVars = new Set(current.variables.map(v => v.name));
|
|
304
|
+
const previousVars = new Set(previous.variables.map(v => v.name));
|
|
305
|
+
|
|
306
|
+
// New required env vars
|
|
307
|
+
for (const v of current.variables) {
|
|
308
|
+
if (v.required && !previousVars.has(v.name)) {
|
|
309
|
+
findings.push(createFinding({
|
|
310
|
+
detectorId: "D_DRIFT_ENV_NEW_REQUIRED",
|
|
311
|
+
severity: strict ? "BLOCK" : "WARN",
|
|
312
|
+
category: "ContractDrift",
|
|
313
|
+
scope: "contracts",
|
|
314
|
+
title: `New required env var: ${v.name}`,
|
|
315
|
+
why: "New required environment variable added",
|
|
316
|
+
confidence: "high",
|
|
317
|
+
evidence: [{
|
|
318
|
+
kind: "file",
|
|
319
|
+
reason: `${v.name} is required but not in previous contract`,
|
|
320
|
+
}],
|
|
321
|
+
}));
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Required vars removed (may break existing deployments)
|
|
326
|
+
for (const v of previous.variables) {
|
|
327
|
+
if (v.required && !currentVars.has(v.name)) {
|
|
328
|
+
findings.push(createFinding({
|
|
329
|
+
detectorId: "D_DRIFT_ENV_REMOVED",
|
|
330
|
+
severity: "INFO",
|
|
331
|
+
category: "ContractDrift",
|
|
332
|
+
scope: "contracts",
|
|
333
|
+
title: `Env var removed: ${v.name}`,
|
|
334
|
+
why: "Environment variable no longer used",
|
|
335
|
+
confidence: "high",
|
|
336
|
+
evidence: [{
|
|
337
|
+
kind: "file",
|
|
338
|
+
reason: `${v.name} was in previous contract but not current`,
|
|
339
|
+
}],
|
|
340
|
+
}));
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Public ā Server (security concern)
|
|
345
|
+
for (const v of current.variables) {
|
|
346
|
+
const prev = previous.variables.find(p => p.name === v.name);
|
|
347
|
+
if (prev && prev.public && !v.public) {
|
|
348
|
+
findings.push(createFinding({
|
|
349
|
+
detectorId: "D_DRIFT_ENV_PUBLIC_TO_SERVER",
|
|
350
|
+
severity: "INFO",
|
|
351
|
+
category: "ContractDrift",
|
|
352
|
+
scope: "contracts",
|
|
353
|
+
title: `Env var moved from public to server: ${v.name}`,
|
|
354
|
+
why: "Variable changed from public to server-only (good for security)",
|
|
355
|
+
confidence: "medium",
|
|
356
|
+
evidence: [{
|
|
357
|
+
kind: "file",
|
|
358
|
+
reason: `${v.name} prefix changed`,
|
|
359
|
+
}],
|
|
360
|
+
}));
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return findings;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Detect auth drift
|
|
369
|
+
*/
|
|
370
|
+
function detectAuthDrift(current, previous, options = {}) {
|
|
371
|
+
const findings = [];
|
|
372
|
+
|
|
373
|
+
// Protected patterns removed
|
|
374
|
+
const currentPatterns = new Set(current.protectedPatterns);
|
|
375
|
+
const previousPatterns = new Set(previous.protectedPatterns);
|
|
376
|
+
|
|
377
|
+
for (const pattern of previousPatterns) {
|
|
378
|
+
if (!currentPatterns.has(pattern)) {
|
|
379
|
+
findings.push(createFinding({
|
|
380
|
+
detectorId: "D_DRIFT_AUTH_PATTERN_REMOVED",
|
|
381
|
+
severity: "BLOCK",
|
|
382
|
+
category: "ContractDrift",
|
|
383
|
+
scope: "contracts",
|
|
384
|
+
title: `Protected pattern removed: ${pattern}`,
|
|
385
|
+
why: "Auth protection pattern was removed from middleware",
|
|
386
|
+
confidence: "high",
|
|
387
|
+
evidence: [{
|
|
388
|
+
kind: "file",
|
|
389
|
+
reason: `Pattern "${pattern}" no longer in matcher`,
|
|
390
|
+
}],
|
|
391
|
+
}));
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Middleware disabled
|
|
396
|
+
if (previous.middleware.next && !current.middleware.next) {
|
|
397
|
+
findings.push(createFinding({
|
|
398
|
+
detectorId: "D_DRIFT_AUTH_MIDDLEWARE_DISABLED",
|
|
399
|
+
severity: "BLOCK",
|
|
400
|
+
category: "ContractDrift",
|
|
401
|
+
scope: "contracts",
|
|
402
|
+
title: "Next.js auth middleware disabled",
|
|
403
|
+
why: "Auth middleware was active but is now disabled",
|
|
404
|
+
confidence: "high",
|
|
405
|
+
evidence: [{
|
|
406
|
+
kind: "file",
|
|
407
|
+
reason: "middleware.ts no longer exports auth matcher",
|
|
408
|
+
}],
|
|
409
|
+
}));
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
return findings;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Detect external service drift
|
|
417
|
+
*/
|
|
418
|
+
function detectExternalDrift(current, previous, options = {}) {
|
|
419
|
+
const findings = [];
|
|
420
|
+
|
|
421
|
+
// Stripe webhook verification removed
|
|
422
|
+
if (previous.stripe.webhookVerified && !current.stripe.webhookVerified) {
|
|
423
|
+
findings.push(createFinding({
|
|
424
|
+
detectorId: "D_DRIFT_STRIPE_VERIFY_REMOVED",
|
|
425
|
+
severity: "BLOCK",
|
|
426
|
+
category: "ContractDrift",
|
|
427
|
+
scope: "contracts",
|
|
428
|
+
title: "Stripe webhook verification removed",
|
|
429
|
+
why: "Stripe webhook signature verification was present but removed",
|
|
430
|
+
confidence: "high",
|
|
431
|
+
evidence: [{
|
|
432
|
+
kind: "file",
|
|
433
|
+
reason: "constructEvent or verifyHeader no longer called",
|
|
434
|
+
}],
|
|
435
|
+
}));
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
return findings;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// =============================================================================
|
|
442
|
+
// CONTRACT SYNC (ctx sync)
|
|
443
|
+
// =============================================================================
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Sync contracts - generate and save
|
|
447
|
+
*/
|
|
448
|
+
function syncContracts(truthpack, repoRoot) {
|
|
449
|
+
const contracts = generateContracts(truthpack);
|
|
450
|
+
|
|
451
|
+
const contractsDir = path.join(repoRoot, ".vibecheck", "contracts");
|
|
452
|
+
fs.mkdirSync(contractsDir, { recursive: true });
|
|
453
|
+
|
|
454
|
+
// Write individual contract files
|
|
455
|
+
for (const type of Object.values(CONTRACT_TYPES)) {
|
|
456
|
+
if (contracts[type]) {
|
|
457
|
+
fs.writeFileSync(
|
|
458
|
+
path.join(contractsDir, `${type}.json`),
|
|
459
|
+
JSON.stringify(contracts[type], null, 2)
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// Write combined contracts
|
|
465
|
+
fs.writeFileSync(
|
|
466
|
+
path.join(contractsDir, "contracts.json"),
|
|
467
|
+
JSON.stringify(contracts, null, 2)
|
|
468
|
+
);
|
|
469
|
+
|
|
470
|
+
// Write hashes for quick drift check
|
|
471
|
+
fs.writeFileSync(
|
|
472
|
+
path.join(contractsDir, "hashes.json"),
|
|
473
|
+
JSON.stringify(contracts.hashes, null, 2)
|
|
474
|
+
);
|
|
475
|
+
|
|
476
|
+
return contracts;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Load previous contracts for drift comparison
|
|
481
|
+
*/
|
|
482
|
+
function loadPreviousContracts(repoRoot) {
|
|
483
|
+
const contractsPath = path.join(repoRoot, ".vibecheck", "contracts", "contracts.json");
|
|
484
|
+
|
|
485
|
+
if (!fs.existsSync(contractsPath)) {
|
|
486
|
+
return null;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
try {
|
|
490
|
+
return JSON.parse(fs.readFileSync(contractsPath, "utf8"));
|
|
491
|
+
} catch {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Guard contracts - check for drift and generate findings
|
|
498
|
+
*/
|
|
499
|
+
function guardContracts(truthpack, repoRoot, options = {}) {
|
|
500
|
+
const previous = loadPreviousContracts(repoRoot);
|
|
501
|
+
|
|
502
|
+
if (!previous) {
|
|
503
|
+
// No previous contracts, just sync
|
|
504
|
+
const contracts = syncContracts(truthpack, repoRoot);
|
|
505
|
+
return {
|
|
506
|
+
isFirstRun: true,
|
|
507
|
+
hasDrift: false,
|
|
508
|
+
findings: [],
|
|
509
|
+
contracts,
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
const current = generateContracts(truthpack);
|
|
514
|
+
const drift = detectDrift(current, previous, options);
|
|
515
|
+
|
|
516
|
+
// If no blockers, update contracts
|
|
517
|
+
const hasBlockers = drift.findings.some(f => f.severity === "BLOCK");
|
|
518
|
+
if (!hasBlockers) {
|
|
519
|
+
syncContracts(truthpack, repoRoot);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
return {
|
|
523
|
+
isFirstRun: false,
|
|
524
|
+
hasDrift: drift.hasDrift,
|
|
525
|
+
hasBlockers,
|
|
526
|
+
findings: drift.findings,
|
|
527
|
+
contracts: current,
|
|
528
|
+
previous,
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// =============================================================================
|
|
533
|
+
// DRIFT EXPLAINABILITY
|
|
534
|
+
// =============================================================================
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Generate detailed drift explanation with remediation
|
|
538
|
+
*/
|
|
539
|
+
function explainDrift(driftResult) {
|
|
540
|
+
const { findings, summary } = driftResult;
|
|
541
|
+
|
|
542
|
+
const explanation = {
|
|
543
|
+
summary: {
|
|
544
|
+
hasDrift: driftResult.hasDrift,
|
|
545
|
+
totalChanges: findings.length,
|
|
546
|
+
byCategory: summary,
|
|
547
|
+
verdict: findings.some(f => f.severity === "BLOCK") ? "BLOCK" :
|
|
548
|
+
findings.some(f => f.severity === "WARN") ? "WARN" : "OK",
|
|
549
|
+
},
|
|
550
|
+
changes: [],
|
|
551
|
+
remediation: [],
|
|
552
|
+
};
|
|
553
|
+
|
|
554
|
+
for (const finding of findings) {
|
|
555
|
+
const change = {
|
|
556
|
+
type: getChangeType(finding.detectorId),
|
|
557
|
+
severity: finding.severity,
|
|
558
|
+
title: finding.title,
|
|
559
|
+
why: finding.why || getWhyMessage(finding),
|
|
560
|
+
impact: getImpactMessage(finding),
|
|
561
|
+
remediation: getRemediationCommand(finding),
|
|
562
|
+
};
|
|
563
|
+
explanation.changes.push(change);
|
|
564
|
+
|
|
565
|
+
if (change.remediation) {
|
|
566
|
+
explanation.remediation.push(change.remediation);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
return explanation;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* Get change type from detector ID
|
|
575
|
+
*/
|
|
576
|
+
function getChangeType(detectorId) {
|
|
577
|
+
const types = {
|
|
578
|
+
"D_DRIFT_ROUTE_NEW": "added",
|
|
579
|
+
"D_DRIFT_ROUTE_REMOVED": "removed",
|
|
580
|
+
"D_DRIFT_AUTH_REMOVED": "modified",
|
|
581
|
+
"D_DRIFT_ENV_NEW_REQUIRED": "added",
|
|
582
|
+
"D_DRIFT_ENV_REMOVED": "removed",
|
|
583
|
+
"D_DRIFT_ENV_PUBLIC_TO_SERVER": "modified",
|
|
584
|
+
"D_DRIFT_AUTH_PATTERN_REMOVED": "removed",
|
|
585
|
+
"D_DRIFT_AUTH_PATTERN_NEW": "added",
|
|
586
|
+
"D_DRIFT_EXTERNAL_NEW": "added",
|
|
587
|
+
"D_DRIFT_EXTERNAL_REMOVED": "removed",
|
|
588
|
+
};
|
|
589
|
+
return types[detectorId] || "unknown";
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Get why message for finding
|
|
594
|
+
*/
|
|
595
|
+
function getWhyMessage(finding) {
|
|
596
|
+
const messages = {
|
|
597
|
+
"D_DRIFT_ROUTE_NEW": "New endpoint referenced by client but not in previous contract",
|
|
598
|
+
"D_DRIFT_ROUTE_REMOVED": "Endpoint was in contract but no longer exists in codebase",
|
|
599
|
+
"D_DRIFT_AUTH_REMOVED": "Route lost auth protection - potential security regression",
|
|
600
|
+
"D_DRIFT_ENV_NEW_REQUIRED": "New required env var may break deployments without it",
|
|
601
|
+
"D_DRIFT_ENV_REMOVED": "Env var no longer used - can be cleaned up",
|
|
602
|
+
"D_DRIFT_AUTH_PATTERN_REMOVED": "Auth protection pattern removed from middleware",
|
|
603
|
+
"D_DRIFT_AUTH_PATTERN_NEW": "New route pattern added to auth middleware",
|
|
604
|
+
"D_DRIFT_EXTERNAL_NEW": "New external API dependency detected",
|
|
605
|
+
"D_DRIFT_EXTERNAL_REMOVED": "External API dependency removed",
|
|
606
|
+
};
|
|
607
|
+
return messages[finding.detectorId] || "Contract changed since last sync";
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* Get impact message for finding
|
|
612
|
+
*/
|
|
613
|
+
function getImpactMessage(finding) {
|
|
614
|
+
if (finding.severity === "BLOCK") {
|
|
615
|
+
return "This change may cause runtime failures or security issues";
|
|
616
|
+
}
|
|
617
|
+
if (finding.severity === "WARN") {
|
|
618
|
+
return "This change should be reviewed before shipping";
|
|
619
|
+
}
|
|
620
|
+
return "This change is informational";
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* Get remediation command for finding
|
|
625
|
+
*/
|
|
626
|
+
function getRemediationCommand(finding) {
|
|
627
|
+
const detectorId = finding.detectorId;
|
|
628
|
+
|
|
629
|
+
// If the change is intentional, sync contracts
|
|
630
|
+
if (detectorId.includes("NEW") || detectorId.includes("ADDED")) {
|
|
631
|
+
return {
|
|
632
|
+
ifIntentional: "vibecheck ctx sync",
|
|
633
|
+
description: "If this change is intentional, sync contracts",
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
if (detectorId.includes("REMOVED")) {
|
|
638
|
+
if (detectorId.includes("ROUTE")) {
|
|
639
|
+
return {
|
|
640
|
+
ifIntentional: "vibecheck ctx sync",
|
|
641
|
+
ifAccidental: `Add route back or remove client call to ${finding.evidence?.[0]?.path || "the endpoint"}`,
|
|
642
|
+
description: "Route was removed - verify this is intentional",
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
if (detectorId.includes("AUTH")) {
|
|
646
|
+
return {
|
|
647
|
+
ifIntentional: "vibecheck ctx sync --force",
|
|
648
|
+
ifAccidental: "Restore auth protection to the route",
|
|
649
|
+
description: "Auth was removed - this is usually NOT intentional",
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
return {
|
|
655
|
+
ifIntentional: "vibecheck ctx sync",
|
|
656
|
+
description: "Review the change and sync if intentional",
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* Write contracts diff to disk
|
|
662
|
+
*/
|
|
663
|
+
function writeContractsDiff(repoRoot, driftResult) {
|
|
664
|
+
const dir = path.join(repoRoot, ".vibecheck");
|
|
665
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
666
|
+
|
|
667
|
+
const explanation = explainDrift(driftResult);
|
|
668
|
+
|
|
669
|
+
const diff = {
|
|
670
|
+
meta: {
|
|
671
|
+
generatedAt: new Date().toISOString(),
|
|
672
|
+
verdict: explanation.summary.verdict,
|
|
673
|
+
},
|
|
674
|
+
...explanation,
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
const diffPath = path.join(dir, "contracts_diff.json");
|
|
678
|
+
fs.writeFileSync(diffPath, JSON.stringify(diff, null, 2));
|
|
679
|
+
|
|
680
|
+
return { path: diffPath, explanation };
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
/**
|
|
684
|
+
* Print drift report to console
|
|
685
|
+
*/
|
|
686
|
+
function printDriftReport(driftResult) {
|
|
687
|
+
const explanation = explainDrift(driftResult);
|
|
688
|
+
|
|
689
|
+
console.log("\n" + "=".repeat(60));
|
|
690
|
+
console.log("š CONTRACT DRIFT REPORT");
|
|
691
|
+
console.log("=".repeat(60));
|
|
692
|
+
|
|
693
|
+
if (!driftResult.hasDrift) {
|
|
694
|
+
console.log("\nā
No drift detected - contracts are in sync\n");
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
const verdictEmoji = {
|
|
699
|
+
BLOCK: "š«",
|
|
700
|
+
WARN: "ā ļø",
|
|
701
|
+
OK: "ā
",
|
|
702
|
+
}[explanation.summary.verdict];
|
|
703
|
+
|
|
704
|
+
console.log(`\nVerdict: ${verdictEmoji} ${explanation.summary.verdict}`);
|
|
705
|
+
console.log(`Changes: ${explanation.summary.totalChanges}`);
|
|
706
|
+
|
|
707
|
+
// Group by severity
|
|
708
|
+
const blockers = explanation.changes.filter(c => c.severity === "BLOCK");
|
|
709
|
+
const warnings = explanation.changes.filter(c => c.severity === "WARN");
|
|
710
|
+
const infos = explanation.changes.filter(c => c.severity === "INFO");
|
|
711
|
+
|
|
712
|
+
if (blockers.length > 0) {
|
|
713
|
+
console.log("\nš« BLOCKERS:");
|
|
714
|
+
for (const change of blockers) {
|
|
715
|
+
console.log(` ${change.type.toUpperCase()}: ${change.title}`);
|
|
716
|
+
console.log(` āā Why: ${change.why}`);
|
|
717
|
+
if (change.remediation?.ifAccidental) {
|
|
718
|
+
console.log(` āā Fix: ${change.remediation.ifAccidental}`);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
if (warnings.length > 0) {
|
|
724
|
+
console.log("\nā ļø WARNINGS:");
|
|
725
|
+
for (const change of warnings) {
|
|
726
|
+
console.log(` ${change.type.toUpperCase()}: ${change.title}`);
|
|
727
|
+
console.log(` āā Why: ${change.why}`);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
if (infos.length > 0) {
|
|
732
|
+
console.log("\nā¹ļø INFO:");
|
|
733
|
+
for (const change of infos) {
|
|
734
|
+
console.log(` ${change.type.toUpperCase()}: ${change.title}`);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// Remediation
|
|
739
|
+
console.log("\n" + "-".repeat(60));
|
|
740
|
+
console.log("REMEDIATION:");
|
|
741
|
+
|
|
742
|
+
if (explanation.summary.verdict === "BLOCK") {
|
|
743
|
+
console.log("\n If changes are INTENTIONAL:");
|
|
744
|
+
console.log(" $ vibecheck ctx sync --force");
|
|
745
|
+
console.log("\n If changes are ACCIDENTAL:");
|
|
746
|
+
console.log(" - Review the blockers above and fix the issues");
|
|
747
|
+
console.log(" - Then run: vibecheck ctx sync");
|
|
748
|
+
} else {
|
|
749
|
+
console.log("\n To accept these changes:");
|
|
750
|
+
console.log(" $ vibecheck ctx sync");
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
console.log("\n" + "=".repeat(60) + "\n");
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// =============================================================================
|
|
757
|
+
// HELPERS
|
|
758
|
+
// =============================================================================
|
|
759
|
+
|
|
760
|
+
function computeHash(content) {
|
|
761
|
+
return crypto.createHash("sha256").update(content).digest("hex").slice(0, 16);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
function countByField(items, field) {
|
|
765
|
+
const counts = {};
|
|
766
|
+
for (const item of items) {
|
|
767
|
+
const value = item[field] || "unknown";
|
|
768
|
+
counts[value] = (counts[value] || 0) + 1;
|
|
769
|
+
}
|
|
770
|
+
return counts;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// =============================================================================
|
|
774
|
+
// EXPORTS
|
|
775
|
+
// =============================================================================
|
|
776
|
+
|
|
777
|
+
module.exports = {
|
|
778
|
+
// Contract types
|
|
779
|
+
CONTRACT_TYPES,
|
|
780
|
+
|
|
781
|
+
// Generation
|
|
782
|
+
generateContracts,
|
|
783
|
+
generateRouteContract,
|
|
784
|
+
generateEnvContract,
|
|
785
|
+
generateAuthContract,
|
|
786
|
+
generateExternalContract,
|
|
787
|
+
|
|
788
|
+
// Drift detection
|
|
789
|
+
detectDrift,
|
|
790
|
+
detectRouteDrift,
|
|
791
|
+
detectEnvDrift,
|
|
792
|
+
detectAuthDrift,
|
|
793
|
+
detectExternalDrift,
|
|
794
|
+
|
|
795
|
+
// Drift explainability
|
|
796
|
+
explainDrift,
|
|
797
|
+
writeContractsDiff,
|
|
798
|
+
printDriftReport,
|
|
799
|
+
|
|
800
|
+
// Sync/Guard
|
|
801
|
+
syncContracts,
|
|
802
|
+
loadPreviousContracts,
|
|
803
|
+
guardContracts,
|
|
804
|
+
};
|