@apifuse/provider-sdk 2.2.0-beta.59 → 2.2.0-beta.61

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.
Files changed (124) hide show
  1. package/AUTHORING.md +33 -16
  2. package/CHANGELOG.md +8 -0
  3. package/bin/apifuse-dev.ts +7 -8
  4. package/bin/apifuse-pack-types.ts +22 -0
  5. package/bin/apifuse-perf.ts +45 -10
  6. package/bin/apifuse-record.ts +6 -8
  7. package/bin/apifuse-submit-check.ts +2 -2
  8. package/dist/config/loader.js +13 -12
  9. package/dist/define.d.ts +3 -2
  10. package/dist/define.js +1 -1
  11. package/dist/dev.js +3 -1
  12. package/dist/engine.d.ts +7 -6
  13. package/dist/engine.js +6 -6
  14. package/dist/error-resolution.js +21 -4
  15. package/dist/errors.d.ts +3 -0
  16. package/dist/errors.js +9 -0
  17. package/dist/handle-meta.d.ts +39 -0
  18. package/dist/handle-meta.js +29 -0
  19. package/dist/handle.d.ts +187 -0
  20. package/dist/handle.js +254 -0
  21. package/dist/i18n/catalog.js +21 -1
  22. package/dist/index.d.ts +6 -4
  23. package/dist/index.js +4 -3
  24. package/dist/lint.d.ts +3 -0
  25. package/dist/lint.js +388 -62
  26. package/dist/provider.d.ts +4 -4
  27. package/dist/provider.js +3 -3
  28. package/dist/runtime/browser.js +2 -1
  29. package/dist/runtime/cache.js +3 -2
  30. package/dist/runtime/diagnostic-env-values.d.ts +5 -0
  31. package/dist/runtime/diagnostic-env-values.js +57 -0
  32. package/dist/runtime/diagnostic-env.d.ts +11 -0
  33. package/dist/runtime/diagnostic-env.js +35 -0
  34. package/dist/runtime/diagnostic-redactor.d.ts +49 -0
  35. package/dist/runtime/diagnostic-redactor.js +569 -0
  36. package/dist/runtime/egress-lease.d.ts +2 -0
  37. package/dist/runtime/egress-lease.js +4 -1
  38. package/dist/runtime/env.js +2 -1
  39. package/dist/runtime/handle-wordlist.d.ts +43 -0
  40. package/dist/runtime/{choice-wordlist.js → handle-wordlist.js} +127 -9
  41. package/dist/runtime/handle.d.ts +71 -0
  42. package/dist/runtime/handle.js +895 -0
  43. package/dist/runtime/instrumentation.js +3 -0
  44. package/dist/runtime/native-network.d.ts +10 -1
  45. package/dist/runtime/native-network.js +230 -29
  46. package/dist/runtime/native-telemetry.d.ts +142 -0
  47. package/dist/runtime/native-telemetry.js +231 -0
  48. package/dist/runtime/ocr.js +2 -1
  49. package/dist/runtime/otlp.js +5 -4
  50. package/dist/runtime/proxy-nodemaven.js +3 -2
  51. package/dist/runtime/request-options.d.ts +7 -0
  52. package/dist/runtime/request-options.js +62 -22
  53. package/dist/runtime/resolver-vendors/browser.js +0 -1
  54. package/dist/runtime/resolver.js +3 -2
  55. package/dist/runtime/state.d.ts +4 -1
  56. package/dist/runtime/state.js +32 -17
  57. package/dist/runtime/stt.js +3 -2
  58. package/dist/runtime/trace.d.ts +5 -0
  59. package/dist/runtime/trace.js +115 -20
  60. package/dist/schema.d.ts +11 -0
  61. package/dist/schema.js +56 -2
  62. package/dist/server/index.d.ts +1 -0
  63. package/dist/server/index.js +1 -0
  64. package/dist/server/self-test-redaction.js +8 -33
  65. package/dist/server/sensitive-values.d.ts +26 -0
  66. package/dist/server/sensitive-values.js +128 -0
  67. package/dist/server/serve-implementation.d.ts +4 -11
  68. package/dist/server/serve-implementation.js +305 -96
  69. package/dist/server/trace-output.d.ts +2 -1
  70. package/dist/server/trace-output.js +46 -14
  71. package/dist/testing/run.js +10 -7
  72. package/dist/trace-sanitization.d.ts +4 -3
  73. package/dist/trace-sanitization.js +45 -22
  74. package/dist/types.d.ts +4 -107
  75. package/package.json +2 -1
  76. package/src/config/loader.ts +13 -12
  77. package/src/define.ts +4 -3
  78. package/src/dev.ts +3 -1
  79. package/src/engine.ts +8 -8
  80. package/src/error-resolution.ts +21 -4
  81. package/src/errors.ts +13 -0
  82. package/src/handle-meta.ts +58 -0
  83. package/src/handle.ts +529 -0
  84. package/src/i18n/catalog.ts +23 -1
  85. package/src/index.ts +28 -13
  86. package/src/lint.ts +456 -71
  87. package/src/provider.ts +10 -20
  88. package/src/runtime/browser.ts +2 -1
  89. package/src/runtime/cache.ts +3 -2
  90. package/src/runtime/diagnostic-env-values.ts +56 -0
  91. package/src/runtime/diagnostic-env.ts +55 -0
  92. package/src/runtime/diagnostic-redactor.ts +662 -0
  93. package/src/runtime/egress-lease.ts +6 -1
  94. package/src/runtime/env.ts +2 -1
  95. package/src/runtime/{choice-wordlist.ts → handle-wordlist.ts} +130 -9
  96. package/src/runtime/handle.ts +1162 -0
  97. package/src/runtime/instrumentation.ts +3 -0
  98. package/src/runtime/native-network.ts +281 -33
  99. package/src/runtime/native-telemetry.ts +366 -0
  100. package/src/runtime/ocr.ts +2 -1
  101. package/src/runtime/otlp.ts +5 -4
  102. package/src/runtime/proxy-nodemaven.ts +3 -2
  103. package/src/runtime/request-options.ts +76 -28
  104. package/src/runtime/resolver-vendors/browser.ts +0 -1
  105. package/src/runtime/resolver.ts +3 -2
  106. package/src/runtime/state.ts +44 -16
  107. package/src/runtime/stt.ts +3 -2
  108. package/src/runtime/trace.ts +168 -26
  109. package/src/schema.ts +63 -2
  110. package/src/server/index.ts +17 -0
  111. package/src/server/self-test-redaction.ts +10 -40
  112. package/src/server/sensitive-values.ts +197 -0
  113. package/src/server/serve-implementation.ts +388 -128
  114. package/src/server/trace-output.ts +77 -17
  115. package/src/testing/run.ts +11 -7
  116. package/src/trace-sanitization.ts +70 -23
  117. package/src/types.ts +4 -137
  118. package/dist/choice-token.d.ts +0 -24
  119. package/dist/choice-token.js +0 -74
  120. package/dist/runtime/choice-wordlist.d.ts +0 -9
  121. package/dist/runtime/choice.d.ts +0 -27
  122. package/dist/runtime/choice.js +0 -801
  123. package/src/choice-token.ts +0 -165
  124. package/src/runtime/choice.ts +0 -1197
@@ -1,5 +1,8 @@
1
- import { createHash } from "node:crypto";
1
+ import { NativeTelemetryCollector } from "../runtime/native-telemetry.js";
2
+ import { STATUS_CODES } from "node:http";
3
+ import { readDiagnosticEnv, withDiagnosticEnv } from "../runtime/diagnostic-env.js";
2
4
  import { AsyncLocalStorage } from "node:async_hooks";
5
+ import { createHash } from "node:crypto";
3
6
  import { existsSync } from "node:fs";
4
7
  import { createRequire } from "node:module";
5
8
  import { join } from "node:path";
@@ -7,29 +10,30 @@ import { Hono } from "hono";
7
10
  import { z } from "zod";
8
11
  import { AuthAbortError, createAuthFlowHelpers } from "../auth.js";
9
12
  import { validateFailClosedDeclaration } from "../declaration-validation.js";
10
- import { safeProviderErrorObservability } from "../error-observability.js";
11
13
  import { createInProcessProviderEngine, ENGINE_OWNED_PROXY_CREDENTIAL_ENV_NAMES, isEngineOwnedEnvName, readEngineProxyCredentials, } from "../engine.js";
14
+ import { safeProviderErrorObservability } from "../error-observability.js";
12
15
  import { SDK_OWNED_PROVIDER_ERROR_CODES, SDK_RUNTIME_OWNED_ERROR_CODES, SDK_STATUS_MAPPED_PROVIDER_ERROR_CODES, } from "../error-resolution.js";
13
16
  import { AuthError, isProviderError, isSessionExpiredError, isTransportError, isValidationError, ProviderError, SDKError, } from "../errors.js";
14
17
  import { sanitizeDiagnosticText } from "../fixture-sanitization.js";
15
18
  import { loadProviderLocaleCatalogs, localizeAuthTurn, } from "../i18n/catalog.js";
16
- import { categoryForStatus, sourceForCategory, isRetryableCategory, PROVIDER_OBSERVABILITY_TAXONOMY_VERSION, } from "../observability.js";
19
+ import { categoryForStatus, isRetryableCategory, PROVIDER_OBSERVABILITY_TAXONOMY_VERSION, sourceForCategory, } from "../observability.js";
17
20
  import { createScratchpad } from "../runtime/auth-flow.js";
18
21
  import { createProviderCache } from "../runtime/cache.js";
19
- import { createProviderChoiceContext, PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV, } from "../runtime/choice.js";
22
+ import { createHandleContext } from "../runtime/handle.js";
20
23
  import { createCredentialContext } from "../runtime/credential.js";
24
+ import { bindDiagnosticSensitiveRegistry, compileProcessDiagnosticSensitiveValues, createDiagnosticRedactor, REDACTION_FAILED, isDiagnosticRedactionSuppressed, bindCriticalDiagnosticRedactor, redactCriticalDiagnosticText, redactDiagnosticText, registerDiagnosticSensitiveValues, } from "../runtime/diagnostic-redactor.js";
21
25
  import { createCeremonyEgressLeaseRuntime, ENGINE_CEREMONY_EGRESS_LEASE, } from "../runtime/egress-lease.js";
22
26
  import { createEnvContext } from "../runtime/env.js";
23
27
  import { executeOperation } from "../runtime/executor.js";
24
28
  import { createHttpClient } from "../runtime/http.js";
25
29
  import { wrapWithInstrumentation } from "../runtime/instrumentation.js";
26
- import { getProviderBaseUrl } from "../runtime/provider.js";
27
30
  import { createOcrClientFromEnv } from "../runtime/ocr.js";
31
+ import { getProviderBaseUrl } from "../runtime/provider.js";
28
32
  import { PROXY_AUTH_IP_DENIED_CODE, PROXY_EDGE_AUTH_REJECTED_CODE, PROXY_POOL_EXHAUSTED_CODE, } from "../runtime/proxy-errors.js";
29
33
  import { PROVIDER_TELEMETRY_HEADER, ProxyTelemetryCollector, } from "../runtime/proxy-telemetry.js";
30
34
  import { closedEnum, RequestTelemetry, tenantOpaqueKeys, } from "../runtime/request-telemetry.js";
35
+ import { bindResolverTelemetry, createUnsupportedResolverClient, inheritResolverTelemetryBinding, } from "../runtime/resolver-shared.js";
31
36
  import { ResolverTelemetryCollector, } from "../runtime/resolver-telemetry.js";
32
- import { createUnsupportedResolverClient, bindResolverTelemetry, inheritResolverTelemetryBinding, } from "../runtime/resolver-shared.js";
33
37
  import { assertRequiredSecretsPresent, listMissingRequiredSecrets, MISSING_SECRET_CODE, } from "../runtime/secrets.js";
34
38
  import { createProviderRuntimeStateFromEnv, createUnsupportedProviderRuntimeState, } from "../runtime/state.js";
35
39
  import { StealthCookieJar } from "../runtime/stealth-cookies.js";
@@ -37,13 +41,14 @@ import { createSttClientFromEnv } from "../runtime/stt.js";
37
41
  import { createTraceContext, getTraceRecorder, updateTraceContextExportMetadata, } from "../runtime/trace.js";
38
42
  import { resolveTraceConfigFromEnv } from "../runtime/trace-config.js";
39
43
  import { parseSchema } from "../schema.js";
40
- import { STATEFUL_NONCE_HEADER as STATEFUL_FORWARDING_NONCE_HEADER, STATEFUL_SIGNATURE_HEADER as STATEFUL_FORWARDING_SIGNATURE_HEADER, STATEFUL_TIMESTAMP_HEADER as STATEFUL_FORWARDING_TIMESTAMP_HEADER, verifyStatefulRequestSignature, } from "../stateful-signing.js";
41
44
  import { StatefulRoutingDeadlineError } from "../stateful/errors.js";
45
+ import { STATEFUL_NONCE_HEADER as STATEFUL_FORWARDING_NONCE_HEADER, STATEFUL_SIGNATURE_HEADER as STATEFUL_FORWARDING_SIGNATURE_HEADER, STATEFUL_TIMESTAMP_HEADER as STATEFUL_FORWARDING_TIMESTAMP_HEADER, verifyStatefulRequestSignature, } from "../stateful-signing.js";
42
46
  import { getStealthProfile } from "../stealth/profiles.js";
43
- import { sanitizeTraceAttributes } from "../trace-sanitization.js";
44
47
  import { APIFUSE_STREAM_DONE_EVENT, APIFUSE_STREAM_ERROR_EVENT, encodeSseEvent, error as streamError, } from "../stream.js";
48
+ import { sanitizeSpanNameForOutput, sanitizeTraceAttributes } from "../trace-sanitization.js";
45
49
  import { VALID_OPERATION_ERROR_STATUSES } from "../types.js";
46
50
  import { resolveSelfTestMasterSecrets } from "./self-test-token.js";
51
+ import { collectStaticDiagnosticSensitiveValues, createDiagnosticEnvObserver, } from "./sensitive-values.js";
47
52
  import { resolveServerTraceContextOptions } from "./trace-output.js";
48
53
  import { AuthFlowRequestSchema, OperationConnectionSchema, OperationRequestSchema, } from "./types.js";
49
54
  const DEFAULT_HOST = "0.0.0.0";
@@ -520,11 +525,8 @@ function createProviderContext(provider, request, operationId, options, state =
520
525
  }
521
526
  : {}),
522
527
  };
523
- const logStealthCleanupError = (error) => logProviderCleanupError(options.logger, provider, "operation", operationId, request.requestId, "stealth", error);
524
- const env = createEnvContext([
525
- ...providerSecretNames(provider),
526
- PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV,
527
- ]);
528
+ const logStealthCleanupError = (error) => logProviderCleanupError(options.logger, provider, "operation", operationId, request.requestId, "stealth", error, scope.redact);
529
+ const env = createEnvContext([...providerSecretNames(provider)]);
528
530
  const credential = createCredentialContext({
529
531
  allowedKeys: provider.credential?.keys,
530
532
  mode: request.connection?.mode,
@@ -560,7 +562,7 @@ function createProviderContext(provider, request, operationId, options, state =
560
562
  browser: provider.runtime === "browser"
561
563
  ? capabilityModules.browser.createBrowserClient({
562
564
  allowedHosts: provider.allowedHosts,
563
- cdpUrl: process.env.APIFUSE__CDP_POOL__URL,
565
+ cdpUrl: readDiagnosticEnv("APIFUSE__CDP_POOL__URL"),
564
566
  headless: true,
565
567
  requireCdpPool: isProductionProviderBrowserMode(provider),
566
568
  stealth: true,
@@ -571,6 +573,8 @@ function createProviderContext(provider, request, operationId, options, state =
571
573
  ? {
572
574
  native: {
573
575
  network: capabilityModules.nativeNetwork.createNativeNetworkClient({
576
+ telemetry: scope.telemetry.proxy,
577
+ nativeTelemetry: scope.nativeTelemetry,
574
578
  egress: provider.native.network,
575
579
  proxyPolicy: resolveNativeProxyPolicy(provider),
576
580
  affinityKey: proxyClientOptions.affinityKey,
@@ -592,15 +596,13 @@ function createProviderContext(provider, request, operationId, options, state =
592
596
  ? bindResolverTelemetry(options.resolver, resolverOptions.telemetry)
593
597
  : undefined) ??
594
598
  createUnsupportedResolverClient("Provider does not declare resolver capability"), signal),
595
- choice: createProviderChoiceContext({
599
+ handle: createHandleContext({
596
600
  providerId: provider.id,
597
- env,
598
601
  request: requestContext,
599
- credential,
600
602
  state: requestState,
601
603
  onTelemetry: (event) => (options.logger ?? defaultProviderServerLogger)({
602
604
  level: "info",
603
- event: "provider_choice_token",
605
+ event: "provider_handle",
604
606
  ...event,
605
607
  }),
606
608
  }),
@@ -668,6 +670,7 @@ function createAuthFlowContext(provider, request, route, options, state, scope,
668
670
  providerId: provider.id,
669
671
  flowId: request.flowId,
670
672
  affinityKey: proxyClientOptions.affinityKey,
673
+ onHandle: (handle) => registerDiagnosticSensitiveValues(scope.trace, [handle]),
671
674
  ...(request.engine?.egressLease ? { handle: request.engine.egressLease } : {}),
672
675
  })
673
676
  : undefined;
@@ -697,7 +700,7 @@ function createAuthFlowContext(provider, request, route, options, state, scope,
697
700
  }
698
701
  : {}),
699
702
  };
700
- const logStealthCleanupError = (error) => logProviderCleanupError(options.logger, provider, "auth", "flow", request.requestId, "stealth", error);
703
+ const logStealthCleanupError = (error) => logProviderCleanupError(options.logger, provider, "auth", "flow", request.requestId, "stealth", error, scope.redact);
701
704
  const credential = request.connection
702
705
  ? createCredentialContext({
703
706
  allowedKeys: provider.credential?.keys,
@@ -727,6 +730,8 @@ function createAuthFlowContext(provider, request, route, options, state, scope,
727
730
  ? {
728
731
  native: {
729
732
  network: capabilityModules.nativeNetwork.createNativeNetworkClient({
733
+ telemetry: scope.telemetry.proxy,
734
+ nativeTelemetry: scope.nativeTelemetry,
730
735
  egress: provider.native.network,
731
736
  proxyPolicy: resolveNativeProxyPolicy(provider),
732
737
  affinityKey: proxyClientOptions.affinityKey,
@@ -786,11 +791,11 @@ function finishRequestCost(input) {
786
791
  cpuTotalMicros: Math.max(0, cpuDelta.user + cpuDelta.system),
787
792
  };
788
793
  }
789
- function zodDetails(error) {
794
+ function zodDetails(error, redact) {
790
795
  return error.issues.map((issue) => ({
791
- path: issue.path.join("."),
792
- code: issue.code,
793
- message: issue.message,
796
+ path: sanitizeSpanNameForOutput(issue.path.join("."), redact),
797
+ code: sanitizeSpanNameForOutput(issue.code, redact),
798
+ message: sanitizeSpanNameForOutput(issue.message, redact),
794
799
  }));
795
800
  }
796
801
  // Category-level projection with code-aware honesty overrides: a missing
@@ -813,7 +818,7 @@ function publicErrorSource(error, category) {
813
818
  }
814
819
  return sourceForCategory(category);
815
820
  }
816
- function toErrorResponse(error, requestId, observabilityDetails) {
821
+ function toErrorResponse(error, requestId, observabilityDetails, redact) {
817
822
  const observability = observabilityDetails;
818
823
  const source = publicErrorSource(error, observability.category);
819
824
  if (error instanceof StatefulRoutingDeadlineError) {
@@ -849,7 +854,7 @@ function toErrorResponse(error, requestId, observabilityDetails) {
849
854
  ...(requestId ? { requestId } : {}),
850
855
  retryable: observability.retryable,
851
856
  source,
852
- details: zodDetails(error),
857
+ details: zodDetails(error, redact),
853
858
  },
854
859
  };
855
860
  }
@@ -879,6 +884,52 @@ function toErrorResponse(error, requestId, observabilityDetails) {
879
884
  // narrowing from a ProviderError-typed value would collapse the negative branch
880
885
  // to `never`. Narrowing from unknown avoids that while still recognizing errors
881
886
  // from a duplicate SDK module instance.
887
+ function ownErrorCode(error) {
888
+ if (error === null || (typeof error !== "object" && typeof error !== "function")) {
889
+ return undefined;
890
+ }
891
+ try {
892
+ const descriptor = Object.getOwnPropertyDescriptor(error, "code");
893
+ return descriptor && Object.hasOwn(descriptor, "value") && typeof descriptor.value === "string"
894
+ ? descriptor.value
895
+ : undefined;
896
+ }
897
+ catch {
898
+ return undefined;
899
+ }
900
+ }
901
+ function errorChainHasCode(error, expected) {
902
+ const seen = new Set();
903
+ let current = error;
904
+ for (let depth = 0; depth < 5; depth++) {
905
+ if (current === null || (typeof current !== "object" && typeof current !== "function")) {
906
+ return false;
907
+ }
908
+ if (seen.has(current))
909
+ return false;
910
+ seen.add(current);
911
+ let code;
912
+ try {
913
+ code = providerErrorCode(current) ?? ownErrorCode(current);
914
+ }
915
+ catch {
916
+ code = ownErrorCode(current);
917
+ }
918
+ if (code === expected)
919
+ return true;
920
+ let cause;
921
+ try {
922
+ cause = Object.getOwnPropertyDescriptor(current, "cause");
923
+ }
924
+ catch {
925
+ return false;
926
+ }
927
+ if (!cause || !Object.hasOwn(cause, "value"))
928
+ return false;
929
+ current = cause.value;
930
+ }
931
+ return false;
932
+ }
882
933
  function providerObservabilityDetails(error, declaredErrorCode) {
883
934
  const declaredRetryable = sdkOwnsErrorResolution(error)
884
935
  ? undefined
@@ -904,24 +955,43 @@ function providerObservabilityDetails(error, declaredErrorCode) {
904
955
  retryable: providerErrorOption(error, "retryable") ?? declaredRetryable ?? false,
905
956
  };
906
957
  }
958
+ // Native proxy resolution throws ProxyResolutionError directly, while HTTP
959
+ // normalizes it beneath a transport_network_error cause and stealth retains
960
+ // the original code. Preserve proxy attribution across all three forms.
961
+ if (errorChainHasCode(error, "PROXY_REQUIRED")) {
962
+ return {
963
+ category: "proxy_pool",
964
+ taxonomyVersion: PROVIDER_OBSERVABILITY_TAXONOMY_VERSION,
965
+ retryable: true,
966
+ };
967
+ }
907
968
  if (!isTransportError(error)) {
908
969
  return undefined;
909
970
  }
910
- const isProxyPoolCode = providerErrorCode(error) === PROXY_POOL_EXHAUSTED_CODE ||
911
- providerErrorCode(error) === PROXY_EDGE_AUTH_REJECTED_CODE ||
912
- providerErrorCode(error) === "PROXY_ALLOCATION_FAILED";
971
+ const errorCode = providerErrorCode(error);
972
+ const isProxyPoolCode = errorCode === PROXY_POOL_EXHAUSTED_CODE ||
973
+ errorCode === PROXY_EDGE_AUTH_REJECTED_CODE ||
974
+ errorCode === "PROXY_ALLOCATION_FAILED" ||
975
+ errorCode === "native_proxy_expired" ||
976
+ errorCode === "native_proxy_invalid";
913
977
  const category = providerErrorOption(error, "category") ??
914
978
  (isProxyPoolCode
915
979
  ? "proxy_pool"
916
- : providerErrorCode(error) === PROXY_AUTH_IP_DENIED_CODE
980
+ : errorCode === PROXY_AUTH_IP_DENIED_CODE
917
981
  ? "anti_bot_blocked"
918
- : providerErrorCode(error) === "transport_timeout"
982
+ : errorCode === "transport_timeout" ||
983
+ errorCode === "native_connection_timeout" ||
984
+ errorCode === "native_connection_idle_timeout"
919
985
  ? "timeout"
920
- : providerErrorCode(error) === "transport_network_error"
986
+ : errorCode === "transport_network_error" ||
987
+ errorCode === "native_connection_failed" ||
988
+ errorCode === "native_connection_closed"
921
989
  ? "network"
922
- : error.upstreamStatus
923
- ? categoryForStatus(error.upstreamStatus)
924
- : "upstream_http");
990
+ : errorCode === "native_connection_aborted"
991
+ ? "client_cancelled"
992
+ : error.upstreamStatus
993
+ ? categoryForStatus(error.upstreamStatus)
994
+ : "upstream_http");
925
995
  return {
926
996
  category,
927
997
  taxonomyVersion: PROVIDER_OBSERVABILITY_TAXONOMY_VERSION,
@@ -1097,13 +1167,13 @@ function extractRequestId(raw) {
1097
1167
  }
1098
1168
  const MAX_PROVIDER_ERROR_CAUSE_FRAMES = 5;
1099
1169
  const MAX_PROVIDER_ERROR_CAUSE_MESSAGE_LENGTH = 300;
1100
- function providerErrorCauseMessage(message) {
1101
- const sanitized = sanitizeDiagnosticText(message);
1170
+ function providerErrorCauseMessage(message, redact) {
1171
+ const sanitized = sanitizeDiagnosticText(redactDiagnosticText(message, redact));
1102
1172
  return sanitized.length > MAX_PROVIDER_ERROR_CAUSE_MESSAGE_LENGTH
1103
1173
  ? `${sanitized.slice(0, MAX_PROVIDER_ERROR_CAUSE_MESSAGE_LENGTH)}… [truncated]`
1104
1174
  : sanitized;
1105
1175
  }
1106
- function providerErrorCauseChain(error) {
1176
+ function providerErrorCauseChain(error, redact) {
1107
1177
  if (!(error instanceof Error) && !isProviderError(error))
1108
1178
  return undefined;
1109
1179
  const seen = new Set([error]);
@@ -1117,9 +1187,9 @@ function providerErrorCauseChain(error) {
1117
1187
  const providerObservability = safeProviderErrorObservability(cause);
1118
1188
  const causeCode = providerErrorCode(cause);
1119
1189
  frames.push({
1120
- errorClass: cause.name,
1121
- ...(causeCode !== undefined ? { code: causeCode } : {}),
1122
- message: providerErrorCauseMessage(message),
1190
+ errorClass: redactDiagnosticText(cause.name, redact),
1191
+ ...(causeCode !== undefined ? { code: redactDiagnosticText(causeCode, redact) } : {}),
1192
+ message: providerErrorCauseMessage(message, redact),
1123
1193
  messageLength: message.length,
1124
1194
  messageFingerprint: createHash("sha256").update(message).digest("hex").slice(0, 12),
1125
1195
  ...(providerObservability ? { providerObservability } : {}),
@@ -1128,7 +1198,7 @@ function providerErrorCauseChain(error) {
1128
1198
  }
1129
1199
  return frames.length > 0 ? frames : undefined;
1130
1200
  }
1131
- function logProviderError(logger, provider, kind, route, requestId, error, status, cost, declaredErrorCode, telemetry, observabilityDetails, correlation = {}) {
1201
+ function logProviderError(logger, provider, kind, route, requestId, error, status, cost, declaredErrorCode, telemetry, observabilityDetails, correlation = {}, redact) {
1132
1202
  const providerCode = isProviderError(error) ? providerErrorCode(error) : undefined;
1133
1203
  const code = isProviderError(error)
1134
1204
  ? (providerCode ?? "provider_error")
@@ -1139,7 +1209,7 @@ function logProviderError(logger, provider, kind, route, requestId, error, statu
1139
1209
  : "internal_error";
1140
1210
  const errorClass = error instanceof Error ? error.name : typeof error;
1141
1211
  const message = error instanceof Error ? error.message : String(error);
1142
- const causeChain = providerErrorCauseChain(error);
1212
+ const causeChain = providerErrorCauseChain(error, redact);
1143
1213
  const details = observabilityDetails;
1144
1214
  const isUnregisteredProviderErrorCode = status === 500 &&
1145
1215
  isProviderError(error) &&
@@ -1158,24 +1228,28 @@ function logProviderError(logger, provider, kind, route, requestId, error, statu
1158
1228
  emit({
1159
1229
  level: status >= 500 ? "error" : "warn",
1160
1230
  event: "provider_request_failed",
1161
- providerId: provider.id,
1231
+ providerId: redactDiagnosticText(provider.id, redact),
1162
1232
  kind,
1163
- route,
1164
- ...(requestId ? { requestId } : {}),
1233
+ route: redactCriticalDiagnosticText(route, redact),
1234
+ ...(requestId ? { requestId: redactCriticalDiagnosticText(requestId, redact) } : {}),
1165
1235
  ...(correlation.connectionId !== undefined
1166
- ? { connectionId: correlation.connectionId }
1236
+ ? { connectionId: redactDiagnosticText(correlation.connectionId, redact) }
1237
+ : {}),
1238
+ ...(correlation.flowId !== undefined
1239
+ ? { flowId: redactDiagnosticText(correlation.flowId, redact) }
1240
+ : {}),
1241
+ ...(correlation.tenantId !== undefined
1242
+ ? { tenantId: redactDiagnosticText(correlation.tenantId, redact) }
1167
1243
  : {}),
1168
- ...(correlation.flowId !== undefined ? { flowId: correlation.flowId } : {}),
1169
- ...(correlation.tenantId !== undefined ? { tenantId: correlation.tenantId } : {}),
1170
1244
  ...(correlation.requestedProviderId !== undefined
1171
- ? { requestedProviderId: correlation.requestedProviderId }
1245
+ ? { requestedProviderId: redactDiagnosticText(correlation.requestedProviderId, redact) }
1172
1246
  : {}),
1173
1247
  status,
1174
1248
  ...cost,
1175
1249
  ...(telemetryPayload ?? {}),
1176
- code,
1177
- errorClass,
1178
- message,
1250
+ code: sanitizeSpanNameForOutput(redactCriticalDiagnosticText(code, redact)),
1251
+ errorClass: redactDiagnosticText(errorClass, redact),
1252
+ message: sanitizeDiagnosticText(redactDiagnosticText(message, redact)),
1179
1253
  ...(causeChain ? { causeChain } : {}),
1180
1254
  ...(providerObservability ? { providerObservability } : {}),
1181
1255
  ...(details.upstreamStatus ? { upstreamStatus: details.upstreamStatus } : {}),
@@ -1188,42 +1262,46 @@ function logProviderError(logger, provider, kind, route, requestId, error, statu
1188
1262
  signalFix: "Declare this code (with status and retryable) in the operation's errorCodes so it serves its intended status instead of 500.",
1189
1263
  }
1190
1264
  : {}),
1191
- ...(error instanceof z.ZodError ? { issues: zodDetails(error) } : {}),
1265
+ ...(error instanceof z.ZodError ? { issues: zodDetails(error, redact) } : {}),
1192
1266
  });
1193
1267
  }
1194
- function logProviderCleanupError(logger, provider, kind, operationId, requestId, resource, error) {
1268
+ function logProviderCleanupError(logger, provider, kind, operationId, requestId, resource, error, redact) {
1195
1269
  const emit = typeof logger === "function" ? logger : defaultProviderServerLogger;
1196
1270
  const errorClass = error instanceof Error ? error.name : typeof error;
1197
1271
  const message = error instanceof Error ? error.message : String(error);
1198
1272
  emit({
1199
1273
  level: "warn",
1200
1274
  event: "provider_cleanup_failed",
1201
- providerId: provider.id,
1275
+ providerId: redactDiagnosticText(provider.id, redact),
1202
1276
  kind,
1203
- route: operationId,
1204
- ...(requestId ? { requestId } : {}),
1277
+ route: redactCriticalDiagnosticText(operationId, redact),
1278
+ ...(requestId ? { requestId: redactCriticalDiagnosticText(requestId, redact) } : {}),
1205
1279
  resource,
1206
- errorClass,
1207
- message,
1280
+ errorClass: redactDiagnosticText(errorClass, redact),
1281
+ message: sanitizeDiagnosticText(redactDiagnosticText(message, redact)),
1208
1282
  });
1209
1283
  }
1210
- function logProviderSuccess(logger, provider, kind, route, requestId, status, cost, telemetry, correlation = {}) {
1284
+ function logProviderSuccess(logger, provider, kind, route, requestId, status, cost, telemetry, correlation = {}, redact) {
1211
1285
  const telemetryPayload = telemetry?.toLogPayload();
1212
1286
  const emit = typeof logger === "function" ? logger : defaultProviderServerLogger;
1213
1287
  emit({
1214
1288
  level: "info",
1215
1289
  event: "provider_request_completed",
1216
- providerId: provider.id,
1290
+ providerId: redactDiagnosticText(provider.id, redact),
1217
1291
  kind,
1218
- route,
1219
- ...(requestId ? { requestId } : {}),
1292
+ route: redactCriticalDiagnosticText(route, redact),
1293
+ ...(requestId ? { requestId: redactCriticalDiagnosticText(requestId, redact) } : {}),
1220
1294
  ...(correlation.connectionId !== undefined
1221
- ? { connectionId: correlation.connectionId }
1295
+ ? { connectionId: redactDiagnosticText(correlation.connectionId, redact) }
1296
+ : {}),
1297
+ ...(correlation.flowId !== undefined
1298
+ ? { flowId: redactDiagnosticText(correlation.flowId, redact) }
1299
+ : {}),
1300
+ ...(correlation.tenantId !== undefined
1301
+ ? { tenantId: redactDiagnosticText(correlation.tenantId, redact) }
1222
1302
  : {}),
1223
- ...(correlation.flowId !== undefined ? { flowId: correlation.flowId } : {}),
1224
- ...(correlation.tenantId !== undefined ? { tenantId: correlation.tenantId } : {}),
1225
1303
  ...(correlation.requestedProviderId !== undefined
1226
- ? { requestedProviderId: correlation.requestedProviderId }
1304
+ ? { requestedProviderId: redactDiagnosticText(correlation.requestedProviderId, redact) }
1227
1305
  : {}),
1228
1306
  status,
1229
1307
  ...cost,
@@ -1276,9 +1354,106 @@ function requestTraceId(headers, requestId) {
1276
1354
  ? createHash("sha256").update(requestId, "utf8").digest("hex").slice(0, 32)
1277
1355
  : undefined));
1278
1356
  }
1357
+ /** Harvest only credential subtrees, iteratively and before schema diagnostics. */
1358
+ function rawRequestCredentials(rawBody, kind) {
1359
+ const record = (value) => value !== null && typeof value === "object" ? value : undefined;
1360
+ const own = (value, key) => {
1361
+ const object = record(value);
1362
+ return object && Object.hasOwn(object, key) ? object[key] : undefined;
1363
+ };
1364
+ const body = kind === "stateful" ? own(rawBody, "operationRequest") : rawBody;
1365
+ const values = [];
1366
+ let remainingBytes = 64 * 1024;
1367
+ let exhausted = false;
1368
+ const add = (value) => {
1369
+ if (typeof value !== "string")
1370
+ return;
1371
+ const bytes = Buffer.byteLength(value, "utf8");
1372
+ if (bytes > remainingBytes) {
1373
+ exhausted = true;
1374
+ return;
1375
+ }
1376
+ remainingBytes -= bytes;
1377
+ if (value)
1378
+ values.push(value);
1379
+ const trimmed = value.trim();
1380
+ if (trimmed && trimmed !== value)
1381
+ values.push(trimmed);
1382
+ };
1383
+ function* entries(object) {
1384
+ for (const key in object) {
1385
+ if (Object.hasOwn(object, key))
1386
+ yield [key, object[key]];
1387
+ }
1388
+ }
1389
+ const visit = (root) => {
1390
+ const object = record(root);
1391
+ if (!object) {
1392
+ add(root);
1393
+ return;
1394
+ }
1395
+ // Connection inventories are usually flat. Walk the root directly and only
1396
+ // allocate iterator frames when a nested credential container is encountered.
1397
+ for (const key in object) {
1398
+ if (!Object.hasOwn(object, key))
1399
+ continue;
1400
+ const value = object[key];
1401
+ add(key);
1402
+ if (exhausted)
1403
+ break;
1404
+ const child = record(value);
1405
+ if (!child) {
1406
+ add(value);
1407
+ if (exhausted)
1408
+ break;
1409
+ continue;
1410
+ }
1411
+ const stack = [{ iterator: entries(child), depth: 1 }];
1412
+ while (stack.length && !exhausted) {
1413
+ const frame = stack[stack.length - 1];
1414
+ const entry = frame.iterator.next();
1415
+ if (entry.done) {
1416
+ stack.pop();
1417
+ continue;
1418
+ }
1419
+ const [key, value] = entry.value;
1420
+ add(key);
1421
+ if (exhausted)
1422
+ break;
1423
+ const child = record(value);
1424
+ if (child) {
1425
+ if (frame.depth >= 8) {
1426
+ exhausted = true;
1427
+ break;
1428
+ }
1429
+ stack.push({ iterator: entries(child), depth: frame.depth + 1 });
1430
+ }
1431
+ else
1432
+ add(value);
1433
+ }
1434
+ if (exhausted)
1435
+ break;
1436
+ }
1437
+ };
1438
+ visit(own(own(body, "connection"), "secrets"));
1439
+ if (kind === "auth" && !exhausted) {
1440
+ add(own(own(body, "engine"), "egressLease"));
1441
+ if (!exhausted)
1442
+ visit(own(body, "input"));
1443
+ }
1444
+ return { values, exhausted };
1445
+ }
1279
1446
  function createRequestScope(input) {
1447
+ const sensitiveRegistry = createDiagnosticRedactor([], input.staticSensitiveValues);
1448
+ const redact = (text) => redactDiagnosticText(text, sensitiveRegistry.redact);
1449
+ bindCriticalDiagnosticRedactor(redact, sensitiveRegistry.redactCritical, sensitiveRegistry.redactStructured, () => sensitiveRegistry.suppressed);
1280
1450
  const requestCost = startRequestCost();
1281
- const traceConfig = resolveTraceConfigFromEnv();
1451
+ const observeEnv = {
1452
+ observe: createDiagnosticEnvObserver(input.provider, sensitiveRegistry.add, sensitiveRegistry.has),
1453
+ finished: false,
1454
+ staticValues: input.staticSensitiveValues,
1455
+ };
1456
+ const traceConfig = withDiagnosticEnv(observeEnv, () => resolveTraceConfigFromEnv());
1282
1457
  const details = {
1283
1458
  route: input.route,
1284
1459
  requestId: input.requestId,
@@ -1297,15 +1472,19 @@ function createRequestScope(input) {
1297
1472
  const initialTraceId = requestTraceId(input.headers, input.requestId);
1298
1473
  const trace = traceConfig
1299
1474
  ? createTraceContext({
1300
- ...resolveServerTraceContextOptions(traceConfig, traceAttributes),
1475
+ ...withDiagnosticEnv(observeEnv, () => resolveServerTraceContextOptions(traceConfig, traceAttributes, undefined, redact)),
1476
+ redact,
1301
1477
  ...(initialTraceId ? { traceId: initialTraceId } : {}),
1302
1478
  })
1303
- : createTraceContext();
1479
+ : createTraceContext({ redact });
1480
+ bindDiagnosticSensitiveRegistry(trace, sensitiveRegistry);
1304
1481
  const proxyCollector = new ProxyTelemetryCollector();
1305
- const resolverCollector = new ResolverTelemetryCollector();
1482
+ const resolverCollector = new ResolverTelemetryCollector({ redact });
1483
+ const nativeCollector = new NativeTelemetryCollector({ redact });
1306
1484
  const telemetry = new RequestTelemetry(trace);
1307
1485
  telemetry.register(proxyCollector);
1308
1486
  telemetry.register(resolverCollector);
1487
+ telemetry.register(nativeCollector);
1309
1488
  let rootRunner = (fn) => fn();
1310
1489
  let resolveRoot;
1311
1490
  const rootTerminal = new Promise((resolve) => {
@@ -1326,13 +1505,13 @@ function createRequestScope(input) {
1326
1505
  return clientCancelledError();
1327
1506
  return undefined;
1328
1507
  };
1329
- const root = trace.span(`request:${input.kind}:${input.route}`, async () => {
1508
+ const root = withDiagnosticEnv(observeEnv, () => trace.span(`request:${input.kind}:${input.route}`, async () => {
1330
1509
  rootRunner = AsyncLocalStorage.snapshot();
1331
1510
  const outcome = await rootTerminal;
1332
1511
  const error = terminalError(outcome);
1333
1512
  if (error !== undefined)
1334
1513
  throw error;
1335
- });
1514
+ }));
1336
1515
  void root.catch(() => undefined);
1337
1516
  const settleRoot = () => {
1338
1517
  if (!terminalOutcome || streamingSetupPending || rootSettled)
@@ -1368,7 +1547,7 @@ function createRequestScope(input) {
1368
1547
  traceAttributes.flow_id = details.flowId;
1369
1548
  traceAttributes.route = details.route;
1370
1549
  const traceId = requestTraceId(details.headers, details.requestId);
1371
- const sanitizedAttributes = Object.fromEntries(Object.entries(sanitizeTraceAttributes(traceAttributes)).map(([key, value]) => [
1550
+ const sanitizedAttributes = Object.fromEntries(Object.entries(sanitizeTraceAttributes(traceAttributes, redact)).map(([key, value]) => [
1372
1551
  key,
1373
1552
  String(value),
1374
1553
  ]));
@@ -1378,9 +1557,18 @@ function createRequestScope(input) {
1378
1557
  });
1379
1558
  };
1380
1559
  const scope = {
1560
+ redact,
1381
1561
  trace,
1382
1562
  telemetry,
1383
1563
  resolverTelemetry: resolverCollector,
1564
+ nativeTelemetry: nativeCollector,
1565
+ seedCredentials(rawBody, kind) {
1566
+ const harvested = rawRequestCredentials(rawBody, kind);
1567
+ sensitiveRegistry.add(harvested.values);
1568
+ // An incomplete inventory cannot certify free text: emit less.
1569
+ if (harvested.exhausted)
1570
+ sensitiveRegistry.suppress();
1571
+ },
1384
1572
  enrich(enrichment) {
1385
1573
  if (terminalOutcome)
1386
1574
  return;
@@ -1442,21 +1630,21 @@ function createRequestScope(input) {
1442
1630
  terminalize(outcome) {
1443
1631
  if (finishedResult)
1444
1632
  return finishedResult;
1633
+ observeEnv.finished = true;
1445
1634
  terminalOutcome = outcome;
1446
1635
  const error = terminalError(outcome);
1447
1636
  finishedResult = {};
1448
1637
  try {
1449
1638
  const declaredErrorCode = error === undefined ? undefined : input.declaredErrorCode?.(error);
1450
- const status = outcome.status ??
1451
- (error === undefined ? 200 : toStatusCode(error, declaredErrorCode));
1639
+ const status = outcome.status ?? (error === undefined ? 200 : toStatusCode(error, declaredErrorCode));
1452
1640
  finishedResult = headerSnapshot(error);
1453
1641
  const cost = finishRequestCost(requestCost);
1454
1642
  try {
1455
1643
  if (error === undefined) {
1456
- logProviderSuccess(input.logger, input.provider, input.kind, details.route, details.requestId, status, cost, telemetry, details.correlation);
1644
+ logProviderSuccess(input.logger, input.provider, input.kind, details.route, details.requestId, status, cost, telemetry, details.correlation, redact);
1457
1645
  }
1458
1646
  else {
1459
- logProviderError(input.logger, input.provider, input.kind, details.route, details.requestId, error, status, cost, declaredErrorCode, telemetry, finishedResult.errorObservability, details.correlation);
1647
+ logProviderError(input.logger, input.provider, input.kind, details.route, details.requestId, error, status, cost, declaredErrorCode, telemetry, finishedResult.errorObservability, details.correlation, redact);
1460
1648
  }
1461
1649
  }
1462
1650
  catch {
@@ -1490,8 +1678,9 @@ function createRequestScope(input) {
1490
1678
  };
1491
1679
  return scope;
1492
1680
  }
1493
- // A raw `Response` result skips `toErrorResponse`, so its body stays
1494
- // provider-owned, but the observability header is still SDK-owned: derive it
1681
+ // A raw `Response` result skips `toErrorResponse`. Its payload shape stays
1682
+ // provider-owned; known credentials in error payloads still need redaction.
1683
+ // The observability header is SDK-owned: derive it
1495
1684
  // from the status. Only timeouts, rate limits, and 5xx are retryable;
1496
1685
  // `isRetryableCategory` would otherwise mark every other 4xx (`upstream_http`)
1497
1686
  // as retryable.
@@ -1505,7 +1694,7 @@ function rawResponseErrorObservability(status) {
1505
1694
  // `rawStatusFallback` is decided by the caller from the outcome, not from a
1506
1695
  // missing snapshot: a failed outcome whose thrown value is `undefined` also has
1507
1696
  // no `errorObservability`, and its 500 carries the SDK envelope, not a raw body.
1508
- function responseWithRequestScopeHeaders(response, finished, rawStatusFallback) {
1697
+ async function responseWithRequestScopeHeaders(response, finished, rawStatusFallback, redact) {
1509
1698
  const headers = new Headers(response.headers);
1510
1699
  headers.delete(PROVIDER_TELEMETRY_HEADER);
1511
1700
  if (finished.providerTelemetryHeader) {
@@ -1519,16 +1708,25 @@ function responseWithRequestScopeHeaders(response, finished, rawStatusFallback)
1519
1708
  if (errorObservability) {
1520
1709
  headers.set(ERROR_OBSERVABILITY_HEADER, JSON.stringify(errorObservability));
1521
1710
  }
1522
- return new Response(response.body, {
1711
+ // Raw Response bodies are provider-owned. Preserve their stream and representation.
1712
+ const body = response.body;
1713
+ const statusText = rawStatusFallback && response.status >= 400
1714
+ ? redactDiagnosticText(response.statusText, redact)
1715
+ : response.statusText;
1716
+ return new Response(body, {
1523
1717
  headers,
1524
1718
  status: response.status,
1525
- statusText: response.statusText,
1719
+ // When free text cannot be certified, use the SDK's standard HTTP reason
1720
+ // phrase. It preserves the status contract without trusting provider text.
1721
+ statusText: statusText === REDACTION_FAILED && isDiagnosticRedactionSuppressed(redact)
1722
+ ? (STATUS_CODES[response.status] ?? "")
1723
+ : statusText,
1526
1724
  });
1527
1725
  }
1528
- function finalizeRequestResponse(scope, response, outcome) {
1726
+ async function finalizeRequestResponse(scope, response, outcome) {
1529
1727
  try {
1530
1728
  const error = outcome.kind === "failed" ? outcome.error : undefined;
1531
- const finalResponse = responseWithRequestScopeHeaders(response, scope.snapshotHeaders(error), outcome.kind === "completed");
1729
+ const finalResponse = await responseWithRequestScopeHeaders(response, scope.snapshotHeaders(error), outcome.kind === "completed", scope.redact);
1532
1730
  scope.terminalize(outcome);
1533
1731
  return finalResponse;
1534
1732
  }
@@ -1706,7 +1904,7 @@ function toSseResponse(operation, result, lifecycle, requestId) {
1706
1904
  }
1707
1905
  catch (error) {
1708
1906
  const message = error instanceof Error ? error.message : "Stream failed";
1709
- controller.enqueue(encoder.encode(encodeSseEvent(streamError("stream_error", message, {
1907
+ controller.enqueue(encoder.encode(encodeSseEvent(streamError("stream_error", sanitizeDiagnosticText(redactDiagnosticText(message, lifecycle.redact)), {
1710
1908
  ...(requestId ? { requestId } : {}),
1711
1909
  }))));
1712
1910
  controller.close();
@@ -1886,7 +2084,7 @@ async function handleOperation(provider, request, operationId, options, state =
1886
2084
  ctx.stealth.close?.();
1887
2085
  }
1888
2086
  catch (error) {
1889
- logProviderCleanupError(options.logger, provider, "operation", operationId, request.requestId, "stealth", error);
2087
+ logProviderCleanupError(options.logger, provider, "operation", operationId, request.requestId, "stealth", error, scope.redact);
1890
2088
  }
1891
2089
  }
1892
2090
  if ("browser" in ctx) {
@@ -1894,11 +2092,12 @@ async function handleOperation(provider, request, operationId, options, state =
1894
2092
  await ctx.browser.close?.();
1895
2093
  }
1896
2094
  catch (error) {
1897
- logProviderCleanupError(options.logger, provider, "operation", operationId, request.requestId, "browser", error);
2095
+ logProviderCleanupError(options.logger, provider, "operation", operationId, request.requestId, "browser", error, scope.redact);
1898
2096
  }
1899
2097
  }
1900
2098
  };
1901
2099
  const streamLifecycle = {
2100
+ redact: scope.redact,
1902
2101
  runStep(fn) {
1903
2102
  return scope.runStreamStep(fn);
1904
2103
  },
@@ -1996,7 +2195,7 @@ async function handleAuthFlow(provider, request, route, options, state, scope, s
1996
2195
  context.stealth.close?.();
1997
2196
  }
1998
2197
  catch (error) {
1999
- logProviderCleanupError(options.logger, provider, "auth", route, request.requestId, "stealth", error);
2198
+ logProviderCleanupError(options.logger, provider, "auth", route, request.requestId, "stealth", error, scope.redact);
2000
2199
  }
2001
2200
  }
2002
2201
  }
@@ -2102,13 +2301,13 @@ function operationRequestFromForwardingEnvelope(envelope) {
2102
2301
  ...(envelope.deadlineAt !== undefined ? { deadlineAt: envelope.deadlineAt } : {}),
2103
2302
  };
2104
2303
  }
2105
- function parseStatefulForwardingEnvelope(rawBody) {
2304
+ function parseStatefulForwardingEnvelope(rawBody, redact) {
2106
2305
  const parsed = ProviderServerStatefulForwardEnvelopeSchema.safeParse(rawBody);
2107
2306
  if (parsed.success)
2108
2307
  return parsed.data;
2109
2308
  throw new ProviderError("Stateful forwarding envelope is invalid.", {
2110
2309
  code: "STATEFUL_FORWARDING_ENVELOPE_INVALID",
2111
- details: zodDetails(parsed.error),
2310
+ details: zodDetails(parsed.error, redact),
2112
2311
  });
2113
2312
  }
2114
2313
  /**
@@ -2142,6 +2341,10 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
2142
2341
  engine: serverOptions.engine ?? createInProcessProviderEngine(),
2143
2342
  };
2144
2343
  const app = new Hono();
2344
+ // Compile the startup inventory once, composed with the shared outside-context fallback.
2345
+ const staticSensitiveValues = compileProcessDiagnosticSensitiveValues(collectStaticDiagnosticSensitiveValues(provider, {
2346
+ statefulForwardingSecret: options.statefulForwarding?.secret,
2347
+ }));
2145
2348
  const logger = options.logger ?? defaultProviderServerLogger;
2146
2349
  const operationErrorCodes = buildOperationErrorCodeLookup(provider);
2147
2350
  const statefulForwardingReplayCache = new StatefulForwardingReplayCache(options.statefulForwarding?.replayCacheMaxEntries ??
@@ -2182,6 +2385,7 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
2182
2385
  const operation = "stateful-internal";
2183
2386
  const requestScope = createRequestScope({
2184
2387
  provider,
2388
+ staticSensitiveValues,
2185
2389
  kind: "operation",
2186
2390
  route: operation,
2187
2391
  headers: Object.fromEntries(c.req.raw.headers.entries()),
@@ -2212,7 +2416,8 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
2212
2416
  code: "STATEFUL_FORWARDING_ENVELOPE_INVALID",
2213
2417
  });
2214
2418
  }
2215
- const envelope = parseStatefulForwardingEnvelope(rawBody);
2419
+ requestScope.seedCredentials(rawBody, "stateful");
2420
+ const envelope = parseStatefulForwardingEnvelope(rawBody, requestScope.redact);
2216
2421
  if (envelope.providerId !== provider.id) {
2217
2422
  throw new ProviderError("Stateful forwarding envelope providerId does not match the served provider.", { code: "STATEFUL_FORWARDING_PROVIDER_MISMATCH" });
2218
2423
  }
@@ -2313,7 +2518,7 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
2313
2518
  ...(requestId ? { requestId } : {}),
2314
2519
  });
2315
2520
  const observabilityDetails = errorObservabilityDetails(error, declaredErrorCode);
2316
- const response = c.json(toErrorResponse(error, requestId, observabilityDetails), status);
2521
+ const response = c.json(toErrorResponse(error, requestId, observabilityDetails, requestScope.redact), status);
2317
2522
  return finalizeRequestResponse(requestScope, response, {
2318
2523
  kind: "failed",
2319
2524
  status,
@@ -2326,6 +2531,7 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
2326
2531
  const operation = c.req.param("operation");
2327
2532
  const requestScope = createRequestScope({
2328
2533
  provider,
2534
+ staticSensitiveValues,
2329
2535
  kind: "operation",
2330
2536
  route: operation,
2331
2537
  operationId: operation,
@@ -2339,6 +2545,7 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
2339
2545
  .clone()
2340
2546
  .json()
2341
2547
  .catch(() => undefined);
2548
+ requestScope.seedCredentials(rawBody, "operation");
2342
2549
  const body = OperationRequestSchema.parse(rawBody);
2343
2550
  const requestHeaders = Object.fromEntries(c.req.raw.headers.entries());
2344
2551
  body.headers = { ...requestHeaders, ...body.headers };
@@ -2356,7 +2563,7 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
2356
2563
  const handled = await handleOperation(provider, body, operation, options, state, requestScope, c.req.raw.signal);
2357
2564
  const response = handled instanceof Response ? handled : c.json(handled);
2358
2565
  return streaming
2359
- ? responseWithRequestScopeHeaders(response, requestScope.snapshotHeaders(), true)
2566
+ ? responseWithRequestScopeHeaders(response, requestScope.snapshotHeaders(), true, requestScope.redact)
2360
2567
  : response;
2361
2568
  };
2362
2569
  const response = streaming
@@ -2375,7 +2582,7 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
2375
2582
  const requestId = extractRequestId(rawBody);
2376
2583
  requestScope.enrich({ ...(requestId ? { requestId } : {}) });
2377
2584
  const observabilityDetails = errorObservabilityDetails(error, declaredErrorCode);
2378
- const response = c.json(toErrorResponse(error, requestId, observabilityDetails), status);
2585
+ const response = c.json(toErrorResponse(error, requestId, observabilityDetails, requestScope.redact), status);
2379
2586
  return finalizeRequestResponse(requestScope, response, {
2380
2587
  kind: "failed",
2381
2588
  status,
@@ -2395,6 +2602,7 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
2395
2602
  let rawBody;
2396
2603
  const requestScope = createRequestScope({
2397
2604
  provider,
2605
+ staticSensitiveValues,
2398
2606
  kind: "auth",
2399
2607
  route: logRoute,
2400
2608
  headers: Object.fromEntries(c.req.raw.headers.entries()),
@@ -2406,6 +2614,7 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
2406
2614
  .clone()
2407
2615
  .json()
2408
2616
  .catch(() => undefined);
2617
+ requestScope.seedCredentials(rawBody, "auth");
2409
2618
  const body = withAuthRequestHeaders(AuthFlowRequestSchema.parse(rawBody), c.req.raw.headers);
2410
2619
  requestScope.enrich({
2411
2620
  requestId: body.requestId,
@@ -2434,7 +2643,7 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
2434
2643
  const requestId = extractRequestId(rawBody);
2435
2644
  requestScope.enrich({ ...(requestId ? { requestId } : {}) });
2436
2645
  const observabilityDetails = errorObservabilityDetails(error);
2437
- const response = c.json(toErrorResponse(error, requestId, observabilityDetails), status);
2646
+ const response = c.json(toErrorResponse(error, requestId, observabilityDetails, requestScope.redact), status);
2438
2647
  return finalizeRequestResponse(requestScope, response, {
2439
2648
  kind: "failed",
2440
2649
  status,