qa360 2.3.0 → 2.3.1
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 +155 -262
- package/{cli/dist → dist}/commands/ai.js +1 -1
- package/{cli/dist → dist}/commands/coverage.js +1 -1
- package/{cli/dist → dist}/commands/crawl.js +2 -2
- package/{cli/dist → dist}/commands/doctor.js +2 -2
- package/{cli/dist → dist}/commands/explain.js +2 -2
- package/{cli/dist → dist}/commands/flakiness.js +1 -1
- package/{cli/dist → dist}/commands/generate.js +1 -1
- package/{cli/dist → dist}/commands/history.js +1 -1
- package/{cli/dist → dist}/commands/monitor.js +3 -3
- package/{cli/dist → dist}/commands/ollama.js +1 -1
- package/{cli/dist → dist}/commands/pack.js +2 -2
- package/{cli/dist → dist}/commands/regression.js +1 -1
- package/{cli/dist → dist}/commands/repair.js +1 -1
- package/{cli/dist → dist}/commands/retry.js +1 -1
- package/{cli/dist → dist}/commands/run.d.ts +1 -1
- package/{cli/dist → dist}/commands/run.js +1 -1
- package/{cli/dist → dist}/commands/secrets.js +1 -1
- package/{cli/dist → dist}/commands/serve.js +1 -1
- package/{cli/dist → dist}/commands/slo.js +1 -1
- package/{cli/dist → dist}/commands/verify.js +1 -1
- package/{cli/dist → dist}/core/adapters/playwright-native-api.d.ts +2 -0
- package/{cli/dist → dist}/core/adapters/playwright-native-api.js +20 -1
- package/{cli/dist → dist}/core/adapters/playwright-ui.d.ts +21 -0
- package/dist/core/adapters/playwright-ui.js +2050 -0
- package/{cli/dist → dist}/core/ai/ollama-provider.js +15 -3
- package/{cli/dist → dist}/core/artifacts/ui-artifacts.js +24 -4
- package/dist/core/auth/backup-codes-provider.d.ts +91 -0
- package/dist/core/auth/backup-codes-provider.js +215 -0
- package/{cli/dist → dist}/core/auth/basic-auth-provider.d.ts +6 -0
- package/{cli/dist → dist}/core/auth/basic-auth-provider.js +24 -6
- package/dist/core/auth/digest-auth-provider.d.ts +116 -0
- package/dist/core/auth/digest-auth-provider.js +244 -0
- package/dist/core/auth/hcaptcha-handler.d.ts +103 -0
- package/dist/core/auth/hcaptcha-handler.js +288 -0
- package/{cli/dist → dist}/core/auth/index.d.ts +81 -4
- package/{cli/dist → dist}/core/auth/index.js +15 -1
- package/dist/core/auth/oauth-handler.d.ts +408 -0
- package/dist/core/auth/oauth-handler.js +636 -0
- package/{cli/dist → dist}/core/auth/oauth2-provider.d.ts +9 -0
- package/dist/core/auth/oauth2-provider.js +227 -0
- package/dist/core/auth/otp-provider.d.ts +93 -0
- package/dist/core/auth/otp-provider.js +288 -0
- package/dist/core/auth/recaptcha-handler.d.ts +119 -0
- package/dist/core/auth/recaptcha-handler.js +301 -0
- package/dist/core/auth/remember-me-handler.d.ts +142 -0
- package/dist/core/auth/remember-me-handler.js +255 -0
- package/dist/core/auth/saml-handler.d.ts +173 -0
- package/dist/core/auth/saml-handler.js +364 -0
- package/dist/core/auth/webauthn-handler.d.ts +182 -0
- package/dist/core/auth/webauthn-handler.js +310 -0
- package/dist/core/crawler/advanced-interactions.d.ts +342 -0
- package/dist/core/crawler/advanced-interactions.js +1069 -0
- package/dist/core/crawler/blob-url-download-handler.d.ts +145 -0
- package/dist/core/crawler/blob-url-download-handler.js +392 -0
- package/dist/core/crawler/consent-handler.d.ts +49 -0
- package/dist/core/crawler/consent-handler.js +258 -0
- package/dist/core/crawler/cookie-manager.d.ts +166 -0
- package/dist/core/crawler/cookie-manager.js +353 -0
- package/dist/core/crawler/coop-coep-handler.d.ts +136 -0
- package/dist/core/crawler/coop-coep-handler.js +338 -0
- package/dist/core/crawler/csp-handler.d.ts +151 -0
- package/dist/core/crawler/csp-handler.js +415 -0
- package/dist/core/crawler/download-handler.d.ts +155 -0
- package/dist/core/crawler/download-handler.js +370 -0
- package/dist/core/crawler/email-testing-handler.d.ts +214 -0
- package/dist/core/crawler/email-testing-handler.js +398 -0
- package/dist/core/crawler/error-tracking-handler.d.ts +177 -0
- package/dist/core/crawler/error-tracking-handler.js +378 -0
- package/dist/core/crawler/form-handler.d.ts +100 -0
- package/dist/core/crawler/form-handler.js +465 -0
- package/dist/core/crawler/framework-wait-handler.d.ts +96 -0
- package/dist/core/crawler/framework-wait-handler.js +464 -0
- package/dist/core/crawler/geolocation-handler.d.ts +112 -0
- package/dist/core/crawler/geolocation-handler.js +276 -0
- package/dist/core/crawler/index.d.ts +78 -0
- package/{cli/dist → dist}/core/crawler/index.js +74 -1
- package/dist/core/crawler/intelligent-selector-generator.d.ts +164 -0
- package/dist/core/crawler/intelligent-selector-generator.js +612 -0
- package/{cli/dist → dist}/core/crawler/journey-generator.js +44 -1
- package/{cli/dist → dist}/core/crawler/page-analyzer.d.ts +16 -1
- package/{cli/dist → dist}/core/crawler/page-analyzer.js +469 -17
- package/dist/core/crawler/permissions-handler.d.ts +112 -0
- package/dist/core/crawler/permissions-handler.js +236 -0
- package/dist/core/crawler/permissions-policy-handler.d.ts +113 -0
- package/dist/core/crawler/permissions-policy-handler.js +402 -0
- package/dist/core/crawler/presets.d.ts +100 -0
- package/dist/core/crawler/presets.js +887 -0
- package/dist/core/crawler/repl-debug-handler.d.ts +105 -0
- package/dist/core/crawler/repl-debug-handler.js +552 -0
- package/dist/core/crawler/reporting-api-handler.d.ts +212 -0
- package/dist/core/crawler/reporting-api-handler.js +344 -0
- package/{cli/dist → dist}/core/crawler/selector-generator.d.ts +9 -0
- package/{cli/dist → dist}/core/crawler/selector-generator.js +99 -23
- package/dist/core/crawler/site-profiler.d.ts +89 -0
- package/dist/core/crawler/site-profiler.js +290 -0
- package/dist/core/crawler/sourcemaps-handler.d.ts +144 -0
- package/dist/core/crawler/sourcemaps-handler.js +420 -0
- package/dist/core/crawler/stacked-modals-handler.d.ts +118 -0
- package/dist/core/crawler/stacked-modals-handler.js +429 -0
- package/dist/core/crawler/trusted-types-handler.d.ts +149 -0
- package/dist/core/crawler/trusted-types-handler.js +413 -0
- package/{cli/dist → dist}/core/crawler/types.d.ts +68 -2
- package/dist/core/crawler/wait-strategies.d.ts +108 -0
- package/dist/core/crawler/wait-strategies.js +399 -0
- package/dist/core/fixtures/factories.d.ts +180 -0
- package/dist/core/fixtures/factories.js +279 -0
- package/dist/core/fixtures/index.d.ts +6 -0
- package/dist/core/fixtures/index.js +6 -0
- package/{cli/dist → dist}/core/generation/crawler-pack-generator.d.ts +13 -3
- package/dist/core/generation/crawler-pack-generator.js +232 -0
- package/{cli/dist → dist}/core/generation/index.d.ts +2 -0
- package/{cli/dist → dist}/core/generation/index.js +2 -0
- package/{cli/dist → dist}/core/index.d.ts +2 -0
- package/{cli/dist → dist}/core/index.js +4 -0
- package/dist/core/network/index.d.ts +7 -0
- package/dist/core/network/index.js +7 -0
- package/dist/core/network/network-manager.d.ts +237 -0
- package/dist/core/network/network-manager.js +343 -0
- package/dist/core/network/network-simulator.d.ts +158 -0
- package/dist/core/network/network-simulator.js +261 -0
- package/{cli/dist → dist}/core/pack/validator.js +2 -2
- package/{cli/dist → dist}/core/pack-v2/migrator.d.ts +5 -0
- package/{cli/dist → dist}/core/pack-v2/migrator.js +81 -6
- package/{cli/dist → dist}/core/pack-v2/validator.js +4 -3
- package/{cli/dist → dist}/core/pom/base-page.js +1 -1
- package/{cli/dist → dist}/core/pom/loader.js +1 -1
- package/dist/core/reporting/index.d.ts +9 -0
- package/dist/core/reporting/index.js +10 -0
- package/dist/core/reporting/junit-reporter.d.ts +114 -0
- package/dist/core/reporting/junit-reporter.js +306 -0
- package/{cli/dist → dist}/core/runner/e2e-helpers.d.ts +1 -1
- package/{cli/dist → dist}/core/runner/e2e-helpers.js +2 -2
- package/{cli/dist → dist}/core/runner/phase3-runner.d.ts +3 -0
- package/{cli/dist → dist}/core/runner/phase3-runner.js +45 -14
- package/dist/core/sharding/test-sharding.d.ts +137 -0
- package/dist/core/sharding/test-sharding.js +233 -0
- package/dist/core/storage/cookie-manager.d.ts +160 -0
- package/dist/core/storage/cookie-manager.js +268 -0
- package/dist/core/storage/index.d.ts +7 -0
- package/dist/core/storage/index.js +7 -0
- package/dist/core/storage/storage-helpers.d.ts +138 -0
- package/dist/core/storage/storage-helpers.js +315 -0
- package/dist/core/test-helpers/index.d.ts +6 -0
- package/dist/core/test-helpers/index.js +6 -0
- package/dist/core/test-helpers/state-reset.d.ts +119 -0
- package/dist/core/test-helpers/state-reset.js +234 -0
- package/{cli/dist → dist}/core/types/pack-v1.d.ts +15 -2
- package/{cli/dist → dist}/core/types/pack-v2.d.ts +1 -1
- package/dist/core/upload/chunked-uploader.d.ts +150 -0
- package/dist/core/upload/chunked-uploader.js +289 -0
- package/dist/core/upload/index.d.ts +11 -0
- package/dist/core/upload/index.js +8 -0
- package/dist/core/upload/mime-validator.d.ts +119 -0
- package/dist/core/upload/mime-validator.js +373 -0
- package/dist/core/upload/presigned-uploader.d.ts +118 -0
- package/dist/core/upload/presigned-uploader.js +274 -0
- package/dist/core/utils/device-emulation.d.ts +194 -0
- package/dist/core/utils/device-emulation.js +380 -0
- package/dist/core/utils/index.d.ts +8 -0
- package/dist/core/utils/index.js +8 -0
- package/dist/core/utils/retry.d.ts +145 -0
- package/dist/core/utils/retry.js +242 -0
- package/dist/core/utils/smart-wait.d.ts +133 -0
- package/dist/core/utils/smart-wait.js +417 -0
- package/dist/core/visual/index.d.ts +7 -0
- package/dist/core/visual/index.js +7 -0
- package/dist/core/visual/pixel-diff.d.ts +87 -0
- package/dist/core/visual/pixel-diff.js +213 -0
- package/dist/core/visual/screenshot-helper.d.ts +130 -0
- package/dist/core/visual/screenshot-helper.js +223 -0
- package/{cli/dist → dist}/utils/config.d.ts +1 -1
- package/examples/README.md +160 -0
- package/examples/accessibility.yml +48 -0
- package/examples/api-basic.yml +27 -0
- package/examples/complete.yml +146 -0
- package/examples/crawler.yml +38 -0
- package/examples/fullstack.yml +78 -0
- package/examples/security.yml +58 -0
- package/examples/ui-advanced.yml +49 -0
- package/examples/ui-basic.yml +24 -0
- package/package.json +33 -67
- package/CHANGELOG.md +0 -330
- package/CONTRIBUTING.md +0 -273
- package/QUICK_START.md +0 -191
- package/cli/CHANGELOG.md +0 -84
- package/cli/LICENSE +0 -24
- package/cli/README.md +0 -222
- package/cli/dist/core/adapters/playwright-ui.js +0 -864
- package/cli/dist/core/auth/oauth2-provider.js +0 -114
- package/cli/dist/core/coverage/analyzer.d.ts +0 -101
- package/cli/dist/core/coverage/analyzer.js +0 -415
- package/cli/dist/core/coverage/collector.d.ts +0 -74
- package/cli/dist/core/coverage/collector.js +0 -459
- package/cli/dist/core/coverage/config.d.ts +0 -37
- package/cli/dist/core/coverage/config.js +0 -156
- package/cli/dist/core/coverage/index.d.ts +0 -11
- package/cli/dist/core/coverage/index.js +0 -15
- package/cli/dist/core/coverage/types.d.ts +0 -267
- package/cli/dist/core/coverage/types.js +0 -6
- package/cli/dist/core/coverage/vault.d.ts +0 -95
- package/cli/dist/core/coverage/vault.js +0 -405
- package/cli/dist/core/crawler/index.d.ts +0 -57
- package/cli/dist/core/fixtures/index.d.ts +0 -8
- package/cli/dist/core/fixtures/index.js +0 -8
- package/cli/dist/core/generation/crawler-pack-generator.js +0 -231
- package/cli/dist/core/reporting/index.d.ts +0 -6
- package/cli/dist/core/reporting/index.js +0 -6
- package/cli/dist/core/visual/index.d.ts +0 -6
- package/cli/dist/core/visual/index.js +0 -6
- package/cli/package.json +0 -76
- package/core/LICENSE +0 -24
- package/core/README.md +0 -105
- package/core/package.json +0 -90
- package/core/schemas/pack.schema.json +0 -236
- /package/{cli/bin → bin}/qa360.js +0 -0
- /package/{cli/dist → dist}/cli-minimal.d.ts +0 -0
- /package/{cli/dist → dist}/cli-minimal.js +0 -0
- /package/{cli/dist → dist}/commands/ai.d.ts +0 -0
- /package/{cli/dist → dist}/commands/ask.d.ts +0 -0
- /package/{cli/dist → dist}/commands/ask.js +0 -0
- /package/{cli/dist → dist}/commands/coverage.d.ts +0 -0
- /package/{cli/dist → dist}/commands/crawl.d.ts +0 -0
- /package/{cli/dist → dist}/commands/doctor.d.ts +0 -0
- /package/{cli/dist → dist}/commands/examples.d.ts +0 -0
- /package/{cli/dist → dist}/commands/examples.js +0 -0
- /package/{cli/dist → dist}/commands/explain.d.ts +0 -0
- /package/{cli/dist → dist}/commands/flakiness.d.ts +0 -0
- /package/{cli/dist → dist}/commands/generate.d.ts +0 -0
- /package/{cli/dist → dist}/commands/history.d.ts +0 -0
- /package/{cli/dist → dist}/commands/init.d.ts +0 -0
- /package/{cli/dist → dist}/commands/init.js +0 -0
- /package/{cli/dist → dist}/commands/monitor.d.ts +0 -0
- /package/{cli/dist → dist}/commands/ollama.d.ts +0 -0
- /package/{cli/dist → dist}/commands/pack.d.ts +0 -0
- /package/{cli/dist → dist}/commands/regression.d.ts +0 -0
- /package/{cli/dist → dist}/commands/repair.d.ts +0 -0
- /package/{cli/dist → dist}/commands/report.d.ts +0 -0
- /package/{cli/dist → dist}/commands/report.js +0 -0
- /package/{cli/dist → dist}/commands/retry.d.ts +0 -0
- /package/{cli/dist → dist}/commands/scan.d.ts +0 -0
- /package/{cli/dist → dist}/commands/scan.js +0 -0
- /package/{cli/dist → dist}/commands/secrets.d.ts +0 -0
- /package/{cli/dist → dist}/commands/serve.d.ts +0 -0
- /package/{cli/dist → dist}/commands/slo.d.ts +0 -0
- /package/{cli/dist → dist}/commands/verify.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/gitleaks-secrets.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/gitleaks-secrets.js +0 -0
- /package/{cli/dist → dist}/core/adapters/jest-adapter.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/jest-adapter.js +0 -0
- /package/{cli/dist → dist}/core/adapters/k6-perf.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/k6-perf.js +0 -0
- /package/{cli/dist → dist}/core/adapters/osv-deps.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/osv-deps.js +0 -0
- /package/{cli/dist → dist}/core/adapters/playwright-native-adapter.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/playwright-native-adapter.js +0 -0
- /package/{cli/dist → dist}/core/adapters/pytest-adapter.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/pytest-adapter.js +0 -0
- /package/{cli/dist → dist}/core/adapters/semgrep-sast.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/semgrep-sast.js +0 -0
- /package/{cli/dist → dist}/core/adapters/unit-test-types.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/unit-test-types.js +0 -0
- /package/{cli/dist → dist}/core/adapters/vitest-adapter.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/vitest-adapter.js +0 -0
- /package/{cli/dist → dist}/core/adapters/zap-dast.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/zap-dast.js +0 -0
- /package/{cli/dist → dist}/core/ai/anthropic-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/anthropic-provider.js +0 -0
- /package/{cli/dist → dist}/core/ai/deepseek-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/deepseek-provider.js +0 -0
- /package/{cli/dist → dist}/core/ai/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/index.js +0 -0
- /package/{cli/dist → dist}/core/ai/llm-client.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/llm-client.js +0 -0
- /package/{cli/dist → dist}/core/ai/mock-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/mock-provider.js +0 -0
- /package/{cli/dist → dist}/core/ai/ollama-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/openai-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/openai-provider.js +0 -0
- /package/{cli/dist → dist}/core/ai/provider-factory.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/provider-factory.js +0 -0
- /package/{cli/dist → dist}/core/artifacts/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/artifacts/index.js +0 -0
- /package/{cli/dist → dist}/core/artifacts/ui-artifacts.d.ts +0 -0
- /package/{cli/dist → dist}/core/assertions/engine.d.ts +0 -0
- /package/{cli/dist → dist}/core/assertions/engine.js +0 -0
- /package/{cli/dist → dist}/core/assertions/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/assertions/index.js +0 -0
- /package/{cli/dist → dist}/core/assertions/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/assertions/types.js +0 -0
- /package/{cli/dist → dist}/core/auth/api-key-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/api-key-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/aws-iam-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/aws-iam-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/azure-ad-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/azure-ad-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/gcp-adc-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/gcp-adc-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/jwt-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/jwt-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/manager.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/manager.js +0 -0
- /package/{cli/dist → dist}/core/auth/totp-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/totp-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/ui-login-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/ui-login-provider.js +0 -0
- /package/{cli/dist → dist}/core/cache/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/cache/index.js +0 -0
- /package/{cli/dist → dist}/core/cache/lru-cache.d.ts +0 -0
- /package/{cli/dist → dist}/core/cache/lru-cache.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/analyzer.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/analyzer.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/collector.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/collector.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/config.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/config.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/index.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/index.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/types.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/types.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/vault.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/vault.js +0 -0
- /package/{cli/dist → dist}/core/crawler/journey-generator.d.ts +0 -0
- /package/{cli/dist → dist}/core/crawler/types.js +0 -0
- /package/{cli/dist → dist}/core/dashboard/assets.d.ts +0 -0
- /package/{cli/dist → dist}/core/dashboard/assets.js +0 -0
- /package/{cli/dist → dist}/core/dashboard/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/dashboard/index.js +0 -0
- /package/{cli/dist → dist}/core/dashboard/server.d.ts +0 -0
- /package/{cli/dist → dist}/core/dashboard/server.js +0 -0
- /package/{cli/dist → dist}/core/dashboard/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/dashboard/types.js +0 -0
- /package/{cli/dist → dist}/core/discoverer/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/discoverer/index.js +0 -0
- /package/{cli/dist → dist}/core/fixtures/loader.d.ts +0 -0
- /package/{cli/dist → dist}/core/fixtures/loader.js +0 -0
- /package/{cli/dist → dist}/core/fixtures/resolver.d.ts +0 -0
- /package/{cli/dist → dist}/core/fixtures/resolver.js +0 -0
- /package/{cli/dist → dist}/core/fixtures/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/fixtures/types.js +0 -0
- /package/{cli/dist → dist}/core/flakiness/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/flakiness/index.js +0 -0
- /package/{cli/dist → dist}/core/generation/code-formatter.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/code-formatter.js +0 -0
- /package/{cli/dist → dist}/core/generation/code-generator.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/code-generator.js +0 -0
- /package/{cli/dist → dist}/core/generation/generator.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/generator.js +0 -0
- /package/{cli/dist → dist}/core/generation/pack-generator.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/pack-generator.js +0 -0
- /package/{cli/dist → dist}/core/generation/prompt-builder.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/prompt-builder.js +0 -0
- /package/{cli/dist → dist}/core/generation/source-analyzer.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/source-analyzer.js +0 -0
- /package/{cli/dist → dist}/core/generation/test-optimizer.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/test-optimizer.js +0 -0
- /package/{cli/dist → dist}/core/generation/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/types.js +0 -0
- /package/{cli/dist → dist}/core/hooks/compose.d.ts +0 -0
- /package/{cli/dist → dist}/core/hooks/compose.js +0 -0
- /package/{cli/dist → dist}/core/hooks/runner.d.ts +0 -0
- /package/{cli/dist → dist}/core/hooks/runner.js +0 -0
- /package/{cli/dist → dist}/core/pack/migrator.d.ts +0 -0
- /package/{cli/dist → dist}/core/pack/migrator.js +0 -0
- /package/{cli/dist → dist}/core/pack/validator.d.ts +0 -0
- /package/{cli/dist → dist}/core/pack-v2/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/pack-v2/index.js +0 -0
- /package/{cli/dist → dist}/core/pack-v2/loader.d.ts +0 -0
- /package/{cli/dist → dist}/core/pack-v2/loader.js +0 -0
- /package/{cli/dist → dist}/core/pack-v2/validator.d.ts +0 -0
- /package/{cli/dist → dist}/core/parallel/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/parallel/index.js +0 -0
- /package/{cli/dist → dist}/core/parallel/parallel-runner.d.ts +0 -0
- /package/{cli/dist → dist}/core/parallel/parallel-runner.js +0 -0
- /package/{cli/dist → dist}/core/pom/base-page.d.ts +0 -0
- /package/{cli/dist → dist}/core/pom/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/pom/index.js +0 -0
- /package/{cli/dist → dist}/core/pom/loader.d.ts +0 -0
- /package/{cli/dist → dist}/core/pom/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/pom/types.js +0 -0
- /package/{cli/dist → dist}/core/proof/bundle.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/bundle.js +0 -0
- /package/{cli/dist → dist}/core/proof/canonicalize.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/canonicalize.js +0 -0
- /package/{cli/dist → dist}/core/proof/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/index.js +0 -0
- /package/{cli/dist → dist}/core/proof/schema.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/schema.js +0 -0
- /package/{cli/dist → dist}/core/proof/signer.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/signer.js +0 -0
- /package/{cli/dist → dist}/core/proof/verifier.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/verifier.js +0 -0
- /package/{cli/dist → dist}/core/regression/detector.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/detector.js +0 -0
- /package/{cli/dist → dist}/core/regression/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/index.js +0 -0
- /package/{cli/dist → dist}/core/regression/trend-analyzer.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/trend-analyzer.js +0 -0
- /package/{cli/dist → dist}/core/regression/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/types.js +0 -0
- /package/{cli/dist → dist}/core/regression/vault.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/vault.js +0 -0
- /package/{cli/dist → dist}/core/repair/engine/fixer.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/engine/fixer.js +0 -0
- /package/{cli/dist → dist}/core/repair/engine/suggestion-engine.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/engine/suggestion-engine.js +0 -0
- /package/{cli/dist → dist}/core/repair/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/index.js +0 -0
- /package/{cli/dist → dist}/core/repair/repairer.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/repairer.js +0 -0
- /package/{cli/dist → dist}/core/repair/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/types.js +0 -0
- /package/{cli/dist → dist}/core/repair/utils/error-analyzer.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/utils/error-analyzer.js +0 -0
- /package/{cli/dist → dist}/core/reporting/html-reporter.d.ts +0 -0
- /package/{cli/dist → dist}/core/reporting/html-reporter.js +0 -0
- /package/{cli/dist → dist}/core/retry/flakiness-integration.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/flakiness-integration.js +0 -0
- /package/{cli/dist → dist}/core/retry/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/index.js +0 -0
- /package/{cli/dist → dist}/core/retry/retry-engine.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/retry-engine.js +0 -0
- /package/{cli/dist → dist}/core/retry/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/types.js +0 -0
- /package/{cli/dist → dist}/core/retry/vault.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/vault.js +0 -0
- /package/{cli/dist → dist}/core/schemas/pack.schema.json +0 -0
- /package/{cli/dist → dist}/core/secrets/crypto.d.ts +0 -0
- /package/{cli/dist → dist}/core/secrets/crypto.js +0 -0
- /package/{cli/dist → dist}/core/secrets/manager.d.ts +0 -0
- /package/{cli/dist → dist}/core/secrets/manager.js +0 -0
- /package/{cli/dist → dist}/core/security/redaction-patterns-extended.d.ts +0 -0
- /package/{cli/dist → dist}/core/security/redaction-patterns-extended.js +0 -0
- /package/{cli/dist → dist}/core/security/redactor.d.ts +0 -0
- /package/{cli/dist → dist}/core/security/redactor.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/assertion-healer.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/assertion-healer.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/engine.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/engine.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/index.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/selector-healer.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/selector-healer.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/types.js +0 -0
- /package/{cli/dist → dist}/core/serve/diagnostics-collector.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/diagnostics-collector.js +0 -0
- /package/{cli/dist → dist}/core/serve/health-checker.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/health-checker.js +0 -0
- /package/{cli/dist → dist}/core/serve/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/index.js +0 -0
- /package/{cli/dist → dist}/core/serve/metrics-collector.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/metrics-collector.js +0 -0
- /package/{cli/dist → dist}/core/serve/process-manager.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/process-manager.js +0 -0
- /package/{cli/dist → dist}/core/serve/server.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/server.js +0 -0
- /package/{cli/dist → dist}/core/slo/config.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/config.js +0 -0
- /package/{cli/dist → dist}/core/slo/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/index.js +0 -0
- /package/{cli/dist → dist}/core/slo/sli-calculator.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/sli-calculator.js +0 -0
- /package/{cli/dist → dist}/core/slo/slo-tracker.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/slo-tracker.js +0 -0
- /package/{cli/dist → dist}/core/slo/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/types.js +0 -0
- /package/{cli/dist → dist}/core/slo/vault.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/vault.js +0 -0
- /package/{cli/dist → dist}/core/tui/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/tui/index.js +0 -0
- /package/{cli/dist → dist}/core/tui/monitor.d.ts +0 -0
- /package/{cli/dist → dist}/core/tui/monitor.js +0 -0
- /package/{cli/dist → dist}/core/tui/renderer.d.ts +0 -0
- /package/{cli/dist → dist}/core/tui/renderer.js +0 -0
- /package/{cli/dist → dist}/core/tui/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/tui/types.js +0 -0
- /package/{cli/dist → dist}/core/types/pack-v1.js +0 -0
- /package/{cli/dist → dist}/core/types/pack-v2.js +0 -0
- /package/{cli/dist → dist}/core/types/trust-score.d.ts +0 -0
- /package/{cli/dist → dist}/core/types/trust-score.js +0 -0
- /package/{cli/dist → dist}/core/vault/cas.d.ts +0 -0
- /package/{cli/dist → dist}/core/vault/cas.js +0 -0
- /package/{cli/dist → dist}/core/vault/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/vault/index.js +0 -0
- /package/{cli/dist → dist}/core/visual/visual-regression.d.ts +0 -0
- /package/{cli/dist → dist}/core/visual/visual-regression.js +0 -0
- /package/{cli/dist → dist}/core/watch/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/watch/index.js +0 -0
- /package/{cli/dist → dist}/core/watch/watch-mode.d.ts +0 -0
- /package/{cli/dist → dist}/core/watch/watch-mode.js +0 -0
- /package/{cli/dist → dist}/generators/index.d.ts +0 -0
- /package/{cli/dist → dist}/generators/index.js +0 -0
- /package/{cli/dist → dist}/generators/json-reporter.d.ts +0 -0
- /package/{cli/dist → dist}/generators/json-reporter.js +0 -0
- /package/{cli/dist → dist}/generators/test-generator.d.ts +0 -0
- /package/{cli/dist → dist}/generators/test-generator.js +0 -0
- /package/{cli/dist → dist}/index.d.ts +0 -0
- /package/{cli/dist → dist}/index.js +0 -0
- /package/{cli/dist → dist}/scanners/dom-scanner.d.ts +0 -0
- /package/{cli/dist → dist}/scanners/dom-scanner.js +0 -0
- /package/{cli/dist → dist}/scanners/index.d.ts +0 -0
- /package/{cli/dist → dist}/scanners/index.js +0 -0
- /package/{cli/dist → dist}/schemas/pack.schema.json +0 -0
- /package/{cli/dist → dist}/types/scan.d.ts +0 -0
- /package/{cli/dist → dist}/types/scan.js +0 -0
- /package/{cli/dist → dist}/utils/config.js +0 -0
|
@@ -32,16 +32,28 @@ export class OllamaProvider {
|
|
|
32
32
|
}
|
|
33
33
|
async isAvailable() {
|
|
34
34
|
try {
|
|
35
|
-
// Use timeout
|
|
35
|
+
// Use a longer timeout (15 seconds) to accommodate slower systems
|
|
36
|
+
// Ollama can take time to respond, especially on first run or with many models
|
|
36
37
|
const controller = new AbortController();
|
|
37
|
-
const timeoutId = setTimeout(() => controller.abort(),
|
|
38
|
+
const timeoutId = setTimeout(() => controller.abort(), 15000);
|
|
38
39
|
const response = await fetch(`${this.baseUrl}/api/tags`, {
|
|
39
40
|
signal: controller.signal,
|
|
40
41
|
});
|
|
41
42
|
clearTimeout(timeoutId);
|
|
42
43
|
return response.ok;
|
|
43
44
|
}
|
|
44
|
-
catch {
|
|
45
|
+
catch (error) {
|
|
46
|
+
// Log the error for debugging (will be visible in verbose mode)
|
|
47
|
+
if (error instanceof Error) {
|
|
48
|
+
if (error.name === 'AbortError') {
|
|
49
|
+
// Timeout - Ollama is slow to respond
|
|
50
|
+
console.debug(`[Ollama] Connection to ${this.baseUrl} timed out after 15s`);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// Other error (ECONNREFUSED, ENOTFOUND, etc.)
|
|
54
|
+
console.debug(`[Ollama] Connection error: ${error.message}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
45
57
|
return false;
|
|
46
58
|
}
|
|
47
59
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* with content-addressable storage (CAS) integration
|
|
6
6
|
*/
|
|
7
7
|
import { mkdirSync, existsSync, writeFileSync, readFileSync, unlinkSync } from 'fs';
|
|
8
|
-
import { join } from 'path';
|
|
8
|
+
import { join, dirname } from 'path';
|
|
9
9
|
import { ContentAddressableStorage } from '../vault/cas.js';
|
|
10
10
|
/**
|
|
11
11
|
* UI Artifacts Manager
|
|
@@ -29,7 +29,10 @@ export class UIArtifactsManager {
|
|
|
29
29
|
this.artifactDir = artifactDir;
|
|
30
30
|
this.casDir = casDir;
|
|
31
31
|
this.currentRunId = `run-${Date.now()}`;
|
|
32
|
-
|
|
32
|
+
// CAS constructor appends '/cas', so pass parent directory
|
|
33
|
+
// If casDir ends with '/cas', strip it to avoid double path
|
|
34
|
+
const casBaseDir = casDir.endsWith('/cas') ? casDir.slice(0, -4) : casDir;
|
|
35
|
+
this.cas = new ContentAddressableStorage(casBaseDir);
|
|
33
36
|
this.ensureDirectories();
|
|
34
37
|
}
|
|
35
38
|
ensureDirectories() {
|
|
@@ -42,7 +45,6 @@ export class UIArtifactsManager {
|
|
|
42
45
|
`${this.artifactDir}/console`,
|
|
43
46
|
`${this.artifactDir}/coverage`,
|
|
44
47
|
this.casDir,
|
|
45
|
-
`${this.casDir}/art`,
|
|
46
48
|
];
|
|
47
49
|
for (const dir of dirs) {
|
|
48
50
|
if (!existsSync(dir)) {
|
|
@@ -89,6 +91,11 @@ export class UIArtifactsManager {
|
|
|
89
91
|
const casPath = this.getCasPath(hash);
|
|
90
92
|
// Store in CAS if not exists
|
|
91
93
|
if (!existsSync(casPath)) {
|
|
94
|
+
// Ensure directory exists before writing
|
|
95
|
+
const casDir = dirname(casPath);
|
|
96
|
+
if (!existsSync(casDir)) {
|
|
97
|
+
mkdirSync(casDir, { recursive: true });
|
|
98
|
+
}
|
|
92
99
|
writeFileSync(casPath, screenshot);
|
|
93
100
|
}
|
|
94
101
|
const artifact = {
|
|
@@ -145,6 +152,10 @@ export class UIArtifactsManager {
|
|
|
145
152
|
const hash = ContentAddressableStorage.hashContent(screenshot);
|
|
146
153
|
const casPath = this.getCasPath(hash);
|
|
147
154
|
if (!existsSync(casPath)) {
|
|
155
|
+
const casDir = dirname(casPath);
|
|
156
|
+
if (!existsSync(casDir)) {
|
|
157
|
+
mkdirSync(casDir, { recursive: true });
|
|
158
|
+
}
|
|
148
159
|
writeFileSync(casPath, screenshot);
|
|
149
160
|
}
|
|
150
161
|
const artifact = {
|
|
@@ -181,6 +192,10 @@ export class UIArtifactsManager {
|
|
|
181
192
|
const casPath = this.getCasPath(hash);
|
|
182
193
|
// Store in CAS
|
|
183
194
|
if (!existsSync(casPath)) {
|
|
195
|
+
const casDir = dirname(casPath);
|
|
196
|
+
if (!existsSync(casDir)) {
|
|
197
|
+
mkdirSync(casDir, { recursive: true });
|
|
198
|
+
}
|
|
184
199
|
writeFileSync(casPath, video);
|
|
185
200
|
}
|
|
186
201
|
// Get video duration (basic estimate)
|
|
@@ -215,6 +230,10 @@ export class UIArtifactsManager {
|
|
|
215
230
|
const hash = ContentAddressableStorage.hashContent(trace);
|
|
216
231
|
const casPath = this.getCasPath(hash);
|
|
217
232
|
if (!existsSync(casPath)) {
|
|
233
|
+
const casDir = dirname(casPath);
|
|
234
|
+
if (!existsSync(casDir)) {
|
|
235
|
+
mkdirSync(casDir, { recursive: true });
|
|
236
|
+
}
|
|
218
237
|
writeFileSync(casPath, trace);
|
|
219
238
|
}
|
|
220
239
|
const artifact = {
|
|
@@ -274,7 +293,8 @@ export class UIArtifactsManager {
|
|
|
274
293
|
*/
|
|
275
294
|
getCasPath(hash) {
|
|
276
295
|
// hash is already a hex string from SHA256
|
|
277
|
-
|
|
296
|
+
// CAS root is at this.casDir/cas/ (ContentAddressableStorage appends '/cas')
|
|
297
|
+
return join(this.casDir, 'cas', 'art', hash.substring(0, 2), hash.substring(2, 4), hash.substring(4));
|
|
278
298
|
}
|
|
279
299
|
/**
|
|
280
300
|
* Generate artifacts summary for reporting
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backup Codes Authentication Provider
|
|
3
|
+
*
|
|
4
|
+
* Handles backup/recovery codes for 2FA scenarios.
|
|
5
|
+
* These are one-time use codes provided to users for account recovery.
|
|
6
|
+
*
|
|
7
|
+
* P1 Feature: Backup codes are essential for 2FA recovery
|
|
8
|
+
*/
|
|
9
|
+
import type { AuthProvider, AuthResult } from './index.js';
|
|
10
|
+
import { type BackupCodesAuthConfig } from './index.js';
|
|
11
|
+
/**
|
|
12
|
+
* Generates backup codes
|
|
13
|
+
* @param count Number of codes to generate
|
|
14
|
+
* @param groups Number of groups in each code (default 2)
|
|
15
|
+
* @param digits Digits per group (default 4)
|
|
16
|
+
* @returns Array of generated backup codes
|
|
17
|
+
*/
|
|
18
|
+
export declare function generateBackupCodes(count?: number, groups?: number, digits?: number): string[];
|
|
19
|
+
/**
|
|
20
|
+
* Normalizes a backup code (removes spaces, converts to uppercase)
|
|
21
|
+
* @param code Backup code to normalize
|
|
22
|
+
*/
|
|
23
|
+
export declare function normalizeBackupCode(code: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Validates backup code format
|
|
26
|
+
* @param code Backup code to validate
|
|
27
|
+
* @param groups Expected number of groups
|
|
28
|
+
* @param digits Expected digits per group
|
|
29
|
+
*/
|
|
30
|
+
export declare function validateBackupCodeFormat(code: string, groups?: number, digits?: number): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Checks if a backup code matches (case-insensitive, ignores spaces and hyphens)
|
|
33
|
+
* @param code Input code
|
|
34
|
+
* @param validCode Valid code to compare against
|
|
35
|
+
*/
|
|
36
|
+
export declare function backupCodeMatches(code: string, validCode: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Backup Codes Authentication Provider
|
|
39
|
+
*/
|
|
40
|
+
export declare class BackupCodesProvider implements AuthProvider<BackupCodesAuthConfig> {
|
|
41
|
+
readonly type: "backup_codes";
|
|
42
|
+
private usedCodes;
|
|
43
|
+
private codeStates;
|
|
44
|
+
authenticate(config: BackupCodesAuthConfig): Promise<AuthResult>;
|
|
45
|
+
/**
|
|
46
|
+
* Marks a backup code as used
|
|
47
|
+
*/
|
|
48
|
+
markAsUsed(code: string): void;
|
|
49
|
+
/**
|
|
50
|
+
* Checks if a backup code has been used
|
|
51
|
+
*/
|
|
52
|
+
isCodeUsed(code: string): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Gets count of remaining unused codes
|
|
55
|
+
*/
|
|
56
|
+
getRemainingCount(totalCodes: number): number;
|
|
57
|
+
/**
|
|
58
|
+
* Generates a session token
|
|
59
|
+
*/
|
|
60
|
+
private generateSessionToken;
|
|
61
|
+
/**
|
|
62
|
+
* Validates backup code configuration
|
|
63
|
+
*/
|
|
64
|
+
validate(config: BackupCodesAuthConfig): Promise<boolean>;
|
|
65
|
+
/**
|
|
66
|
+
* Clears cached backup code state
|
|
67
|
+
*/
|
|
68
|
+
clear(config: BackupCodesAuthConfig): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Clears all backup code states
|
|
71
|
+
*/
|
|
72
|
+
clearAllStates(): void;
|
|
73
|
+
/**
|
|
74
|
+
* Gets all used codes
|
|
75
|
+
*/
|
|
76
|
+
getUsedCodes(): string[];
|
|
77
|
+
/**
|
|
78
|
+
* Resets a backup code (marks as unused)
|
|
79
|
+
* Use with caution - typically codes should not be reusable
|
|
80
|
+
*/
|
|
81
|
+
resetCode(code: string): void;
|
|
82
|
+
/**
|
|
83
|
+
* Bulk sets codes as used
|
|
84
|
+
*/
|
|
85
|
+
markMultipleAsUsed(codes: string[]): void;
|
|
86
|
+
private getCacheKey;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Creates a backup codes provider instance
|
|
90
|
+
*/
|
|
91
|
+
export declare function createBackupCodesProvider(): BackupCodesProvider;
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backup Codes Authentication Provider
|
|
3
|
+
*
|
|
4
|
+
* Handles backup/recovery codes for 2FA scenarios.
|
|
5
|
+
* These are one-time use codes provided to users for account recovery.
|
|
6
|
+
*
|
|
7
|
+
* P1 Feature: Backup codes are essential for 2FA recovery
|
|
8
|
+
*/
|
|
9
|
+
import { createCacheKey, authCache } from './index.js';
|
|
10
|
+
/**
|
|
11
|
+
* Generates backup codes
|
|
12
|
+
* @param count Number of codes to generate
|
|
13
|
+
* @param groups Number of groups in each code (default 2)
|
|
14
|
+
* @param digits Digits per group (default 4)
|
|
15
|
+
* @returns Array of generated backup codes
|
|
16
|
+
*/
|
|
17
|
+
export function generateBackupCodes(count = 10, groups = 2, digits = 4) {
|
|
18
|
+
const codes = [];
|
|
19
|
+
for (let i = 0; i < count; i++) {
|
|
20
|
+
const codeGroups = [];
|
|
21
|
+
for (let j = 0; j < groups; j++) {
|
|
22
|
+
const min = Math.pow(10, digits - 1);
|
|
23
|
+
const max = Math.pow(10, digits) - 1;
|
|
24
|
+
codeGroups.push(Math.floor(min + Math.random() * (max - min + 1))
|
|
25
|
+
.toString()
|
|
26
|
+
.padStart(digits, '0'));
|
|
27
|
+
}
|
|
28
|
+
codes.push(codeGroups.join('-'));
|
|
29
|
+
}
|
|
30
|
+
return codes;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Normalizes a backup code (removes spaces, converts to uppercase)
|
|
34
|
+
* @param code Backup code to normalize
|
|
35
|
+
*/
|
|
36
|
+
export function normalizeBackupCode(code) {
|
|
37
|
+
return code.replace(/[\s-]/g, '').toUpperCase();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Validates backup code format
|
|
41
|
+
* @param code Backup code to validate
|
|
42
|
+
* @param groups Expected number of groups
|
|
43
|
+
* @param digits Expected digits per group
|
|
44
|
+
*/
|
|
45
|
+
export function validateBackupCodeFormat(code, groups = 2, digits = 4) {
|
|
46
|
+
// Remove spaces and hyphens for validation
|
|
47
|
+
const normalized = code.replace(/[\s-]/g, '');
|
|
48
|
+
// Build pattern for specified groups and digits
|
|
49
|
+
const expectedLength = groups * digits;
|
|
50
|
+
const regex = new RegExp(`^\\d{${expectedLength}}$`);
|
|
51
|
+
return regex.test(normalized);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Checks if a backup code matches (case-insensitive, ignores spaces and hyphens)
|
|
55
|
+
* @param code Input code
|
|
56
|
+
* @param validCode Valid code to compare against
|
|
57
|
+
*/
|
|
58
|
+
export function backupCodeMatches(code, validCode) {
|
|
59
|
+
return normalizeBackupCode(code) === normalizeBackupCode(validCode);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Backup Codes Authentication Provider
|
|
63
|
+
*/
|
|
64
|
+
export class BackupCodesProvider {
|
|
65
|
+
type = 'backup_codes';
|
|
66
|
+
usedCodes = new Set();
|
|
67
|
+
codeStates = new Map();
|
|
68
|
+
async authenticate(config) {
|
|
69
|
+
const { code, validCodes } = config;
|
|
70
|
+
if (!code) {
|
|
71
|
+
return {
|
|
72
|
+
success: false,
|
|
73
|
+
error: 'Backup code is required'
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
const normalizedCode = normalizeBackupCode(code);
|
|
77
|
+
// Check if code was already used
|
|
78
|
+
if (this.usedCodes.has(normalizedCode)) {
|
|
79
|
+
return {
|
|
80
|
+
success: false,
|
|
81
|
+
error: 'Backup code has already been used'
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// If validCodes provided, verify against them
|
|
85
|
+
if (validCodes && validCodes.length > 0) {
|
|
86
|
+
const isValid = validCodes.some(validCode => backupCodeMatches(normalizedCode, validCode));
|
|
87
|
+
if (!isValid) {
|
|
88
|
+
return {
|
|
89
|
+
success: false,
|
|
90
|
+
error: 'Invalid backup code'
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Mark code as used
|
|
95
|
+
this.markAsUsed(normalizedCode);
|
|
96
|
+
// Generate session token
|
|
97
|
+
const token = this.generateSessionToken();
|
|
98
|
+
return {
|
|
99
|
+
success: true,
|
|
100
|
+
credentials: {
|
|
101
|
+
type: 'backup_codes',
|
|
102
|
+
headers: {
|
|
103
|
+
'Authorization': `Bearer ${token}`,
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
expiresAt: Date.now() + 24 * 60 * 60 * 1000, // 24 hours
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Marks a backup code as used
|
|
111
|
+
*/
|
|
112
|
+
markAsUsed(code) {
|
|
113
|
+
const normalized = normalizeBackupCode(code);
|
|
114
|
+
this.usedCodes.add(normalized);
|
|
115
|
+
const existingState = this.codeStates.get(normalized);
|
|
116
|
+
if (existingState) {
|
|
117
|
+
existingState.used = true;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
this.codeStates.set(normalized, {
|
|
121
|
+
code: normalized,
|
|
122
|
+
used: true,
|
|
123
|
+
createdAt: Date.now(),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Checks if a backup code has been used
|
|
129
|
+
*/
|
|
130
|
+
isCodeUsed(code) {
|
|
131
|
+
return this.usedCodes.has(normalizeBackupCode(code));
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Gets count of remaining unused codes
|
|
135
|
+
*/
|
|
136
|
+
getRemainingCount(totalCodes) {
|
|
137
|
+
return Math.max(0, totalCodes - this.usedCodes.size);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Generates a session token
|
|
141
|
+
*/
|
|
142
|
+
generateSessionToken() {
|
|
143
|
+
const crypto = require('node:crypto');
|
|
144
|
+
return crypto.randomBytes(32).toString('hex');
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Validates backup code configuration
|
|
148
|
+
*/
|
|
149
|
+
async validate(config) {
|
|
150
|
+
if (!config.code) {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
// Basic format validation (XXX-XXX or similar)
|
|
154
|
+
const normalized = normalizeBackupCode(config.code);
|
|
155
|
+
return /^\d{4,}-?\d{4,}$/.test(normalized);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Clears cached backup code state
|
|
159
|
+
*/
|
|
160
|
+
async clear(config) {
|
|
161
|
+
const key = this.getCacheKey(config);
|
|
162
|
+
authCache.clear(key);
|
|
163
|
+
if (config.code) {
|
|
164
|
+
this.usedCodes.delete(normalizeBackupCode(config.code));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Clears all backup code states
|
|
169
|
+
*/
|
|
170
|
+
clearAllStates() {
|
|
171
|
+
this.usedCodes.clear();
|
|
172
|
+
this.codeStates.clear();
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Gets all used codes
|
|
176
|
+
*/
|
|
177
|
+
getUsedCodes() {
|
|
178
|
+
return Array.from(this.usedCodes);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Resets a backup code (marks as unused)
|
|
182
|
+
* Use with caution - typically codes should not be reusable
|
|
183
|
+
*/
|
|
184
|
+
resetCode(code) {
|
|
185
|
+
const normalized = normalizeBackupCode(code);
|
|
186
|
+
this.usedCodes.delete(normalized);
|
|
187
|
+
const state = this.codeStates.get(normalized);
|
|
188
|
+
if (state) {
|
|
189
|
+
state.used = false;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Bulk sets codes as used
|
|
194
|
+
*/
|
|
195
|
+
markMultipleAsUsed(codes) {
|
|
196
|
+
codes.forEach(code => this.markAsUsed(code));
|
|
197
|
+
}
|
|
198
|
+
getCacheKey(config) {
|
|
199
|
+
const crypto = require('node:crypto');
|
|
200
|
+
const hash = crypto
|
|
201
|
+
.createHash('sha256')
|
|
202
|
+
.update(config.code || '')
|
|
203
|
+
.digest('hex')
|
|
204
|
+
.substring(0, 16);
|
|
205
|
+
return createCacheKey('backup_codes', hash);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Creates a backup codes provider instance
|
|
210
|
+
*/
|
|
211
|
+
export function createBackupCodesProvider() {
|
|
212
|
+
return new BackupCodesProvider();
|
|
213
|
+
}
|
|
214
|
+
// Re-export types and utilities
|
|
215
|
+
// Types are exported from index.ts
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* Bearer Token and Basic Authentication Providers
|
|
3
3
|
*
|
|
4
4
|
* Handles generic bearer token and HTTP Basic Authentication.
|
|
5
|
+
*
|
|
6
|
+
* P0 Feature: Native browser Basic Auth popup (WWW-Authenticate headers)
|
|
7
|
+
* - useNativePopup: true uses Playwright's httpCredentials for browser popup
|
|
8
|
+
* - useNativePopup: false (default) uses Authorization header
|
|
5
9
|
*/
|
|
6
10
|
import { AuthProvider, AuthResult, BearerAuthConfig, BasicAuthConfig } from './index.js';
|
|
7
11
|
/**
|
|
@@ -16,6 +20,8 @@ export declare class BearerProvider implements AuthProvider<BearerAuthConfig> {
|
|
|
16
20
|
}
|
|
17
21
|
/**
|
|
18
22
|
* Basic Authentication Provider
|
|
23
|
+
*
|
|
24
|
+
* P0: Supports both header-based and native browser popup authentication
|
|
19
25
|
*/
|
|
20
26
|
export declare class BasicAuthProvider implements AuthProvider<BasicAuthConfig> {
|
|
21
27
|
readonly type: "basic";
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* Bearer Token and Basic Authentication Providers
|
|
3
3
|
*
|
|
4
4
|
* Handles generic bearer token and HTTP Basic Authentication.
|
|
5
|
+
*
|
|
6
|
+
* P0 Feature: Native browser Basic Auth popup (WWW-Authenticate headers)
|
|
7
|
+
* - useNativePopup: true uses Playwright's httpCredentials for browser popup
|
|
8
|
+
* - useNativePopup: false (default) uses Authorization header
|
|
5
9
|
*/
|
|
6
10
|
import { parseToken, encodeBasicAuth, authCache, createCacheKey } from './index.js';
|
|
7
11
|
/**
|
|
@@ -57,11 +61,13 @@ export class BearerProvider {
|
|
|
57
61
|
}
|
|
58
62
|
/**
|
|
59
63
|
* Basic Authentication Provider
|
|
64
|
+
*
|
|
65
|
+
* P0: Supports both header-based and native browser popup authentication
|
|
60
66
|
*/
|
|
61
67
|
export class BasicAuthProvider {
|
|
62
68
|
type = 'basic';
|
|
63
69
|
async authenticate(config) {
|
|
64
|
-
const { username, password, cache } = config;
|
|
70
|
+
const { username, password, cache, useNativePopup, origin } = config;
|
|
65
71
|
if (!username || !password) {
|
|
66
72
|
return {
|
|
67
73
|
success: false,
|
|
@@ -78,10 +84,21 @@ export class BasicAuthProvider {
|
|
|
78
84
|
}
|
|
79
85
|
const credentials = {
|
|
80
86
|
type: 'basic',
|
|
81
|
-
headers: {
|
|
82
|
-
'Authorization': encodeBasicAuth(username, password)
|
|
83
|
-
}
|
|
84
87
|
};
|
|
88
|
+
// P0: Native browser popup (WWW-Authenticate)
|
|
89
|
+
if (useNativePopup) {
|
|
90
|
+
credentials.httpCredentials = {
|
|
91
|
+
username,
|
|
92
|
+
password,
|
|
93
|
+
origin
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
// Default: Header-based auth
|
|
98
|
+
credentials.headers = {
|
|
99
|
+
'Authorization': encodeBasicAuth(username, password)
|
|
100
|
+
};
|
|
101
|
+
}
|
|
85
102
|
// Cache if enabled
|
|
86
103
|
if (cache?.enabled !== false) {
|
|
87
104
|
const ttl = cache?.ttl || 3600;
|
|
@@ -105,7 +122,8 @@ export class BasicAuthProvider {
|
|
|
105
122
|
return !!config.username && !!config.password;
|
|
106
123
|
}
|
|
107
124
|
getCacheKey(config) {
|
|
108
|
-
// Use username as identifier
|
|
109
|
-
|
|
125
|
+
// Use username + mode as identifier
|
|
126
|
+
const mode = config.useNativePopup ? 'native' : 'header';
|
|
127
|
+
return createCacheKey('basic', `${config.username || 'default'}-${mode}`);
|
|
110
128
|
}
|
|
111
129
|
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Digest Authentication Provider
|
|
3
|
+
*
|
|
4
|
+
* Implements HTTP Digest Authentication (RFC 2617).
|
|
5
|
+
* Handles challenge-response flow with nonce handling.
|
|
6
|
+
*
|
|
7
|
+
* P1 Feature: Digest Auth is more secure than Basic Auth as it doesn't send
|
|
8
|
+
* the password in plaintext. Instead, it uses a challenge-response mechanism
|
|
9
|
+
* with MD5 hashing.
|
|
10
|
+
*
|
|
11
|
+
* Algorithm:
|
|
12
|
+
* 1. Client makes request without auth
|
|
13
|
+
* 2. Server responds with 401 and WWW-Authenticate header containing:
|
|
14
|
+
* - realm: Protection space
|
|
15
|
+
* - nonce: Server-generated unique value
|
|
16
|
+
* - qop: Quality of protection (auth or auth-int)
|
|
17
|
+
* - opaque: Client should return unchanged
|
|
18
|
+
* 3. Client calculates response using MD5 and retries
|
|
19
|
+
*
|
|
20
|
+
* Response calculation:
|
|
21
|
+
* HA1 = MD5(username:realm:password)
|
|
22
|
+
* HA2 = MD5(method:digestURI)
|
|
23
|
+
* response = MD5(HA1:nonce:HA2) // simplified
|
|
24
|
+
*/
|
|
25
|
+
import type { AuthProvider, AuthResult } from './index.js';
|
|
26
|
+
import { type DigestAuthConfig } from './index.js';
|
|
27
|
+
/**
|
|
28
|
+
* Parsed WWW-Authenticate header
|
|
29
|
+
*/
|
|
30
|
+
interface DigestChallenge {
|
|
31
|
+
realm: string;
|
|
32
|
+
nonce: string;
|
|
33
|
+
qop?: string;
|
|
34
|
+
opaque?: string;
|
|
35
|
+
algorithm?: string;
|
|
36
|
+
stale?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Digest Authentication credentials
|
|
40
|
+
*/
|
|
41
|
+
export interface DigestCredentials {
|
|
42
|
+
type: 'digest';
|
|
43
|
+
username: string;
|
|
44
|
+
realm: string;
|
|
45
|
+
nonce: string;
|
|
46
|
+
uri: string;
|
|
47
|
+
response: string;
|
|
48
|
+
qop?: string;
|
|
49
|
+
opaque?: string;
|
|
50
|
+
nc: string;
|
|
51
|
+
cnonce: string;
|
|
52
|
+
algorithm: string;
|
|
53
|
+
headers: Record<string, string>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Parses WWW-Authenticate header for Digest challenge
|
|
57
|
+
* @example
|
|
58
|
+
* parseDigestHeader('Digest realm="test", nonce="abc123", qop="auth"')
|
|
59
|
+
* // => { realm: 'test', nonce: 'abc123', qop: 'auth' }
|
|
60
|
+
*/
|
|
61
|
+
export declare function parseDigestHeader(header: string): DigestChallenge | null;
|
|
62
|
+
/**
|
|
63
|
+
* Calculates Digest response
|
|
64
|
+
* @param username Username
|
|
65
|
+
* @param password Password
|
|
66
|
+
* @param realm Realm from challenge
|
|
67
|
+
* @param nonce Nonce from challenge
|
|
68
|
+
* @param method HTTP method
|
|
69
|
+
* @param uri Request URI
|
|
70
|
+
* @param qop Quality of protection
|
|
71
|
+
* @param opaque Opaque value from challenge
|
|
72
|
+
* @param nc Nonce count
|
|
73
|
+
* @param cnonce Client nonce
|
|
74
|
+
*/
|
|
75
|
+
export declare function calculateDigestResponse(username: string, password: string, realm: string, nonce: string, method: string, uri: string, qop?: string, opaque?: string, nc?: string, cnonce?: string): string;
|
|
76
|
+
/**
|
|
77
|
+
* Digest Authentication Provider
|
|
78
|
+
*/
|
|
79
|
+
export declare class DigestAuthProvider implements AuthProvider<DigestAuthConfig> {
|
|
80
|
+
readonly type: "digest";
|
|
81
|
+
private storedChallenges;
|
|
82
|
+
private nonceCounters;
|
|
83
|
+
authenticate(config: DigestAuthConfig): Promise<AuthResult>;
|
|
84
|
+
/**
|
|
85
|
+
* Stores a Digest challenge received from server
|
|
86
|
+
*/
|
|
87
|
+
storeChallenge(url: string, challenge: DigestChallenge): void;
|
|
88
|
+
/**
|
|
89
|
+
* Retrieves stored challenge for a URL
|
|
90
|
+
*/
|
|
91
|
+
getChallenge(url: string): DigestChallenge | undefined;
|
|
92
|
+
/**
|
|
93
|
+
* Builds Authorization header for a request using stored challenge
|
|
94
|
+
*/
|
|
95
|
+
buildAuthorizationHeader(url: string, method: string, config: DigestAuthConfig): Promise<string | null>;
|
|
96
|
+
/**
|
|
97
|
+
* Gets next nonce count for a given nonce
|
|
98
|
+
*/
|
|
99
|
+
private getNonceCount;
|
|
100
|
+
/**
|
|
101
|
+
* Handles 401 response and returns new request headers
|
|
102
|
+
*/
|
|
103
|
+
handleChallenge(url: string, method: string, authenticateHeader: string, config: DigestAuthConfig): Promise<Record<string, string> | null>;
|
|
104
|
+
clear(config: DigestAuthConfig): Promise<void>;
|
|
105
|
+
validate(config: DigestAuthConfig): Promise<boolean>;
|
|
106
|
+
private getCacheKey;
|
|
107
|
+
/**
|
|
108
|
+
* Clears stored challenges and counters
|
|
109
|
+
*/
|
|
110
|
+
clearState(): void;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Creates a Digest auth provider instance
|
|
114
|
+
*/
|
|
115
|
+
export declare function createDigestAuthProvider(): DigestAuthProvider;
|
|
116
|
+
export {};
|