@zigrivers/scaffold 3.28.0 → 3.30.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/README.md +5 -1
- package/content/guides/.gitkeep +0 -0
- package/content/guides/AUTHORING.md +143 -0
- package/content/guides/cli/index.html +1502 -0
- package/content/guides/cli/index.md +206 -0
- package/content/guides/concepts/index.html +1617 -0
- package/content/guides/concepts/index.md +347 -0
- package/content/guides/dashboard/index.html +1560 -0
- package/content/guides/dashboard/index.md +264 -0
- package/content/guides/index.html +1188 -0
- package/content/guides/install/.diagrams/diagram-0.svg +1 -0
- package/content/guides/install/.diagrams/manifest.json +3 -0
- package/content/guides/install/index.html +1300 -0
- package/content/guides/install/index.md +186 -0
- package/content/guides/knowledge/.diagrams/diagram-0.svg +1 -0
- package/content/guides/knowledge/.diagrams/manifest.json +3 -0
- package/content/guides/knowledge/index.html +1412 -0
- package/content/guides/knowledge/index.md +209 -0
- package/content/guides/knowledge-freshness/.diagrams/diagram-0.svg +1 -0
- package/content/guides/knowledge-freshness/.diagrams/manifest.json +3 -0
- package/content/guides/knowledge-freshness/index.html +2442 -0
- package/content/guides/knowledge-freshness/index.md +893 -0
- package/content/guides/mmr/.diagrams/diagram-0.svg +1 -0
- package/content/guides/mmr/.diagrams/manifest.json +3 -0
- package/content/guides/mmr/index.html +1746 -0
- package/content/guides/mmr/index.md +426 -0
- package/content/guides/multi-agent/.diagrams/diagram-0.svg +1 -0
- package/content/guides/multi-agent/.diagrams/manifest.json +3 -0
- package/content/guides/multi-agent/index.html +1362 -0
- package/content/guides/multi-agent/index.md +243 -0
- package/content/guides/observability/.diagrams/diagram-0.svg +1 -0
- package/content/guides/observability/.diagrams/diagram-1.svg +1 -0
- package/content/guides/observability/.diagrams/diagram-2.svg +1 -0
- package/content/guides/observability/.diagrams/diagram-3.svg +1 -0
- package/content/guides/observability/.diagrams/manifest.json +6 -0
- package/content/guides/observability/index.html +2904 -0
- package/content/guides/observability/index.md +1097 -0
- package/content/guides/pipeline/.diagrams/diagram-0.svg +1 -0
- package/content/guides/pipeline/.diagrams/diagram-1.svg +1 -0
- package/content/guides/pipeline/.diagrams/manifest.json +4 -0
- package/content/guides/pipeline/index.html +1632 -0
- package/content/guides/pipeline/index.md +387 -0
- package/content/guides/review-workflow/.diagrams/diagram-0.svg +1 -0
- package/content/guides/review-workflow/.diagrams/diagram-1.svg +1 -0
- package/content/guides/review-workflow/.diagrams/manifest.json +4 -0
- package/content/guides/review-workflow/index.html +1437 -0
- package/content/guides/review-workflow/index.md +248 -0
- package/content/knowledge/VERSION +1 -0
- package/content/knowledge/backend/backend-api-design.md +8 -0
- package/content/knowledge/backend/backend-architecture.md +8 -0
- package/content/knowledge/backend/backend-async-patterns.md +7 -0
- package/content/knowledge/backend/backend-auth-patterns.md +9 -0
- package/content/knowledge/backend/backend-conventions.md +6 -0
- package/content/knowledge/backend/backend-data-modeling.md +7 -0
- package/content/knowledge/backend/backend-deployment.md +8 -0
- package/content/knowledge/backend/backend-dev-environment.md +5 -0
- package/content/knowledge/backend/backend-fintech-broker-integration.md +6 -0
- package/content/knowledge/backend/backend-fintech-compliance.md +10 -2
- package/content/knowledge/backend/backend-fintech-data-modeling.md +6 -0
- package/content/knowledge/backend/backend-fintech-ledger.md +6 -0
- package/content/knowledge/backend/backend-fintech-observability.md +6 -0
- package/content/knowledge/backend/backend-fintech-order-lifecycle.md +6 -0
- package/content/knowledge/backend/backend-fintech-risk-management.md +6 -0
- package/content/knowledge/backend/backend-fintech-testing.md +6 -0
- package/content/knowledge/backend/backend-observability.md +7 -0
- package/content/knowledge/backend/backend-project-structure.md +6 -0
- package/content/knowledge/backend/backend-requirements.md +6 -0
- package/content/knowledge/backend/backend-security.md +7 -0
- package/content/knowledge/backend/backend-testing.md +7 -0
- package/content/knowledge/backend/backend-worker-patterns.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-architecture.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-content-scripts.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-conventions.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-cross-browser.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-dev-environment.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-manifest.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-project-structure.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-requirements.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-security.md +7 -0
- package/content/knowledge/browser-extension/browser-extension-service-workers.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-store-submission.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-testing.md +6 -0
- package/content/knowledge/cli/cli-architecture.md +4 -0
- package/content/knowledge/cli/cli-conventions.md +4 -0
- package/content/knowledge/cli/cli-dev-environment.md +5 -0
- package/content/knowledge/cli/cli-distribution-patterns.md +5 -0
- package/content/knowledge/cli/cli-interactivity-patterns.md +4 -0
- package/content/knowledge/cli/cli-output-patterns.md +4 -0
- package/content/knowledge/cli/cli-project-structure.md +4 -0
- package/content/knowledge/cli/cli-requirements.md +4 -0
- package/content/knowledge/cli/cli-shell-integration.md +4 -0
- package/content/knowledge/cli/cli-testing.md +4 -0
- package/content/knowledge/core/adr-craft.md +8 -0
- package/content/knowledge/core/ai-memory-management.md +6 -0
- package/content/knowledge/core/api-design.md +6 -0
- package/content/knowledge/core/automated-review-tooling.md +8 -0
- package/content/knowledge/core/claude-md-patterns.md +8 -0
- package/content/knowledge/core/coding-conventions.md +8 -0
- package/content/knowledge/core/database-design.md +8 -0
- package/content/knowledge/core/design-system-tokens.md +8 -0
- package/content/knowledge/core/dev-environment.md +4 -0
- package/content/knowledge/core/domain-modeling.md +6 -0
- package/content/knowledge/core/eval-craft.md +6 -0
- package/content/knowledge/core/git-workflow-patterns.md +8 -0
- package/content/knowledge/core/multi-model-research-dispatch.md +6 -0
- package/content/knowledge/core/multi-model-review-dispatch.md +6 -0
- package/content/knowledge/core/multi-service-api-contracts.md +5 -0
- package/content/knowledge/core/multi-service-architecture.md +5 -0
- package/content/knowledge/core/multi-service-auth.md +6 -0
- package/content/knowledge/core/multi-service-data-ownership.md +8 -0
- package/content/knowledge/core/multi-service-observability.md +8 -0
- package/content/knowledge/core/multi-service-resilience.md +5 -0
- package/content/knowledge/core/multi-service-task-decomposition.md +8 -0
- package/content/knowledge/core/multi-service-testing.md +5 -0
- package/content/knowledge/core/operations-runbook.md +8 -0
- package/content/knowledge/core/project-structure-patterns.md +4 -0
- package/content/knowledge/core/review-step-template.md +4 -0
- package/content/knowledge/core/security-best-practices.md +6 -0
- package/content/knowledge/core/system-architecture.md +6 -0
- package/content/knowledge/core/task-decomposition.md +5 -0
- package/content/knowledge/core/task-tracking.md +8 -0
- package/content/knowledge/core/tech-stack-selection.md +8 -0
- package/content/knowledge/core/test-skeleton-generation.md +4 -0
- package/content/knowledge/core/testing-strategy.md +8 -0
- package/content/knowledge/core/user-stories.md +8 -0
- package/content/knowledge/core/user-story-innovation.md +4 -0
- package/content/knowledge/core/ux-specification.md +5 -0
- package/content/knowledge/data-pipeline/data-pipeline-architecture.md +5 -0
- package/content/knowledge/data-pipeline/data-pipeline-batch-patterns.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-conventions.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-dev-environment.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-orchestration.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-project-structure.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-quality.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-requirements.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-schema-management.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-security.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-streaming-patterns.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-testing.md +4 -0
- package/content/knowledge/data-science/data-science-architecture.md +5 -0
- package/content/knowledge/data-science/data-science-conventions.md +6 -0
- package/content/knowledge/data-science/data-science-data-versioning.md +6 -0
- package/content/knowledge/data-science/data-science-dev-environment.md +6 -0
- package/content/knowledge/data-science/data-science-experiment-tracking.md +8 -0
- package/content/knowledge/data-science/data-science-model-evaluation.md +5 -0
- package/content/knowledge/data-science/data-science-notebook-discipline.md +5 -0
- package/content/knowledge/data-science/data-science-observability.md +6 -0
- package/content/knowledge/data-science/data-science-project-structure.md +5 -0
- package/content/knowledge/data-science/data-science-reproducibility.md +8 -0
- package/content/knowledge/data-science/data-science-requirements.md +5 -0
- package/content/knowledge/data-science/data-science-security.md +8 -0
- package/content/knowledge/data-science/data-science-testing.md +5 -0
- package/content/knowledge/execution/enhancement-workflow.md +4 -0
- package/content/knowledge/execution/multi-agent-coordination.md +12 -1
- package/content/knowledge/execution/task-claiming-strategy.md +4 -0
- package/content/knowledge/execution/tdd-execution-loop.md +5 -0
- package/content/knowledge/execution/worktree-management.md +5 -0
- package/content/knowledge/finalization/apply-fixes-and-freeze.md +4 -0
- package/content/knowledge/finalization/developer-onboarding.md +4 -0
- package/content/knowledge/finalization/implementation-playbook.md +4 -0
- package/content/knowledge/game/game-accessibility.md +4 -0
- package/content/knowledge/game/game-ai-patterns.md +4 -0
- package/content/knowledge/game/game-asset-pipeline.md +4 -0
- package/content/knowledge/game/game-audio-design.md +4 -0
- package/content/knowledge/game/game-binary-vcs-strategy.md +5 -0
- package/content/knowledge/game/game-design-document.md +4 -0
- package/content/knowledge/game/game-domain-patterns.md +4 -0
- package/content/knowledge/game/game-economy-design.md +4 -0
- package/content/knowledge/game/game-engine-selection.md +4 -0
- package/content/knowledge/game/game-ideation.md +4 -0
- package/content/knowledge/game/game-input-systems.md +4 -0
- package/content/knowledge/game/game-level-content-design.md +4 -0
- package/content/knowledge/game/game-liveops-analytics.md +4 -0
- package/content/knowledge/game/game-localization.md +4 -0
- package/content/knowledge/game/game-milestone-definitions.md +4 -0
- package/content/knowledge/game/game-modding-ugc.md +4 -0
- package/content/knowledge/game/game-narrative-design.md +4 -0
- package/content/knowledge/game/game-networking.md +4 -0
- package/content/knowledge/game/game-performance-budgeting.md +4 -0
- package/content/knowledge/game/game-platform-certification.md +6 -0
- package/content/knowledge/game/game-project-structure.md +4 -0
- package/content/knowledge/game/game-save-systems.md +4 -0
- package/content/knowledge/game/game-testing-strategy.md +4 -0
- package/content/knowledge/game/game-ui-patterns.md +4 -0
- package/content/knowledge/game/game-vr-ar-design.md +6 -0
- package/content/knowledge/library/library-api-design.md +4 -0
- package/content/knowledge/library/library-architecture.md +4 -0
- package/content/knowledge/library/library-bundling.md +4 -0
- package/content/knowledge/library/library-conventions.md +5 -0
- package/content/knowledge/library/library-dev-environment.md +4 -0
- package/content/knowledge/library/library-documentation.md +4 -0
- package/content/knowledge/library/library-project-structure.md +4 -0
- package/content/knowledge/library/library-requirements.md +4 -0
- package/content/knowledge/library/library-security.md +4 -0
- package/content/knowledge/library/library-testing.md +4 -0
- package/content/knowledge/library/library-type-definitions.md +4 -0
- package/content/knowledge/library/library-versioning.md +5 -0
- package/content/knowledge/ml/ml-architecture.md +4 -0
- package/content/knowledge/ml/ml-conventions.md +4 -0
- package/content/knowledge/ml/ml-dev-environment.md +4 -0
- package/content/knowledge/ml/ml-experiment-tracking.md +6 -0
- package/content/knowledge/ml/ml-model-evaluation.md +4 -0
- package/content/knowledge/ml/ml-observability.md +5 -0
- package/content/knowledge/ml/ml-project-structure.md +4 -0
- package/content/knowledge/ml/ml-requirements.md +4 -0
- package/content/knowledge/ml/ml-security.md +5 -0
- package/content/knowledge/ml/ml-serving-patterns.md +4 -0
- package/content/knowledge/ml/ml-testing.md +4 -0
- package/content/knowledge/ml/ml-training-patterns.md +4 -0
- package/content/knowledge/mobile-app/mobile-app-architecture.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-conventions.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-deployment.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-dev-environment.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-distribution.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-observability.md +7 -0
- package/content/knowledge/mobile-app/mobile-app-offline-patterns.md +7 -0
- package/content/knowledge/mobile-app/mobile-app-project-structure.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-push-notifications.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-requirements.md +7 -0
- package/content/knowledge/mobile-app/mobile-app-security.md +8 -0
- package/content/knowledge/mobile-app/mobile-app-testing.md +6 -0
- package/content/knowledge/product/gap-analysis.md +4 -0
- package/content/knowledge/product/ideation-craft.md +4 -0
- package/content/knowledge/product/prd-craft.md +4 -0
- package/content/knowledge/product/prd-innovation.md +4 -0
- package/content/knowledge/product/vision-craft.md +4 -0
- package/content/knowledge/product/vision-innovation.md +4 -0
- package/content/knowledge/research/research-architecture.md +4 -0
- package/content/knowledge/research/research-conventions.md +6 -0
- package/content/knowledge/research/research-dev-environment.md +6 -0
- package/content/knowledge/research/research-experiment-loop.md +4 -0
- package/content/knowledge/research/research-experiment-tracking.md +6 -0
- package/content/knowledge/research/research-ml-architecture-search.md +4 -0
- package/content/knowledge/research/research-ml-evaluation.md +4 -0
- package/content/knowledge/research/research-ml-experiment-tracking.md +6 -0
- package/content/knowledge/research/research-ml-training-patterns.md +4 -0
- package/content/knowledge/research/research-observability.md +5 -0
- package/content/knowledge/research/research-overfitting-prevention.md +5 -0
- package/content/knowledge/research/research-project-structure.md +5 -0
- package/content/knowledge/research/research-quant-backtesting.md +4 -0
- package/content/knowledge/research/research-quant-market-data.md +4 -0
- package/content/knowledge/research/research-quant-metrics.md +4 -0
- package/content/knowledge/research/research-quant-requirements.md +4 -0
- package/content/knowledge/research/research-quant-risk.md +4 -0
- package/content/knowledge/research/research-quant-strategy-patterns.md +4 -0
- package/content/knowledge/research/research-requirements.md +5 -0
- package/content/knowledge/research/research-security.md +5 -0
- package/content/knowledge/research/research-sim-compute-management.md +4 -0
- package/content/knowledge/research/research-sim-engine-patterns.md +4 -0
- package/content/knowledge/research/research-sim-parameter-spaces.md +4 -0
- package/content/knowledge/research/research-sim-validation.md +4 -0
- package/content/knowledge/research/research-testing.md +5 -0
- package/content/knowledge/review/review-adr.md +6 -0
- package/content/knowledge/review/review-api-design.md +6 -0
- package/content/knowledge/review/review-art-bible.md +4 -0
- package/content/knowledge/review/review-database-design.md +5 -0
- package/content/knowledge/review/review-domain-modeling.md +5 -0
- package/content/knowledge/review/review-game-design.md +4 -0
- package/content/knowledge/review/review-game-economy.md +4 -0
- package/content/knowledge/review/review-game-ui.md +5 -0
- package/content/knowledge/review/review-implementation-tasks.md +5 -0
- package/content/knowledge/review/review-methodology.md +4 -0
- package/content/knowledge/review/review-netcode.md +4 -0
- package/content/knowledge/review/review-operations.md +6 -0
- package/content/knowledge/review/review-platform-cert.md +4 -0
- package/content/knowledge/review/review-prd.md +4 -0
- package/content/knowledge/review/review-security.md +7 -0
- package/content/knowledge/review/review-system-architecture.md +6 -0
- package/content/knowledge/review/review-testing-strategy.md +6 -0
- package/content/knowledge/review/review-user-stories.md +5 -0
- package/content/knowledge/review/review-ux-specification.md +6 -0
- package/content/knowledge/review/review-vision.md +4 -0
- package/content/knowledge/tools/post-implementation-review-methodology.md +4 -0
- package/content/knowledge/tools/release-management.md +5 -0
- package/content/knowledge/tools/session-analysis.md +4 -0
- package/content/knowledge/tools/version-strategy.md +4 -0
- package/content/knowledge/validation/critical-path-analysis.md +4 -0
- package/content/knowledge/validation/cross-phase-consistency.md +4 -0
- package/content/knowledge/validation/decision-completeness.md +5 -0
- package/content/knowledge/validation/dependency-validation.md +4 -0
- package/content/knowledge/validation/implementability-review.md +4 -0
- package/content/knowledge/validation/scope-management.md +4 -0
- package/content/knowledge/validation/traceability.md +4 -0
- package/content/knowledge/web-app/web-app-api-patterns.md +6 -0
- package/content/knowledge/web-app/web-app-architecture.md +6 -0
- package/content/knowledge/web-app/web-app-auth-patterns.md +9 -0
- package/content/knowledge/web-app/web-app-conventions.md +5 -0
- package/content/knowledge/web-app/web-app-data-patterns.md +6 -0
- package/content/knowledge/web-app/web-app-deployment-workflow.md +6 -0
- package/content/knowledge/web-app/web-app-deployment.md +6 -0
- package/content/knowledge/web-app/web-app-design-system.md +6 -0
- package/content/knowledge/web-app/web-app-dev-environment.md +6 -0
- package/content/knowledge/web-app/web-app-observability.md +6 -0
- package/content/knowledge/web-app/web-app-project-structure.md +5 -0
- package/content/knowledge/web-app/web-app-rendering-strategies.md +6 -0
- package/content/knowledge/web-app/web-app-requirements.md +6 -0
- package/content/knowledge/web-app/web-app-security.md +8 -0
- package/content/knowledge/web-app/web-app-session-patterns.md +7 -0
- package/content/knowledge/web-app/web-app-testing.md +6 -0
- package/content/knowledge/web-app/web-app-ux-patterns.md +6 -0
- package/content/knowledge/web3/web3-access-control.md +8 -0
- package/content/knowledge/web3/web3-architecture.md +7 -0
- package/content/knowledge/web3/web3-audit-workflow.md +7 -0
- package/content/knowledge/web3/web3-common-vulnerabilities.md +8 -0
- package/content/knowledge/web3/web3-conventions.md +6 -0
- package/content/knowledge/web3/web3-deployment-and-verification.md +7 -0
- package/content/knowledge/web3/web3-dev-environment.md +6 -0
- package/content/knowledge/web3/web3-gas-optimization.md +7 -0
- package/content/knowledge/web3/web3-oracles-and-external-data.md +7 -0
- package/content/knowledge/web3/web3-project-structure.md +6 -0
- package/content/knowledge/web3/web3-requirements.md +6 -0
- package/content/knowledge/web3/web3-security.md +8 -0
- package/content/knowledge/web3/web3-testing.md +6 -0
- package/content/knowledge/web3/web3-upgradeability.md +7 -0
- package/content/tools/knowledge-audit-entry.md +79 -0
- package/content/tools/review-code.md +41 -14
- package/content/tools/review-pr.md +32 -14
- package/dist/cli/commands/dashboard.d.ts +1 -1
- package/dist/cli/commands/dashboard.d.ts.map +1 -1
- package/dist/cli/commands/dashboard.js +10 -10
- package/dist/cli/commands/dashboard.js.map +1 -1
- package/dist/cli/commands/dashboard.test.js +1 -1
- package/dist/cli/commands/dashboard.test.js.map +1 -1
- package/dist/cli/commands/guides.d.ts +24 -0
- package/dist/cli/commands/guides.d.ts.map +1 -0
- package/dist/cli/commands/guides.js +103 -0
- package/dist/cli/commands/guides.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-anti-over-rewrite.d.ts +9 -0
- package/dist/cli/commands/knowledge-freshness-anti-over-rewrite.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-anti-over-rewrite.js +112 -0
- package/dist/cli/commands/knowledge-freshness-anti-over-rewrite.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-audit-apply.d.ts +8 -0
- package/dist/cli/commands/knowledge-freshness-audit-apply.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-audit-apply.js +96 -0
- package/dist/cli/commands/knowledge-freshness-audit-apply.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-audit-prefilter.d.ts +7 -0
- package/dist/cli/commands/knowledge-freshness-audit-prefilter.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-audit-prefilter.js +42 -0
- package/dist/cli/commands/knowledge-freshness-audit-prefilter.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-audit-run-entry.d.ts +9 -0
- package/dist/cli/commands/knowledge-freshness-audit-run-entry.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-audit-run-entry.js +63 -0
- package/dist/cli/commands/knowledge-freshness-audit-run-entry.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-bump-version.d.ts +8 -0
- package/dist/cli/commands/knowledge-freshness-bump-version.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-bump-version.js +34 -0
- package/dist/cli/commands/knowledge-freshness-bump-version.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-deep-guidance-check.d.ts +7 -0
- package/dist/cli/commands/knowledge-freshness-deep-guidance-check.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-deep-guidance-check.js +51 -0
- package/dist/cli/commands/knowledge-freshness-deep-guidance-check.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-link-check.d.ts +7 -0
- package/dist/cli/commands/knowledge-freshness-link-check.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-link-check.js +57 -0
- package/dist/cli/commands/knowledge-freshness-link-check.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-lint-unsourced.d.ts +8 -0
- package/dist/cli/commands/knowledge-freshness-lint-unsourced.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-lint-unsourced.js +58 -0
- package/dist/cli/commands/knowledge-freshness-lint-unsourced.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness.d.ts +4 -0
- package/dist/cli/commands/knowledge-freshness.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness.js +25 -0
- package/dist/cli/commands/knowledge-freshness.js.map +1 -0
- package/dist/cli/commands/observe.d.ts +4 -0
- package/dist/cli/commands/observe.d.ts.map +1 -1
- package/dist/cli/commands/observe.js +13 -0
- package/dist/cli/commands/observe.js.map +1 -1
- package/dist/cli/commands/observe.test.js +46 -0
- package/dist/cli/commands/observe.test.js.map +1 -1
- package/dist/cli/commands/validate-knowledge.d.ts +4 -0
- package/dist/cli/commands/validate-knowledge.d.ts.map +1 -0
- package/dist/cli/commands/validate-knowledge.js +32 -0
- package/dist/cli/commands/validate-knowledge.js.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +6 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/adapters/claude-code.d.ts.map +1 -1
- package/dist/core/adapters/claude-code.js +6 -3
- package/dist/core/adapters/claude-code.js.map +1 -1
- package/dist/core/adapters/claude-code.test.js +45 -1
- package/dist/core/adapters/claude-code.test.js.map +1 -1
- package/dist/core/assembly/engine.d.ts.map +1 -1
- package/dist/core/assembly/engine.js +7 -3
- package/dist/core/assembly/engine.js.map +1 -1
- package/dist/core/assembly/engine.test.js +45 -1
- package/dist/core/assembly/engine.test.js.map +1 -1
- package/dist/core/assembly/gap-signal-tail.d.ts +18 -0
- package/dist/core/assembly/gap-signal-tail.d.ts.map +1 -0
- package/dist/core/assembly/gap-signal-tail.js +43 -0
- package/dist/core/assembly/gap-signal-tail.js.map +1 -0
- package/dist/core/assembly/gap-signal-tail.test.d.ts +2 -0
- package/dist/core/assembly/gap-signal-tail.test.d.ts.map +1 -0
- package/dist/core/assembly/gap-signal-tail.test.js +49 -0
- package/dist/core/assembly/gap-signal-tail.test.js.map +1 -0
- package/dist/core/assembly/knowledge-loader.d.ts +11 -0
- package/dist/core/assembly/knowledge-loader.d.ts.map +1 -1
- package/dist/core/assembly/knowledge-loader.js +54 -1
- package/dist/core/assembly/knowledge-loader.js.map +1 -1
- package/dist/core/assembly/knowledge-loader.test.js +73 -0
- package/dist/core/assembly/knowledge-loader.test.js.map +1 -1
- package/dist/guides/build.d.ts +12 -0
- package/dist/guides/build.d.ts.map +1 -0
- package/dist/guides/build.js +55 -0
- package/dist/guides/build.js.map +1 -0
- package/dist/guides/build.test.d.ts +2 -0
- package/dist/guides/build.test.d.ts.map +1 -0
- package/dist/guides/build.test.js +82 -0
- package/dist/guides/build.test.js.map +1 -0
- package/dist/guides/chrome.d.ts +24 -0
- package/dist/guides/chrome.d.ts.map +1 -0
- package/dist/guides/chrome.js +118 -0
- package/dist/guides/chrome.js.map +1 -0
- package/dist/guides/cli-guides.test.d.ts +2 -0
- package/dist/guides/cli-guides.test.d.ts.map +1 -0
- package/dist/guides/cli-guides.test.js +41 -0
- package/dist/guides/cli-guides.test.js.map +1 -0
- package/dist/guides/dashboard-theme.css +1073 -0
- package/dist/guides/directives-callout.test.d.ts +2 -0
- package/dist/guides/directives-callout.test.d.ts.map +1 -0
- package/dist/guides/directives-callout.test.js +22 -0
- package/dist/guides/directives-callout.test.js.map +1 -0
- package/dist/guides/directives-chart.test.d.ts +2 -0
- package/dist/guides/directives-chart.test.d.ts.map +1 -0
- package/dist/guides/directives-chart.test.js +25 -0
- package/dist/guides/directives-chart.test.js.map +1 -0
- package/dist/guides/directives-cite.test.d.ts +2 -0
- package/dist/guides/directives-cite.test.d.ts.map +1 -0
- package/dist/guides/directives-cite.test.js +26 -0
- package/dist/guides/directives-cite.test.js.map +1 -0
- package/dist/guides/directives-filter-table.test.d.ts +2 -0
- package/dist/guides/directives-filter-table.test.d.ts.map +1 -0
- package/dist/guides/directives-filter-table.test.js +22 -0
- package/dist/guides/directives-filter-table.test.js.map +1 -0
- package/dist/guides/directives-sev.test.d.ts +2 -0
- package/dist/guides/directives-sev.test.d.ts.map +1 -0
- package/dist/guides/directives-sev.test.js +15 -0
- package/dist/guides/directives-sev.test.js.map +1 -0
- package/dist/guides/directives-tabs.test.d.ts +2 -0
- package/dist/guides/directives-tabs.test.d.ts.map +1 -0
- package/dist/guides/directives-tabs.test.js +52 -0
- package/dist/guides/directives-tabs.test.js.map +1 -0
- package/dist/guides/directives.d.ts +8 -0
- package/dist/guides/directives.d.ts.map +1 -0
- package/dist/guides/directives.js +182 -0
- package/dist/guides/directives.js.map +1 -0
- package/dist/guides/fs-guides.test.d.ts +2 -0
- package/dist/guides/fs-guides.test.d.ts.map +1 -0
- package/dist/guides/fs-guides.test.js +14 -0
- package/dist/guides/fs-guides.test.js.map +1 -0
- package/dist/guides/index-page.d.ts +3 -0
- package/dist/guides/index-page.d.ts.map +1 -0
- package/dist/guides/index-page.js +14 -0
- package/dist/guides/index-page.js.map +1 -0
- package/dist/guides/links.d.ts +14 -0
- package/dist/guides/links.d.ts.map +1 -0
- package/dist/guides/links.js +56 -0
- package/dist/guides/links.js.map +1 -0
- package/dist/guides/links.test.d.ts +2 -0
- package/dist/guides/links.test.d.ts.map +1 -0
- package/dist/guides/links.test.js +72 -0
- package/dist/guides/links.test.js.map +1 -0
- package/dist/guides/lint.d.ts +6 -0
- package/dist/guides/lint.d.ts.map +1 -0
- package/dist/guides/lint.js +27 -0
- package/dist/guides/lint.js.map +1 -0
- package/dist/guides/lint.test.d.ts +2 -0
- package/dist/guides/lint.test.d.ts.map +1 -0
- package/dist/guides/lint.test.js +24 -0
- package/dist/guides/lint.test.js.map +1 -0
- package/dist/guides/loader.d.ts +4 -0
- package/dist/guides/loader.d.ts.map +1 -0
- package/dist/guides/loader.js +63 -0
- package/dist/guides/loader.js.map +1 -0
- package/dist/guides/loader.test.d.ts +2 -0
- package/dist/guides/loader.test.d.ts.map +1 -0
- package/dist/guides/loader.test.js +85 -0
- package/dist/guides/loader.test.js.map +1 -0
- package/dist/guides/mermaid-sanitize.test.d.ts +2 -0
- package/dist/guides/mermaid-sanitize.test.d.ts.map +1 -0
- package/dist/guides/mermaid-sanitize.test.js +57 -0
- package/dist/guides/mermaid-sanitize.test.js.map +1 -0
- package/dist/guides/mermaid.d.ts +18 -0
- package/dist/guides/mermaid.d.ts.map +1 -0
- package/dist/guides/mermaid.js +137 -0
- package/dist/guides/mermaid.js.map +1 -0
- package/dist/guides/mermaid.test.d.ts +2 -0
- package/dist/guides/mermaid.test.d.ts.map +1 -0
- package/dist/guides/mermaid.test.js +105 -0
- package/dist/guides/mermaid.test.js.map +1 -0
- package/dist/guides/render.d.ts +13 -0
- package/dist/guides/render.d.ts.map +1 -0
- package/dist/guides/render.js +58 -0
- package/dist/guides/render.js.map +1 -0
- package/dist/guides/render.test.d.ts +2 -0
- package/dist/guides/render.test.d.ts.map +1 -0
- package/dist/guides/render.test.js +46 -0
- package/dist/guides/render.test.js.map +1 -0
- package/dist/guides/sanitize.d.ts +3 -0
- package/dist/guides/sanitize.d.ts.map +1 -0
- package/dist/guides/sanitize.js +77 -0
- package/dist/guides/sanitize.js.map +1 -0
- package/dist/guides/sanitize.test.d.ts +2 -0
- package/dist/guides/sanitize.test.d.ts.map +1 -0
- package/dist/guides/sanitize.test.js +45 -0
- package/dist/guides/sanitize.test.js.map +1 -0
- package/dist/guides/template.d.ts +11 -0
- package/dist/guides/template.d.ts.map +1 -0
- package/dist/guides/template.js +38 -0
- package/dist/guides/template.js.map +1 -0
- package/dist/guides/template.test.d.ts +2 -0
- package/dist/guides/template.test.d.ts.map +1 -0
- package/dist/guides/template.test.js +41 -0
- package/dist/guides/template.test.js.map +1 -0
- package/dist/guides/types.d.ts +20 -0
- package/dist/guides/types.d.ts.map +1 -0
- package/dist/guides/types.js +2 -0
- package/dist/guides/types.js.map +1 -0
- package/dist/knowledge-freshness/audit-apply-pr.d.ts +64 -0
- package/dist/knowledge-freshness/audit-apply-pr.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-apply-pr.js +309 -0
- package/dist/knowledge-freshness/audit-apply-pr.js.map +1 -0
- package/dist/knowledge-freshness/audit-apply-pr.test.d.ts +2 -0
- package/dist/knowledge-freshness/audit-apply-pr.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-apply-pr.test.js +211 -0
- package/dist/knowledge-freshness/audit-apply-pr.test.js.map +1 -0
- package/dist/knowledge-freshness/audit-apply.d.ts +16 -0
- package/dist/knowledge-freshness/audit-apply.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-apply.js +193 -0
- package/dist/knowledge-freshness/audit-apply.js.map +1 -0
- package/dist/knowledge-freshness/audit-apply.test.d.ts +2 -0
- package/dist/knowledge-freshness/audit-apply.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-apply.test.js +482 -0
- package/dist/knowledge-freshness/audit-apply.test.js.map +1 -0
- package/dist/knowledge-freshness/audit-prefilter.d.ts +12 -0
- package/dist/knowledge-freshness/audit-prefilter.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-prefilter.js +74 -0
- package/dist/knowledge-freshness/audit-prefilter.js.map +1 -0
- package/dist/knowledge-freshness/audit-prefilter.test.d.ts +2 -0
- package/dist/knowledge-freshness/audit-prefilter.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-prefilter.test.js +78 -0
- package/dist/knowledge-freshness/audit-prefilter.test.js.map +1 -0
- package/dist/knowledge-freshness/audit-runner.d.ts +135 -0
- package/dist/knowledge-freshness/audit-runner.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-runner.js +168 -0
- package/dist/knowledge-freshness/audit-runner.js.map +1 -0
- package/dist/knowledge-freshness/audit-runner.test.d.ts +2 -0
- package/dist/knowledge-freshness/audit-runner.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-runner.test.js +130 -0
- package/dist/knowledge-freshness/audit-runner.test.js.map +1 -0
- package/dist/knowledge-freshness/bump-version.d.ts +24 -0
- package/dist/knowledge-freshness/bump-version.d.ts.map +1 -0
- package/dist/knowledge-freshness/bump-version.js +69 -0
- package/dist/knowledge-freshness/bump-version.js.map +1 -0
- package/dist/knowledge-freshness/bump-version.test.d.ts +2 -0
- package/dist/knowledge-freshness/bump-version.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/bump-version.test.js +82 -0
- package/dist/knowledge-freshness/bump-version.test.js.map +1 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.d.ts +86 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.js +210 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.js.map +1 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.test.d.ts +2 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.test.js +115 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.test.js.map +1 -0
- package/dist/knowledge-freshness/gates/changed-files.d.ts +53 -0
- package/dist/knowledge-freshness/gates/changed-files.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/changed-files.js +128 -0
- package/dist/knowledge-freshness/gates/changed-files.js.map +1 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.d.ts +23 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.js +27 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.js.map +1 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.test.d.ts +2 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.test.js +23 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.test.js.map +1 -0
- package/dist/knowledge-freshness/gates/link-check.d.ts +55 -0
- package/dist/knowledge-freshness/gates/link-check.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/link-check.js +161 -0
- package/dist/knowledge-freshness/gates/link-check.js.map +1 -0
- package/dist/knowledge-freshness/gates/link-check.test.d.ts +2 -0
- package/dist/knowledge-freshness/gates/link-check.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/link-check.test.js +76 -0
- package/dist/knowledge-freshness/gates/link-check.test.js.map +1 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.d.ts +40 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.js +143 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.js.map +1 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.test.d.ts +2 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.test.js +68 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.test.js.map +1 -0
- package/dist/knowledge-freshness/gates/parse-entry.d.ts +25 -0
- package/dist/knowledge-freshness/gates/parse-entry.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/parse-entry.js +41 -0
- package/dist/knowledge-freshness/gates/parse-entry.js.map +1 -0
- package/dist/knowledge-freshness/gates/parse-entry.test.d.ts +2 -0
- package/dist/knowledge-freshness/gates/parse-entry.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/parse-entry.test.js +34 -0
- package/dist/knowledge-freshness/gates/parse-entry.test.js.map +1 -0
- package/dist/knowledge-freshness/providers/anthropic.d.ts +33 -0
- package/dist/knowledge-freshness/providers/anthropic.d.ts.map +1 -0
- package/dist/knowledge-freshness/providers/anthropic.js +36 -0
- package/dist/knowledge-freshness/providers/anthropic.js.map +1 -0
- package/dist/knowledge-freshness/providers/anthropic.test.d.ts +2 -0
- package/dist/knowledge-freshness/providers/anthropic.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/providers/anthropic.test.js +32 -0
- package/dist/knowledge-freshness/providers/anthropic.test.js.map +1 -0
- package/dist/knowledge-freshness/providers/deepseek.d.ts +33 -0
- package/dist/knowledge-freshness/providers/deepseek.d.ts.map +1 -0
- package/dist/knowledge-freshness/providers/deepseek.js +157 -0
- package/dist/knowledge-freshness/providers/deepseek.js.map +1 -0
- package/dist/knowledge-freshness/providers/deepseek.test.d.ts +2 -0
- package/dist/knowledge-freshness/providers/deepseek.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/providers/deepseek.test.js +142 -0
- package/dist/knowledge-freshness/providers/deepseek.test.js.map +1 -0
- package/dist/knowledge-freshness/providers/index.d.ts +41 -0
- package/dist/knowledge-freshness/providers/index.d.ts.map +1 -0
- package/dist/knowledge-freshness/providers/index.js +108 -0
- package/dist/knowledge-freshness/providers/index.js.map +1 -0
- package/dist/knowledge-freshness/providers/index.test.d.ts +2 -0
- package/dist/knowledge-freshness/providers/index.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/providers/index.test.js +97 -0
- package/dist/knowledge-freshness/providers/index.test.js.map +1 -0
- package/dist/knowledge-freshness/source-hash.d.ts +39 -0
- package/dist/knowledge-freshness/source-hash.d.ts.map +1 -0
- package/dist/knowledge-freshness/source-hash.js +180 -0
- package/dist/knowledge-freshness/source-hash.js.map +1 -0
- package/dist/knowledge-freshness/source-hash.test.d.ts +2 -0
- package/dist/knowledge-freshness/source-hash.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/source-hash.test.js +63 -0
- package/dist/knowledge-freshness/source-hash.test.js.map +1 -0
- package/dist/knowledge-freshness/source-url-validator.d.ts +57 -0
- package/dist/knowledge-freshness/source-url-validator.d.ts.map +1 -0
- package/dist/knowledge-freshness/source-url-validator.js +304 -0
- package/dist/knowledge-freshness/source-url-validator.js.map +1 -0
- package/dist/knowledge-freshness/source-url-validator.test.d.ts +2 -0
- package/dist/knowledge-freshness/source-url-validator.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/source-url-validator.test.js +167 -0
- package/dist/knowledge-freshness/source-url-validator.test.js.map +1 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.d.ts +3 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.d.ts.map +1 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.js +165 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.js.map +1 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.test.d.ts +2 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.test.d.ts.map +1 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.test.js +421 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.test.js.map +1 -0
- package/dist/observability/checks/lens-i-lessons-scanner.d.ts +16 -0
- package/dist/observability/checks/lens-i-lessons-scanner.d.ts.map +1 -0
- package/dist/observability/checks/lens-i-lessons-scanner.js +106 -0
- package/dist/observability/checks/lens-i-lessons-scanner.js.map +1 -0
- package/dist/observability/checks/lens-i-lessons-scanner.test.d.ts +2 -0
- package/dist/observability/checks/lens-i-lessons-scanner.test.d.ts.map +1 -0
- package/dist/observability/checks/lens-i-lessons-scanner.test.js +174 -0
- package/dist/observability/checks/lens-i-lessons-scanner.test.js.map +1 -0
- package/dist/observability/engine/api.d.ts +4 -0
- package/dist/observability/engine/api.d.ts.map +1 -1
- package/dist/observability/engine/api.js +17 -1
- package/dist/observability/engine/api.js.map +1 -1
- package/dist/observability/engine/checks/observability-config.d.ts +4 -0
- package/dist/observability/engine/checks/observability-config.d.ts.map +1 -1
- package/dist/observability/engine/checks/observability-config.js +1 -0
- package/dist/observability/engine/checks/observability-config.js.map +1 -1
- package/dist/observability/engine/checks/registry.d.ts.map +1 -1
- package/dist/observability/engine/checks/registry.js +7 -0
- package/dist/observability/engine/checks/registry.js.map +1 -1
- package/dist/observability/engine/checks/registry.test.js +3 -2
- package/dist/observability/engine/checks/registry.test.js.map +1 -1
- package/dist/observability/engine/checks/runner.d.ts +30 -0
- package/dist/observability/engine/checks/runner.d.ts.map +1 -1
- package/dist/observability/engine/checks/runner.js +8 -1
- package/dist/observability/engine/checks/runner.js.map +1 -1
- package/dist/observability/engine/checks/runner.test.js +74 -0
- package/dist/observability/engine/checks/runner.test.js.map +1 -1
- package/dist/observability/engine/event-schemas.d.ts.map +1 -1
- package/dist/observability/engine/event-schemas.js +41 -3
- package/dist/observability/engine/event-schemas.js.map +1 -1
- package/dist/observability/engine/event-schemas.test.js +105 -0
- package/dist/observability/engine/event-schemas.test.js.map +1 -1
- package/dist/observability/engine/fix-flow.d.ts +7 -0
- package/dist/observability/engine/fix-flow.d.ts.map +1 -1
- package/dist/observability/engine/fix-flow.js +5 -3
- package/dist/observability/engine/fix-flow.js.map +1 -1
- package/dist/observability/engine/knowledge-root-integration.test.d.ts +2 -0
- package/dist/observability/engine/knowledge-root-integration.test.d.ts.map +1 -0
- package/dist/observability/engine/knowledge-root-integration.test.js +103 -0
- package/dist/observability/engine/knowledge-root-integration.test.js.map +1 -0
- package/dist/observability/engine/types.d.ts +20 -1
- package/dist/observability/engine/types.d.ts.map +1 -1
- package/dist/observability/engine/types.test.js +1 -1
- package/dist/observability/engine/types.test.js.map +1 -1
- package/dist/observability/knowledge-index.d.ts +145 -0
- package/dist/observability/knowledge-index.d.ts.map +1 -0
- package/dist/observability/knowledge-index.js +353 -0
- package/dist/observability/knowledge-index.js.map +1 -0
- package/dist/observability/knowledge-index.test.d.ts +2 -0
- package/dist/observability/knowledge-index.test.d.ts.map +1 -0
- package/dist/observability/knowledge-index.test.js +364 -0
- package/dist/observability/knowledge-index.test.js.map +1 -0
- package/dist/observability/renderers/markdown.d.ts.map +1 -1
- package/dist/observability/renderers/markdown.js +14 -0
- package/dist/observability/renderers/markdown.js.map +1 -1
- package/dist/observability/renderers/markdown.test.js +30 -0
- package/dist/observability/renderers/markdown.test.js.map +1 -1
- package/dist/types/assembly.d.ts +10 -0
- package/dist/types/assembly.d.ts.map +1 -1
- package/dist/utils/fs.d.ts +6 -0
- package/dist/utils/fs.d.ts.map +1 -1
- package/dist/utils/fs.js +13 -0
- package/dist/utils/fs.js.map +1 -1
- package/dist/validation/knowledge-frontmatter-validator.d.ts +15 -0
- package/dist/validation/knowledge-frontmatter-validator.d.ts.map +1 -0
- package/dist/validation/knowledge-frontmatter-validator.js +131 -0
- package/dist/validation/knowledge-frontmatter-validator.js.map +1 -0
- package/dist/validation/knowledge-frontmatter-validator.test.d.ts +2 -0
- package/dist/validation/knowledge-frontmatter-validator.test.d.ts.map +1 -0
- package/dist/validation/knowledge-frontmatter-validator.test.js +66 -0
- package/dist/validation/knowledge-frontmatter-validator.test.js.map +1 -0
- package/package.json +13 -4
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type Resolver } from './source-url-validator.js';
|
|
2
|
+
/** Production fetch implementation. Tests inject a mock via opts.fetchImpl. */
|
|
3
|
+
export type FetchImpl = (input: string, init?: Record<string, unknown>) => Promise<Response>;
|
|
4
|
+
/** Test-injectable options. Production callers omit this. */
|
|
5
|
+
export interface FetchAndHashOptions {
|
|
6
|
+
resolver?: Resolver;
|
|
7
|
+
/** Per-fetch timeout in ms (each hop is bounded separately). Default 30s. */
|
|
8
|
+
timeoutMs?: number;
|
|
9
|
+
/** Body size ceiling in bytes. Default 5 MiB. */
|
|
10
|
+
maxBodyBytes?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Override the fetch implementation. Used only by tests so they can
|
|
13
|
+
* mock responses without going to the network. Production uses undici's
|
|
14
|
+
* fetch so the pinning Agent dispatcher API matches.
|
|
15
|
+
*/
|
|
16
|
+
fetchImpl?: FetchImpl;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* GET a URL and sha256 its body. Used by:
|
|
20
|
+
* - audit-prefilter: to detect upstream changes (compare fresh hash
|
|
21
|
+
* against the frontmatter's stored hash)
|
|
22
|
+
* - audit-apply: to compute deterministic hashes for persistence,
|
|
23
|
+
* preferring them over LLM-emitted content_hash values
|
|
24
|
+
*
|
|
25
|
+
* Validates EVERY hop (initial URL + each redirect target) against the SSRF
|
|
26
|
+
* guard. A naive `fetch(url)` follows redirects automatically, so a source
|
|
27
|
+
* pointing at a public URL that 302's to localhost / 169.254.169.254 would
|
|
28
|
+
* bypass the guard (round-4 F-002). We do redirects manually, validate the
|
|
29
|
+
* Location header, and cap at MAX_REDIRECT_HOPS.
|
|
30
|
+
*
|
|
31
|
+
* Throws on guard failure, network failure, non-2xx final responses, or
|
|
32
|
+
* redirect-without-Location so callers can decide whether to skip
|
|
33
|
+
* (pre-filter) or abort (apply).
|
|
34
|
+
*/
|
|
35
|
+
export declare function fetchAndHash(url: string, opts?: FetchAndHashOptions): Promise<{
|
|
36
|
+
hash: string;
|
|
37
|
+
body: string;
|
|
38
|
+
}>;
|
|
39
|
+
//# sourceMappingURL=source-hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-hash.d.ts","sourceRoot":"","sources":["../../src/knowledge-freshness/source-hash.ts"],"names":[],"mappings":"AAOA,OAAO,EAA+C,KAAK,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AAEtG,+EAA+E;AAC/E,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAW5F,6DAA6D;AAC7D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB;AA+BD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,mBAAwB,GAC7B,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CA4EzC"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import net from 'node:net';
|
|
3
|
+
// Use undici's own fetch (not Node's built-in) so the Agent dispatcher we
|
|
4
|
+
// pass matches the same undici version. Node's built-in fetch uses its
|
|
5
|
+
// internally-bundled undici which can drift in dispatcher API from the
|
|
6
|
+
// npm-installed package, producing "invalid onError method" at runtime.
|
|
7
|
+
import { fetch as undiciFetch, Agent } from 'undici';
|
|
8
|
+
import { assertSafeSourceUrlWithDns, defaultResolver } from './source-url-validator.js';
|
|
9
|
+
const MAX_REDIRECT_HOPS = 5;
|
|
10
|
+
const DEFAULT_FETCH_TIMEOUT_MS = 30_000;
|
|
11
|
+
/**
|
|
12
|
+
* Cap on the response body. 5 MiB is comfortably larger than any real spec
|
|
13
|
+
* page (OWASP Top 10 is ~50 KiB) and small enough that even a malicious
|
|
14
|
+
* 100 MB response can't exhaust memory (round-7 F-003).
|
|
15
|
+
*/
|
|
16
|
+
const MAX_RESPONSE_BODY_BYTES = 5 * 1024 * 1024;
|
|
17
|
+
/**
|
|
18
|
+
* Build an undici Agent whose connection lookup is pinned to a specific IP.
|
|
19
|
+
* Used to close the DNS-rebinding TOCTOU gap: the validator already resolved
|
|
20
|
+
* the hostname and approved every IP. Pinning fetch to one of those IPs
|
|
21
|
+
* prevents a second DNS lookup at fetch time from returning a private/
|
|
22
|
+
* loopback target (round-7 F-002).
|
|
23
|
+
*
|
|
24
|
+
* The undici lookup callback follows Node's `dns.lookup` signature, so we
|
|
25
|
+
* return the pinned IP directly without re-resolving.
|
|
26
|
+
*/
|
|
27
|
+
function pinningAgent(pinnedIp) {
|
|
28
|
+
const family = net.isIP(pinnedIp) === 6 ? 6 : 4;
|
|
29
|
+
// Node's `dns.lookup` callback has TWO forms depending on `opts.all`:
|
|
30
|
+
// all=true → callback(err, [{address, family}])
|
|
31
|
+
// all=false → callback(err, address, family)
|
|
32
|
+
// undici can invoke either, so handle both shapes — otherwise we get
|
|
33
|
+
// `ERR_INVALID_IP_ADDRESS: Invalid IP address: undefined` when undici
|
|
34
|
+
// passes `{all: true}` and we call the 3-arg form.
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
36
|
+
const lookup = (_hostname, opts, callback) => {
|
|
37
|
+
if (opts && opts.all === true) {
|
|
38
|
+
callback(null, [{ address: pinnedIp, family }]);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
callback(null, pinnedIp, family);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
return new Agent({ connect: { lookup } });
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* GET a URL and sha256 its body. Used by:
|
|
48
|
+
* - audit-prefilter: to detect upstream changes (compare fresh hash
|
|
49
|
+
* against the frontmatter's stored hash)
|
|
50
|
+
* - audit-apply: to compute deterministic hashes for persistence,
|
|
51
|
+
* preferring them over LLM-emitted content_hash values
|
|
52
|
+
*
|
|
53
|
+
* Validates EVERY hop (initial URL + each redirect target) against the SSRF
|
|
54
|
+
* guard. A naive `fetch(url)` follows redirects automatically, so a source
|
|
55
|
+
* pointing at a public URL that 302's to localhost / 169.254.169.254 would
|
|
56
|
+
* bypass the guard (round-4 F-002). We do redirects manually, validate the
|
|
57
|
+
* Location header, and cap at MAX_REDIRECT_HOPS.
|
|
58
|
+
*
|
|
59
|
+
* Throws on guard failure, network failure, non-2xx final responses, or
|
|
60
|
+
* redirect-without-Location so callers can decide whether to skip
|
|
61
|
+
* (pre-filter) or abort (apply).
|
|
62
|
+
*/
|
|
63
|
+
export async function fetchAndHash(url, opts = {}) {
|
|
64
|
+
const resolver = opts.resolver ?? defaultResolver;
|
|
65
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;
|
|
66
|
+
const maxBodyBytes = opts.maxBodyBytes ?? MAX_RESPONSE_BODY_BYTES;
|
|
67
|
+
const doFetch = opts.fetchImpl ?? undiciFetch;
|
|
68
|
+
let current = url;
|
|
69
|
+
for (let hop = 0; hop <= MAX_REDIRECT_HOPS; hop++) {
|
|
70
|
+
// DNS-rebinding guard: also resolve the hostname and check every returned
|
|
71
|
+
// IP, not just the literal hostname (round-5 F-001). Round-7 F-002 pins
|
|
72
|
+
// the fetch to the first validated IP. Round-8 F-001/F-002 closes the
|
|
73
|
+
// residual TOCTOU by having the validator RETURN the validated IP list
|
|
74
|
+
// — we don't resolve again here.
|
|
75
|
+
const { url: validated, ips } = await assertSafeSourceUrlWithDns(current, resolver);
|
|
76
|
+
let host = validated.hostname;
|
|
77
|
+
if (host.startsWith('[') && host.endsWith(']'))
|
|
78
|
+
host = host.slice(1, -1);
|
|
79
|
+
const pinnedIp = ips[0];
|
|
80
|
+
// Pin only when the host is a hostname, not when the URL already used an
|
|
81
|
+
// IP literal — that case has no rebinding window. `ips` from the
|
|
82
|
+
// validator already contains the literal itself in that case.
|
|
83
|
+
const dispatcher = net.isIP(host) === 0 && pinnedIp ? pinningAgent(pinnedIp) : undefined;
|
|
84
|
+
// Per-hop timeout (round-6 F-003): a hanging server would otherwise block
|
|
85
|
+
// the daily cron indefinitely. AbortSignal.timeout is built-in to Node 22+.
|
|
86
|
+
//
|
|
87
|
+
// The dispatcher must stay alive until the response body is fully read
|
|
88
|
+
// (round-9 F-002). Earlier rounds closed it right after fetch() returned
|
|
89
|
+
// headers, but res.body is a stream — closing the agent mid-stream
|
|
90
|
+
// would stall or truncate reads. Wrap the entire per-hop handling in
|
|
91
|
+
// try/finally so the close only happens after body consumption (or after
|
|
92
|
+
// we decide to follow a redirect, in which case the body is discarded).
|
|
93
|
+
let res;
|
|
94
|
+
try {
|
|
95
|
+
res = await doFetch(current, {
|
|
96
|
+
redirect: 'manual',
|
|
97
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
98
|
+
// `dispatcher` is an undici extension to the WHATWG fetch standard.
|
|
99
|
+
...(dispatcher ? { dispatcher } : {}),
|
|
100
|
+
});
|
|
101
|
+
// 3xx with a Location header → re-validate and follow.
|
|
102
|
+
if (res.status >= 300 && res.status < 400) {
|
|
103
|
+
const location = res.headers.get('location');
|
|
104
|
+
if (!location) {
|
|
105
|
+
throw new Error(`fetch ${current} returned ${res.status} with no Location header`);
|
|
106
|
+
}
|
|
107
|
+
// Drain/cancel the redirect response so the underlying connection is
|
|
108
|
+
// free before we close the agent. Without this, agent.close() can
|
|
109
|
+
// race the still-open response body.
|
|
110
|
+
try {
|
|
111
|
+
await res.body?.cancel();
|
|
112
|
+
}
|
|
113
|
+
catch { /* noop */ }
|
|
114
|
+
// Resolve relative redirects against the URL we just hit.
|
|
115
|
+
current = new URL(location, current).toString();
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (!res.ok) {
|
|
119
|
+
// Drain the error body so Agent.close() doesn't wait on an active
|
|
120
|
+
// stream (round-10 F-001). A slow or large error body would otherwise
|
|
121
|
+
// hang the cron despite the size + timeout guards on success.
|
|
122
|
+
try {
|
|
123
|
+
await res.body?.cancel();
|
|
124
|
+
}
|
|
125
|
+
catch { /* noop */ }
|
|
126
|
+
throw new Error(`fetch ${current} returned HTTP ${res.status}`);
|
|
127
|
+
}
|
|
128
|
+
// Read body with a size cap so a malicious or massive response can't
|
|
129
|
+
// exhaust memory (round-7 F-003). The reader is cancelled on size
|
|
130
|
+
// overflow inside readBodyWithLimit so Agent.close() won't stall.
|
|
131
|
+
const body = await readBodyWithLimit(res, maxBodyBytes, current);
|
|
132
|
+
const hash = `sha256:${createHash('sha256').update(body).digest('hex')}`;
|
|
133
|
+
return { hash, body };
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
// Close the agent only AFTER the body has been consumed (or the
|
|
137
|
+
// redirect response cancelled). Each hop builds a fresh agent because
|
|
138
|
+
// the hostname can change between hops, so we never reuse one.
|
|
139
|
+
if (dispatcher)
|
|
140
|
+
await dispatcher.close();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
throw new Error(`fetch ${url} exceeded ${MAX_REDIRECT_HOPS} redirects`);
|
|
144
|
+
}
|
|
145
|
+
async function readBodyWithLimit(res, max, url) {
|
|
146
|
+
if (!res.body)
|
|
147
|
+
return await res.text();
|
|
148
|
+
const reader = res.body.getReader();
|
|
149
|
+
const chunks = [];
|
|
150
|
+
let total = 0;
|
|
151
|
+
let cancelled = false;
|
|
152
|
+
try {
|
|
153
|
+
while (true) {
|
|
154
|
+
const { done, value } = await reader.read();
|
|
155
|
+
if (done)
|
|
156
|
+
break;
|
|
157
|
+
if (value) {
|
|
158
|
+
total += value.byteLength;
|
|
159
|
+
if (total > max) {
|
|
160
|
+
// Cancel the reader so the underlying stream closes and
|
|
161
|
+
// Agent.close() (called in the caller's finally) doesn't wait on
|
|
162
|
+
// an unbounded inflight body (round-10 F-001).
|
|
163
|
+
cancelled = true;
|
|
164
|
+
try {
|
|
165
|
+
await reader.cancel();
|
|
166
|
+
}
|
|
167
|
+
catch { /* noop */ }
|
|
168
|
+
throw new Error(`fetch ${url} response exceeded ${max} bytes (DoS guard)`);
|
|
169
|
+
}
|
|
170
|
+
chunks.push(value);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
if (!cancelled)
|
|
176
|
+
reader.releaseLock?.();
|
|
177
|
+
}
|
|
178
|
+
return new TextDecoder('utf-8').decode(Buffer.concat(chunks));
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=source-hash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-hash.js","sourceRoot":"","sources":["../../src/knowledge-freshness/source-hash.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-hash.test.d.ts","sourceRoot":"","sources":["../../src/knowledge-freshness/source-hash.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { fetchAndHash } from './source-hash.js';
|
|
3
|
+
// Stub resolver: every public hostname resolves to a single public IP.
|
|
4
|
+
// Tests that want to exercise DNS-rebinding rejection inject a different
|
|
5
|
+
// resolver that returns a private IP.
|
|
6
|
+
const publicResolver = async () => ['93.184.216.34'];
|
|
7
|
+
// Build a FetchImpl mock that returns a queue of pre-built Responses.
|
|
8
|
+
function mockFetch(...responses) {
|
|
9
|
+
const queue = [...responses];
|
|
10
|
+
return vi.fn(async () => {
|
|
11
|
+
const next = queue.shift();
|
|
12
|
+
if (!next)
|
|
13
|
+
throw new Error('mock fetch: no more queued responses');
|
|
14
|
+
return next;
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
describe('fetchAndHash', () => {
|
|
18
|
+
it('returns a sha256:-prefixed hex digest of the response body', async () => {
|
|
19
|
+
const fetchImpl = mockFetch(new Response('hello world', { status: 200 }));
|
|
20
|
+
const { hash, body } = await fetchAndHash('https://example.org/anything', { resolver: publicResolver, fetchImpl });
|
|
21
|
+
expect(hash).toBe('sha256:b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9');
|
|
22
|
+
expect(body).toBe('hello world');
|
|
23
|
+
});
|
|
24
|
+
it('throws on non-2xx response', async () => {
|
|
25
|
+
const fetchImpl = mockFetch(new Response('', { status: 503 }));
|
|
26
|
+
await expect(fetchAndHash('https://example.org/down', { resolver: publicResolver, fetchImpl })).rejects.toThrow(/503/);
|
|
27
|
+
});
|
|
28
|
+
// Round-4 F-002: redirect validation
|
|
29
|
+
it('follows a redirect to a public URL and hashes the final body', async () => {
|
|
30
|
+
const fetchImpl = mockFetch(new Response('', { status: 302, headers: { Location: 'https://example.org/final' } }), new Response('hello world', { status: 200 }));
|
|
31
|
+
const { hash } = await fetchAndHash('https://example.org/start', { resolver: publicResolver, fetchImpl });
|
|
32
|
+
expect(hash).toBe('sha256:b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9');
|
|
33
|
+
});
|
|
34
|
+
it('rejects a redirect that targets a private network (SSRF via 302)', async () => {
|
|
35
|
+
const fetchImpl = mockFetch(new Response('', { status: 302, headers: { Location: 'http://169.254.169.254/latest/meta-data/' } }));
|
|
36
|
+
await expect(fetchAndHash('https://example.org/looks-fine', { resolver: publicResolver, fetchImpl })).rejects.toThrow(/refusing to fetch/);
|
|
37
|
+
});
|
|
38
|
+
it('rejects a redirect chain ending in localhost', async () => {
|
|
39
|
+
const fetchImpl = mockFetch(new Response('', { status: 302, headers: { Location: 'https://b.example.org/' } }), new Response('', { status: 302, headers: { Location: 'http://localhost:8080/' } }));
|
|
40
|
+
await expect(fetchAndHash('https://a.example.org/', { resolver: publicResolver, fetchImpl })).rejects.toThrow(/refusing to fetch/);
|
|
41
|
+
});
|
|
42
|
+
it('errors when a 3xx response is missing a Location header', async () => {
|
|
43
|
+
const fetchImpl = mockFetch(new Response('', { status: 302 }));
|
|
44
|
+
await expect(fetchAndHash('https://example.org/x', { resolver: publicResolver, fetchImpl })).rejects.toThrow(/no Location header/);
|
|
45
|
+
});
|
|
46
|
+
it('errors after exceeding the redirect-hop limit', async () => {
|
|
47
|
+
// 6 consecutive redirects → 1 initial + 5 follow-ups = 6 fetches, then bail.
|
|
48
|
+
const fetchImpl = vi.fn(async () => new Response('', { status: 302, headers: { Location: 'https://hop.example.org/' } }));
|
|
49
|
+
await expect(fetchAndHash('https://example.org/start', { resolver: publicResolver, fetchImpl })).rejects.toThrow(/exceeded/);
|
|
50
|
+
});
|
|
51
|
+
// Round-5 F-001: DNS-rebinding guard
|
|
52
|
+
it('rejects a hostname that resolves to a private IPv4 (DNS-rebinding)', async () => {
|
|
53
|
+
const rebindingResolver = async () => ['127.0.0.1'];
|
|
54
|
+
const fetchImpl = mockFetch(new Response('', { status: 200 }));
|
|
55
|
+
await expect(fetchAndHash('https://attacker.example/', { resolver: rebindingResolver, fetchImpl })).rejects.toThrow(/DNS-rebinding/);
|
|
56
|
+
});
|
|
57
|
+
it('rejects a hostname that resolves to a private IPv6 (DNS-rebinding)', async () => {
|
|
58
|
+
const rebindingResolver = async () => ['fe80::1'];
|
|
59
|
+
const fetchImpl = mockFetch(new Response('', { status: 200 }));
|
|
60
|
+
await expect(fetchAndHash('https://attacker.example/', { resolver: rebindingResolver, fetchImpl })).rejects.toThrow(/DNS-rebinding/);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
//# sourceMappingURL=source-hash.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-hash.test.js","sourceRoot":"","sources":["../../src/knowledge-freshness/source-hash.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export type ValidationResult = {
|
|
2
|
+
ok: true;
|
|
3
|
+
url: URL;
|
|
4
|
+
} | {
|
|
5
|
+
ok: false;
|
|
6
|
+
reason: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function validateSourceUrl(raw: string): ValidationResult;
|
|
9
|
+
/**
|
|
10
|
+
* Resolve a hostname to its A/AAAA records. Pulled out as an injectable type
|
|
11
|
+
* so tests can stub DNS without hitting the network. The real resolver uses
|
|
12
|
+
* Node's `dns.promises`.
|
|
13
|
+
*/
|
|
14
|
+
export type Resolver = (host: string) => Promise<string[]>;
|
|
15
|
+
export declare const defaultResolver: Resolver;
|
|
16
|
+
/**
|
|
17
|
+
* Same as `assertSafeSourceUrl`, but ALSO resolves the hostname and checks
|
|
18
|
+
* every returned IP against the IPv4/IPv6 blocklists. Prevents DNS-rebinding
|
|
19
|
+
* attacks where a public hostname resolves to a private IP (round-5 F-001).
|
|
20
|
+
*
|
|
21
|
+
* Returns BOTH the URL and the validated IPs so callers can pin the fetch
|
|
22
|
+
* to one of those IPs without resolving again (round-8 F-001/F-002).
|
|
23
|
+
* Performing a second DNS lookup at fetch time would re-open the TOCTOU
|
|
24
|
+
* window the validator was supposed to close.
|
|
25
|
+
*
|
|
26
|
+
* For raw IP literals, `ips` contains the literal itself (no DNS lookup).
|
|
27
|
+
*/
|
|
28
|
+
export interface DnsValidatedUrl {
|
|
29
|
+
url: URL;
|
|
30
|
+
ips: string[];
|
|
31
|
+
}
|
|
32
|
+
export declare function assertSafeSourceUrlWithDns(raw: string, resolver?: Resolver): Promise<DnsValidatedUrl>;
|
|
33
|
+
/**
|
|
34
|
+
* Throws if the URL would route to a restricted target. Use at every external
|
|
35
|
+
* fetch boundary; the helper is intentionally identical for prefilter, apply,
|
|
36
|
+
* and meta-prompt dispatch so one guard covers all three callsites.
|
|
37
|
+
*/
|
|
38
|
+
export declare function assertSafeSourceUrl(raw: string): URL;
|
|
39
|
+
/**
|
|
40
|
+
* Load the allowlist from `docs/knowledge-freshness/authoritative-sources.yaml`
|
|
41
|
+
* (relative to `projectRoot`). Used by the operations / CI gate to flag
|
|
42
|
+
* out-of-list sources as warnings (not hard blocks per resolved decision #4).
|
|
43
|
+
* Returns an empty Set when the file is missing so the caller treats every
|
|
44
|
+
* host as out-of-list and warns — the safer default than "silently allow".
|
|
45
|
+
*/
|
|
46
|
+
interface Allowlist {
|
|
47
|
+
hosts: string[];
|
|
48
|
+
github_repos: string[];
|
|
49
|
+
}
|
|
50
|
+
export declare function loadAuthoritativeAllowlist(projectRoot: string): Allowlist;
|
|
51
|
+
/**
|
|
52
|
+
* Returns true if `url`'s host (or github repo path) appears in the allowlist.
|
|
53
|
+
* Decision #4 (locked): off-allowlist sources warn, not block.
|
|
54
|
+
*/
|
|
55
|
+
export declare function isAllowlistedSource(url: URL, allowlist: Allowlist): boolean;
|
|
56
|
+
export {};
|
|
57
|
+
//# sourceMappingURL=source-url-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-url-validator.d.ts","sourceRoot":"","sources":["../../src/knowledge-freshness/source-url-validator.ts"],"names":[],"mappings":"AAmIA,MAAM,MAAM,gBAAgB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,GAAG,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAErF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAwC/D;AAED;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;AAE1D,eAAO,MAAM,eAAe,EAAE,QAY7B,CAAA;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,eAAe;IAAG,GAAG,EAAE,GAAG,CAAC;IAAC,GAAG,EAAE,MAAM,EAAE,CAAA;CAAE;AAE5D,wBAAsB,0BAA0B,CAC9C,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,QAA0B,GACnC,OAAO,CAAC,eAAe,CAAC,CA+B1B;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAUpD;AAED;;;;;;GAMG;AACH,UAAU,SAAS;IAAG,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE;AAE/D,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAkBzE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAsB3E"}
|