@apifuse/provider-sdk 2.2.0-beta.59 → 2.2.0-beta.60
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 +16 -0
- package/CHANGELOG.md +4 -0
- package/bin/apifuse-dev.ts +2 -1
- package/bin/apifuse-perf.ts +41 -4
- package/bin/apifuse-record.ts +3 -2
- package/dist/config/loader.js +13 -12
- package/dist/engine.js +3 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/lint.js +36 -15
- package/dist/provider.d.ts +1 -1
- package/dist/provider.js +1 -1
- package/dist/runtime/browser.js +2 -1
- package/dist/runtime/cache.js +3 -2
- package/dist/runtime/diagnostic-env-values.d.ts +5 -0
- package/dist/runtime/diagnostic-env-values.js +57 -0
- package/dist/runtime/diagnostic-env.d.ts +11 -0
- package/dist/runtime/diagnostic-env.js +35 -0
- package/dist/runtime/diagnostic-redactor.d.ts +49 -0
- package/dist/runtime/diagnostic-redactor.js +569 -0
- package/dist/runtime/egress-lease.d.ts +2 -0
- package/dist/runtime/egress-lease.js +4 -1
- package/dist/runtime/env.js +2 -1
- package/dist/runtime/instrumentation.js +3 -0
- package/dist/runtime/ocr.js +2 -1
- package/dist/runtime/otlp.js +5 -4
- package/dist/runtime/proxy-nodemaven.js +3 -2
- package/dist/runtime/request-options.d.ts +7 -0
- package/dist/runtime/request-options.js +62 -22
- package/dist/runtime/resolver-vendors/browser.js +0 -1
- package/dist/runtime/resolver.js +3 -2
- package/dist/runtime/stt.js +3 -2
- package/dist/runtime/trace.d.ts +5 -0
- package/dist/runtime/trace.js +115 -20
- package/dist/schema.d.ts +11 -0
- package/dist/schema.js +56 -2
- package/dist/server/self-test-redaction.js +8 -33
- package/dist/server/sensitive-values.d.ts +26 -0
- package/dist/server/sensitive-values.js +131 -0
- package/dist/server/serve-implementation.js +219 -78
- package/dist/server/trace-output.d.ts +2 -1
- package/dist/server/trace-output.js +46 -14
- package/dist/trace-sanitization.d.ts +4 -3
- package/dist/trace-sanitization.js +45 -22
- package/package.json +2 -1
- package/src/config/loader.ts +13 -12
- package/src/engine.ts +3 -2
- package/src/index.ts +2 -0
- package/src/lint.ts +42 -16
- package/src/provider.ts +1 -0
- package/src/runtime/browser.ts +2 -1
- package/src/runtime/cache.ts +3 -2
- package/src/runtime/diagnostic-env-values.ts +56 -0
- package/src/runtime/diagnostic-env.ts +55 -0
- package/src/runtime/diagnostic-redactor.ts +662 -0
- package/src/runtime/egress-lease.ts +6 -1
- package/src/runtime/env.ts +2 -1
- package/src/runtime/instrumentation.ts +3 -0
- package/src/runtime/ocr.ts +2 -1
- package/src/runtime/otlp.ts +5 -4
- package/src/runtime/proxy-nodemaven.ts +3 -2
- package/src/runtime/request-options.ts +76 -28
- package/src/runtime/resolver-vendors/browser.ts +0 -1
- package/src/runtime/resolver.ts +3 -2
- package/src/runtime/stt.ts +3 -2
- package/src/runtime/trace.ts +168 -26
- package/src/schema.ts +63 -2
- package/src/server/self-test-redaction.ts +10 -40
- package/src/server/sensitive-values.ts +200 -0
- package/src/server/serve-implementation.ts +301 -96
- package/src/server/trace-output.ts +77 -17
- package/src/trace-sanitization.ts +70 -23
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { STATUS_CODES } from "node:http";
|
|
2
|
+
import { readDiagnosticEnv, withDiagnosticEnv } from "../runtime/diagnostic-env.js";
|
|
2
3
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
3
5
|
import { existsSync } from "node:fs";
|
|
4
6
|
import { createRequire } from "node:module";
|
|
5
7
|
import { join } from "node:path";
|
|
@@ -7,29 +9,30 @@ import { Hono } from "hono";
|
|
|
7
9
|
import { z } from "zod";
|
|
8
10
|
import { AuthAbortError, createAuthFlowHelpers } from "../auth.js";
|
|
9
11
|
import { validateFailClosedDeclaration } from "../declaration-validation.js";
|
|
10
|
-
import { safeProviderErrorObservability } from "../error-observability.js";
|
|
11
12
|
import { createInProcessProviderEngine, ENGINE_OWNED_PROXY_CREDENTIAL_ENV_NAMES, isEngineOwnedEnvName, readEngineProxyCredentials, } from "../engine.js";
|
|
13
|
+
import { safeProviderErrorObservability } from "../error-observability.js";
|
|
12
14
|
import { SDK_OWNED_PROVIDER_ERROR_CODES, SDK_RUNTIME_OWNED_ERROR_CODES, SDK_STATUS_MAPPED_PROVIDER_ERROR_CODES, } from "../error-resolution.js";
|
|
13
15
|
import { AuthError, isProviderError, isSessionExpiredError, isTransportError, isValidationError, ProviderError, SDKError, } from "../errors.js";
|
|
14
16
|
import { sanitizeDiagnosticText } from "../fixture-sanitization.js";
|
|
15
17
|
import { loadProviderLocaleCatalogs, localizeAuthTurn, } from "../i18n/catalog.js";
|
|
16
|
-
import { categoryForStatus,
|
|
18
|
+
import { categoryForStatus, isRetryableCategory, PROVIDER_OBSERVABILITY_TAXONOMY_VERSION, sourceForCategory, } from "../observability.js";
|
|
17
19
|
import { createScratchpad } from "../runtime/auth-flow.js";
|
|
18
20
|
import { createProviderCache } from "../runtime/cache.js";
|
|
19
21
|
import { createProviderChoiceContext, PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV, } from "../runtime/choice.js";
|
|
20
22
|
import { createCredentialContext } from "../runtime/credential.js";
|
|
23
|
+
import { bindDiagnosticSensitiveRegistry, compileProcessDiagnosticSensitiveValues, createDiagnosticRedactor, REDACTION_FAILED, isDiagnosticRedactionSuppressed, bindCriticalDiagnosticRedactor, redactCriticalDiagnosticText, redactDiagnosticText, registerDiagnosticSensitiveValues, } from "../runtime/diagnostic-redactor.js";
|
|
21
24
|
import { createCeremonyEgressLeaseRuntime, ENGINE_CEREMONY_EGRESS_LEASE, } from "../runtime/egress-lease.js";
|
|
22
25
|
import { createEnvContext } from "../runtime/env.js";
|
|
23
26
|
import { executeOperation } from "../runtime/executor.js";
|
|
24
27
|
import { createHttpClient } from "../runtime/http.js";
|
|
25
28
|
import { wrapWithInstrumentation } from "../runtime/instrumentation.js";
|
|
26
|
-
import { getProviderBaseUrl } from "../runtime/provider.js";
|
|
27
29
|
import { createOcrClientFromEnv } from "../runtime/ocr.js";
|
|
30
|
+
import { getProviderBaseUrl } from "../runtime/provider.js";
|
|
28
31
|
import { PROXY_AUTH_IP_DENIED_CODE, PROXY_EDGE_AUTH_REJECTED_CODE, PROXY_POOL_EXHAUSTED_CODE, } from "../runtime/proxy-errors.js";
|
|
29
32
|
import { PROVIDER_TELEMETRY_HEADER, ProxyTelemetryCollector, } from "../runtime/proxy-telemetry.js";
|
|
30
33
|
import { closedEnum, RequestTelemetry, tenantOpaqueKeys, } from "../runtime/request-telemetry.js";
|
|
34
|
+
import { bindResolverTelemetry, createUnsupportedResolverClient, inheritResolverTelemetryBinding, } from "../runtime/resolver-shared.js";
|
|
31
35
|
import { ResolverTelemetryCollector, } from "../runtime/resolver-telemetry.js";
|
|
32
|
-
import { createUnsupportedResolverClient, bindResolverTelemetry, inheritResolverTelemetryBinding, } from "../runtime/resolver-shared.js";
|
|
33
36
|
import { assertRequiredSecretsPresent, listMissingRequiredSecrets, MISSING_SECRET_CODE, } from "../runtime/secrets.js";
|
|
34
37
|
import { createProviderRuntimeStateFromEnv, createUnsupportedProviderRuntimeState, } from "../runtime/state.js";
|
|
35
38
|
import { StealthCookieJar } from "../runtime/stealth-cookies.js";
|
|
@@ -37,13 +40,14 @@ import { createSttClientFromEnv } from "../runtime/stt.js";
|
|
|
37
40
|
import { createTraceContext, getTraceRecorder, updateTraceContextExportMetadata, } from "../runtime/trace.js";
|
|
38
41
|
import { resolveTraceConfigFromEnv } from "../runtime/trace-config.js";
|
|
39
42
|
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
43
|
import { StatefulRoutingDeadlineError } from "../stateful/errors.js";
|
|
44
|
+
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
45
|
import { getStealthProfile } from "../stealth/profiles.js";
|
|
43
|
-
import { sanitizeTraceAttributes } from "../trace-sanitization.js";
|
|
44
46
|
import { APIFUSE_STREAM_DONE_EVENT, APIFUSE_STREAM_ERROR_EVENT, encodeSseEvent, error as streamError, } from "../stream.js";
|
|
47
|
+
import { sanitizeSpanNameForOutput, sanitizeTraceAttributes } from "../trace-sanitization.js";
|
|
45
48
|
import { VALID_OPERATION_ERROR_STATUSES } from "../types.js";
|
|
46
49
|
import { resolveSelfTestMasterSecrets } from "./self-test-token.js";
|
|
50
|
+
import { collectStaticDiagnosticSensitiveValues, createDiagnosticEnvObserver, } from "./sensitive-values.js";
|
|
47
51
|
import { resolveServerTraceContextOptions } from "./trace-output.js";
|
|
48
52
|
import { AuthFlowRequestSchema, OperationConnectionSchema, OperationRequestSchema, } from "./types.js";
|
|
49
53
|
const DEFAULT_HOST = "0.0.0.0";
|
|
@@ -520,7 +524,7 @@ function createProviderContext(provider, request, operationId, options, state =
|
|
|
520
524
|
}
|
|
521
525
|
: {}),
|
|
522
526
|
};
|
|
523
|
-
const logStealthCleanupError = (error) => logProviderCleanupError(options.logger, provider, "operation", operationId, request.requestId, "stealth", error);
|
|
527
|
+
const logStealthCleanupError = (error) => logProviderCleanupError(options.logger, provider, "operation", operationId, request.requestId, "stealth", error, scope.redact);
|
|
524
528
|
const env = createEnvContext([
|
|
525
529
|
...providerSecretNames(provider),
|
|
526
530
|
PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV,
|
|
@@ -560,7 +564,7 @@ function createProviderContext(provider, request, operationId, options, state =
|
|
|
560
564
|
browser: provider.runtime === "browser"
|
|
561
565
|
? capabilityModules.browser.createBrowserClient({
|
|
562
566
|
allowedHosts: provider.allowedHosts,
|
|
563
|
-
cdpUrl:
|
|
567
|
+
cdpUrl: readDiagnosticEnv("APIFUSE__CDP_POOL__URL"),
|
|
564
568
|
headless: true,
|
|
565
569
|
requireCdpPool: isProductionProviderBrowserMode(provider),
|
|
566
570
|
stealth: true,
|
|
@@ -668,6 +672,7 @@ function createAuthFlowContext(provider, request, route, options, state, scope,
|
|
|
668
672
|
providerId: provider.id,
|
|
669
673
|
flowId: request.flowId,
|
|
670
674
|
affinityKey: proxyClientOptions.affinityKey,
|
|
675
|
+
onHandle: (handle) => registerDiagnosticSensitiveValues(scope.trace, [handle]),
|
|
671
676
|
...(request.engine?.egressLease ? { handle: request.engine.egressLease } : {}),
|
|
672
677
|
})
|
|
673
678
|
: undefined;
|
|
@@ -697,7 +702,7 @@ function createAuthFlowContext(provider, request, route, options, state, scope,
|
|
|
697
702
|
}
|
|
698
703
|
: {}),
|
|
699
704
|
};
|
|
700
|
-
const logStealthCleanupError = (error) => logProviderCleanupError(options.logger, provider, "auth", "flow", request.requestId, "stealth", error);
|
|
705
|
+
const logStealthCleanupError = (error) => logProviderCleanupError(options.logger, provider, "auth", "flow", request.requestId, "stealth", error, scope.redact);
|
|
701
706
|
const credential = request.connection
|
|
702
707
|
? createCredentialContext({
|
|
703
708
|
allowedKeys: provider.credential?.keys,
|
|
@@ -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
|
}
|
|
@@ -1097,13 +1102,13 @@ function extractRequestId(raw) {
|
|
|
1097
1102
|
}
|
|
1098
1103
|
const MAX_PROVIDER_ERROR_CAUSE_FRAMES = 5;
|
|
1099
1104
|
const MAX_PROVIDER_ERROR_CAUSE_MESSAGE_LENGTH = 300;
|
|
1100
|
-
function providerErrorCauseMessage(message) {
|
|
1101
|
-
const sanitized = sanitizeDiagnosticText(message);
|
|
1105
|
+
function providerErrorCauseMessage(message, redact) {
|
|
1106
|
+
const sanitized = sanitizeDiagnosticText(redactDiagnosticText(message, redact));
|
|
1102
1107
|
return sanitized.length > MAX_PROVIDER_ERROR_CAUSE_MESSAGE_LENGTH
|
|
1103
1108
|
? `${sanitized.slice(0, MAX_PROVIDER_ERROR_CAUSE_MESSAGE_LENGTH)}… [truncated]`
|
|
1104
1109
|
: sanitized;
|
|
1105
1110
|
}
|
|
1106
|
-
function providerErrorCauseChain(error) {
|
|
1111
|
+
function providerErrorCauseChain(error, redact) {
|
|
1107
1112
|
if (!(error instanceof Error) && !isProviderError(error))
|
|
1108
1113
|
return undefined;
|
|
1109
1114
|
const seen = new Set([error]);
|
|
@@ -1117,9 +1122,9 @@ function providerErrorCauseChain(error) {
|
|
|
1117
1122
|
const providerObservability = safeProviderErrorObservability(cause);
|
|
1118
1123
|
const causeCode = providerErrorCode(cause);
|
|
1119
1124
|
frames.push({
|
|
1120
|
-
errorClass: cause.name,
|
|
1121
|
-
...(causeCode !== undefined ? { code: causeCode } : {}),
|
|
1122
|
-
message: providerErrorCauseMessage(message),
|
|
1125
|
+
errorClass: redactDiagnosticText(cause.name, redact),
|
|
1126
|
+
...(causeCode !== undefined ? { code: redactDiagnosticText(causeCode, redact) } : {}),
|
|
1127
|
+
message: providerErrorCauseMessage(message, redact),
|
|
1123
1128
|
messageLength: message.length,
|
|
1124
1129
|
messageFingerprint: createHash("sha256").update(message).digest("hex").slice(0, 12),
|
|
1125
1130
|
...(providerObservability ? { providerObservability } : {}),
|
|
@@ -1128,7 +1133,7 @@ function providerErrorCauseChain(error) {
|
|
|
1128
1133
|
}
|
|
1129
1134
|
return frames.length > 0 ? frames : undefined;
|
|
1130
1135
|
}
|
|
1131
|
-
function logProviderError(logger, provider, kind, route, requestId, error, status, cost, declaredErrorCode, telemetry, observabilityDetails, correlation = {}) {
|
|
1136
|
+
function logProviderError(logger, provider, kind, route, requestId, error, status, cost, declaredErrorCode, telemetry, observabilityDetails, correlation = {}, redact) {
|
|
1132
1137
|
const providerCode = isProviderError(error) ? providerErrorCode(error) : undefined;
|
|
1133
1138
|
const code = isProviderError(error)
|
|
1134
1139
|
? (providerCode ?? "provider_error")
|
|
@@ -1139,7 +1144,7 @@ function logProviderError(logger, provider, kind, route, requestId, error, statu
|
|
|
1139
1144
|
: "internal_error";
|
|
1140
1145
|
const errorClass = error instanceof Error ? error.name : typeof error;
|
|
1141
1146
|
const message = error instanceof Error ? error.message : String(error);
|
|
1142
|
-
const causeChain = providerErrorCauseChain(error);
|
|
1147
|
+
const causeChain = providerErrorCauseChain(error, redact);
|
|
1143
1148
|
const details = observabilityDetails;
|
|
1144
1149
|
const isUnregisteredProviderErrorCode = status === 500 &&
|
|
1145
1150
|
isProviderError(error) &&
|
|
@@ -1158,24 +1163,28 @@ function logProviderError(logger, provider, kind, route, requestId, error, statu
|
|
|
1158
1163
|
emit({
|
|
1159
1164
|
level: status >= 500 ? "error" : "warn",
|
|
1160
1165
|
event: "provider_request_failed",
|
|
1161
|
-
providerId: provider.id,
|
|
1166
|
+
providerId: redactDiagnosticText(provider.id, redact),
|
|
1162
1167
|
kind,
|
|
1163
|
-
route,
|
|
1164
|
-
...(requestId ? { requestId } : {}),
|
|
1168
|
+
route: redactCriticalDiagnosticText(route, redact),
|
|
1169
|
+
...(requestId ? { requestId: redactCriticalDiagnosticText(requestId, redact) } : {}),
|
|
1165
1170
|
...(correlation.connectionId !== undefined
|
|
1166
|
-
? { connectionId: correlation.connectionId }
|
|
1171
|
+
? { connectionId: redactDiagnosticText(correlation.connectionId, redact) }
|
|
1172
|
+
: {}),
|
|
1173
|
+
...(correlation.flowId !== undefined
|
|
1174
|
+
? { flowId: redactDiagnosticText(correlation.flowId, redact) }
|
|
1175
|
+
: {}),
|
|
1176
|
+
...(correlation.tenantId !== undefined
|
|
1177
|
+
? { tenantId: redactDiagnosticText(correlation.tenantId, redact) }
|
|
1167
1178
|
: {}),
|
|
1168
|
-
...(correlation.flowId !== undefined ? { flowId: correlation.flowId } : {}),
|
|
1169
|
-
...(correlation.tenantId !== undefined ? { tenantId: correlation.tenantId } : {}),
|
|
1170
1179
|
...(correlation.requestedProviderId !== undefined
|
|
1171
|
-
? { requestedProviderId: correlation.requestedProviderId }
|
|
1180
|
+
? { requestedProviderId: redactDiagnosticText(correlation.requestedProviderId, redact) }
|
|
1172
1181
|
: {}),
|
|
1173
1182
|
status,
|
|
1174
1183
|
...cost,
|
|
1175
1184
|
...(telemetryPayload ?? {}),
|
|
1176
|
-
code,
|
|
1177
|
-
errorClass,
|
|
1178
|
-
message,
|
|
1185
|
+
code: sanitizeSpanNameForOutput(redactCriticalDiagnosticText(code, redact)),
|
|
1186
|
+
errorClass: redactDiagnosticText(errorClass, redact),
|
|
1187
|
+
message: sanitizeDiagnosticText(redactDiagnosticText(message, redact)),
|
|
1179
1188
|
...(causeChain ? { causeChain } : {}),
|
|
1180
1189
|
...(providerObservability ? { providerObservability } : {}),
|
|
1181
1190
|
...(details.upstreamStatus ? { upstreamStatus: details.upstreamStatus } : {}),
|
|
@@ -1188,42 +1197,46 @@ function logProviderError(logger, provider, kind, route, requestId, error, statu
|
|
|
1188
1197
|
signalFix: "Declare this code (with status and retryable) in the operation's errorCodes so it serves its intended status instead of 500.",
|
|
1189
1198
|
}
|
|
1190
1199
|
: {}),
|
|
1191
|
-
...(error instanceof z.ZodError ? { issues: zodDetails(error) } : {}),
|
|
1200
|
+
...(error instanceof z.ZodError ? { issues: zodDetails(error, redact) } : {}),
|
|
1192
1201
|
});
|
|
1193
1202
|
}
|
|
1194
|
-
function logProviderCleanupError(logger, provider, kind, operationId, requestId, resource, error) {
|
|
1203
|
+
function logProviderCleanupError(logger, provider, kind, operationId, requestId, resource, error, redact) {
|
|
1195
1204
|
const emit = typeof logger === "function" ? logger : defaultProviderServerLogger;
|
|
1196
1205
|
const errorClass = error instanceof Error ? error.name : typeof error;
|
|
1197
1206
|
const message = error instanceof Error ? error.message : String(error);
|
|
1198
1207
|
emit({
|
|
1199
1208
|
level: "warn",
|
|
1200
1209
|
event: "provider_cleanup_failed",
|
|
1201
|
-
providerId: provider.id,
|
|
1210
|
+
providerId: redactDiagnosticText(provider.id, redact),
|
|
1202
1211
|
kind,
|
|
1203
|
-
route: operationId,
|
|
1204
|
-
...(requestId ? { requestId } : {}),
|
|
1212
|
+
route: redactCriticalDiagnosticText(operationId, redact),
|
|
1213
|
+
...(requestId ? { requestId: redactCriticalDiagnosticText(requestId, redact) } : {}),
|
|
1205
1214
|
resource,
|
|
1206
|
-
errorClass,
|
|
1207
|
-
message,
|
|
1215
|
+
errorClass: redactDiagnosticText(errorClass, redact),
|
|
1216
|
+
message: sanitizeDiagnosticText(redactDiagnosticText(message, redact)),
|
|
1208
1217
|
});
|
|
1209
1218
|
}
|
|
1210
|
-
function logProviderSuccess(logger, provider, kind, route, requestId, status, cost, telemetry, correlation = {}) {
|
|
1219
|
+
function logProviderSuccess(logger, provider, kind, route, requestId, status, cost, telemetry, correlation = {}, redact) {
|
|
1211
1220
|
const telemetryPayload = telemetry?.toLogPayload();
|
|
1212
1221
|
const emit = typeof logger === "function" ? logger : defaultProviderServerLogger;
|
|
1213
1222
|
emit({
|
|
1214
1223
|
level: "info",
|
|
1215
1224
|
event: "provider_request_completed",
|
|
1216
|
-
providerId: provider.id,
|
|
1225
|
+
providerId: redactDiagnosticText(provider.id, redact),
|
|
1217
1226
|
kind,
|
|
1218
|
-
route,
|
|
1219
|
-
...(requestId ? { requestId } : {}),
|
|
1227
|
+
route: redactCriticalDiagnosticText(route, redact),
|
|
1228
|
+
...(requestId ? { requestId: redactCriticalDiagnosticText(requestId, redact) } : {}),
|
|
1220
1229
|
...(correlation.connectionId !== undefined
|
|
1221
|
-
? { connectionId: correlation.connectionId }
|
|
1230
|
+
? { connectionId: redactDiagnosticText(correlation.connectionId, redact) }
|
|
1231
|
+
: {}),
|
|
1232
|
+
...(correlation.flowId !== undefined
|
|
1233
|
+
? { flowId: redactDiagnosticText(correlation.flowId, redact) }
|
|
1234
|
+
: {}),
|
|
1235
|
+
...(correlation.tenantId !== undefined
|
|
1236
|
+
? { tenantId: redactDiagnosticText(correlation.tenantId, redact) }
|
|
1222
1237
|
: {}),
|
|
1223
|
-
...(correlation.flowId !== undefined ? { flowId: correlation.flowId } : {}),
|
|
1224
|
-
...(correlation.tenantId !== undefined ? { tenantId: correlation.tenantId } : {}),
|
|
1225
1238
|
...(correlation.requestedProviderId !== undefined
|
|
1226
|
-
? { requestedProviderId: correlation.requestedProviderId }
|
|
1239
|
+
? { requestedProviderId: redactDiagnosticText(correlation.requestedProviderId, redact) }
|
|
1227
1240
|
: {}),
|
|
1228
1241
|
status,
|
|
1229
1242
|
...cost,
|
|
@@ -1276,9 +1289,106 @@ function requestTraceId(headers, requestId) {
|
|
|
1276
1289
|
? createHash("sha256").update(requestId, "utf8").digest("hex").slice(0, 32)
|
|
1277
1290
|
: undefined));
|
|
1278
1291
|
}
|
|
1292
|
+
/** Harvest only credential subtrees, iteratively and before schema diagnostics. */
|
|
1293
|
+
function rawRequestCredentials(rawBody, kind) {
|
|
1294
|
+
const record = (value) => value !== null && typeof value === "object" ? value : undefined;
|
|
1295
|
+
const own = (value, key) => {
|
|
1296
|
+
const object = record(value);
|
|
1297
|
+
return object && Object.hasOwn(object, key) ? object[key] : undefined;
|
|
1298
|
+
};
|
|
1299
|
+
const body = kind === "stateful" ? own(rawBody, "operationRequest") : rawBody;
|
|
1300
|
+
const values = [];
|
|
1301
|
+
let remainingBytes = 64 * 1024;
|
|
1302
|
+
let exhausted = false;
|
|
1303
|
+
const add = (value) => {
|
|
1304
|
+
if (typeof value !== "string")
|
|
1305
|
+
return;
|
|
1306
|
+
const bytes = Buffer.byteLength(value, "utf8");
|
|
1307
|
+
if (bytes > remainingBytes) {
|
|
1308
|
+
exhausted = true;
|
|
1309
|
+
return;
|
|
1310
|
+
}
|
|
1311
|
+
remainingBytes -= bytes;
|
|
1312
|
+
if (value)
|
|
1313
|
+
values.push(value);
|
|
1314
|
+
const trimmed = value.trim();
|
|
1315
|
+
if (trimmed && trimmed !== value)
|
|
1316
|
+
values.push(trimmed);
|
|
1317
|
+
};
|
|
1318
|
+
function* entries(object) {
|
|
1319
|
+
for (const key in object) {
|
|
1320
|
+
if (Object.hasOwn(object, key))
|
|
1321
|
+
yield [key, object[key]];
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
const visit = (root) => {
|
|
1325
|
+
const object = record(root);
|
|
1326
|
+
if (!object) {
|
|
1327
|
+
add(root);
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1330
|
+
// Connection inventories are usually flat. Walk the root directly and only
|
|
1331
|
+
// allocate iterator frames when a nested credential container is encountered.
|
|
1332
|
+
for (const key in object) {
|
|
1333
|
+
if (!Object.hasOwn(object, key))
|
|
1334
|
+
continue;
|
|
1335
|
+
const value = object[key];
|
|
1336
|
+
add(key);
|
|
1337
|
+
if (exhausted)
|
|
1338
|
+
break;
|
|
1339
|
+
const child = record(value);
|
|
1340
|
+
if (!child) {
|
|
1341
|
+
add(value);
|
|
1342
|
+
if (exhausted)
|
|
1343
|
+
break;
|
|
1344
|
+
continue;
|
|
1345
|
+
}
|
|
1346
|
+
const stack = [{ iterator: entries(child), depth: 1 }];
|
|
1347
|
+
while (stack.length && !exhausted) {
|
|
1348
|
+
const frame = stack[stack.length - 1];
|
|
1349
|
+
const entry = frame.iterator.next();
|
|
1350
|
+
if (entry.done) {
|
|
1351
|
+
stack.pop();
|
|
1352
|
+
continue;
|
|
1353
|
+
}
|
|
1354
|
+
const [key, value] = entry.value;
|
|
1355
|
+
add(key);
|
|
1356
|
+
if (exhausted)
|
|
1357
|
+
break;
|
|
1358
|
+
const child = record(value);
|
|
1359
|
+
if (child) {
|
|
1360
|
+
if (frame.depth >= 8) {
|
|
1361
|
+
exhausted = true;
|
|
1362
|
+
break;
|
|
1363
|
+
}
|
|
1364
|
+
stack.push({ iterator: entries(child), depth: frame.depth + 1 });
|
|
1365
|
+
}
|
|
1366
|
+
else
|
|
1367
|
+
add(value);
|
|
1368
|
+
}
|
|
1369
|
+
if (exhausted)
|
|
1370
|
+
break;
|
|
1371
|
+
}
|
|
1372
|
+
};
|
|
1373
|
+
visit(own(own(body, "connection"), "secrets"));
|
|
1374
|
+
if (kind === "auth" && !exhausted) {
|
|
1375
|
+
add(own(own(body, "engine"), "egressLease"));
|
|
1376
|
+
if (!exhausted)
|
|
1377
|
+
visit(own(body, "input"));
|
|
1378
|
+
}
|
|
1379
|
+
return { values, exhausted };
|
|
1380
|
+
}
|
|
1279
1381
|
function createRequestScope(input) {
|
|
1382
|
+
const sensitiveRegistry = createDiagnosticRedactor([], input.staticSensitiveValues);
|
|
1383
|
+
const redact = (text) => redactDiagnosticText(text, sensitiveRegistry.redact);
|
|
1384
|
+
bindCriticalDiagnosticRedactor(redact, sensitiveRegistry.redactCritical, sensitiveRegistry.redactStructured, () => sensitiveRegistry.suppressed);
|
|
1280
1385
|
const requestCost = startRequestCost();
|
|
1281
|
-
const
|
|
1386
|
+
const observeEnv = {
|
|
1387
|
+
observe: createDiagnosticEnvObserver(input.provider, sensitiveRegistry.add, sensitiveRegistry.has),
|
|
1388
|
+
finished: false,
|
|
1389
|
+
staticValues: input.staticSensitiveValues,
|
|
1390
|
+
};
|
|
1391
|
+
const traceConfig = withDiagnosticEnv(observeEnv, () => resolveTraceConfigFromEnv());
|
|
1282
1392
|
const details = {
|
|
1283
1393
|
route: input.route,
|
|
1284
1394
|
requestId: input.requestId,
|
|
@@ -1297,12 +1407,14 @@ function createRequestScope(input) {
|
|
|
1297
1407
|
const initialTraceId = requestTraceId(input.headers, input.requestId);
|
|
1298
1408
|
const trace = traceConfig
|
|
1299
1409
|
? createTraceContext({
|
|
1300
|
-
...resolveServerTraceContextOptions(traceConfig, traceAttributes),
|
|
1410
|
+
...withDiagnosticEnv(observeEnv, () => resolveServerTraceContextOptions(traceConfig, traceAttributes, undefined, redact)),
|
|
1411
|
+
redact,
|
|
1301
1412
|
...(initialTraceId ? { traceId: initialTraceId } : {}),
|
|
1302
1413
|
})
|
|
1303
|
-
: createTraceContext();
|
|
1414
|
+
: createTraceContext({ redact });
|
|
1415
|
+
bindDiagnosticSensitiveRegistry(trace, sensitiveRegistry);
|
|
1304
1416
|
const proxyCollector = new ProxyTelemetryCollector();
|
|
1305
|
-
const resolverCollector = new ResolverTelemetryCollector();
|
|
1417
|
+
const resolverCollector = new ResolverTelemetryCollector({ redact });
|
|
1306
1418
|
const telemetry = new RequestTelemetry(trace);
|
|
1307
1419
|
telemetry.register(proxyCollector);
|
|
1308
1420
|
telemetry.register(resolverCollector);
|
|
@@ -1326,13 +1438,13 @@ function createRequestScope(input) {
|
|
|
1326
1438
|
return clientCancelledError();
|
|
1327
1439
|
return undefined;
|
|
1328
1440
|
};
|
|
1329
|
-
const root = trace.span(`request:${input.kind}:${input.route}`, async () => {
|
|
1441
|
+
const root = withDiagnosticEnv(observeEnv, () => trace.span(`request:${input.kind}:${input.route}`, async () => {
|
|
1330
1442
|
rootRunner = AsyncLocalStorage.snapshot();
|
|
1331
1443
|
const outcome = await rootTerminal;
|
|
1332
1444
|
const error = terminalError(outcome);
|
|
1333
1445
|
if (error !== undefined)
|
|
1334
1446
|
throw error;
|
|
1335
|
-
});
|
|
1447
|
+
}));
|
|
1336
1448
|
void root.catch(() => undefined);
|
|
1337
1449
|
const settleRoot = () => {
|
|
1338
1450
|
if (!terminalOutcome || streamingSetupPending || rootSettled)
|
|
@@ -1368,7 +1480,7 @@ function createRequestScope(input) {
|
|
|
1368
1480
|
traceAttributes.flow_id = details.flowId;
|
|
1369
1481
|
traceAttributes.route = details.route;
|
|
1370
1482
|
const traceId = requestTraceId(details.headers, details.requestId);
|
|
1371
|
-
const sanitizedAttributes = Object.fromEntries(Object.entries(sanitizeTraceAttributes(traceAttributes)).map(([key, value]) => [
|
|
1483
|
+
const sanitizedAttributes = Object.fromEntries(Object.entries(sanitizeTraceAttributes(traceAttributes, redact)).map(([key, value]) => [
|
|
1372
1484
|
key,
|
|
1373
1485
|
String(value),
|
|
1374
1486
|
]));
|
|
@@ -1378,9 +1490,17 @@ function createRequestScope(input) {
|
|
|
1378
1490
|
});
|
|
1379
1491
|
};
|
|
1380
1492
|
const scope = {
|
|
1493
|
+
redact,
|
|
1381
1494
|
trace,
|
|
1382
1495
|
telemetry,
|
|
1383
1496
|
resolverTelemetry: resolverCollector,
|
|
1497
|
+
seedCredentials(rawBody, kind) {
|
|
1498
|
+
const harvested = rawRequestCredentials(rawBody, kind);
|
|
1499
|
+
sensitiveRegistry.add(harvested.values);
|
|
1500
|
+
// An incomplete inventory cannot certify free text: emit less.
|
|
1501
|
+
if (harvested.exhausted)
|
|
1502
|
+
sensitiveRegistry.suppress();
|
|
1503
|
+
},
|
|
1384
1504
|
enrich(enrichment) {
|
|
1385
1505
|
if (terminalOutcome)
|
|
1386
1506
|
return;
|
|
@@ -1442,21 +1562,21 @@ function createRequestScope(input) {
|
|
|
1442
1562
|
terminalize(outcome) {
|
|
1443
1563
|
if (finishedResult)
|
|
1444
1564
|
return finishedResult;
|
|
1565
|
+
observeEnv.finished = true;
|
|
1445
1566
|
terminalOutcome = outcome;
|
|
1446
1567
|
const error = terminalError(outcome);
|
|
1447
1568
|
finishedResult = {};
|
|
1448
1569
|
try {
|
|
1449
1570
|
const declaredErrorCode = error === undefined ? undefined : input.declaredErrorCode?.(error);
|
|
1450
|
-
const status = outcome.status ??
|
|
1451
|
-
(error === undefined ? 200 : toStatusCode(error, declaredErrorCode));
|
|
1571
|
+
const status = outcome.status ?? (error === undefined ? 200 : toStatusCode(error, declaredErrorCode));
|
|
1452
1572
|
finishedResult = headerSnapshot(error);
|
|
1453
1573
|
const cost = finishRequestCost(requestCost);
|
|
1454
1574
|
try {
|
|
1455
1575
|
if (error === undefined) {
|
|
1456
|
-
logProviderSuccess(input.logger, input.provider, input.kind, details.route, details.requestId, status, cost, telemetry, details.correlation);
|
|
1576
|
+
logProviderSuccess(input.logger, input.provider, input.kind, details.route, details.requestId, status, cost, telemetry, details.correlation, redact);
|
|
1457
1577
|
}
|
|
1458
1578
|
else {
|
|
1459
|
-
logProviderError(input.logger, input.provider, input.kind, details.route, details.requestId, error, status, cost, declaredErrorCode, telemetry, finishedResult.errorObservability, details.correlation);
|
|
1579
|
+
logProviderError(input.logger, input.provider, input.kind, details.route, details.requestId, error, status, cost, declaredErrorCode, telemetry, finishedResult.errorObservability, details.correlation, redact);
|
|
1460
1580
|
}
|
|
1461
1581
|
}
|
|
1462
1582
|
catch {
|
|
@@ -1490,8 +1610,9 @@ function createRequestScope(input) {
|
|
|
1490
1610
|
};
|
|
1491
1611
|
return scope;
|
|
1492
1612
|
}
|
|
1493
|
-
// A raw `Response` result skips `toErrorResponse
|
|
1494
|
-
// provider-owned
|
|
1613
|
+
// A raw `Response` result skips `toErrorResponse`. Its payload shape stays
|
|
1614
|
+
// provider-owned; known credentials in error payloads still need redaction.
|
|
1615
|
+
// The observability header is SDK-owned: derive it
|
|
1495
1616
|
// from the status. Only timeouts, rate limits, and 5xx are retryable;
|
|
1496
1617
|
// `isRetryableCategory` would otherwise mark every other 4xx (`upstream_http`)
|
|
1497
1618
|
// as retryable.
|
|
@@ -1505,7 +1626,7 @@ function rawResponseErrorObservability(status) {
|
|
|
1505
1626
|
// `rawStatusFallback` is decided by the caller from the outcome, not from a
|
|
1506
1627
|
// missing snapshot: a failed outcome whose thrown value is `undefined` also has
|
|
1507
1628
|
// no `errorObservability`, and its 500 carries the SDK envelope, not a raw body.
|
|
1508
|
-
function responseWithRequestScopeHeaders(response, finished, rawStatusFallback) {
|
|
1629
|
+
async function responseWithRequestScopeHeaders(response, finished, rawStatusFallback, redact) {
|
|
1509
1630
|
const headers = new Headers(response.headers);
|
|
1510
1631
|
headers.delete(PROVIDER_TELEMETRY_HEADER);
|
|
1511
1632
|
if (finished.providerTelemetryHeader) {
|
|
@@ -1519,16 +1640,25 @@ function responseWithRequestScopeHeaders(response, finished, rawStatusFallback)
|
|
|
1519
1640
|
if (errorObservability) {
|
|
1520
1641
|
headers.set(ERROR_OBSERVABILITY_HEADER, JSON.stringify(errorObservability));
|
|
1521
1642
|
}
|
|
1522
|
-
|
|
1643
|
+
// Raw Response bodies are provider-owned. Preserve their stream and representation.
|
|
1644
|
+
const body = response.body;
|
|
1645
|
+
const statusText = rawStatusFallback && response.status >= 400
|
|
1646
|
+
? redactDiagnosticText(response.statusText, redact)
|
|
1647
|
+
: response.statusText;
|
|
1648
|
+
return new Response(body, {
|
|
1523
1649
|
headers,
|
|
1524
1650
|
status: response.status,
|
|
1525
|
-
|
|
1651
|
+
// When free text cannot be certified, use the SDK's standard HTTP reason
|
|
1652
|
+
// phrase. It preserves the status contract without trusting provider text.
|
|
1653
|
+
statusText: statusText === REDACTION_FAILED && isDiagnosticRedactionSuppressed(redact)
|
|
1654
|
+
? (STATUS_CODES[response.status] ?? "")
|
|
1655
|
+
: statusText,
|
|
1526
1656
|
});
|
|
1527
1657
|
}
|
|
1528
|
-
function finalizeRequestResponse(scope, response, outcome) {
|
|
1658
|
+
async function finalizeRequestResponse(scope, response, outcome) {
|
|
1529
1659
|
try {
|
|
1530
1660
|
const error = outcome.kind === "failed" ? outcome.error : undefined;
|
|
1531
|
-
const finalResponse = responseWithRequestScopeHeaders(response, scope.snapshotHeaders(error), outcome.kind === "completed");
|
|
1661
|
+
const finalResponse = await responseWithRequestScopeHeaders(response, scope.snapshotHeaders(error), outcome.kind === "completed", scope.redact);
|
|
1532
1662
|
scope.terminalize(outcome);
|
|
1533
1663
|
return finalResponse;
|
|
1534
1664
|
}
|
|
@@ -1706,7 +1836,7 @@ function toSseResponse(operation, result, lifecycle, requestId) {
|
|
|
1706
1836
|
}
|
|
1707
1837
|
catch (error) {
|
|
1708
1838
|
const message = error instanceof Error ? error.message : "Stream failed";
|
|
1709
|
-
controller.enqueue(encoder.encode(encodeSseEvent(streamError("stream_error", message, {
|
|
1839
|
+
controller.enqueue(encoder.encode(encodeSseEvent(streamError("stream_error", sanitizeDiagnosticText(redactDiagnosticText(message, lifecycle.redact)), {
|
|
1710
1840
|
...(requestId ? { requestId } : {}),
|
|
1711
1841
|
}))));
|
|
1712
1842
|
controller.close();
|
|
@@ -1886,7 +2016,7 @@ async function handleOperation(provider, request, operationId, options, state =
|
|
|
1886
2016
|
ctx.stealth.close?.();
|
|
1887
2017
|
}
|
|
1888
2018
|
catch (error) {
|
|
1889
|
-
logProviderCleanupError(options.logger, provider, "operation", operationId, request.requestId, "stealth", error);
|
|
2019
|
+
logProviderCleanupError(options.logger, provider, "operation", operationId, request.requestId, "stealth", error, scope.redact);
|
|
1890
2020
|
}
|
|
1891
2021
|
}
|
|
1892
2022
|
if ("browser" in ctx) {
|
|
@@ -1894,11 +2024,12 @@ async function handleOperation(provider, request, operationId, options, state =
|
|
|
1894
2024
|
await ctx.browser.close?.();
|
|
1895
2025
|
}
|
|
1896
2026
|
catch (error) {
|
|
1897
|
-
logProviderCleanupError(options.logger, provider, "operation", operationId, request.requestId, "browser", error);
|
|
2027
|
+
logProviderCleanupError(options.logger, provider, "operation", operationId, request.requestId, "browser", error, scope.redact);
|
|
1898
2028
|
}
|
|
1899
2029
|
}
|
|
1900
2030
|
};
|
|
1901
2031
|
const streamLifecycle = {
|
|
2032
|
+
redact: scope.redact,
|
|
1902
2033
|
runStep(fn) {
|
|
1903
2034
|
return scope.runStreamStep(fn);
|
|
1904
2035
|
},
|
|
@@ -1996,7 +2127,7 @@ async function handleAuthFlow(provider, request, route, options, state, scope, s
|
|
|
1996
2127
|
context.stealth.close?.();
|
|
1997
2128
|
}
|
|
1998
2129
|
catch (error) {
|
|
1999
|
-
logProviderCleanupError(options.logger, provider, "auth", route, request.requestId, "stealth", error);
|
|
2130
|
+
logProviderCleanupError(options.logger, provider, "auth", route, request.requestId, "stealth", error, scope.redact);
|
|
2000
2131
|
}
|
|
2001
2132
|
}
|
|
2002
2133
|
}
|
|
@@ -2102,13 +2233,13 @@ function operationRequestFromForwardingEnvelope(envelope) {
|
|
|
2102
2233
|
...(envelope.deadlineAt !== undefined ? { deadlineAt: envelope.deadlineAt } : {}),
|
|
2103
2234
|
};
|
|
2104
2235
|
}
|
|
2105
|
-
function parseStatefulForwardingEnvelope(rawBody) {
|
|
2236
|
+
function parseStatefulForwardingEnvelope(rawBody, redact) {
|
|
2106
2237
|
const parsed = ProviderServerStatefulForwardEnvelopeSchema.safeParse(rawBody);
|
|
2107
2238
|
if (parsed.success)
|
|
2108
2239
|
return parsed.data;
|
|
2109
2240
|
throw new ProviderError("Stateful forwarding envelope is invalid.", {
|
|
2110
2241
|
code: "STATEFUL_FORWARDING_ENVELOPE_INVALID",
|
|
2111
|
-
details: zodDetails(parsed.error),
|
|
2242
|
+
details: zodDetails(parsed.error, redact),
|
|
2112
2243
|
});
|
|
2113
2244
|
}
|
|
2114
2245
|
/**
|
|
@@ -2142,6 +2273,10 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
|
|
|
2142
2273
|
engine: serverOptions.engine ?? createInProcessProviderEngine(),
|
|
2143
2274
|
};
|
|
2144
2275
|
const app = new Hono();
|
|
2276
|
+
// Compile the startup inventory once, composed with the shared outside-context fallback.
|
|
2277
|
+
const staticSensitiveValues = compileProcessDiagnosticSensitiveValues(collectStaticDiagnosticSensitiveValues(provider, {
|
|
2278
|
+
statefulForwardingSecret: options.statefulForwarding?.secret,
|
|
2279
|
+
}));
|
|
2145
2280
|
const logger = options.logger ?? defaultProviderServerLogger;
|
|
2146
2281
|
const operationErrorCodes = buildOperationErrorCodeLookup(provider);
|
|
2147
2282
|
const statefulForwardingReplayCache = new StatefulForwardingReplayCache(options.statefulForwarding?.replayCacheMaxEntries ??
|
|
@@ -2182,6 +2317,7 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
|
|
|
2182
2317
|
const operation = "stateful-internal";
|
|
2183
2318
|
const requestScope = createRequestScope({
|
|
2184
2319
|
provider,
|
|
2320
|
+
staticSensitiveValues,
|
|
2185
2321
|
kind: "operation",
|
|
2186
2322
|
route: operation,
|
|
2187
2323
|
headers: Object.fromEntries(c.req.raw.headers.entries()),
|
|
@@ -2212,7 +2348,8 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
|
|
|
2212
2348
|
code: "STATEFUL_FORWARDING_ENVELOPE_INVALID",
|
|
2213
2349
|
});
|
|
2214
2350
|
}
|
|
2215
|
-
|
|
2351
|
+
requestScope.seedCredentials(rawBody, "stateful");
|
|
2352
|
+
const envelope = parseStatefulForwardingEnvelope(rawBody, requestScope.redact);
|
|
2216
2353
|
if (envelope.providerId !== provider.id) {
|
|
2217
2354
|
throw new ProviderError("Stateful forwarding envelope providerId does not match the served provider.", { code: "STATEFUL_FORWARDING_PROVIDER_MISMATCH" });
|
|
2218
2355
|
}
|
|
@@ -2313,7 +2450,7 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
|
|
|
2313
2450
|
...(requestId ? { requestId } : {}),
|
|
2314
2451
|
});
|
|
2315
2452
|
const observabilityDetails = errorObservabilityDetails(error, declaredErrorCode);
|
|
2316
|
-
const response = c.json(toErrorResponse(error, requestId, observabilityDetails), status);
|
|
2453
|
+
const response = c.json(toErrorResponse(error, requestId, observabilityDetails, requestScope.redact), status);
|
|
2317
2454
|
return finalizeRequestResponse(requestScope, response, {
|
|
2318
2455
|
kind: "failed",
|
|
2319
2456
|
status,
|
|
@@ -2326,6 +2463,7 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
|
|
|
2326
2463
|
const operation = c.req.param("operation");
|
|
2327
2464
|
const requestScope = createRequestScope({
|
|
2328
2465
|
provider,
|
|
2466
|
+
staticSensitiveValues,
|
|
2329
2467
|
kind: "operation",
|
|
2330
2468
|
route: operation,
|
|
2331
2469
|
operationId: operation,
|
|
@@ -2339,6 +2477,7 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
|
|
|
2339
2477
|
.clone()
|
|
2340
2478
|
.json()
|
|
2341
2479
|
.catch(() => undefined);
|
|
2480
|
+
requestScope.seedCredentials(rawBody, "operation");
|
|
2342
2481
|
const body = OperationRequestSchema.parse(rawBody);
|
|
2343
2482
|
const requestHeaders = Object.fromEntries(c.req.raw.headers.entries());
|
|
2344
2483
|
body.headers = { ...requestHeaders, ...body.headers };
|
|
@@ -2356,7 +2495,7 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
|
|
|
2356
2495
|
const handled = await handleOperation(provider, body, operation, options, state, requestScope, c.req.raw.signal);
|
|
2357
2496
|
const response = handled instanceof Response ? handled : c.json(handled);
|
|
2358
2497
|
return streaming
|
|
2359
|
-
? responseWithRequestScopeHeaders(response, requestScope.snapshotHeaders(), true)
|
|
2498
|
+
? responseWithRequestScopeHeaders(response, requestScope.snapshotHeaders(), true, requestScope.redact)
|
|
2360
2499
|
: response;
|
|
2361
2500
|
};
|
|
2362
2501
|
const response = streaming
|
|
@@ -2375,7 +2514,7 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
|
|
|
2375
2514
|
const requestId = extractRequestId(rawBody);
|
|
2376
2515
|
requestScope.enrich({ ...(requestId ? { requestId } : {}) });
|
|
2377
2516
|
const observabilityDetails = errorObservabilityDetails(error, declaredErrorCode);
|
|
2378
|
-
const response = c.json(toErrorResponse(error, requestId, observabilityDetails), status);
|
|
2517
|
+
const response = c.json(toErrorResponse(error, requestId, observabilityDetails, requestScope.redact), status);
|
|
2379
2518
|
return finalizeRequestResponse(requestScope, response, {
|
|
2380
2519
|
kind: "failed",
|
|
2381
2520
|
status,
|
|
@@ -2395,6 +2534,7 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
|
|
|
2395
2534
|
let rawBody;
|
|
2396
2535
|
const requestScope = createRequestScope({
|
|
2397
2536
|
provider,
|
|
2537
|
+
staticSensitiveValues,
|
|
2398
2538
|
kind: "auth",
|
|
2399
2539
|
route: logRoute,
|
|
2400
2540
|
headers: Object.fromEntries(c.req.raw.headers.entries()),
|
|
@@ -2406,6 +2546,7 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
|
|
|
2406
2546
|
.clone()
|
|
2407
2547
|
.json()
|
|
2408
2548
|
.catch(() => undefined);
|
|
2549
|
+
requestScope.seedCredentials(rawBody, "auth");
|
|
2409
2550
|
const body = withAuthRequestHeaders(AuthFlowRequestSchema.parse(rawBody), c.req.raw.headers);
|
|
2410
2551
|
requestScope.enrich({
|
|
2411
2552
|
requestId: body.requestId,
|
|
@@ -2434,7 +2575,7 @@ function createServerAppWithCapabilityModules(provider, serverOptions, capabilit
|
|
|
2434
2575
|
const requestId = extractRequestId(rawBody);
|
|
2435
2576
|
requestScope.enrich({ ...(requestId ? { requestId } : {}) });
|
|
2436
2577
|
const observabilityDetails = errorObservabilityDetails(error);
|
|
2437
|
-
const response = c.json(toErrorResponse(error, requestId, observabilityDetails), status);
|
|
2578
|
+
const response = c.json(toErrorResponse(error, requestId, observabilityDetails, requestScope.redact), status);
|
|
2438
2579
|
return finalizeRequestResponse(requestScope, response, {
|
|
2439
2580
|
kind: "failed",
|
|
2440
2581
|
status,
|