@apifuse/provider-sdk 2.2.0-beta.3 → 2.2.0-beta.31
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/AUTHORING.md +493 -5
- package/CHANGELOG.md +131 -1
- package/README.md +52 -6
- package/SUBMISSION.md +1 -1
- package/bin/apifuse-check.ts +106 -62
- package/bin/apifuse-create.ts +1 -1
- package/bin/apifuse-dev.ts +63 -55
- package/bin/apifuse-pack-check.ts +22 -2
- package/bin/apifuse-pack-smoke.ts +78 -82
- package/bin/apifuse-pack-types.ts +583 -0
- package/bin/apifuse-perf.ts +59 -140
- package/bin/apifuse-record.ts +698 -113
- package/bin/apifuse-submit-check.ts +517 -44
- package/bin/apifuse-sync-assets.ts +117 -0
- package/bin/apifuse.ts +1 -1
- package/bin/submit-check-delimited-text.ts +50 -0
- package/bin/submit-check-xml.ts +1 -1
- package/dist/auth-turn/index.d.ts +4 -4
- package/dist/auth-turn/index.js +1 -1
- package/dist/auth.d.ts +16 -2
- package/dist/auth.js +76 -18
- package/dist/ceremonies/index.d.ts +9 -1
- package/dist/ceremonies/index.js +117 -29
- package/dist/cli/commands.d.ts +1 -1
- package/dist/cli/commands.js +8 -0
- package/dist/cli/create.d.ts +3 -0
- package/dist/cli/create.js +34 -35
- package/dist/cli/prompt-assets.d.ts +80 -0
- package/dist/cli/prompt-assets.js +743 -0
- package/dist/cli/templates/provider/AGENTS.md.tpl +17 -8
- package/dist/cli/templates/provider/README.md.tpl +4 -4
- package/dist/config/loader.d.ts +176 -17
- package/dist/config/loader.js +434 -161
- package/dist/contract-serialization.d.ts +2 -2
- package/dist/contract-serialization.js +7 -14
- package/dist/contract-types.d.ts +3 -2
- package/dist/contract.d.ts +3 -3
- package/dist/contract.js +6 -6
- package/dist/declaration-validation.d.ts +23 -0
- package/dist/declaration-validation.js +159 -0
- package/dist/define.d.ts +13 -1
- package/dist/define.js +391 -122
- package/dist/dev.d.ts +1 -1
- package/dist/dev.js +1 -1
- package/dist/error-resolution.d.ts +4 -0
- package/dist/error-resolution.js +123 -0
- package/dist/errors.d.ts +19 -1
- package/dist/errors.js +41 -3
- package/dist/fixture-sanitization.d.ts +26 -0
- package/dist/fixture-sanitization.js +216 -0
- package/dist/i18n/catalog.d.ts +2 -2
- package/dist/i18n/catalog.js +4 -10
- package/dist/i18n/index.d.ts +2 -2
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/keys.d.ts +2 -2
- package/dist/index.d.ts +50 -42
- package/dist/index.js +41 -37
- package/dist/lint.d.ts +6 -1
- package/dist/lint.js +370 -18
- package/dist/native-address.d.ts +43 -0
- package/dist/native-address.js +281 -0
- package/dist/native-egress-policy.d.ts +31 -0
- package/dist/native-egress-policy.js +288 -0
- package/dist/observability.d.ts +5 -2
- package/dist/observability.js +48 -1
- package/dist/provider.d.ts +13 -11
- package/dist/provider.js +10 -9
- package/dist/public-schema-field-lint.d.ts +1 -1
- package/dist/recipes/gov-api.js +1 -1
- package/dist/runtime/auth-flow.d.ts +3 -1
- package/dist/runtime/auth-flow.js +8 -3
- package/dist/runtime/browser.d.ts +1 -1
- package/dist/runtime/browser.js +138 -40
- package/dist/runtime/cache.d.ts +2 -1
- package/dist/runtime/cache.js +173 -23
- package/dist/runtime/choice-wordlist.d.ts +9 -0
- package/dist/runtime/choice-wordlist.js +138 -0
- package/dist/runtime/choice.d.ts +14 -1
- package/dist/runtime/choice.js +566 -101
- package/dist/runtime/credential.d.ts +1 -1
- package/dist/runtime/credential.js +1 -1
- package/dist/runtime/env.d.ts +1 -1
- package/dist/runtime/executor.d.ts +1 -1
- package/dist/runtime/executor.js +25 -3
- package/dist/runtime/http.d.ts +3 -2
- package/dist/runtime/http.js +517 -55
- package/dist/runtime/insights.d.ts +1 -1
- package/dist/runtime/insights.js +6 -13
- package/dist/runtime/instrumentation.d.ts +2 -2
- package/dist/runtime/instrumentation.js +371 -23
- package/dist/runtime/keyring.js +1 -1
- package/dist/runtime/namespace.js +1 -1
- package/dist/runtime/native-network-errors.d.ts +33 -0
- package/dist/runtime/native-network-errors.js +69 -0
- package/dist/runtime/native-network.d.ts +96 -0
- package/dist/runtime/native-network.js +1232 -0
- package/dist/runtime/ocr.d.ts +29 -0
- package/dist/runtime/ocr.js +440 -0
- package/dist/runtime/otlp.d.ts +1 -1
- package/dist/runtime/perf.d.ts +1 -1
- package/dist/runtime/provider.d.ts +1 -1
- package/dist/runtime/provider.js +1 -2
- package/dist/runtime/proxy-errors.d.ts +1 -1
- package/dist/runtime/proxy-errors.js +9 -7
- package/dist/runtime/proxy-nodemaven.d.ts +56 -0
- package/dist/runtime/proxy-nodemaven.js +146 -0
- package/dist/runtime/proxy-retry-policy.d.ts +2 -2
- package/dist/runtime/proxy-retry-policy.js +2 -2
- package/dist/runtime/proxy-telemetry.d.ts +2 -1
- package/dist/runtime/proxy-telemetry.js +58 -52
- package/dist/runtime/redirects.d.ts +29 -0
- package/dist/runtime/redirects.js +36 -0
- package/dist/runtime/redis.d.ts +1 -1
- package/dist/runtime/redis.js +5 -5
- package/dist/runtime/request-options.d.ts +68 -1
- package/dist/runtime/request-options.js +548 -0
- package/dist/runtime/resolver-config.d.ts +6 -0
- package/dist/runtime/resolver-config.js +6 -0
- package/dist/runtime/resolver-public.d.ts +1 -0
- package/dist/runtime/resolver-public.js +1 -0
- package/dist/runtime/resolver-shared.d.ts +3 -0
- package/dist/runtime/resolver-shared.js +12 -0
- package/dist/runtime/resolver-vendors/bindings.d.ts +48 -0
- package/dist/runtime/resolver-vendors/bindings.js +40 -0
- package/dist/runtime/resolver-vendors/browser.d.ts +20 -0
- package/dist/runtime/resolver-vendors/browser.js +282 -0
- package/dist/runtime/resolver-vendors/hosts.d.ts +2 -0
- package/dist/runtime/resolver-vendors/hosts.js +33 -0
- package/dist/runtime/resolver-vendors/twocaptcha.d.ts +24 -0
- package/dist/runtime/resolver-vendors/twocaptcha.js +368 -0
- package/dist/runtime/resolver-vendors/types.d.ts +83 -0
- package/dist/runtime/resolver-vendors/types.js +69 -0
- package/dist/runtime/resolver.d.ts +59 -0
- package/dist/runtime/resolver.js +705 -0
- package/dist/runtime/secrets.d.ts +27 -0
- package/dist/runtime/secrets.js +51 -0
- package/dist/runtime/state.d.ts +5 -2
- package/dist/runtime/state.js +280 -74
- package/dist/runtime/stealth-cookies.d.ts +20 -0
- package/dist/runtime/stealth-cookies.js +111 -0
- package/dist/runtime/stealth.d.ts +30 -5
- package/dist/runtime/stealth.js +523 -259
- package/dist/runtime/stt.d.ts +1 -1
- package/dist/runtime/stt.js +12 -27
- package/dist/runtime/timeout.d.ts +5 -0
- package/dist/runtime/timeout.js +12 -0
- package/dist/runtime/trace.d.ts +2 -2
- package/dist/runtime/trace.js +2 -4
- package/dist/runtime/waterfall.d.ts +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +7 -15
- package/dist/serve.d.ts +1 -1
- package/dist/serve.js +1 -1
- package/dist/server/index.d.ts +7 -7
- package/dist/server/index.js +6 -6
- package/dist/server/self-test-input-tokens.d.ts +2 -1
- package/dist/server/self-test-input-tokens.js +18 -14
- package/dist/server/self-test-redaction.d.ts +1 -1
- package/dist/server/self-test-redaction.js +1 -1
- package/dist/server/self-test.d.ts +117 -3
- package/dist/server/self-test.js +787 -151
- package/dist/server/serve-implementation.d.ts +210 -0
- package/dist/server/serve-implementation.js +2078 -0
- package/dist/server/serve.d.ts +1 -70
- package/dist/server/serve.js +1 -1143
- package/dist/server/types.d.ts +34 -9
- package/dist/server/types.js +8 -1
- package/dist/stateful/errors.d.ts +19 -0
- package/dist/stateful/errors.js +24 -0
- package/dist/stateful/http-provider-event-emitter.d.ts +40 -0
- package/dist/stateful/http-provider-event-emitter.js +237 -0
- package/dist/stateful/http-session-owner-registry.d.ts +44 -0
- package/dist/stateful/http-session-owner-registry.js +210 -0
- package/dist/stateful/index.d.ts +18 -0
- package/dist/stateful/index.js +18 -0
- package/dist/stateful/provider-event-delivery-failures.d.ts +32 -0
- package/dist/stateful/provider-event-delivery-failures.js +43 -0
- package/dist/stateful/provider-event-pipeline-metrics.d.ts +46 -0
- package/dist/stateful/provider-event-pipeline-metrics.js +48 -0
- package/dist/stateful/provider-event-pipeline.d.ts +50 -0
- package/dist/stateful/provider-event-pipeline.js +1 -0
- package/dist/stateful/provider-events.d.ts +101 -0
- package/dist/stateful/provider-events.js +289 -0
- package/dist/stateful/session-key.d.ts +15 -0
- package/dist/stateful/session-key.js +86 -0
- package/dist/stateful/stateful-provider-adapter-context.d.ts +5 -0
- package/dist/stateful/stateful-provider-adapter-context.js +42 -0
- package/dist/stateful/stateful-provider-adapter-metrics.d.ts +15 -0
- package/dist/stateful/stateful-provider-adapter-metrics.js +21 -0
- package/dist/stateful/stateful-provider-adapter.d.ts +98 -0
- package/dist/stateful/stateful-provider-adapter.js +287 -0
- package/dist/stateful/stateful-provider-observability.d.ts +62 -0
- package/dist/stateful/stateful-provider-observability.js +161 -0
- package/dist/stateful/stateful-provider-owner-forwarder.d.ts +41 -0
- package/dist/stateful/stateful-provider-owner-forwarder.js +215 -0
- package/dist/stateful/stateful-provider-runtime-context.d.ts +32 -0
- package/dist/stateful/stateful-provider-runtime-context.js +60 -0
- package/dist/stateful/stateful-provider-runtime-executor.d.ts +34 -0
- package/dist/stateful/stateful-provider-runtime-executor.js +52 -0
- package/dist/stateful/stateful-provider-session-routing.d.ts +67 -0
- package/dist/stateful/stateful-provider-session-routing.js +345 -0
- package/dist/stateful/stateful-provider-session-runtime.d.ts +98 -0
- package/dist/stateful/stateful-provider-session-runtime.js +245 -0
- package/dist/stateful-signing.d.ts +18 -0
- package/dist/stateful-signing.js +27 -0
- package/dist/stealth/profiles.d.ts +1 -1
- package/dist/stealth/profiles.js +21 -21
- package/dist/stream-evidence.d.ts +74 -0
- package/dist/stream-evidence.js +785 -0
- package/dist/stream.d.ts +1 -1
- package/dist/stream.js +7 -1
- package/dist/testing/index.d.ts +3 -2
- package/dist/testing/index.js +3 -2
- package/dist/testing/run.d.ts +32 -2
- package/dist/testing/run.js +488 -28
- package/dist/types.d.ts +566 -19
- package/dist/types.js +1 -0
- package/dist/user-input.d.ts +30 -0
- package/dist/user-input.js +66 -0
- package/package.json +42 -7
- package/src/auth-turn/index.ts +2 -2
- package/src/auth.ts +146 -86
- package/src/ceremonies/index.ts +167 -92
- package/src/cli/commands.ts +10 -0
- package/src/cli/create.ts +42 -35
- package/src/cli/prompt-assets.ts +865 -0
- package/src/cli/templates/provider/AGENTS.md.tpl +17 -8
- package/src/cli/templates/provider/README.md.tpl +4 -4
- package/src/config/loader.ts +667 -289
- package/src/contract-serialization.ts +10 -18
- package/src/contract-types.ts +3 -2
- package/src/contract.ts +14 -28
- package/src/declaration-validation.ts +202 -0
- package/src/define.ts +631 -495
- package/src/dev.ts +4 -9
- package/src/error-resolution.ts +128 -0
- package/src/errors.ts +56 -11
- package/src/fixture-sanitization.ts +247 -0
- package/src/i18n/catalog.ts +10 -32
- package/src/i18n/index.ts +2 -2
- package/src/i18n/keys.ts +5 -11
- package/src/index.ts +158 -44
- package/src/lint.ts +488 -154
- package/src/native-address.ts +340 -0
- package/src/native-egress-policy.ts +358 -0
- package/src/observability.ts +51 -1
- package/src/provider.ts +66 -11
- package/src/public-schema-field-lint.ts +7 -33
- package/src/recipes/gov-api.ts +2 -5
- package/src/runtime/auth-flow.ts +13 -7
- package/src/runtime/browser.ts +252 -207
- package/src/runtime/cache.ts +209 -81
- package/src/runtime/choice-wordlist.ts +145 -0
- package/src/runtime/choice.ts +758 -197
- package/src/runtime/credential.ts +2 -2
- package/src/runtime/env.ts +1 -1
- package/src/runtime/executor.ts +37 -19
- package/src/runtime/http.ts +645 -65
- package/src/runtime/insights.ts +15 -53
- package/src/runtime/instrumentation.ts +530 -67
- package/src/runtime/keyring.ts +7 -19
- package/src/runtime/namespace.ts +2 -7
- package/src/runtime/native-network-errors.ts +99 -0
- package/src/runtime/native-network.ts +1605 -0
- package/src/runtime/ocr.ts +523 -0
- package/src/runtime/otlp.ts +12 -23
- package/src/runtime/perf.ts +1 -1
- package/src/runtime/provider.ts +4 -9
- package/src/runtime/proxy-errors.ts +29 -42
- package/src/runtime/proxy-nodemaven.ts +221 -0
- package/src/runtime/proxy-retry-policy.ts +3 -3
- package/src/runtime/proxy-telemetry.ts +84 -77
- package/src/runtime/redirects.ts +66 -0
- package/src/runtime/redis.ts +10 -13
- package/src/runtime/request-options.ts +679 -9
- package/src/runtime/resolver-config.ts +6 -0
- package/src/runtime/resolver-public.ts +18 -0
- package/src/runtime/resolver-shared.ts +17 -0
- package/src/runtime/resolver-vendors/bindings.ts +56 -0
- package/src/runtime/resolver-vendors/browser.ts +408 -0
- package/src/runtime/resolver-vendors/hosts.ts +38 -0
- package/src/runtime/resolver-vendors/twocaptcha.ts +500 -0
- package/src/runtime/resolver-vendors/types.ts +173 -0
- package/src/runtime/resolver.ts +1060 -0
- package/src/runtime/secrets.ts +64 -0
- package/src/runtime/state.ts +399 -161
- package/src/runtime/stealth-cookies.ts +132 -0
- package/src/runtime/stealth.ts +681 -295
- package/src/runtime/stt.ts +39 -113
- package/src/runtime/timeout.ts +18 -0
- package/src/runtime/trace.ts +14 -44
- package/src/runtime/waterfall.ts +5 -18
- package/src/schema.ts +23 -84
- package/src/serve.ts +6 -1
- package/src/server/index.ts +30 -7
- package/src/server/self-test-input-tokens.ts +29 -14
- package/src/server/self-test-redaction.ts +2 -2
- package/src/server/self-test.ts +1030 -180
- package/src/server/serve-implementation.ts +3062 -0
- package/src/server/serve.ts +1 -1781
- package/src/server/types.ts +12 -13
- package/src/stateful/README.md +146 -0
- package/src/stateful/errors.ts +35 -0
- package/src/stateful/http-provider-event-emitter.ts +314 -0
- package/src/stateful/http-session-owner-registry.ts +306 -0
- package/src/stateful/index.ts +18 -0
- package/src/stateful/provider-event-delivery-failures.ts +80 -0
- package/src/stateful/provider-event-pipeline-metrics.ts +95 -0
- package/src/stateful/provider-event-pipeline.ts +61 -0
- package/src/stateful/provider-events.ts +462 -0
- package/src/stateful/session-key.ts +111 -0
- package/src/stateful/stateful-provider-adapter-context.ts +59 -0
- package/src/stateful/stateful-provider-adapter-metrics.ts +48 -0
- package/src/stateful/stateful-provider-adapter.ts +562 -0
- package/src/stateful/stateful-provider-observability.ts +261 -0
- package/src/stateful/stateful-provider-owner-forwarder.ts +287 -0
- package/src/stateful/stateful-provider-runtime-context.ts +92 -0
- package/src/stateful/stateful-provider-runtime-executor.ts +96 -0
- package/src/stateful/stateful-provider-session-routing.ts +546 -0
- package/src/stateful/stateful-provider-session-runtime.ts +403 -0
- package/src/stateful-signing.ts +46 -0
- package/src/stealth/profiles.ts +27 -33
- package/src/stream-evidence.ts +988 -0
- package/src/stream.ts +16 -20
- package/src/testing/index.ts +11 -2
- package/src/testing/run.ts +668 -74
- package/src/types.ts +665 -35
- package/src/user-input.ts +118 -0
- package/dist/cli/templates/provider/CLAUDE.md.tpl +0 -1
- package/src/cli/templates/provider/CLAUDE.md.tpl +0 -1
- /package/dist/cli/templates/provider/{skills → .agents/skills}/fixtures-and-recording/SKILL.md.tpl +0 -0
- /package/dist/cli/templates/provider/{skills → .agents/skills}/health-checks-and-fail-closed/SKILL.md.tpl +0 -0
- /package/dist/cli/templates/provider/{skills → .agents/skills}/normalization-standards/SKILL.md.tpl +0 -0
- /package/dist/cli/templates/provider/{skills → .agents/skills}/pagination-and-counts/SKILL.md.tpl +0 -0
- /package/dist/cli/templates/provider/{skills → .agents/skills}/upstream-contract-verification/SKILL.md.tpl +0 -0
- /package/dist/cli/templates/provider/{skills → .agents/skills}/upstream-notes/README.md.tpl +0 -0
- /package/src/cli/templates/provider/{skills → .agents/skills}/fixtures-and-recording/SKILL.md.tpl +0 -0
- /package/src/cli/templates/provider/{skills → .agents/skills}/health-checks-and-fail-closed/SKILL.md.tpl +0 -0
- /package/src/cli/templates/provider/{skills → .agents/skills}/normalization-standards/SKILL.md.tpl +0 -0
- /package/src/cli/templates/provider/{skills → .agents/skills}/pagination-and-counts/SKILL.md.tpl +0 -0
- /package/src/cli/templates/provider/{skills → .agents/skills}/upstream-contract-verification/SKILL.md.tpl +0 -0
- /package/src/cli/templates/provider/{skills → .agents/skills}/upstream-notes/README.md.tpl +0 -0
package/dist/runtime/cache.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
|
-
import { providerCacheRedisUrlFromEnv } from "../config/loader";
|
|
3
|
-
import {
|
|
1
|
+
import { createHash, createHmac } from "node:crypto";
|
|
2
|
+
import { providerCacheRedisUrlFromEnv } from "../config/loader.js";
|
|
3
|
+
import { ProviderError } from "../errors.js";
|
|
4
|
+
import { createProviderRedisClient, ensureRedisReady, withRedisTimeout, } from "./redis.js";
|
|
5
|
+
export const APIFUSE__CACHE__KEY_PEPPER_ENV = "APIFUSE__CACHE__KEY_PEPPER";
|
|
4
6
|
const DEFAULT_PREFIX = "apifuse:provider-cache:v1";
|
|
5
7
|
const DEFAULT_MEMORY_MAX_ENTRIES = 1_000;
|
|
6
8
|
const DEFAULT_REDIS_TIMEOUT_MS = 150;
|
|
9
|
+
const SECRET_SCOPED_KEY_MARKER = "[secret-scoped";
|
|
7
10
|
const SECRET_FIELD_NAMES = new Set([
|
|
8
11
|
"authorization",
|
|
9
12
|
"cookie",
|
|
@@ -18,6 +21,7 @@ const SECRET_FIELD_NAMES = new Set([
|
|
|
18
21
|
"refresh_token",
|
|
19
22
|
]);
|
|
20
23
|
const sharedBackends = new Map();
|
|
24
|
+
let warnedAboutUnpepperedSecretKeys = false;
|
|
21
25
|
function backendKey(redisUrl) {
|
|
22
26
|
return redisUrl ?? "memory";
|
|
23
27
|
}
|
|
@@ -55,26 +59,160 @@ function shouldRedactField(name, extra) {
|
|
|
55
59
|
normalized.includes("password") ||
|
|
56
60
|
normalized.includes("secret"));
|
|
57
61
|
}
|
|
58
|
-
function
|
|
62
|
+
function unsupportedSecretValue(path, reason) {
|
|
63
|
+
throw new ProviderError(`Secret cache-key values must be JSON-safe; ${reason} at ${path}.`, {
|
|
64
|
+
code: "CACHE_KEY_SECRET_VALUE_UNSUPPORTED",
|
|
65
|
+
fix: "Convert the secret cache-key selector to JSON-safe primitives, arrays, or plain objects.",
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function assertJsonSafeSecretValue(value, reportedPath, ancestors = new Set()) {
|
|
69
|
+
if (value === undefined)
|
|
70
|
+
return;
|
|
71
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
72
|
+
return;
|
|
73
|
+
if (typeof value === "number") {
|
|
74
|
+
if (!Number.isFinite(value))
|
|
75
|
+
unsupportedSecretValue(reportedPath, "non-finite numbers are unsupported");
|
|
76
|
+
if (Object.is(value, -0))
|
|
77
|
+
unsupportedSecretValue(reportedPath, "negative zero is unsupported");
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (typeof value !== "object") {
|
|
81
|
+
unsupportedSecretValue(reportedPath, `${typeof value} values are unsupported`);
|
|
82
|
+
}
|
|
83
|
+
if (ancestors.has(value))
|
|
84
|
+
unsupportedSecretValue(reportedPath, "cyclic values are unsupported");
|
|
85
|
+
ancestors.add(value);
|
|
86
|
+
try {
|
|
87
|
+
if (Array.isArray(value)) {
|
|
88
|
+
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
89
|
+
unsupportedSecretValue(reportedPath, "symbol-keyed array properties are unsupported");
|
|
90
|
+
}
|
|
91
|
+
const expectedNames = new Set(["length"]);
|
|
92
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
93
|
+
const key = String(index);
|
|
94
|
+
expectedNames.add(key);
|
|
95
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
96
|
+
if (!descriptor)
|
|
97
|
+
unsupportedSecretValue(reportedPath, "sparse arrays are unsupported");
|
|
98
|
+
if (!descriptor.enumerable || !("value" in descriptor)) {
|
|
99
|
+
unsupportedSecretValue(reportedPath, "array accessors are unsupported");
|
|
100
|
+
}
|
|
101
|
+
assertJsonSafeSecretValue(descriptor.value, reportedPath, ancestors);
|
|
102
|
+
}
|
|
103
|
+
if (Object.getOwnPropertyNames(value).some((name) => !expectedNames.has(name))) {
|
|
104
|
+
unsupportedSecretValue(reportedPath, "custom array properties are unsupported");
|
|
105
|
+
}
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const prototype = Object.getPrototypeOf(value);
|
|
109
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
110
|
+
unsupportedSecretValue(reportedPath, "non-plain objects are unsupported");
|
|
111
|
+
}
|
|
112
|
+
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
113
|
+
unsupportedSecretValue(reportedPath, "symbol-keyed properties are unsupported");
|
|
114
|
+
}
|
|
115
|
+
for (const key of Object.getOwnPropertyNames(value)) {
|
|
116
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
117
|
+
if (!descriptor?.enumerable || !("value" in descriptor)) {
|
|
118
|
+
unsupportedSecretValue(reportedPath, "non-enumerable properties and accessors are unsupported");
|
|
119
|
+
}
|
|
120
|
+
assertJsonSafeSecretValue(descriptor.value, reportedPath, ancestors);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
finally {
|
|
124
|
+
ancestors.delete(value);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function containsUndefined(value) {
|
|
128
|
+
if (value === undefined)
|
|
129
|
+
return true;
|
|
130
|
+
if (Array.isArray(value))
|
|
131
|
+
return value.some(containsUndefined);
|
|
132
|
+
if (isRecord(value))
|
|
133
|
+
return Object.values(value).some(containsUndefined);
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
function tagSecretValue(value) {
|
|
137
|
+
if (value === undefined)
|
|
138
|
+
return ["undefined"];
|
|
139
|
+
if (value === null)
|
|
140
|
+
return ["null"];
|
|
141
|
+
if (typeof value === "string")
|
|
142
|
+
return ["string", value];
|
|
143
|
+
if (typeof value === "number")
|
|
144
|
+
return ["number", value];
|
|
145
|
+
if (typeof value === "boolean")
|
|
146
|
+
return ["boolean", value];
|
|
147
|
+
if (Array.isArray(value))
|
|
148
|
+
return ["array", value.map(tagSecretValue)];
|
|
149
|
+
return [
|
|
150
|
+
"object",
|
|
151
|
+
Object.entries(value).map(([key, entry]) => [
|
|
152
|
+
key,
|
|
153
|
+
tagSecretValue(entry),
|
|
154
|
+
]),
|
|
155
|
+
];
|
|
156
|
+
}
|
|
157
|
+
function serializeSecretValue(value) {
|
|
158
|
+
if (!containsUndefined(value))
|
|
159
|
+
return JSON.stringify([value]);
|
|
160
|
+
return `undefined-v1:${JSON.stringify(tagSecretValue(value))}`;
|
|
161
|
+
}
|
|
162
|
+
function warnAboutUnpepperedSecretKey() {
|
|
163
|
+
if (warnedAboutUnpepperedSecretKeys)
|
|
164
|
+
return;
|
|
165
|
+
warnedAboutUnpepperedSecretKeys = true;
|
|
166
|
+
console.warn(JSON.stringify({
|
|
167
|
+
level: "warn",
|
|
168
|
+
event: "provider_cache_secret_key_unpeppered",
|
|
169
|
+
message: `Secret-bearing cache keys are using unkeyed SHA-256 because ${APIFUSE__CACHE__KEY_PEPPER_ENV} is not configured.`,
|
|
170
|
+
}));
|
|
171
|
+
}
|
|
172
|
+
function normalizeKeyPart(value, extra, pepper) {
|
|
59
173
|
if (Array.isArray(value)) {
|
|
60
|
-
|
|
174
|
+
const entries = value.map((entry) => normalizeKeyPart(entry, extra, pepper));
|
|
175
|
+
return {
|
|
176
|
+
value: entries.map((entry) => entry.value),
|
|
177
|
+
secretScoped: entries.some((entry) => entry.secretScoped),
|
|
178
|
+
};
|
|
61
179
|
}
|
|
62
180
|
if (isRecord(value)) {
|
|
63
|
-
const normalized =
|
|
181
|
+
const normalized = Object.create(null);
|
|
182
|
+
let secretScoped = false;
|
|
64
183
|
for (const key of Object.keys(value).sort()) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
184
|
+
const part = shouldRedactField(key, extra)
|
|
185
|
+
? hashSecretValue(value[key], key, extra, pepper)
|
|
186
|
+
: normalizeKeyPart(value[key], extra, pepper);
|
|
187
|
+
normalized[key] = part.value;
|
|
188
|
+
secretScoped ||= part.secretScoped;
|
|
68
189
|
}
|
|
69
|
-
return normalized;
|
|
190
|
+
return { value: normalized, secretScoped };
|
|
70
191
|
}
|
|
71
|
-
return value;
|
|
192
|
+
return { value, secretScoped: false };
|
|
193
|
+
}
|
|
194
|
+
function hashSecretValue(value, fieldName, extra, pepper) {
|
|
195
|
+
assertJsonSafeSecretValue(value, `${fieldName} (inside secret value)`);
|
|
196
|
+
const canonical = serializeSecretValue(normalizeKeyPart(value, extra, pepper).value);
|
|
197
|
+
if (pepper === undefined) {
|
|
198
|
+
warnAboutUnpepperedSecretKey();
|
|
199
|
+
const digest = createHash("sha256").update(canonical).digest("hex");
|
|
200
|
+
return { value: `sha256:${digest}`, secretScoped: true };
|
|
201
|
+
}
|
|
202
|
+
const digest = createHmac("sha256", pepper).update(canonical).digest("hex");
|
|
203
|
+
return { value: `hmac-sha256:${digest}`, secretScoped: true };
|
|
204
|
+
}
|
|
205
|
+
function metadataKeys(events, secretScopedKeys) {
|
|
206
|
+
let secretScopedIndex = 0;
|
|
207
|
+
return Array.from(new Set(events.map((event) => event.key))).map((key) => {
|
|
208
|
+
if (!secretScopedKeys.has(key))
|
|
209
|
+
return key;
|
|
210
|
+
secretScopedIndex += 1;
|
|
211
|
+
return `${SECRET_SCOPED_KEY_MARKER}#${secretScopedIndex}]`;
|
|
212
|
+
});
|
|
72
213
|
}
|
|
73
214
|
function stableHash(value) {
|
|
74
|
-
return createHash("sha256")
|
|
75
|
-
.update(JSON.stringify(value))
|
|
76
|
-
.digest("hex")
|
|
77
|
-
.slice(0, 32);
|
|
215
|
+
return createHash("sha256").update(JSON.stringify(value)).digest("hex").slice(0, 32);
|
|
78
216
|
}
|
|
79
217
|
function jitteredTtlMs(ttlMs, jitterPct) {
|
|
80
218
|
if (!jitterPct || jitterPct <= 0)
|
|
@@ -141,10 +279,13 @@ async function withRedisFallback(operation) {
|
|
|
141
279
|
}
|
|
142
280
|
export function createProviderCache(options) {
|
|
143
281
|
const redisUrl = options.redisUrl ?? providerCacheRedisUrlFromEnv();
|
|
282
|
+
const configuredPepper = process.env[APIFUSE__CACHE__KEY_PEPPER_ENV];
|
|
283
|
+
const pepper = configuredPepper && configuredPepper.length > 0 ? configuredPepper : undefined;
|
|
144
284
|
const backend = getSharedBackend(redisUrl);
|
|
145
285
|
const memoryMaxEntries = Math.max(1, options.memoryMaxEntries ?? DEFAULT_MEMORY_MAX_ENTRIES);
|
|
146
286
|
const now = options.now ?? Date.now;
|
|
147
287
|
const events = [];
|
|
288
|
+
const secretScopedKeys = new Set();
|
|
148
289
|
function record(meta) {
|
|
149
290
|
events.push(meta);
|
|
150
291
|
}
|
|
@@ -269,8 +410,11 @@ export function createProviderCache(options) {
|
|
|
269
410
|
return {
|
|
270
411
|
key(namespace, parts, keyOptions) {
|
|
271
412
|
const extra = new Set((keyOptions?.redactFields ?? []).map((field) => field.toLowerCase()));
|
|
272
|
-
const normalized = normalizeKeyPart(parts, extra);
|
|
273
|
-
|
|
413
|
+
const normalized = normalizeKeyPart(parts, extra, pepper);
|
|
414
|
+
const key = `${DEFAULT_PREFIX}:${options.providerId}:${namespace}:${stableHash(normalized.value)}`;
|
|
415
|
+
if (normalized.secretScoped)
|
|
416
|
+
secretScopedKeys.add(key);
|
|
417
|
+
return key;
|
|
274
418
|
},
|
|
275
419
|
async get(key) {
|
|
276
420
|
const result = await read(key);
|
|
@@ -282,8 +426,7 @@ export function createProviderCache(options) {
|
|
|
282
426
|
async delete(key) {
|
|
283
427
|
backend.memory.delete(key);
|
|
284
428
|
const redis = backend.redis;
|
|
285
|
-
if (!redis ||
|
|
286
|
-
!(await ensureRedisReady(redis, DEFAULT_REDIS_TIMEOUT_MS))) {
|
|
429
|
+
if (!redis || !(await ensureRedisReady(redis, DEFAULT_REDIS_TIMEOUT_MS))) {
|
|
287
430
|
return;
|
|
288
431
|
}
|
|
289
432
|
await withRedisFallback(() => redis.del(key));
|
|
@@ -316,19 +459,25 @@ export function createProviderCache(options) {
|
|
|
316
459
|
return {
|
|
317
460
|
hit: events.some((event) => event.hit),
|
|
318
461
|
stale: events.some((event) => event.stale),
|
|
319
|
-
keys:
|
|
462
|
+
keys: metadataKeys(events, secretScopedKeys),
|
|
320
463
|
source: sourceSummary(events),
|
|
321
464
|
};
|
|
322
465
|
},
|
|
323
466
|
};
|
|
324
467
|
}
|
|
325
468
|
export function createBypassProviderCache(options) {
|
|
469
|
+
const configuredPepper = process.env[APIFUSE__CACHE__KEY_PEPPER_ENV];
|
|
470
|
+
const pepper = configuredPepper && configuredPepper.length > 0 ? configuredPepper : undefined;
|
|
326
471
|
const events = [];
|
|
472
|
+
const secretScopedKeys = new Set();
|
|
327
473
|
return {
|
|
328
474
|
key(namespace, parts, keyOptions) {
|
|
329
475
|
const extra = new Set((keyOptions?.redactFields ?? []).map((field) => field.toLowerCase()));
|
|
330
|
-
const normalized = normalizeKeyPart(parts, extra);
|
|
331
|
-
|
|
476
|
+
const normalized = normalizeKeyPart(parts, extra, pepper);
|
|
477
|
+
const key = `${DEFAULT_PREFIX}:${options.providerId}:${namespace}:${stableHash(normalized.value)}`;
|
|
478
|
+
if (normalized.secretScoped)
|
|
479
|
+
secretScopedKeys.add(key);
|
|
480
|
+
return key;
|
|
332
481
|
},
|
|
333
482
|
async get(_key) {
|
|
334
483
|
return null;
|
|
@@ -356,7 +505,7 @@ export function createBypassProviderCache(options) {
|
|
|
356
505
|
return {
|
|
357
506
|
hit: false,
|
|
358
507
|
stale: false,
|
|
359
|
-
keys:
|
|
508
|
+
keys: metadataKeys(events, secretScopedKeys),
|
|
360
509
|
source: sourceSummary(events),
|
|
361
510
|
};
|
|
362
511
|
},
|
|
@@ -369,4 +518,5 @@ export function resetProviderCacheForTests() {
|
|
|
369
518
|
backend.redis?.disconnect();
|
|
370
519
|
}
|
|
371
520
|
sharedBackends.clear();
|
|
521
|
+
warnedAboutUnpepperedSecretKeys = false;
|
|
372
522
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const CHOICE_WORDLIST_SIZE = 1296;
|
|
2
|
+
export declare const CHOICE_WORD_ENTROPY_BITS: number;
|
|
3
|
+
export declare const STANDARD_CHOICE_WORD_COUNT = 4;
|
|
4
|
+
export declare const HIGH_CHOICE_WORD_COUNT = 5;
|
|
5
|
+
export declare const STANDARD_CHOICE_ENTROPY_BITS: number;
|
|
6
|
+
export declare const HIGH_CHOICE_ENTROPY_BITS: number;
|
|
7
|
+
export declare const EFF_SHORT_WORDLIST_2: readonly string[];
|
|
8
|
+
export declare function choiceWordAt(index: number): string;
|
|
9
|
+
export declare function isChoiceWord(value: string): boolean;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Official EFF Short Wordlist #2, embedded unchanged from:
|
|
3
|
+
* https://www.eff.org/files/2016/09/08/eff_short_wordlist_2_0.txt
|
|
4
|
+
*
|
|
5
|
+
* The source's dice-roll column is intentionally omitted; word order is preserved.
|
|
6
|
+
*/
|
|
7
|
+
const EFF_SHORT_WORDLIST_2_TEXT = `
|
|
8
|
+
aardvark abandoned abbreviate abdomen abhorrence abiding abnormal abrasion absorbing abundant abyss
|
|
9
|
+
academy accountant acetone achiness acid acoustics acquire acrobat actress acuteness aerosol
|
|
10
|
+
aesthetic affidavit afloat afraid aftershave again agency aggressor aghast agitate agnostic
|
|
11
|
+
agonizing agreeing aidless aimlessly ajar alarmclock albatross alchemy alfalfa algae aliens
|
|
12
|
+
alkaline almanac alongside alphabet already also altitude aluminum always amazingly ambulance
|
|
13
|
+
amendment amiable ammunition amnesty amoeba amplifier amuser anagram anchor android anesthesia
|
|
14
|
+
angelfish animal anklet announcer anonymous answer antelope anxiety anyplace aorta apartment apnea
|
|
15
|
+
apostrophe apple apricot aquamarine arachnid arbitrate ardently arena argument aristocrat armchair
|
|
16
|
+
aromatic arrowhead arsonist artichoke asbestos ascend aseptic ashamed asinine asleep asocial
|
|
17
|
+
asparagus astronaut asymmetric atlas atmosphere atom atrocious attic atypical auctioneer auditorium
|
|
18
|
+
augmented auspicious automobile auxiliary avalanche avenue aviator avocado awareness awhile awkward
|
|
19
|
+
awning awoke axially azalea babbling backpack badass bagpipe bakery balancing bamboo banana
|
|
20
|
+
barracuda basket bathrobe bazooka blade blender blimp blouse blurred boatyard bobcat body bogusness
|
|
21
|
+
bohemian boiler bonnet boots borough bossiness bottle bouquet boxlike breath briefcase broom
|
|
22
|
+
brushes bubblegum buckle buddhist buffalo bullfrog bunny busboy buzzard cabin cactus cadillac
|
|
23
|
+
cafeteria cage cahoots cajoling cakewalk calculator camera canister capsule carrot cashew cathedral
|
|
24
|
+
caucasian caviar ceasefire cedar celery cement census ceramics cesspool chalkboard cheesecake
|
|
25
|
+
chimney chlorine chopsticks chrome chute cilantro cinnamon circle cityscape civilian clay clergyman
|
|
26
|
+
clipboard clock clubhouse coathanger cobweb coconut codeword coexistent coffeecake cognitive
|
|
27
|
+
cohabitate collarbone computer confetti copier cornea cosmetics cotton couch coverless coyote
|
|
28
|
+
coziness crawfish crewmember crib croissant crumble crystal cubical cucumber cuddly cufflink
|
|
29
|
+
cuisine culprit cup curry cushion cuticle cybernetic cyclist cylinder cymbal cynicism cypress
|
|
30
|
+
cytoplasm dachshund daffodil dagger dairy dalmatian dandelion dartboard dastardly datebook daughter
|
|
31
|
+
dawn daytime dazzler dealer debris decal dedicate deepness defrost degree dehydrator deliverer
|
|
32
|
+
democrat dentist deodorant depot deranged desktop detergent device dexterity diamond dibs
|
|
33
|
+
dictionary diffuser digit dilated dimple dinnerware dioxide diploma directory dishcloth ditto
|
|
34
|
+
dividers dizziness doctor dodge doll dominoes donut doorstep dorsal double downstairs dozed
|
|
35
|
+
drainpipe dresser driftwood droppings drum dryer dubiously duckling duffel dugout dumpster duplex
|
|
36
|
+
durable dustpan dutiful duvet dwarfism dwelling dwindling dynamite dyslexia eagerness earlobe easel
|
|
37
|
+
eavesdrop ebook eccentric echoless eclipse ecosystem ecstasy edged editor educator eelworm eerie
|
|
38
|
+
effects eggnog egomaniac ejection elastic elbow elderly elephant elfishly eliminator elk elliptical
|
|
39
|
+
elongated elsewhere elusive elves emancipate embroidery emcee emerald emission emoticon emperor
|
|
40
|
+
emulate enactment enchilada endorphin energy enforcer engine enhance enigmatic enjoyably enlarged
|
|
41
|
+
enormous enquirer enrollment ensemble entryway enunciate envoy enzyme epidemic equipment erasable
|
|
42
|
+
ergonomic erratic eruption escalator eskimo esophagus espresso essay estrogen etching eternal
|
|
43
|
+
ethics etiquette eucalyptus eulogy euphemism euthanize evacuation evergreen evidence evolution exam
|
|
44
|
+
excerpt exerciser exfoliate exhale exist exorcist explode exquisite exterior exuberant fabric
|
|
45
|
+
factory faded failsafe falcon family fanfare fasten faucet favorite feasibly february federal
|
|
46
|
+
feedback feigned feline femur fence ferret festival fettuccine feudalist feverish fiberglass
|
|
47
|
+
fictitious fiddle figurine fillet finalist fiscally fixture flashlight fleshiness flight florist
|
|
48
|
+
flypaper foamless focus foggy folksong fondue footpath fossil fountain fox fragment freeway fridge
|
|
49
|
+
frosting fruit fryingpan gadget gainfully gallstone gamekeeper gangway garlic gaslight gathering
|
|
50
|
+
gauntlet gearbox gecko gem generator geographer gerbil gesture getaway geyser ghoulishly gibberish
|
|
51
|
+
giddiness giftshop gigabyte gimmick giraffe giveaway gizmo glasses gleeful glisten glove glucose
|
|
52
|
+
glycerin gnarly gnomish goatskin goggles goldfish gong gooey gorgeous gosling gothic gourmet
|
|
53
|
+
governor grape greyhound grill groundhog grumbling guacamole guerrilla guitar gullible gumdrop
|
|
54
|
+
gurgling gusto gutless gymnast gynecology gyration habitat hacking haggard haiku halogen hamburger
|
|
55
|
+
handgun happiness hardhat hastily hatchling haughty hazelnut headband hedgehog hefty heinously
|
|
56
|
+
helmet hemoglobin henceforth herbs hesitation hexagon hubcap huddling huff hugeness hullabaloo
|
|
57
|
+
human hunter hurricane hushing hyacinth hybrid hydrant hygienist hypnotist ibuprofen icepack icing
|
|
58
|
+
iconic identical idiocy idly igloo ignition iguana illuminate imaging imbecile imitator immigrant
|
|
59
|
+
imprint iodine ionosphere ipad iphone iridescent irksome iron irrigation island isotope issueless
|
|
60
|
+
italicize itemizer itinerary itunes ivory jabbering jackrabbit jaguar jailhouse jalapeno jamboree
|
|
61
|
+
janitor jarring jasmine jaundice jawbreaker jaywalker jazz jealous jeep jelly jeopardize jersey
|
|
62
|
+
jetski jezebel jiffy jigsaw jingling jobholder jockstrap jogging john joinable jokingly journal
|
|
63
|
+
jovial joystick jubilant judiciary juggle juice jujitsu jukebox jumpiness junkyard juror justifying
|
|
64
|
+
juvenile kabob kamikaze kangaroo karate kayak keepsake kennel kerosene ketchup khaki kickstand
|
|
65
|
+
kilogram kimono kingdom kiosk kissing kite kleenex knapsack kneecap knickers koala krypton
|
|
66
|
+
laboratory ladder lakefront lantern laptop laryngitis lasagna latch laundry lavender laxative
|
|
67
|
+
lazybones lecturer leftover leggings leisure lemon length leopard leprechaun lettuce leukemia
|
|
68
|
+
levers lewdness liability library licorice lifeboat lightbulb likewise lilac limousine lint lioness
|
|
69
|
+
lipstick liquid listless litter liverwurst lizard llama luau lubricant lucidity ludicrous luggage
|
|
70
|
+
lukewarm lullaby lumberjack lunchbox luridness luscious luxurious lyrics macaroni maestro magazine
|
|
71
|
+
mahogany maimed majority makeover malformed mammal mango mapmaker marbles massager matchstick
|
|
72
|
+
maverick maximum mayonnaise moaning mobilize moccasin modify moisture molecule momentum monastery
|
|
73
|
+
moonshine mortuary mosquito motorcycle mousetrap movie mower mozzarella muckiness mudflow mugshot
|
|
74
|
+
mule mummy mundane muppet mural mustard mutation myriad myspace myth nail namesake nanosecond
|
|
75
|
+
napkin narrator nastiness natives nautically navigate nearest nebula nectar nefarious negotiator
|
|
76
|
+
neither nemesis neoliberal nephew nervously nest netting neuron nevermore nextdoor nicotine niece
|
|
77
|
+
nimbleness nintendo nirvana nuclear nugget nuisance nullify numbing nuptials nursery nutcracker
|
|
78
|
+
nylon oasis oat obediently obituary object obliterate obnoxious observer obtain obvious occupation
|
|
79
|
+
oceanic octopus ocular office oftentimes oiliness ointment older olympics omissible omnivorous
|
|
80
|
+
oncoming onion onlooker onstage onward onyx oomph opaquely opera opium opossum opponent optical
|
|
81
|
+
opulently oscillator osmosis ostrich otherwise ought outhouse ovation oven owlish oxford oxidize
|
|
82
|
+
oxygen oyster ozone pacemaker padlock pageant pajamas palm pamphlet pantyhose paprika parakeet
|
|
83
|
+
passport patio pauper pavement payphone pebble peculiarly pedometer pegboard pelican penguin peony
|
|
84
|
+
pepperoni peroxide pesticide petroleum pewter pharmacy pheasant phonebook phrasing physician plank
|
|
85
|
+
pledge plotted plug plywood pneumonia podiatrist poetic pogo poison poking policeman poncho popcorn
|
|
86
|
+
porcupine postcard poultry powerboat prairie pretzel princess propeller prune pry pseudo psychopath
|
|
87
|
+
publisher pucker pueblo pulley pumpkin punchbowl puppy purse pushup putt puzzle pyramid python
|
|
88
|
+
quarters quesadilla quilt quote racoon radish ragweed railroad rampantly rancidity rarity raspberry
|
|
89
|
+
ravishing rearrange rebuilt receipt reentry refinery register rehydrate reimburse rejoicing
|
|
90
|
+
rekindle relic remote renovator reopen reporter request rerun reservoir retriever reunion revolver
|
|
91
|
+
rewrite rhapsody rhetoric rhino rhubarb rhyme ribbon riches ridden rigidness rimmed riptide riskily
|
|
92
|
+
ritzy riverboat roamer robe rocket romancer ropelike rotisserie roundtable royal rubber rudderless
|
|
93
|
+
rugby ruined rulebook rummage running rupture rustproof sabotage sacrifice saddlebag saffron
|
|
94
|
+
sainthood saltshaker samurai sandworm sapphire sardine sassy satchel sauna savage saxophone scarf
|
|
95
|
+
scenario schoolbook scientist scooter scrapbook sculpture scythe secretary sedative segregator
|
|
96
|
+
seismology selected semicolon senator septum sequence serpent sesame settler severely shack shelf
|
|
97
|
+
shirt shovel shrimp shuttle shyness siamese sibling siesta silicon simmering singles sisterhood
|
|
98
|
+
sitcom sixfold sizable skateboard skeleton skies skulk skylight slapping sled slingshot sloth
|
|
99
|
+
slumbering smartphone smelliness smitten smokestack smudge snapshot sneezing sniff snowsuit
|
|
100
|
+
snugness speakers sphinx spider splashing sponge sprout spur spyglass squirrel statue steamboat
|
|
101
|
+
stingray stopwatch strawberry student stylus suave subway suction suds suffocate sugar suitcase
|
|
102
|
+
sulphur superstore surfer sushi swan sweatshirt swimwear sword sycamore syllable symphony synagogue
|
|
103
|
+
syringes systemize tablespoon taco tadpole taekwondo tagalong takeout tallness tamale tanned
|
|
104
|
+
tapestry tarantula tastebud tattoo tavern thaw theater thimble thorn throat thumb thwarting tiara
|
|
105
|
+
tidbit tiebreaker tiger timid tinsel tiptoeing tirade tissue tractor tree tripod trousers trucks
|
|
106
|
+
tryout tubeless tuesday tugboat tulip tumbleweed tupperware turtle tusk tutorial tuxedo tweezers
|
|
107
|
+
twins tyrannical ultrasound umbrella umpire unarmored unbuttoned uncle underwear unevenness
|
|
108
|
+
unflavored ungloved unhinge unicycle unjustly unknown unlocking unmarked unnoticed unopened unpaved
|
|
109
|
+
unquenched unroll unscrewing untied unusual unveiled unwrinkled unyielding unzip upbeat upcountry
|
|
110
|
+
update upfront upgrade upholstery upkeep upload uppercut upright upstairs uptown upwind uranium
|
|
111
|
+
urban urchin urethane urgent urologist username usher utensil utility utmost utopia utterance
|
|
112
|
+
vacuum vagrancy valuables vanquished vaporizer varied vaseline vegetable vehicle velcro vendor
|
|
113
|
+
vertebrae vestibule veteran vexingly vicinity videogame viewfinder vigilante village vinegar violin
|
|
114
|
+
viperfish virus visor vitamins vivacious vixen vocalist vogue voicemail volleyball voucher voyage
|
|
115
|
+
vulnerable waffle wagon wakeup walrus wanderer wasp water waving wheat whisper wholesaler wick
|
|
116
|
+
widow wielder wifeless wikipedia wildcat windmill wipeout wired wishbone wizardry wobbliness
|
|
117
|
+
wolverine womb woolworker workbasket wound wrangle wreckage wristwatch wrongdoing xerox xylophone
|
|
118
|
+
yacht yahoo yard yearbook yesterday yiddish yield yo-yo yodel yogurt yuppie zealot zebra zeppelin
|
|
119
|
+
zestfully zigzagged zillion zipping zirconium zodiac zombie zookeeper zucchini
|
|
120
|
+
`;
|
|
121
|
+
export const CHOICE_WORDLIST_SIZE = 1_296;
|
|
122
|
+
export const CHOICE_WORD_ENTROPY_BITS = Math.log2(CHOICE_WORDLIST_SIZE);
|
|
123
|
+
export const STANDARD_CHOICE_WORD_COUNT = 4;
|
|
124
|
+
export const HIGH_CHOICE_WORD_COUNT = 5;
|
|
125
|
+
export const STANDARD_CHOICE_ENTROPY_BITS = STANDARD_CHOICE_WORD_COUNT * CHOICE_WORD_ENTROPY_BITS;
|
|
126
|
+
export const HIGH_CHOICE_ENTROPY_BITS = HIGH_CHOICE_WORD_COUNT * CHOICE_WORD_ENTROPY_BITS;
|
|
127
|
+
export const EFF_SHORT_WORDLIST_2 = Object.freeze(EFF_SHORT_WORDLIST_2_TEXT.trim().split(/\s+/));
|
|
128
|
+
const EFF_SHORT_WORD_SET = new Set(EFF_SHORT_WORDLIST_2);
|
|
129
|
+
export function choiceWordAt(index) {
|
|
130
|
+
const word = EFF_SHORT_WORDLIST_2[index];
|
|
131
|
+
if (word === undefined) {
|
|
132
|
+
throw new RangeError(`Choice word index is out of range: ${index}`);
|
|
133
|
+
}
|
|
134
|
+
return word;
|
|
135
|
+
}
|
|
136
|
+
export function isChoiceWord(value) {
|
|
137
|
+
return EFF_SHORT_WORD_SET.has(value);
|
|
138
|
+
}
|
package/dist/runtime/choice.d.ts
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
|
-
import type { CredentialContext, EnvContext, ProviderChoiceContext, ProviderRequestContext, ProviderRuntimeState } from "../types";
|
|
1
|
+
import type { CredentialContext, EnvContext, ProviderChoiceConsumeMode, ProviderChoiceContext, ProviderRequestContext, ProviderRuntimeState } from "../types.js";
|
|
2
2
|
export declare const PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV = "APIFUSE__PROVIDER_RUNTIME__CHOICE_TOKEN_MASTER_SECRET";
|
|
3
|
+
export declare const PROVIDER_RUNTIME_CHOICE_WORD_ISSUANCE_ENV = "APIFUSE__PROVIDER_RUNTIME__CHOICE_WORD_ISSUANCE";
|
|
4
|
+
export type ProviderChoiceTelemetryEvent = {
|
|
5
|
+
readonly providerId: string;
|
|
6
|
+
readonly purpose: string;
|
|
7
|
+
readonly operation: "parse" | "consume";
|
|
8
|
+
readonly format: "word" | "legacy";
|
|
9
|
+
readonly outcome: "success" | "not-found" | "invalid" | "unsupported" | "error";
|
|
10
|
+
readonly consumeMode: ProviderChoiceConsumeMode;
|
|
11
|
+
readonly consumed: boolean;
|
|
12
|
+
readonly replay: boolean;
|
|
13
|
+
};
|
|
3
14
|
export type CreateProviderChoiceContextOptions = {
|
|
4
15
|
readonly providerId: string;
|
|
5
16
|
readonly env?: EnvContext;
|
|
@@ -8,6 +19,8 @@ export type CreateProviderChoiceContextOptions = {
|
|
|
8
19
|
readonly state?: ProviderRuntimeState;
|
|
9
20
|
readonly masterSecret?: string;
|
|
10
21
|
readonly kid?: string;
|
|
22
|
+
/** Receives allowlisted metadata only; token and payload values are never included. */
|
|
23
|
+
readonly onTelemetry?: (event: ProviderChoiceTelemetryEvent) => void;
|
|
11
24
|
};
|
|
12
25
|
export declare function createProviderChoiceContext(options: CreateProviderChoiceContextOptions): ProviderChoiceContext;
|
|
13
26
|
export declare function createTestProviderChoiceContext(options: Omit<CreateProviderChoiceContextOptions, "masterSecret"> & {
|