@enricai/barnacle 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +958 -0
- package/dist/api/errors.d.ts +88 -0
- package/dist/api/errors.d.ts.map +1 -0
- package/dist/api/errors.js +164 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/api/helpers/envelope.d.ts +13 -0
- package/dist/api/helpers/envelope.d.ts.map +1 -0
- package/dist/api/helpers/envelope.js +20 -0
- package/dist/api/helpers/envelope.js.map +1 -0
- package/dist/api/helpers/reply.d.ts +9 -0
- package/dist/api/helpers/reply.d.ts.map +1 -0
- package/dist/api/helpers/reply.js +14 -0
- package/dist/api/helpers/reply.js.map +1 -0
- package/dist/api/plugins/auth.d.ts +27 -0
- package/dist/api/plugins/auth.d.ts.map +1 -0
- package/dist/api/plugins/auth.js +111 -0
- package/dist/api/plugins/auth.js.map +1 -0
- package/dist/api/plugins/error-handler.d.ts +12 -0
- package/dist/api/plugins/error-handler.d.ts.map +1 -0
- package/dist/api/plugins/error-handler.js +72 -0
- package/dist/api/plugins/error-handler.js.map +1 -0
- package/dist/api/plugins/request-context.d.ts +17 -0
- package/dist/api/plugins/request-context.d.ts.map +1 -0
- package/dist/api/plugins/request-context.js +61 -0
- package/dist/api/plugins/request-context.js.map +1 -0
- package/dist/api/routes/health.d.ts +55 -0
- package/dist/api/routes/health.d.ts.map +1 -0
- package/dist/api/routes/health.js +137 -0
- package/dist/api/routes/health.js.map +1 -0
- package/dist/api/routes/plugins-introspection.d.ts +17 -0
- package/dist/api/routes/plugins-introspection.d.ts.map +1 -0
- package/dist/api/routes/plugins-introspection.js +13 -0
- package/dist/api/routes/plugins-introspection.js.map +1 -0
- package/dist/api/schemas/common.d.ts +114 -0
- package/dist/api/schemas/common.d.ts.map +1 -0
- package/dist/api/schemas/common.js +109 -0
- package/dist/api/schemas/common.js.map +1 -0
- package/dist/api/schemas/telemetry.d.ts +66 -0
- package/dist/api/schemas/telemetry.d.ts.map +1 -0
- package/dist/api/schemas/telemetry.js +52 -0
- package/dist/api/schemas/telemetry.js.map +1 -0
- package/dist/cache/keyed-ttl-cache.d.ts +45 -0
- package/dist/cache/keyed-ttl-cache.d.ts.map +1 -0
- package/dist/cache/keyed-ttl-cache.js +69 -0
- package/dist/cache/keyed-ttl-cache.js.map +1 -0
- package/dist/cache/response-cache.d.ts +37 -0
- package/dist/cache/response-cache.d.ts.map +1 -0
- package/dist/cache/response-cache.js +114 -0
- package/dist/cache/response-cache.js.map +1 -0
- package/dist/config.d.ts +258 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +138 -0
- package/dist/config.js.map +1 -0
- package/dist/lib/applicant-payload.d.ts +28 -0
- package/dist/lib/applicant-payload.d.ts.map +1 -0
- package/dist/lib/applicant-payload.js +20 -0
- package/dist/lib/applicant-payload.js.map +1 -0
- package/dist/lib/application-address.d.ts +16 -0
- package/dist/lib/application-address.d.ts.map +1 -0
- package/dist/lib/application-address.js +20 -0
- package/dist/lib/application-address.js.map +1 -0
- package/dist/lib/application-answers.d.ts +151 -0
- package/dist/lib/application-answers.d.ts.map +1 -0
- package/dist/lib/application-answers.js +95 -0
- package/dist/lib/application-answers.js.map +1 -0
- package/dist/lib/application-identity.d.ts +18 -0
- package/dist/lib/application-identity.d.ts.map +1 -0
- package/dist/lib/application-identity.js +20 -0
- package/dist/lib/application-identity.js.map +1 -0
- package/dist/lib/application-resume.d.ts +21 -0
- package/dist/lib/application-resume.d.ts.map +1 -0
- package/dist/lib/application-resume.js +23 -0
- package/dist/lib/application-resume.js.map +1 -0
- package/dist/lib/bedrock.d.ts +22 -0
- package/dist/lib/bedrock.d.ts.map +1 -0
- package/dist/lib/bedrock.js +35 -0
- package/dist/lib/bedrock.js.map +1 -0
- package/dist/lib/case-insensitive-headers.d.ts +15 -0
- package/dist/lib/case-insensitive-headers.d.ts.map +1 -0
- package/dist/lib/case-insensitive-headers.js +29 -0
- package/dist/lib/case-insensitive-headers.js.map +1 -0
- package/dist/lib/chromium-client-hints.d.ts +11 -0
- package/dist/lib/chromium-client-hints.d.ts.map +1 -0
- package/dist/lib/chromium-client-hints.js +17 -0
- package/dist/lib/chromium-client-hints.js.map +1 -0
- package/dist/lib/cookie-value.d.ts +8 -0
- package/dist/lib/cookie-value.d.ts.map +1 -0
- package/dist/lib/cookie-value.js +14 -0
- package/dist/lib/cookie-value.js.map +1 -0
- package/dist/lib/datadog.d.ts +8 -0
- package/dist/lib/datadog.d.ts.map +1 -0
- package/dist/lib/datadog.js +27 -0
- package/dist/lib/datadog.js.map +1 -0
- package/dist/lib/dd-metrics.d.ts +28 -0
- package/dist/lib/dd-metrics.d.ts.map +1 -0
- package/dist/lib/dd-metrics.js +62 -0
- package/dist/lib/dd-metrics.js.map +1 -0
- package/dist/lib/dispatch-metrics.d.ts +19 -0
- package/dist/lib/dispatch-metrics.d.ts.map +1 -0
- package/dist/lib/dispatch-metrics.js +65 -0
- package/dist/lib/dispatch-metrics.js.map +1 -0
- package/dist/lib/env.d.ts +37 -0
- package/dist/lib/env.d.ts.map +1 -0
- package/dist/lib/env.js +70 -0
- package/dist/lib/env.js.map +1 -0
- package/dist/lib/errors.d.ts +15 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +20 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/http.d.ts +7 -0
- package/dist/lib/http.d.ts.map +1 -0
- package/dist/lib/http.js +14 -0
- package/dist/lib/http.js.map +1 -0
- package/dist/lib/job-tracking.d.ts +17 -0
- package/dist/lib/job-tracking.d.ts.map +1 -0
- package/dist/lib/job-tracking.js +19 -0
- package/dist/lib/job-tracking.js.map +1 -0
- package/dist/lib/llm/anthropic-client.d.ts +12 -0
- package/dist/lib/llm/anthropic-client.d.ts.map +1 -0
- package/dist/lib/llm/anthropic-client.js +23 -0
- package/dist/lib/llm/anthropic-client.js.map +1 -0
- package/dist/lib/llm/judge.d.ts +57 -0
- package/dist/lib/llm/judge.d.ts.map +1 -0
- package/dist/lib/llm/judge.js +123 -0
- package/dist/lib/llm/judge.js.map +1 -0
- package/dist/lib/llm/judges/error-messages.d.ts +38 -0
- package/dist/lib/llm/judges/error-messages.d.ts.map +1 -0
- package/dist/lib/llm/judges/error-messages.js +72 -0
- package/dist/lib/llm/judges/error-messages.js.map +1 -0
- package/dist/lib/llm/judges/invalid-fields.d.ts +43 -0
- package/dist/lib/llm/judges/invalid-fields.d.ts.map +1 -0
- package/dist/lib/llm/judges/invalid-fields.js +80 -0
- package/dist/lib/llm/judges/invalid-fields.js.map +1 -0
- package/dist/lib/llm/judges/modal-priority.d.ts +41 -0
- package/dist/lib/llm/judges/modal-priority.d.ts.map +1 -0
- package/dist/lib/llm/judges/modal-priority.js +74 -0
- package/dist/lib/llm/judges/modal-priority.js.map +1 -0
- package/dist/lib/llm/judges/select-option.d.ts +49 -0
- package/dist/lib/llm/judges/select-option.d.ts.map +1 -0
- package/dist/lib/llm/judges/select-option.js +90 -0
- package/dist/lib/llm/judges/select-option.js.map +1 -0
- package/dist/lib/llm/judges/verify-submit.d.ts +68 -0
- package/dist/lib/llm/judges/verify-submit.d.ts.map +1 -0
- package/dist/lib/llm/judges/verify-submit.js +89 -0
- package/dist/lib/llm/judges/verify-submit.js.map +1 -0
- package/dist/lib/llm/schemas.d.ts +220 -0
- package/dist/lib/llm/schemas.d.ts.map +1 -0
- package/dist/lib/llm/schemas.js +239 -0
- package/dist/lib/llm/schemas.js.map +1 -0
- package/dist/lib/logging.d.ts +39 -0
- package/dist/lib/logging.d.ts.map +1 -0
- package/dist/lib/logging.js +219 -0
- package/dist/lib/logging.js.map +1 -0
- package/dist/lib/multipart.d.ts +34 -0
- package/dist/lib/multipart.d.ts.map +1 -0
- package/dist/lib/multipart.js +55 -0
- package/dist/lib/multipart.js.map +1 -0
- package/dist/lib/option-matcher.d.ts +15 -0
- package/dist/lib/option-matcher.d.ts.map +1 -0
- package/dist/lib/option-matcher.js +69 -0
- package/dist/lib/option-matcher.js.map +1 -0
- package/dist/lib/phone.d.ts +11 -0
- package/dist/lib/phone.d.ts.map +1 -0
- package/dist/lib/phone.js +17 -0
- package/dist/lib/phone.js.map +1 -0
- package/dist/lib/random.d.ts +22 -0
- package/dist/lib/random.d.ts.map +1 -0
- package/dist/lib/random.js +33 -0
- package/dist/lib/random.js.map +1 -0
- package/dist/lib/statsd.d.ts +11 -0
- package/dist/lib/statsd.d.ts.map +1 -0
- package/dist/lib/statsd.js +68 -0
- package/dist/lib/statsd.js.map +1 -0
- package/dist/lib/telemetry/call-capture.d.ts +89 -0
- package/dist/lib/telemetry/call-capture.d.ts.map +1 -0
- package/dist/lib/telemetry/call-capture.js +190 -0
- package/dist/lib/telemetry/call-capture.js.map +1 -0
- package/dist/lib/telemetry/call-types.d.ts +65 -0
- package/dist/lib/telemetry/call-types.d.ts.map +1 -0
- package/dist/lib/telemetry/call-types.js +68 -0
- package/dist/lib/telemetry/call-types.js.map +1 -0
- package/dist/lib/telemetry/run-state.d.ts +15 -0
- package/dist/lib/telemetry/run-state.d.ts.map +1 -0
- package/dist/lib/telemetry/run-state.js +23 -0
- package/dist/lib/telemetry/run-state.js.map +1 -0
- package/dist/lib/telemetry/s3-sink.d.ts +48 -0
- package/dist/lib/telemetry/s3-sink.d.ts.map +1 -0
- package/dist/lib/telemetry/s3-sink.js +229 -0
- package/dist/lib/telemetry/s3-sink.js.map +1 -0
- package/dist/lib/telemetry/submission-capture.d.ts +45 -0
- package/dist/lib/telemetry/submission-capture.d.ts.map +1 -0
- package/dist/lib/telemetry/submission-capture.js +57 -0
- package/dist/lib/telemetry/submission-capture.js.map +1 -0
- package/dist/lib/telemetry/telemetry-paths.d.ts +59 -0
- package/dist/lib/telemetry/telemetry-paths.d.ts.map +1 -0
- package/dist/lib/telemetry/telemetry-paths.js +103 -0
- package/dist/lib/telemetry/telemetry-paths.js.map +1 -0
- package/dist/lib/tracking-click.d.ts +20 -0
- package/dist/lib/tracking-click.d.ts.map +1 -0
- package/dist/lib/tracking-click.js +75 -0
- package/dist/lib/tracking-click.js.map +1 -0
- package/dist/lib/url-capture.d.ts +8 -0
- package/dist/lib/url-capture.d.ts.map +1 -0
- package/dist/lib/url-capture.js +17 -0
- package/dist/lib/url-capture.js.map +1 -0
- package/dist/lib/us-states.d.ts +20 -0
- package/dist/lib/us-states.d.ts.map +1 -0
- package/dist/lib/us-states.js +86 -0
- package/dist/lib/us-states.js.map +1 -0
- package/dist/lib/zod-multipart.d.ts +18 -0
- package/dist/lib/zod-multipart.d.ts.map +1 -0
- package/dist/lib/zod-multipart.js +35 -0
- package/dist/lib/zod-multipart.js.map +1 -0
- package/dist/plugins/config-plugin.d.ts +77 -0
- package/dist/plugins/config-plugin.d.ts.map +1 -0
- package/dist/plugins/config-plugin.js +216 -0
- package/dist/plugins/config-plugin.js.map +1 -0
- package/dist/plugins/discover.d.ts +72 -0
- package/dist/plugins/discover.d.ts.map +1 -0
- package/dist/plugins/discover.js +265 -0
- package/dist/plugins/discover.js.map +1 -0
- package/dist/plugins/json-schema-to-zod.d.ts +47 -0
- package/dist/plugins/json-schema-to-zod.d.ts.map +1 -0
- package/dist/plugins/json-schema-to-zod.js +85 -0
- package/dist/plugins/json-schema-to-zod.js.map +1 -0
- package/dist/plugins/loader.d.ts +34 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js +348 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/plugin-api-version.d.ts +8 -0
- package/dist/plugins/plugin-api-version.d.ts.map +1 -0
- package/dist/plugins/plugin-api-version.js +11 -0
- package/dist/plugins/plugin-api-version.js.map +1 -0
- package/dist/plugins/plugin-manifest-envelope.d.ts +16 -0
- package/dist/plugins/plugin-manifest-envelope.d.ts.map +1 -0
- package/dist/plugins/plugin-manifest-envelope.js +19 -0
- package/dist/plugins/plugin-manifest-envelope.js.map +1 -0
- package/dist/scraper/behavioral-signals.d.ts +16 -0
- package/dist/scraper/behavioral-signals.d.ts.map +1 -0
- package/dist/scraper/behavioral-signals.js +30 -0
- package/dist/scraper/behavioral-signals.js.map +1 -0
- package/dist/scraper/errors.d.ts +193 -0
- package/dist/scraper/errors.d.ts.map +1 -0
- package/dist/scraper/errors.js +226 -0
- package/dist/scraper/errors.js.map +1 -0
- package/dist/scraper/fixtures.d.ts +23 -0
- package/dist/scraper/fixtures.d.ts.map +1 -0
- package/dist/scraper/fixtures.js +48 -0
- package/dist/scraper/fixtures.js.map +1 -0
- package/dist/scraper/flow-runner.d.ts +1319 -0
- package/dist/scraper/flow-runner.d.ts.map +1 -0
- package/dist/scraper/flow-runner.js +5637 -0
- package/dist/scraper/flow-runner.js.map +1 -0
- package/dist/scraper/graphql-client.d.ts +30 -0
- package/dist/scraper/graphql-client.d.ts.map +1 -0
- package/dist/scraper/graphql-client.js +14 -0
- package/dist/scraper/graphql-client.js.map +1 -0
- package/dist/scraper/http-client.d.ts +75 -0
- package/dist/scraper/http-client.d.ts.map +1 -0
- package/dist/scraper/http-client.js +189 -0
- package/dist/scraper/http-client.js.map +1 -0
- package/dist/scraper/http-status-classifier.d.ts +12 -0
- package/dist/scraper/http-status-classifier.d.ts.map +1 -0
- package/dist/scraper/http-status-classifier.js +29 -0
- package/dist/scraper/http-status-classifier.js.map +1 -0
- package/dist/scraper/metrics.d.ts +50 -0
- package/dist/scraper/metrics.d.ts.map +1 -0
- package/dist/scraper/metrics.js +85 -0
- package/dist/scraper/metrics.js.map +1 -0
- package/dist/scraper/navigate.d.ts +20 -0
- package/dist/scraper/navigate.d.ts.map +1 -0
- package/dist/scraper/navigate.js +30 -0
- package/dist/scraper/navigate.js.map +1 -0
- package/dist/scraper/oracle-sentinels.d.ts +22 -0
- package/dist/scraper/oracle-sentinels.d.ts.map +1 -0
- package/dist/scraper/oracle-sentinels.js +40 -0
- package/dist/scraper/oracle-sentinels.js.map +1 -0
- package/dist/scraper/parse-json-response.d.ts +16 -0
- package/dist/scraper/parse-json-response.d.ts.map +1 -0
- package/dist/scraper/parse-json-response.js +37 -0
- package/dist/scraper/parse-json-response.js.map +1 -0
- package/dist/scraper/pool.d.ts +37 -0
- package/dist/scraper/pool.d.ts.map +1 -0
- package/dist/scraper/pool.js +105 -0
- package/dist/scraper/pool.js.map +1 -0
- package/dist/scraper/rate-limited-json-client.d.ts +35 -0
- package/dist/scraper/rate-limited-json-client.d.ts.map +1 -0
- package/dist/scraper/rate-limited-json-client.js +29 -0
- package/dist/scraper/rate-limited-json-client.js.map +1 -0
- package/dist/scraper/raw-fetch.d.ts +49 -0
- package/dist/scraper/raw-fetch.d.ts.map +1 -0
- package/dist/scraper/raw-fetch.js +40 -0
- package/dist/scraper/raw-fetch.js.map +1 -0
- package/dist/scraper/require-response-field.d.ts +23 -0
- package/dist/scraper/require-response-field.d.ts.map +1 -0
- package/dist/scraper/require-response-field.js +42 -0
- package/dist/scraper/require-response-field.js.map +1 -0
- package/dist/scraper/retry.d.ts +33 -0
- package/dist/scraper/retry.d.ts.map +1 -0
- package/dist/scraper/retry.js +122 -0
- package/dist/scraper/retry.js.map +1 -0
- package/dist/scraper/session-browserbase.d.ts +35 -0
- package/dist/scraper/session-browserbase.d.ts.map +1 -0
- package/dist/scraper/session-browserbase.js +198 -0
- package/dist/scraper/session-browserbase.js.map +1 -0
- package/dist/scraper/session-shared.d.ts +29 -0
- package/dist/scraper/session-shared.d.ts.map +1 -0
- package/dist/scraper/session-shared.js +35 -0
- package/dist/scraper/session-shared.js.map +1 -0
- package/dist/scraper/session-steel.d.ts +31 -0
- package/dist/scraper/session-steel.d.ts.map +1 -0
- package/dist/scraper/session-steel.js +140 -0
- package/dist/scraper/session-steel.js.map +1 -0
- package/dist/scraper/session-warmup.d.ts +31 -0
- package/dist/scraper/session-warmup.d.ts.map +1 -0
- package/dist/scraper/session-warmup.js +46 -0
- package/dist/scraper/session-warmup.js.map +1 -0
- package/dist/scraper/session.d.ts +21 -0
- package/dist/scraper/session.d.ts.map +1 -0
- package/dist/scraper/session.js +28 -0
- package/dist/scraper/session.js.map +1 -0
- package/dist/scraper/stagehand-guard.d.ts +128 -0
- package/dist/scraper/stagehand-guard.d.ts.map +1 -0
- package/dist/scraper/stagehand-guard.js +337 -0
- package/dist/scraper/stagehand-guard.js.map +1 -0
- package/dist/scraper/throttle.d.ts +21 -0
- package/dist/scraper/throttle.d.ts.map +1 -0
- package/dist/scraper/throttle.js +45 -0
- package/dist/scraper/throttle.js.map +1 -0
- package/dist/scripts/hca-inbox-poll.d.ts +19 -0
- package/dist/scripts/hca-inbox-poll.d.ts.map +1 -0
- package/dist/scripts/hca-inbox-poll.js +151 -0
- package/dist/scripts/hca-inbox-poll.js.map +1 -0
- package/dist/scripts/judge-llm-batch.d.ts +98 -0
- package/dist/scripts/judge-llm-batch.d.ts.map +1 -0
- package/dist/scripts/judge-llm-batch.js +350 -0
- package/dist/scripts/judge-llm-batch.js.map +1 -0
- package/dist/scripts/llm-heal.d.ts +165 -0
- package/dist/scripts/llm-heal.d.ts.map +1 -0
- package/dist/scripts/llm-heal.js +595 -0
- package/dist/scripts/llm-heal.js.map +1 -0
- package/dist/scripts/migrate-telemetry-dir-names.d.ts +57 -0
- package/dist/scripts/migrate-telemetry-dir-names.d.ts.map +1 -0
- package/dist/scripts/migrate-telemetry-dir-names.js +156 -0
- package/dist/scripts/migrate-telemetry-dir-names.js.map +1 -0
- package/dist/scripts/probe-setinputfiles.d.ts +28 -0
- package/dist/scripts/probe-setinputfiles.d.ts.map +1 -0
- package/dist/scripts/probe-setinputfiles.js +95 -0
- package/dist/scripts/probe-setinputfiles.js.map +1 -0
- package/dist/scripts/recon-browser.d.ts +304 -0
- package/dist/scripts/recon-browser.d.ts.map +1 -0
- package/dist/scripts/recon-browser.js +1833 -0
- package/dist/scripts/recon-browser.js.map +1 -0
- package/dist/scripts/recon-generate.d.ts +182 -0
- package/dist/scripts/recon-generate.d.ts.map +1 -0
- package/dist/scripts/recon-generate.js +2572 -0
- package/dist/scripts/recon-generate.js.map +1 -0
- package/dist/scripts/recon-heal.d.ts +176 -0
- package/dist/scripts/recon-heal.d.ts.map +1 -0
- package/dist/scripts/recon-heal.js +584 -0
- package/dist/scripts/recon-heal.js.map +1 -0
- package/dist/scripts/recon-http.d.ts +19 -0
- package/dist/scripts/recon-http.d.ts.map +1 -0
- package/dist/scripts/recon-http.js +377 -0
- package/dist/scripts/recon-http.js.map +1 -0
- package/dist/scripts/recon-replay-jobs.d.ts +21 -0
- package/dist/scripts/recon-replay-jobs.d.ts.map +1 -0
- package/dist/scripts/recon-replay-jobs.js +221 -0
- package/dist/scripts/recon-replay-jobs.js.map +1 -0
- package/dist/scripts/recon-shared.d.ts +52 -0
- package/dist/scripts/recon-shared.d.ts.map +1 -0
- package/dist/scripts/recon-shared.js +68 -0
- package/dist/scripts/recon-shared.js.map +1 -0
- package/dist/scripts/recon-summarize.d.ts +15 -0
- package/dist/scripts/recon-summarize.d.ts.map +1 -0
- package/dist/scripts/recon-summarize.js +233 -0
- package/dist/scripts/recon-summarize.js.map +1 -0
- package/dist/scripts/smoke-test.d.ts +22 -0
- package/dist/scripts/smoke-test.d.ts.map +1 -0
- package/dist/scripts/smoke-test.js +236 -0
- package/dist/scripts/smoke-test.js.map +1 -0
- package/dist/server.d.ts +10 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +189 -0
- package/dist/server.js.map +1 -0
- package/dist/site-plugin.d.ts +226 -0
- package/dist/site-plugin.d.ts.map +1 -0
- package/dist/site-plugin.js +13 -0
- package/dist/site-plugin.js.map +1 -0
- package/dist/testing/answers-fixture.d.ts +13 -0
- package/dist/testing/answers-fixture.d.ts.map +1 -0
- package/dist/testing/answers-fixture.js +37 -0
- package/dist/testing/answers-fixture.js.map +1 -0
- package/dist/testing/batch-email-confirmation.d.ts +58 -0
- package/dist/testing/batch-email-confirmation.d.ts.map +1 -0
- package/dist/testing/batch-email-confirmation.js +62 -0
- package/dist/testing/batch-email-confirmation.js.map +1 -0
- package/dist/testing/batch-report.d.ts +33 -0
- package/dist/testing/batch-report.d.ts.map +1 -0
- package/dist/testing/batch-report.js +30 -0
- package/dist/testing/batch-report.js.map +1 -0
- package/dist/testing/contract-parity-suite.d.ts +55 -0
- package/dist/testing/contract-parity-suite.d.ts.map +1 -0
- package/dist/testing/contract-parity-suite.js +39 -0
- package/dist/testing/contract-parity-suite.js.map +1 -0
- package/dist/testing/coverage-guard-suite.d.ts +46 -0
- package/dist/testing/coverage-guard-suite.d.ts.map +1 -0
- package/dist/testing/coverage-guard-suite.js +39 -0
- package/dist/testing/coverage-guard-suite.js.map +1 -0
- package/dist/testing/fixtures/resume.pdf +54 -0
- package/dist/testing/integration-runner.d.ts +62 -0
- package/dist/testing/integration-runner.d.ts.map +1 -0
- package/dist/testing/integration-runner.js +46 -0
- package/dist/testing/integration-runner.js.map +1 -0
- package/dist/testing/mock-fetch-response.d.ts +7 -0
- package/dist/testing/mock-fetch-response.d.ts.map +1 -0
- package/dist/testing/mock-fetch-response.js +16 -0
- package/dist/testing/mock-fetch-response.js.map +1 -0
- package/dist/testing/persona-fixture.d.ts +77 -0
- package/dist/testing/persona-fixture.d.ts.map +1 -0
- package/dist/testing/persona-fixture.js +83 -0
- package/dist/testing/persona-fixture.js.map +1 -0
- package/dist/testing/replay-integration-suite.d.ts +50 -0
- package/dist/testing/replay-integration-suite.d.ts.map +1 -0
- package/dist/testing/replay-integration-suite.js +45 -0
- package/dist/testing/replay-integration-suite.js.map +1 -0
- package/dist/testing/resume-fixture.d.ts +39 -0
- package/dist/testing/resume-fixture.d.ts.map +1 -0
- package/dist/testing/resume-fixture.js +38 -0
- package/dist/testing/resume-fixture.js.map +1 -0
- package/dist/testmail/client.d.ts +61 -0
- package/dist/testmail/client.d.ts.map +1 -0
- package/dist/testmail/client.js +190 -0
- package/dist/testmail/client.js.map +1 -0
- package/dist/testmail/errors.d.ts +18 -0
- package/dist/testmail/errors.d.ts.map +1 -0
- package/dist/testmail/errors.js +29 -0
- package/dist/testmail/errors.js.map +1 -0
- package/dist/types/dispatch-metrics.d.ts +46 -0
- package/dist/types/dispatch-metrics.d.ts.map +1 -0
- package/dist/types/dispatch-metrics.js +25 -0
- package/dist/types/dispatch-metrics.js.map +1 -0
- package/dist/types/logging.d.ts +11 -0
- package/dist/types/logging.d.ts.map +1 -0
- package/dist/types/logging.js +3 -0
- package/dist/types/logging.js.map +1 -0
- package/package.json +283 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { type ErrorCode } from "../api/schemas/common";
|
|
2
|
+
/**
|
|
3
|
+
* Representation of the error envelope on the wire. Every non-2xx
|
|
4
|
+
* response from Barnacle conforms to this shape so clients can share a
|
|
5
|
+
* single parser across all error types.
|
|
6
|
+
*/
|
|
7
|
+
interface ApiStatusDetail {
|
|
8
|
+
code: number;
|
|
9
|
+
codeDescription: string;
|
|
10
|
+
detailType: string;
|
|
11
|
+
message: string;
|
|
12
|
+
}
|
|
13
|
+
interface ApiErrorEnvelope {
|
|
14
|
+
status: {
|
|
15
|
+
httpStatus: string;
|
|
16
|
+
dateTime: string;
|
|
17
|
+
details: ApiStatusDetail[];
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Maps an error code to the HTTP status we return. Status codes come
|
|
22
|
+
* from the `http-status-codes` package (battle-tested, RFC-aligned, used
|
|
23
|
+
* by Express and thousands of production APIs) so we don't maintain our
|
|
24
|
+
* own numeric table.
|
|
25
|
+
*
|
|
26
|
+
* The envelope uses `httpStatus` as a string. Barnacle also sets the actual
|
|
27
|
+
* HTTP status code so modern clients can branch on either.
|
|
28
|
+
*/
|
|
29
|
+
export declare function httpStatusForCode(code: ErrorCode): number;
|
|
30
|
+
/**
|
|
31
|
+
* Converts an HTTP status number into the upper-snake-case string used in
|
|
32
|
+
* the response envelope (e.g. 400 → `"BAD_REQUEST"`). Uses `getReasonPhrase`
|
|
33
|
+
* from `http-status-codes`, then uppercases and replaces non-alphanumeric
|
|
34
|
+
* runs with `_` (e.g. `I'm a teapot` → `I_M_A_TEAPOT`).
|
|
35
|
+
*/
|
|
36
|
+
export declare function httpStatusString(status: number): string;
|
|
37
|
+
/**
|
|
38
|
+
* Base class for every structured error Barnacle surfaces to clients. Each
|
|
39
|
+
* subclass hard-codes an error code; the plugin-level error handler
|
|
40
|
+
* reads `code` + `message` and builds the envelope.
|
|
41
|
+
*/
|
|
42
|
+
export declare class ApiError extends Error {
|
|
43
|
+
readonly code: ErrorCode;
|
|
44
|
+
readonly detailType: string;
|
|
45
|
+
constructor(code: ErrorCode, message: string, detailType?: string);
|
|
46
|
+
}
|
|
47
|
+
export declare class UnauthorizedError extends ApiError {
|
|
48
|
+
constructor(message?: string);
|
|
49
|
+
}
|
|
50
|
+
export declare class FieldViolationError extends ApiError {
|
|
51
|
+
constructor(message: string);
|
|
52
|
+
}
|
|
53
|
+
export declare class ThrottledRequestError extends ApiError {
|
|
54
|
+
constructor(message?: string);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The upstream vendor has locked the target URL (e.g. Oracle ORA_URL_LOCKED).
|
|
58
|
+
* Signals "back off and retry later" — not a browser-fallback trigger.
|
|
59
|
+
*/
|
|
60
|
+
export declare class UrlLockedError extends ApiError {
|
|
61
|
+
constructor(message?: string);
|
|
62
|
+
}
|
|
63
|
+
export declare class ScrapeFailureError extends ApiError {
|
|
64
|
+
constructor(message?: string);
|
|
65
|
+
}
|
|
66
|
+
export declare class CaptchaEncounteredError extends ApiError {
|
|
67
|
+
constructor(message?: string);
|
|
68
|
+
}
|
|
69
|
+
export declare class EmptyResultsApiError extends ApiError {
|
|
70
|
+
constructor(message?: string);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The OTP a candidate supplied to /resume was rejected by Oracle HCM, which
|
|
74
|
+
* surfaces as a 401/403 on the first AccessCode-authed call. Distinct from a
|
|
75
|
+
* generic scrape failure so Vivian can re-prompt for the code rather than
|
|
76
|
+
* treating the resume as terminally failed.
|
|
77
|
+
*/
|
|
78
|
+
export declare class InvalidOtpError extends ApiError {
|
|
79
|
+
constructor(message?: string);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Builds an error envelope for the given code + message. Used by the
|
|
83
|
+
* Fastify error handler and anywhere else a manual non-200 response needs
|
|
84
|
+
* to be emitted (e.g. Fastify's built-in rate-limit 429).
|
|
85
|
+
*/
|
|
86
|
+
export declare function buildErrorEnvelope(code: ErrorCode, message: string, detailType?: string): ApiErrorEnvelope;
|
|
87
|
+
export {};
|
|
88
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/api/errors.ts"],"names":[],"mappings":"AAGA,OAAO,EAAwC,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE5F;;;;GAIG;AACH,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,gBAAgB;IACxB,MAAM,EAAE;QACN,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,eAAe,EAAE,CAAC;KAC5B,CAAC;CACH;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAgCzD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAQvD;AAED;;;;GAIG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,SAAgB,IAAI,EAAE,SAAS,CAAC;IAChC,SAAgB,UAAU,EAAE,MAAM,CAAC;gBAEvB,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,SAAU;CAMnE;AAED,qBAAa,iBAAkB,SAAQ,QAAQ;gBACjC,OAAO,SAA4C;CAGhE;AAED,qBAAa,mBAAoB,SAAQ,QAAQ;gBACnC,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,qBAAsB,SAAQ,QAAQ;gBACrC,OAAO,SAAwB;CAG5C;AAED;;;GAGG;AACH,qBAAa,cAAe,SAAQ,QAAQ;gBAC9B,OAAO,SAA6D;CAGjF;AAED,qBAAa,kBAAmB,SAAQ,QAAQ;gBAClC,OAAO,SAA0C;CAG9D;AAED,qBAAa,uBAAwB,SAAQ,QAAQ;gBACvC,OAAO,SAA2C;CAG/D;AAED,qBAAa,oBAAqB,SAAQ,QAAQ;gBACpC,OAAO,SAA6C;CAGjE;AAED;;;;;GAKG;AACH,qBAAa,eAAgB,SAAQ,QAAQ;gBAC/B,OAAO,SAA4C;CAGhE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,MAAM,EACf,UAAU,SAAU,GACnB,gBAAgB,CAgBlB"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InvalidOtpError = exports.EmptyResultsApiError = exports.CaptchaEncounteredError = exports.ScrapeFailureError = exports.UrlLockedError = exports.ThrottledRequestError = exports.FieldViolationError = exports.UnauthorizedError = exports.ApiError = void 0;
|
|
4
|
+
exports.httpStatusForCode = httpStatusForCode;
|
|
5
|
+
exports.httpStatusString = httpStatusString;
|
|
6
|
+
exports.buildErrorEnvelope = buildErrorEnvelope;
|
|
7
|
+
const date_fns_1 = require("date-fns");
|
|
8
|
+
const http_status_codes_1 = require("http-status-codes");
|
|
9
|
+
const common_1 = require("../api/schemas/common");
|
|
10
|
+
/**
|
|
11
|
+
* Maps an error code to the HTTP status we return. Status codes come
|
|
12
|
+
* from the `http-status-codes` package (battle-tested, RFC-aligned, used
|
|
13
|
+
* by Express and thousands of production APIs) so we don't maintain our
|
|
14
|
+
* own numeric table.
|
|
15
|
+
*
|
|
16
|
+
* The envelope uses `httpStatus` as a string. Barnacle also sets the actual
|
|
17
|
+
* HTTP status code so modern clients can branch on either.
|
|
18
|
+
*/
|
|
19
|
+
function httpStatusForCode(code) {
|
|
20
|
+
switch (code) {
|
|
21
|
+
case common_1.ERROR_CODES.PARTIAL_CONTENT_SUCCESS:
|
|
22
|
+
return http_status_codes_1.StatusCodes.PARTIAL_CONTENT;
|
|
23
|
+
case common_1.ERROR_CODES.AUTHORIZATION_ERROR:
|
|
24
|
+
return http_status_codes_1.StatusCodes.UNAUTHORIZED;
|
|
25
|
+
case common_1.ERROR_CODES.DECODING_ERROR:
|
|
26
|
+
case common_1.ERROR_CODES.FIELD_VIOLATION:
|
|
27
|
+
case common_1.ERROR_CODES.EMPTY_REQUEST:
|
|
28
|
+
return http_status_codes_1.StatusCodes.BAD_REQUEST;
|
|
29
|
+
case common_1.ERROR_CODES.RESOURCE_NOT_FOUND:
|
|
30
|
+
case common_1.ERROR_CODES.INDEX_NOT_FOUND:
|
|
31
|
+
return http_status_codes_1.StatusCodes.NOT_FOUND;
|
|
32
|
+
case common_1.ERROR_CODES.THROTTLED_REQUEST:
|
|
33
|
+
case common_1.ERROR_CODES.URL_LOCKED:
|
|
34
|
+
return http_status_codes_1.StatusCodes.TOO_MANY_REQUESTS;
|
|
35
|
+
case common_1.ERROR_CODES.TIME_OUT:
|
|
36
|
+
return http_status_codes_1.StatusCodes.GATEWAY_TIMEOUT;
|
|
37
|
+
case common_1.ERROR_CODES.EMPTY_RESULTS:
|
|
38
|
+
return http_status_codes_1.StatusCodes.NOT_FOUND;
|
|
39
|
+
case common_1.ERROR_CODES.CLIENT_CALL_ERROR:
|
|
40
|
+
case common_1.ERROR_CODES.GENERIC_ERROR:
|
|
41
|
+
case common_1.ERROR_CODES.EXTRA_DETAIL:
|
|
42
|
+
case common_1.ERROR_CODES.SCRAPE_FAILURE:
|
|
43
|
+
case common_1.ERROR_CODES.CAPTCHA_ENCOUNTERED:
|
|
44
|
+
case common_1.ERROR_CODES.VERIFICATION_TRIGGER_FAILED:
|
|
45
|
+
return http_status_codes_1.StatusCodes.INTERNAL_SERVER_ERROR;
|
|
46
|
+
case common_1.ERROR_CODES.RESUME_INVALID_OTP:
|
|
47
|
+
return http_status_codes_1.StatusCodes.BAD_REQUEST;
|
|
48
|
+
default:
|
|
49
|
+
return http_status_codes_1.StatusCodes.INTERNAL_SERVER_ERROR;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Converts an HTTP status number into the upper-snake-case string used in
|
|
54
|
+
* the response envelope (e.g. 400 → `"BAD_REQUEST"`). Uses `getReasonPhrase`
|
|
55
|
+
* from `http-status-codes`, then uppercases and replaces non-alphanumeric
|
|
56
|
+
* runs with `_` (e.g. `I'm a teapot` → `I_M_A_TEAPOT`).
|
|
57
|
+
*/
|
|
58
|
+
function httpStatusString(status) {
|
|
59
|
+
try {
|
|
60
|
+
return (0, http_status_codes_1.getReasonPhrase)(status)
|
|
61
|
+
.toUpperCase()
|
|
62
|
+
.replace(/[^A-Z0-9]+/g, "_");
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return `HTTP_${status}`;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Base class for every structured error Barnacle surfaces to clients. Each
|
|
70
|
+
* subclass hard-codes an error code; the plugin-level error handler
|
|
71
|
+
* reads `code` + `message` and builds the envelope.
|
|
72
|
+
*/
|
|
73
|
+
class ApiError extends Error {
|
|
74
|
+
code;
|
|
75
|
+
detailType;
|
|
76
|
+
constructor(code, message, detailType = "ERROR") {
|
|
77
|
+
super(message);
|
|
78
|
+
this.name = new.target.name;
|
|
79
|
+
this.code = code;
|
|
80
|
+
this.detailType = detailType;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
exports.ApiError = ApiError;
|
|
84
|
+
class UnauthorizedError extends ApiError {
|
|
85
|
+
constructor(message = "missing or invalid Authorization header") {
|
|
86
|
+
super(common_1.ERROR_CODES.AUTHORIZATION_ERROR, message);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
exports.UnauthorizedError = UnauthorizedError;
|
|
90
|
+
class FieldViolationError extends ApiError {
|
|
91
|
+
constructor(message) {
|
|
92
|
+
super(common_1.ERROR_CODES.FIELD_VIOLATION, message);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.FieldViolationError = FieldViolationError;
|
|
96
|
+
class ThrottledRequestError extends ApiError {
|
|
97
|
+
constructor(message = "rate limit exceeded") {
|
|
98
|
+
super(common_1.ERROR_CODES.THROTTLED_REQUEST, message);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.ThrottledRequestError = ThrottledRequestError;
|
|
102
|
+
/**
|
|
103
|
+
* The upstream vendor has locked the target URL (e.g. Oracle ORA_URL_LOCKED).
|
|
104
|
+
* Signals "back off and retry later" — not a browser-fallback trigger.
|
|
105
|
+
*/
|
|
106
|
+
class UrlLockedError extends ApiError {
|
|
107
|
+
constructor(message = "target URL is locked by the upstream vendor; retry later") {
|
|
108
|
+
super(common_1.ERROR_CODES.URL_LOCKED, message);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exports.UrlLockedError = UrlLockedError;
|
|
112
|
+
class ScrapeFailureError extends ApiError {
|
|
113
|
+
constructor(message = "scraper failed to fulfill the request") {
|
|
114
|
+
super(common_1.ERROR_CODES.SCRAPE_FAILURE, message);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exports.ScrapeFailureError = ScrapeFailureError;
|
|
118
|
+
class CaptchaEncounteredError extends ApiError {
|
|
119
|
+
constructor(message = "captcha challenge encountered upstream") {
|
|
120
|
+
super(common_1.ERROR_CODES.CAPTCHA_ENCOUNTERED, message);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
exports.CaptchaEncounteredError = CaptchaEncounteredError;
|
|
124
|
+
class EmptyResultsApiError extends ApiError {
|
|
125
|
+
constructor(message = "scrape completed but returned no results") {
|
|
126
|
+
super(common_1.ERROR_CODES.EMPTY_RESULTS, message);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
exports.EmptyResultsApiError = EmptyResultsApiError;
|
|
130
|
+
/**
|
|
131
|
+
* The OTP a candidate supplied to /resume was rejected by Oracle HCM, which
|
|
132
|
+
* surfaces as a 401/403 on the first AccessCode-authed call. Distinct from a
|
|
133
|
+
* generic scrape failure so Vivian can re-prompt for the code rather than
|
|
134
|
+
* treating the resume as terminally failed.
|
|
135
|
+
*/
|
|
136
|
+
class InvalidOtpError extends ApiError {
|
|
137
|
+
constructor(message = "provided OTP was rejected by Oracle HCM") {
|
|
138
|
+
super(common_1.ERROR_CODES.RESUME_INVALID_OTP, message);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
exports.InvalidOtpError = InvalidOtpError;
|
|
142
|
+
/**
|
|
143
|
+
* Builds an error envelope for the given code + message. Used by the
|
|
144
|
+
* Fastify error handler and anywhere else a manual non-200 response needs
|
|
145
|
+
* to be emitted (e.g. Fastify's built-in rate-limit 429).
|
|
146
|
+
*/
|
|
147
|
+
function buildErrorEnvelope(code, message, detailType = "ERROR") {
|
|
148
|
+
const httpStatus = httpStatusForCode(code);
|
|
149
|
+
return {
|
|
150
|
+
status: {
|
|
151
|
+
httpStatus: httpStatusString(httpStatus),
|
|
152
|
+
dateTime: (0, date_fns_1.formatISO)(new Date()),
|
|
153
|
+
details: [
|
|
154
|
+
{
|
|
155
|
+
code,
|
|
156
|
+
codeDescription: common_1.ERROR_CODE_DESCRIPTIONS[code],
|
|
157
|
+
detailType,
|
|
158
|
+
message,
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/api/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the success envelope — `{ status: { httpStatus: "OK", ... } }`
|
|
3
|
+
* merged with the domain payload. Service methods return the complete
|
|
4
|
+
* envelope-shaped object so route handlers just pass them through.
|
|
5
|
+
*/
|
|
6
|
+
export declare function successEnvelope<T extends object>(payload: T): {
|
|
7
|
+
status: {
|
|
8
|
+
httpStatus: string;
|
|
9
|
+
dateTime: string;
|
|
10
|
+
details: unknown[];
|
|
11
|
+
};
|
|
12
|
+
} & T;
|
|
13
|
+
//# sourceMappingURL=envelope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../../../src/api/helpers/envelope.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAC9C,OAAO,EAAE,CAAC,GACT;IACD,MAAM,EAAE;QACN,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,OAAO,EAAE,CAAC;KACpB,CAAC;CACH,GAAG,CAAC,CASJ"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.successEnvelope = successEnvelope;
|
|
4
|
+
const date_fns_1 = require("date-fns");
|
|
5
|
+
/**
|
|
6
|
+
* Builds the success envelope — `{ status: { httpStatus: "OK", ... } }`
|
|
7
|
+
* merged with the domain payload. Service methods return the complete
|
|
8
|
+
* envelope-shaped object so route handlers just pass them through.
|
|
9
|
+
*/
|
|
10
|
+
function successEnvelope(payload) {
|
|
11
|
+
return {
|
|
12
|
+
status: {
|
|
13
|
+
httpStatus: "OK",
|
|
14
|
+
dateTime: (0, date_fns_1.formatISO)(new Date()),
|
|
15
|
+
details: [],
|
|
16
|
+
},
|
|
17
|
+
...payload,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=envelope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.js","sourceRoot":"","sources":["../../../src/api/helpers/envelope.ts"],"names":[],"mappings":";;AAOA,0CAiBC;AAxBD,uCAAqC;AAErC;;;;GAIG;AACH,SAAgB,eAAe,CAC7B,OAAU;IAQV,OAAO;QACL,MAAM,EAAE;YACN,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,IAAA,oBAAS,EAAC,IAAI,IAAI,EAAE,CAAC;YAC/B,OAAO,EAAE,EAAE;SACZ;QACD,GAAG,OAAO;KACX,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FastifyReply } from "fastify";
|
|
2
|
+
import type { ErrorCode } from "../../api/schemas/common";
|
|
3
|
+
import type { DispatchMetrics } from "../../types/dispatch-metrics";
|
|
4
|
+
/**
|
|
5
|
+
* Sends a standard error envelope on the given reply, optionally including
|
|
6
|
+
* dispatch metrics so Vivian can forward step-level detail even on failures.
|
|
7
|
+
*/
|
|
8
|
+
export declare function replyWithError(reply: FastifyReply, code: ErrorCode, message: string, detailType?: string, statusOverride?: number, metrics?: DispatchMetrics): void;
|
|
9
|
+
//# sourceMappingURL=reply.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reply.d.ts","sourceRoot":"","sources":["../../../src/api/helpers/reply.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEhE;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,MAAM,EACvB,OAAO,CAAC,EAAE,eAAe,GACxB,IAAI,CAIN"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.replyWithError = replyWithError;
|
|
4
|
+
const errors_1 = require("../../api/errors");
|
|
5
|
+
/**
|
|
6
|
+
* Sends a standard error envelope on the given reply, optionally including
|
|
7
|
+
* dispatch metrics so Vivian can forward step-level detail even on failures.
|
|
8
|
+
*/
|
|
9
|
+
function replyWithError(reply, code, message, detailType, statusOverride, metrics) {
|
|
10
|
+
const envelope = (0, errors_1.buildErrorEnvelope)(code, message, detailType);
|
|
11
|
+
const body = metrics ? { ...envelope, metrics } : envelope;
|
|
12
|
+
void reply.status(statusOverride ?? (0, errors_1.httpStatusForCode)(code)).send(body);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=reply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reply.js","sourceRoot":"","sources":["../../../src/api/helpers/reply.ts"],"names":[],"mappings":";;AAUA,wCAWC;AAnBD,yCAAqE;AAIrE;;;GAGG;AACH,SAAgB,cAAc,CAC5B,KAAmB,EACnB,IAAe,EACf,OAAe,EACf,UAAmB,EACnB,cAAuB,EACvB,OAAyB;IAEzB,MAAM,QAAQ,GAAG,IAAA,2BAAkB,EAAC,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IAC/D,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC3D,KAAK,KAAK,CAAC,MAAM,CAAC,cAAc,IAAI,IAAA,0BAAiB,EAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1E,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { FastifyInstance } from "fastify";
|
|
2
|
+
declare module "fastify" {
|
|
3
|
+
interface FastifyInstance {
|
|
4
|
+
authenticate: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
interface FastifyRequest {
|
|
7
|
+
apiKeyTier?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Short SHA-256 fingerprint of the matching bcrypt hash, or the
|
|
10
|
+
* literal `"dev-bypass"` when DEV_BYPASS_AUTH is used. Lets ops
|
|
11
|
+
* trace "which client hit this route" in logs without leaking the
|
|
12
|
+
* plaintext token or the full bcrypt hash.
|
|
13
|
+
*/
|
|
14
|
+
apiKeyFingerprint?: string;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Fastify plugin exposing `app.authenticate`. Routes attach it via
|
|
19
|
+
* `{ onRequest: [app.authenticate] }` to require a valid Bearer token.
|
|
20
|
+
*
|
|
21
|
+
* Dev-only escape hatch: `DEV_BYPASS_AUTH=true` allows unauthenticated
|
|
22
|
+
* access in non-production environments. NEVER set this in prod.
|
|
23
|
+
*/
|
|
24
|
+
declare function authPlugin(app: FastifyInstance): Promise<void>;
|
|
25
|
+
declare const _default: typeof authPlugin;
|
|
26
|
+
export default _default;
|
|
27
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/api/plugins/auth.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAS7E,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,eAAe;QACvB,YAAY,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KAC/E;IACD,UAAU,cAAc;QACtB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB;;;;;WAKG;QACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B;CACF;AAsCD;;;;;;GAMG;AACH,iBAAe,UAAU,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA6D7D;;AAED,wBAEG"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_crypto_1 = require("node:crypto");
|
|
7
|
+
const bcryptjs_1 = require("bcryptjs");
|
|
8
|
+
const fastify_plugin_1 = __importDefault(require("fastify-plugin"));
|
|
9
|
+
const errors_1 = require("../../api/errors");
|
|
10
|
+
const config_1 = require("../../config");
|
|
11
|
+
const logging_1 = require("../../lib/logging");
|
|
12
|
+
const logger = (0, logging_1.getLogger)({ name: "api/plugins/auth" });
|
|
13
|
+
/**
|
|
14
|
+
* Derives a short, stable fingerprint from a bcrypt hash. 12 hex chars
|
|
15
|
+
* = 48 bits — enough to tell registered keys apart in a log stream
|
|
16
|
+
* without making offline collision attacks viable.
|
|
17
|
+
*/
|
|
18
|
+
function fingerprintHash(hash) {
|
|
19
|
+
return (0, node_crypto_1.createHash)("sha256").update(hash).digest("hex").slice(0, 12);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Extracts the Bearer token from the Authorization header. Returns `null`
|
|
23
|
+
* if the header is missing or malformed — callers must translate that
|
|
24
|
+
* into the UnauthorizedError.
|
|
25
|
+
*/
|
|
26
|
+
function extractBearer(authHeader) {
|
|
27
|
+
if (!authHeader)
|
|
28
|
+
return null;
|
|
29
|
+
const parts = authHeader.trim().split(/\s+/);
|
|
30
|
+
if (parts.length !== 2)
|
|
31
|
+
return null;
|
|
32
|
+
if (parts[0]?.toLowerCase() !== "bearer")
|
|
33
|
+
return null;
|
|
34
|
+
const token = parts[1];
|
|
35
|
+
if (!token || token.length < 8)
|
|
36
|
+
return null;
|
|
37
|
+
return token;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Compares the plaintext token against every registered bcrypt hash. We
|
|
41
|
+
* walk the array linearly — bcrypt.compare is constant-time for a given
|
|
42
|
+
* input + hash, and the hash count is small (tens).
|
|
43
|
+
*/
|
|
44
|
+
async function findMatchingHash(token, hashes) {
|
|
45
|
+
for (const hash of hashes) {
|
|
46
|
+
if (await (0, bcryptjs_1.compare)(token, hash))
|
|
47
|
+
return hash;
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Fastify plugin exposing `app.authenticate`. Routes attach it via
|
|
53
|
+
* `{ onRequest: [app.authenticate] }` to require a valid Bearer token.
|
|
54
|
+
*
|
|
55
|
+
* Dev-only escape hatch: `DEV_BYPASS_AUTH=true` allows unauthenticated
|
|
56
|
+
* access in non-production environments. NEVER set this in prod.
|
|
57
|
+
*/
|
|
58
|
+
async function authPlugin(app) {
|
|
59
|
+
// Reload config at plugin-registration time so tests can toggle
|
|
60
|
+
// DEV_BYPASS_AUTH and spin up a fresh server instance without the
|
|
61
|
+
// frozen module-scope `config` singleton getting in the way.
|
|
62
|
+
const cfg = (0, config_1.loadConfig)();
|
|
63
|
+
// Loud startup warn if dev-bypass is active. NODE_ENV unset defaults
|
|
64
|
+
// to "development" (see lib/env.ts), so a container that forgets to
|
|
65
|
+
// set NODE_ENV while DEV_BYPASS_AUTH=true would silently accept
|
|
66
|
+
// unauthenticated traffic without any runtime signal. Emitting at
|
|
67
|
+
// plugin registration means every boot of every environment logs
|
|
68
|
+
// the state — much harder to miss than discovering it via a breach.
|
|
69
|
+
if (cfg.auth.devBypass && cfg.nodeEnv !== "production") {
|
|
70
|
+
logger.warn(`DEV_BYPASS_AUTH is active (NODE_ENV=${cfg.nodeEnv}) — all requests will bypass authentication. DO NOT use this in production.`);
|
|
71
|
+
}
|
|
72
|
+
else if (cfg.auth.devBypass && cfg.nodeEnv === "production") {
|
|
73
|
+
// devBypass=true + NODE_ENV=production means the env var is present
|
|
74
|
+
// but the production guard disarmed it. Still loud-warn because
|
|
75
|
+
// that's a misconfiguration worth catching.
|
|
76
|
+
logger.warn("DEV_BYPASS_AUTH=true in production — the production guard disarmed it, but the env var should be removed from the deploy.");
|
|
77
|
+
}
|
|
78
|
+
app.decorate("authenticate", async (request, _reply) => {
|
|
79
|
+
if (cfg.auth.devBypass && cfg.nodeEnv !== "production") {
|
|
80
|
+
request.apiKeyTier = "dev";
|
|
81
|
+
// Stamp a stable sentinel fingerprint so log-aggregator
|
|
82
|
+
// filters on `apiKeyFingerprint` don't miss dev-bypass traffic.
|
|
83
|
+
request.apiKeyFingerprint = "dev-bypass";
|
|
84
|
+
request.log = request.log.child({ apiKeyFingerprint: "dev-bypass" });
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const token = extractBearer(request.headers.authorization);
|
|
88
|
+
if (!token) {
|
|
89
|
+
throw new errors_1.UnauthorizedError("missing or malformed Authorization: Bearer header");
|
|
90
|
+
}
|
|
91
|
+
if (cfg.auth.hashedKeys.length === 0) {
|
|
92
|
+
throw new errors_1.UnauthorizedError("no API keys configured on server");
|
|
93
|
+
}
|
|
94
|
+
const match = await findMatchingHash(token, cfg.auth.hashedKeys);
|
|
95
|
+
if (!match) {
|
|
96
|
+
throw new errors_1.UnauthorizedError("invalid API key");
|
|
97
|
+
}
|
|
98
|
+
request.apiKeyTier = "standard";
|
|
99
|
+
const fingerprint = fingerprintHash(match);
|
|
100
|
+
request.apiKeyFingerprint = fingerprint;
|
|
101
|
+
// Bind the fingerprint onto the per-request pino child so every
|
|
102
|
+
// subsequent log line for this request carries the identity
|
|
103
|
+
// automatically — no scattered `{ apiKeyFingerprint: ... }`
|
|
104
|
+
// calls in service code.
|
|
105
|
+
request.log = request.log.child({ apiKeyFingerprint: fingerprint });
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
exports.default = (0, fastify_plugin_1.default)(authPlugin, {
|
|
109
|
+
name: "auth",
|
|
110
|
+
});
|
|
111
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/api/plugins/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FastifyInstance } from "fastify";
|
|
2
|
+
/**
|
|
3
|
+
* Fastify plugin that replaces Fastify's default error serializer with the
|
|
4
|
+
* engine error envelope. Every non-2xx response — Zod validation failures,
|
|
5
|
+
* thrown `ApiError` subclasses, 404s, unhandled crashes — serializes through
|
|
6
|
+
* the same `{ status: { httpStatus, dateTime, details: [...] } }` shape all
|
|
7
|
+
* clients expect.
|
|
8
|
+
*/
|
|
9
|
+
declare function errorHandlerPlugin(app: FastifyInstance): Promise<void>;
|
|
10
|
+
declare const _default: typeof errorHandlerPlugin;
|
|
11
|
+
export default _default;
|
|
12
|
+
//# sourceMappingURL=error-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../../src/api/plugins/error-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAW/C;;;;;;GAMG;AACH,iBAAe,kBAAkB,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAkFrE;;AAED,wBAEG"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const fastify_plugin_1 = __importDefault(require("fastify-plugin"));
|
|
7
|
+
const fastify_type_provider_zod_1 = require("fastify-type-provider-zod");
|
|
8
|
+
const v4_1 = require("zod/v4");
|
|
9
|
+
const errors_1 = require("../../api/errors");
|
|
10
|
+
const reply_1 = require("../../api/helpers/reply");
|
|
11
|
+
const common_1 = require("../../api/schemas/common");
|
|
12
|
+
const errors_2 = require("../../scraper/errors");
|
|
13
|
+
/**
|
|
14
|
+
* Fastify plugin that replaces Fastify's default error serializer with the
|
|
15
|
+
* engine error envelope. Every non-2xx response — Zod validation failures,
|
|
16
|
+
* thrown `ApiError` subclasses, 404s, unhandled crashes — serializes through
|
|
17
|
+
* the same `{ status: { httpStatus, dateTime, details: [...] } }` shape all
|
|
18
|
+
* clients expect.
|
|
19
|
+
*/
|
|
20
|
+
async function errorHandlerPlugin(app) {
|
|
21
|
+
app.setNotFoundHandler((_request, reply) => {
|
|
22
|
+
(0, reply_1.replyWithError)(reply, common_1.ERROR_CODES.RESOURCE_NOT_FOUND, `route ${_request.method} ${_request.url} not found`);
|
|
23
|
+
});
|
|
24
|
+
app.setErrorHandler((error, request, reply) => {
|
|
25
|
+
const metrics = error.metrics;
|
|
26
|
+
if ((0, fastify_type_provider_zod_1.hasZodFastifySchemaValidationErrors)(error)) {
|
|
27
|
+
const message = error.validation
|
|
28
|
+
.map((issue) => `${issue.instancePath || "body"}: ${issue.message}`)
|
|
29
|
+
.join("; ");
|
|
30
|
+
(0, reply_1.replyWithError)(reply, common_1.ERROR_CODES.FIELD_VIOLATION, message, undefined, undefined, metrics);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (error instanceof v4_1.ZodError) {
|
|
34
|
+
const message = error.issues
|
|
35
|
+
.map((issue) => `${issue.path.join(".") || "body"}: ${issue.message}`)
|
|
36
|
+
.join("; ");
|
|
37
|
+
(0, reply_1.replyWithError)(reply, common_1.ERROR_CODES.FIELD_VIOLATION, message, undefined, undefined, metrics);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (error instanceof errors_1.ApiError) {
|
|
41
|
+
(0, reply_1.replyWithError)(reply, error.code, error.message, error.detailType, undefined, metrics);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
// Scraper errors that escaped the service-layer catch (captcha hits,
|
|
45
|
+
// exhausted selector retries, session timeouts) surface to clients as
|
|
46
|
+
// the dedicated codes 2004 / 2003 rather than a generic 1008 — the
|
|
47
|
+
// whole reason those codes exist is for clients to distinguish scrape
|
|
48
|
+
// failures from upstream target-site failures.
|
|
49
|
+
if (error instanceof errors_2.ScraperError) {
|
|
50
|
+
const code = error instanceof errors_2.CaptchaError
|
|
51
|
+
? common_1.ERROR_CODES.CAPTCHA_ENCOUNTERED
|
|
52
|
+
: common_1.ERROR_CODES.SCRAPE_FAILURE;
|
|
53
|
+
(0, reply_1.replyWithError)(reply, code, error.message, undefined, undefined, metrics);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const err = error;
|
|
57
|
+
if (typeof err.statusCode === "number" && err.statusCode === 429) {
|
|
58
|
+
(0, reply_1.replyWithError)(reply, common_1.ERROR_CODES.THROTTLED_REQUEST, err.message || "rate limit exceeded", undefined, undefined, metrics);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (typeof err.statusCode === "number" && err.statusCode < 500) {
|
|
62
|
+
(0, reply_1.replyWithError)(reply, common_1.ERROR_CODES.GENERIC_ERROR, err.message || "request failed", undefined, err.statusCode, metrics);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
request.log.error({ err }, "unhandled error");
|
|
66
|
+
(0, reply_1.replyWithError)(reply, common_1.ERROR_CODES.GENERIC_ERROR, "internal server error", undefined, undefined, metrics);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
exports.default = (0, fastify_plugin_1.default)(errorHandlerPlugin, {
|
|
70
|
+
name: "error-handler",
|
|
71
|
+
});
|
|
72
|
+
//# sourceMappingURL=error-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../../src/api/plugins/error-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FastifyInstance } from "fastify";
|
|
2
|
+
declare module "fastify" {
|
|
3
|
+
interface FastifyRequest {
|
|
4
|
+
correlationId?: string;
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Propagates request IDs and correlation IDs so logs can be stitched across
|
|
9
|
+
* services. We echo an inbound X-Request-ID when provided, otherwise
|
|
10
|
+
* generate a nanoid (replacing Fastify's per-process `req-N` default,
|
|
11
|
+
* which collides across pods), and always echo on response. Correlation
|
|
12
|
+
* IDs are echo-only — we never invent one.
|
|
13
|
+
*/
|
|
14
|
+
declare function requestContextPlugin(app: FastifyInstance): Promise<void>;
|
|
15
|
+
declare const _default: typeof requestContextPlugin;
|
|
16
|
+
export default _default;
|
|
17
|
+
//# sourceMappingURL=request-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../../src/api/plugins/request-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,SAAS,CAAC;AA0B/D,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,cAAc;QACtB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB;CACF;AAED;;;;;;GAMG;AACH,iBAAe,oBAAoB,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBvE;;AAED,wBAEG"}
|