@slates/provider 1.0.0-rc.27 → 1.0.0-rc.28
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/dist/index.cjs +34 -8
- package/dist/index.d.cts +50 -5
- package/dist/index.d.ts +50 -5
- package/dist/index.module.js +33 -8
- package/package.json +1 -1
- package/src/action/getFileUrlTool.ts +2 -1
- package/src/action/triggerGroup.ts +65 -3
- package/src/auth/redact.test.ts +31 -2
- package/src/auth/redact.ts +24 -11
- package/src/axios/trace.test.ts +21 -0
- package/src/axios/trace.ts +7 -1
package/dist/index.cjs
CHANGED
|
@@ -86,6 +86,7 @@ __export(index_exports, {
|
|
|
86
86
|
isApiErrorRecord: () => isApiErrorRecord,
|
|
87
87
|
isAxiosErrorLike: () => isAxiosErrorLike,
|
|
88
88
|
isServiceErrorData: () => isServiceErrorData,
|
|
89
|
+
isUrlEmbeddedCredential: () => isUrlEmbeddedCredential,
|
|
89
90
|
mapServiceErrorCode: () => mapServiceErrorCode,
|
|
90
91
|
mapServiceErrorToSlateErrorInput: () => mapServiceErrorToSlateErrorInput,
|
|
91
92
|
mergeScopes: () => mergeScopes,
|
|
@@ -1074,10 +1075,14 @@ var AuthConfigSecretRedactor = class {
|
|
|
1074
1075
|
return this.secretToPlaceholder.get(stringValue) ?? stringValue;
|
|
1075
1076
|
});
|
|
1076
1077
|
}
|
|
1077
|
-
|
|
1078
|
-
|
|
1078
|
+
/** `embeddable` limits which secrets are also replaced inside longer strings. */
|
|
1079
|
+
redactEmbedded(value, embeddable = () => true) {
|
|
1080
|
+
let secrets = [...this.secretToPlaceholder.entries()].filter(
|
|
1081
|
+
([secret, placeholder]) => embeddable(secret, placeholder.slice(AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX.length))
|
|
1082
|
+
).map(([secret]) => secret);
|
|
1083
|
+
if (secrets.length === 0) return this.redact(value);
|
|
1079
1084
|
let pattern = new RegExp(
|
|
1080
|
-
|
|
1085
|
+
secrets.sort((a, b) => b.length - a.length).map((secret) => secret.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|"),
|
|
1081
1086
|
"g"
|
|
1082
1087
|
);
|
|
1083
1088
|
return this.transform(value, (stringValue) => {
|
|
@@ -1130,18 +1135,21 @@ var AuthConfigSecretRedactor = class {
|
|
|
1130
1135
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1131
1136
|
}
|
|
1132
1137
|
};
|
|
1138
|
+
var URL_CREDENTIAL_KEY = /^(?:.*[-_])?(?:token|secret|password|api[-_]?key)$/i;
|
|
1139
|
+
var isUrlEmbeddedCredential = (secret, path) => secret.length >= 8 && URL_CREDENTIAL_KEY.test(path.split(".").pop() ?? "");
|
|
1133
1140
|
var redactUrlAttachmentSecrets = (attachments, authConfig) => {
|
|
1134
1141
|
if (!authConfig || !attachments) return attachments;
|
|
1135
1142
|
let redactor = new AuthConfigSecretRedactor(authConfig);
|
|
1136
1143
|
return attachments.map((attachment) => {
|
|
1137
1144
|
if (attachment.content.type !== "url") return attachment;
|
|
1138
|
-
|
|
1145
|
+
let { url, headers, query } = attachment.content;
|
|
1139
1146
|
return {
|
|
1140
1147
|
...attachment,
|
|
1141
1148
|
content: {
|
|
1142
1149
|
...attachment.content,
|
|
1143
|
-
|
|
1144
|
-
|
|
1150
|
+
url: redactor.redactEmbedded(url, isUrlEmbeddedCredential),
|
|
1151
|
+
...headers ? { headers: redactor.redactEmbedded(headers) } : {},
|
|
1152
|
+
...query ? { query: redactor.redactEmbedded(query) } : {}
|
|
1145
1153
|
}
|
|
1146
1154
|
};
|
|
1147
1155
|
});
|
|
@@ -1191,6 +1199,7 @@ var getFileUrlTool = (spec2, handleGetFileUrl) => tool(spec2, {
|
|
|
1191
1199
|
return {
|
|
1192
1200
|
output: {
|
|
1193
1201
|
...output,
|
|
1202
|
+
url: redactor.redactEmbedded(output.url, isUrlEmbeddedCredential),
|
|
1194
1203
|
...output.headers ? { headers: redactor.redactEmbedded(output.headers) } : {},
|
|
1195
1204
|
...output.query ? { query: redactor.redactEmbedded(output.query) } : {}
|
|
1196
1205
|
},
|
|
@@ -1288,6 +1297,9 @@ var SlateTriggerGroup = class _SlateTriggerGroup {
|
|
|
1288
1297
|
get webhook() {
|
|
1289
1298
|
return this._params.webhook;
|
|
1290
1299
|
}
|
|
1300
|
+
get gateway() {
|
|
1301
|
+
return this._params.gateway;
|
|
1302
|
+
}
|
|
1291
1303
|
get routingMatchers() {
|
|
1292
1304
|
return this._params.routingMatchers;
|
|
1293
1305
|
}
|
|
@@ -1304,6 +1316,7 @@ var SlateTriggerGroupBuilder = class {
|
|
|
1304
1316
|
#source = null;
|
|
1305
1317
|
#polling = null;
|
|
1306
1318
|
#webhook = null;
|
|
1319
|
+
#gateway = null;
|
|
1307
1320
|
#routingMatchers = null;
|
|
1308
1321
|
polling(props) {
|
|
1309
1322
|
if (this.#source) {
|
|
@@ -1333,6 +1346,15 @@ var SlateTriggerGroupBuilder = class {
|
|
|
1333
1346
|
};
|
|
1334
1347
|
return this;
|
|
1335
1348
|
}
|
|
1349
|
+
/** Receive events over a platform-managed persistent connection (e.g. a WebSocket gateway). */
|
|
1350
|
+
gateway(props) {
|
|
1351
|
+
if (this.#source) {
|
|
1352
|
+
throw new SlateDeclarationError("Trigger group invocation is already defined");
|
|
1353
|
+
}
|
|
1354
|
+
this.#source = "gateway";
|
|
1355
|
+
this.#gateway = { connect: props.connect, receive: props.receive };
|
|
1356
|
+
return this;
|
|
1357
|
+
}
|
|
1336
1358
|
routingMatchers(handler) {
|
|
1337
1359
|
this.#routingMatchers = handler;
|
|
1338
1360
|
return this;
|
|
@@ -1340,7 +1362,7 @@ var SlateTriggerGroupBuilder = class {
|
|
|
1340
1362
|
build() {
|
|
1341
1363
|
if (!this.#source) {
|
|
1342
1364
|
throw new SlateDeclarationError(
|
|
1343
|
-
"Trigger group invocation (polling or
|
|
1365
|
+
"Trigger group invocation (polling, webhook, or gateway) is not defined"
|
|
1344
1366
|
);
|
|
1345
1367
|
}
|
|
1346
1368
|
if (!this.#routingMatchers) {
|
|
@@ -1351,6 +1373,7 @@ var SlateTriggerGroupBuilder = class {
|
|
|
1351
1373
|
source: this.#source,
|
|
1352
1374
|
polling: this.#polling ?? void 0,
|
|
1353
1375
|
webhook: this.#webhook ?? void 0,
|
|
1376
|
+
gateway: this.#gateway ?? void 0,
|
|
1354
1377
|
routingMatchers: this.#routingMatchers
|
|
1355
1378
|
});
|
|
1356
1379
|
}
|
|
@@ -2140,6 +2163,7 @@ var redactHashFragment = (hash, redactor) => {
|
|
|
2140
2163
|
);
|
|
2141
2164
|
return redacted ? `#${redacted}` : "";
|
|
2142
2165
|
};
|
|
2166
|
+
var isEmbeddedPathSecret = (secret, path) => secret.length >= 8 && isSecretKeyName(path.split(".").pop() ?? "");
|
|
2143
2167
|
var sanitizeUrl = (value, redactor) => {
|
|
2144
2168
|
if (!value) return value;
|
|
2145
2169
|
try {
|
|
@@ -2148,6 +2172,7 @@ var sanitizeUrl = (value, redactor) => {
|
|
|
2148
2172
|
url.username = "";
|
|
2149
2173
|
url.password = "";
|
|
2150
2174
|
}
|
|
2175
|
+
if (redactor) url.pathname = redactor.redactEmbedded(url.pathname, isEmbeddedPathSecret);
|
|
2151
2176
|
for (let key of Array.from(url.searchParams.keys())) {
|
|
2152
2177
|
if (isUrlFormSecretKeyName(key)) {
|
|
2153
2178
|
url.searchParams.set(key, REDACTED_VALUE);
|
|
@@ -2160,7 +2185,7 @@ var sanitizeUrl = (value, redactor) => {
|
|
|
2160
2185
|
url.hash = redactHashFragment(url.hash, redactor);
|
|
2161
2186
|
return decodeRedactedMarker(url.toString());
|
|
2162
2187
|
} catch {
|
|
2163
|
-
let text = redactor ? redactor.
|
|
2188
|
+
let text = redactor ? redactor.redactEmbedded(value, isEmbeddedPathSecret) : value;
|
|
2164
2189
|
return text.replace(
|
|
2165
2190
|
/([?&]([^=&#]+)=)([^&#]+)/g,
|
|
2166
2191
|
(_match, prefix, key, rawValue) => isUrlFormSecretKeyName(key) ? `${prefix}${REDACTED_VALUE}` : `${prefix}${rawValue}`
|
|
@@ -3012,6 +3037,7 @@ var skipWebhook = (reason, response) => ({
|
|
|
3012
3037
|
isApiErrorRecord,
|
|
3013
3038
|
isAxiosErrorLike,
|
|
3014
3039
|
isServiceErrorData,
|
|
3040
|
+
isUrlEmbeddedCredential,
|
|
3015
3041
|
mapServiceErrorCode,
|
|
3016
3042
|
mapServiceErrorToSlateErrorInput,
|
|
3017
3043
|
mergeScopes,
|
package/dist/index.d.cts
CHANGED
|
@@ -50,15 +50,17 @@ declare class AuthConfigSecretRedactor {
|
|
|
50
50
|
private readonly secretToPlaceholder;
|
|
51
51
|
constructor(authConfig: Record<string, unknown> | undefined);
|
|
52
52
|
redact<T>(value: T): T;
|
|
53
|
-
|
|
53
|
+
/** `embeddable` limits which secrets are also replaced inside longer strings. */
|
|
54
|
+
redactEmbedded<T>(value: T, embeddable?: (secret: string, path: string) => boolean): T;
|
|
54
55
|
private buildSecretMap;
|
|
55
56
|
private transform;
|
|
56
57
|
private isPlainObject;
|
|
57
58
|
}
|
|
59
|
+
declare let isUrlEmbeddedCredential: (secret: string, path: string) => boolean;
|
|
58
60
|
/**
|
|
59
61
|
* Applied to every finalized attachment list right before it's sent over
|
|
60
62
|
* `slates/action.tool.invoke` (see @slates/provider-handler). Only `type: 'url'` attachments
|
|
61
|
-
* carry
|
|
63
|
+
* carry credentials -- content/upload_reference attachments pass through untouched.
|
|
62
64
|
*/
|
|
63
65
|
declare let redactUrlAttachmentSecrets: (attachments: SlateAttachment[] | undefined, authConfig: Record<string, unknown> | undefined) => SlateAttachment[] | undefined;
|
|
64
66
|
|
|
@@ -523,6 +525,41 @@ type SlateTriggerGroupPollHandler<ConfigType extends {}, AuthType extends {}> =
|
|
|
523
525
|
}[];
|
|
524
526
|
updatedState?: any;
|
|
525
527
|
}>;
|
|
528
|
+
interface SlateGatewayEvent {
|
|
529
|
+
payload: any;
|
|
530
|
+
idempotencyKey?: string;
|
|
531
|
+
}
|
|
532
|
+
type SlateTriggerGroupGatewayConnectHandler<ConfigType extends {}, AuthType extends {}> = (context: SlateContext<ConfigType, AuthType, {
|
|
533
|
+
state: any | null;
|
|
534
|
+
}>) => Promise<{
|
|
535
|
+
url: string;
|
|
536
|
+
state?: any;
|
|
537
|
+
}>;
|
|
538
|
+
/** `closed` is set, with no frames, when the socket closed unexpectedly. */
|
|
539
|
+
type SlateTriggerGroupGatewayReceiveHandler<ConfigType extends {}, AuthType extends {}> = (context: SlateContext<ConfigType, AuthType, {
|
|
540
|
+
state: any | null;
|
|
541
|
+
frames: string[];
|
|
542
|
+
closed?: {
|
|
543
|
+
code: number;
|
|
544
|
+
reason: string;
|
|
545
|
+
} | null;
|
|
546
|
+
}>) => Promise<{
|
|
547
|
+
state?: any;
|
|
548
|
+
send?: string[];
|
|
549
|
+
events?: SlateGatewayEvent[];
|
|
550
|
+
/** With `expectsAck`, the hub reconnects when no `heartbeatAcked` arrives before the next beat. */
|
|
551
|
+
heartbeat?: {
|
|
552
|
+
intervalMs: number;
|
|
553
|
+
frame: string;
|
|
554
|
+
expectsAck?: boolean;
|
|
555
|
+
} | null;
|
|
556
|
+
/** Set when `frames` included the provider's heartbeat acknowledgement. */
|
|
557
|
+
heartbeatAcked?: boolean;
|
|
558
|
+
close?: {
|
|
559
|
+
reconnect: boolean;
|
|
560
|
+
reason?: string;
|
|
561
|
+
} | null;
|
|
562
|
+
}>;
|
|
526
563
|
type SlateWebhookTargetListHandler<ConfigType extends {}, AuthType extends {}> = (context: SlateContext<ConfigType, AuthType, {
|
|
527
564
|
pageToken: any | null;
|
|
528
565
|
}>) => Promise<{
|
|
@@ -574,6 +611,10 @@ interface SlateTriggerGroupPollingParameters<ConfigType extends {}, AuthType ext
|
|
|
574
611
|
intervalSeconds: number;
|
|
575
612
|
pollEvents: SlateTriggerGroupPollHandler<ConfigType, AuthType>;
|
|
576
613
|
}
|
|
614
|
+
interface SlateTriggerGroupGatewayParameters<ConfigType extends {}, AuthType extends {}> {
|
|
615
|
+
connect: SlateTriggerGroupGatewayConnectHandler<ConfigType, AuthType>;
|
|
616
|
+
receive: SlateTriggerGroupGatewayReceiveHandler<ConfigType, AuthType>;
|
|
617
|
+
}
|
|
577
618
|
interface SlateTriggerGroupWebhookAutoRegistrationParameters<ConfigType extends {}, AuthType extends {}> {
|
|
578
619
|
webhookTargetList: SlateWebhookTargetListHandler<ConfigType, AuthType>;
|
|
579
620
|
webhookRegister: SlateWebhookRegisterHandler<ConfigType, AuthType>;
|
|
@@ -598,9 +639,10 @@ interface SlateTriggerGroupCreateParameters<InputType extends {} = Record<string
|
|
|
598
639
|
eventSchema?: z$1.ZodType<InputType>;
|
|
599
640
|
}
|
|
600
641
|
interface SlateTriggerGroupParameters<ConfigType extends {}, AuthType extends {}, InputType extends {} = Record<string, unknown>> extends SlateTriggerGroupCreateParameters<InputType> {
|
|
601
|
-
source: 'polling' | 'webhook';
|
|
642
|
+
source: 'polling' | 'webhook' | 'gateway';
|
|
602
643
|
polling?: SlateTriggerGroupPollingParameters<ConfigType, AuthType>;
|
|
603
644
|
webhook?: SlateTriggerGroupWebhookParameters<ConfigType, AuthType>;
|
|
645
|
+
gateway?: SlateTriggerGroupGatewayParameters<ConfigType, AuthType>;
|
|
604
646
|
routingMatchers: SlateTriggerGroupRoutingMatchersHandler<ConfigType, AuthType>;
|
|
605
647
|
}
|
|
606
648
|
declare class SlateTriggerGroup<ConfigType extends {}, AuthType extends {}, InputType extends {} = Record<string, unknown>> {
|
|
@@ -614,9 +656,10 @@ declare class SlateTriggerGroup<ConfigType extends {}, AuthType extends {}, Inpu
|
|
|
614
656
|
get description(): string | undefined;
|
|
615
657
|
get metadata(): Record<string, any> | undefined;
|
|
616
658
|
get eventSchema(): z$1.ZodType<InputType, unknown, z$1.core.$ZodTypeInternals<InputType, unknown>>;
|
|
617
|
-
get source(): "polling" | "webhook";
|
|
659
|
+
get source(): "polling" | "webhook" | "gateway";
|
|
618
660
|
get polling(): SlateTriggerGroupPollingParameters<ConfigType, AuthType> | undefined;
|
|
619
661
|
get webhook(): SlateTriggerGroupWebhookParameters<ConfigType, AuthType> | undefined;
|
|
662
|
+
get gateway(): SlateTriggerGroupGatewayParameters<ConfigType, AuthType> | undefined;
|
|
620
663
|
get routingMatchers(): SlateTriggerGroupRoutingMatchersHandler<ConfigType, AuthType>;
|
|
621
664
|
}
|
|
622
665
|
declare class SlateTriggerGroupBuilder<ConfigType extends {}, AuthType extends {}, InputType extends {} = Record<string, unknown>> {
|
|
@@ -634,6 +677,8 @@ declare class SlateTriggerGroupBuilder<ConfigType extends {}, AuthType extends {
|
|
|
634
677
|
manualRegistration?: SlateTriggerGroupWebhookManualRegistrationParameters<UserConfigSchema, FullConfigSchema>;
|
|
635
678
|
process: SlateWebhookProcessHandler;
|
|
636
679
|
}): SlateTriggerGroupBuilder<ConfigType, AuthType, InputType>;
|
|
680
|
+
/** Receive events over a platform-managed persistent connection (e.g. a WebSocket gateway). */
|
|
681
|
+
gateway(props: SlateTriggerGroupGatewayParameters<ConfigType, AuthType>): SlateTriggerGroupBuilder<ConfigType, AuthType, InputType>;
|
|
637
682
|
routingMatchers(handler: SlateTriggerGroupRoutingMatchersHandler<ConfigType, AuthType>): SlateTriggerGroupBuilder<ConfigType, AuthType, InputType>;
|
|
638
683
|
build(): SlateTriggerGroup<ConfigType, AuthType, InputType>;
|
|
639
684
|
}
|
|
@@ -1094,4 +1139,4 @@ declare let skipWebhook: (reason: string, response?: Response | SlateWebhookHttp
|
|
|
1094
1139
|
response: Response | SlateWebhookHttpResponseInit;
|
|
1095
1140
|
};
|
|
1096
1141
|
|
|
1097
|
-
export { AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX, type ApiErrorBuildHelpers, type ApiErrorDetailOptions, type ApiErrorResponse, type ApiErrorStatus, type ApiServiceError, AuthConfigSecretRedactor, type BuildApiServiceErrorOptions, type CreateHmacSignatureOptions, GET_FILE_URL_TOOL_ID, type GetFileUrlHandler, type GetFileUrlToolInput, type GetFileUrlToolOutput, type NormalizeOAuthTokenResponseOptions, type OAuthExpiresAtOptions, type OAuthRefreshTokenFallbackMode, type OAuthTokenResponse, Slate, SlateAction, SlateActionBuilder, type SlateActionCreateParameters, type SlateActionDocsReference, type SlateActionParameters, type SlateActionParametersAny, type SlateActionParametersTool, type SlateActionParametersTrigger, type SlateActionScopeClause, type SlateActionScopeClauseInput, type SlateActionScopeValue, type SlateActionScopes, type SlateActionScopesInput, type SlateActionType, SlateAdapter, type SlateAdapterCapability, SlateAdapterSpec, type SlateAdapterSpecParameters, type SlateAddAttachmentContent, type SlateAddAttachmentInput, type SlateAttachment, type SlateAttachmentInlineContent, type SlateAttachmentUploadReferenceContent, type SlateAttachmentUrlContent, SlateAuth, type SlateAuthDocsReference, type SlateAuthType, type SlateAuthWithCustomData, type SlateAuthWithNone, type SlateAuthWithOauth, type SlateAuthWithServiceAccount, type SlateAuthWithToken, type SlateAuthenticatedAxiosDefaults, type SlateAxiosDefaults, type SlateAxiosErrorAdapter, type SlateAxiosErrorOptions, SlateConfig, type SlateConfigDocsReference, SlateContext, SlateDeclarationError, SlateDefaultPollingIntervalSeconds, type SlateDirectUploadInput, type SlateDocsReference, SlateError, type SlateErrorInput, type SlateErrorIssue, type SlateErrorKind, type SlateErrorProviderInfo, type SlateErrorResponse, type SlateErrorUpstreamInfo, type SlateLiveInvocationInfo, type SlateLogEntry, type SlateLogFields, type SlateLogListener, type SlateLogMessageInput, type SlateLogType, SlateLogger, type SlateProviderDocsReference, SlatePublicContext, SlatePublicTool, type SlatePublicToolInvocationHandler, type SlatePublicToolParameters, type SlateServiceErrorData, SlateSpecification, type SlateSpecificationCreateParameters, type SlateSpecificationParameters, SlateTool, type SlateToolInvocationHandler, type SlateToolParameters, SlateTrigger, SlateTriggerGroup, SlateTriggerGroupBuilder, type SlateTriggerGroupCreateParameters, type SlateTriggerGroupParameters, type SlateTriggerGroupPollHandler, type SlateTriggerGroupPollingParameters, type SlateTriggerGroupRoutingMatchersHandler, type SlateTriggerGroupWebhookAutoRegistrationParameters, type SlateTriggerGroupWebhookManualRegistrationParameters, type SlateTriggerGroupWebhookParameters, type SlateTriggerMappingHandler, type SlateTriggerMatchesHandler, type SlateTriggerParameters, type SlateTriggerRoutingMatcher, type SlateTypedDocsReference, type SlateWebhookHttpResponseInit, type SlateWebhookManualFinishHandler, type SlateWebhookManualSetupHandler, type SlateWebhookProcessHandler, type SlateWebhookRegisterHandler, type SlateWebhookSkipped, type SlateWebhookTarget, type SlateWebhookTargetListHandler, type SlateWebhookTargetOwnership, type SlateWebhookUnregisterHandler, type VerifyHmacSignatureOptions, adapterSpec, allOf, anyOf, auth, axios, buildApiServiceError, collectApiErrorDetails, config, createApiServiceError, createAuthenticatedAxios, createAxios, createBase64Attachment, createHmacSignature, createSlateError, createTextAttachment, createUrlAttachment, extractApiErrorMessage, getApiErrorResponse, getApiErrorStatus, getBase64ByteLength, getCurrentContext, getFileUrlTool, getFileUrlToolInputSchema, getFileUrlToolOutputSchema, getGraphWebhookValidationResponse, getMetaWebhookVerificationResponse, getOAuthExpiresAtFromExpiresIn, getResponseHeaderValue, getServiceErrorData, graphWebhookHttp, inferSlateErrorFromAxios, isApiErrorRecord, isAxiosErrorLike, isServiceErrorData, mapServiceErrorCode, mapServiceErrorToSlateErrorInput, mergeScopes, metaWebhookHttp, normalizeOAuthTokenResponse, pickDefined, publicTool, redactUrlAttachmentSecrets, requestAxios, requestAxiosData, runWithContext, scopeClause, setIfDefined, skipWebhook, spec, statusLabelForApiError, tool, trigger, triggerGroup, uploadAttachmentDirect, validateScopes, verifyHmacSignature };
|
|
1142
|
+
export { AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX, type ApiErrorBuildHelpers, type ApiErrorDetailOptions, type ApiErrorResponse, type ApiErrorStatus, type ApiServiceError, AuthConfigSecretRedactor, type BuildApiServiceErrorOptions, type CreateHmacSignatureOptions, GET_FILE_URL_TOOL_ID, type GetFileUrlHandler, type GetFileUrlToolInput, type GetFileUrlToolOutput, type NormalizeOAuthTokenResponseOptions, type OAuthExpiresAtOptions, type OAuthRefreshTokenFallbackMode, type OAuthTokenResponse, Slate, SlateAction, SlateActionBuilder, type SlateActionCreateParameters, type SlateActionDocsReference, type SlateActionParameters, type SlateActionParametersAny, type SlateActionParametersTool, type SlateActionParametersTrigger, type SlateActionScopeClause, type SlateActionScopeClauseInput, type SlateActionScopeValue, type SlateActionScopes, type SlateActionScopesInput, type SlateActionType, SlateAdapter, type SlateAdapterCapability, SlateAdapterSpec, type SlateAdapterSpecParameters, type SlateAddAttachmentContent, type SlateAddAttachmentInput, type SlateAttachment, type SlateAttachmentInlineContent, type SlateAttachmentUploadReferenceContent, type SlateAttachmentUrlContent, SlateAuth, type SlateAuthDocsReference, type SlateAuthType, type SlateAuthWithCustomData, type SlateAuthWithNone, type SlateAuthWithOauth, type SlateAuthWithServiceAccount, type SlateAuthWithToken, type SlateAuthenticatedAxiosDefaults, type SlateAxiosDefaults, type SlateAxiosErrorAdapter, type SlateAxiosErrorOptions, SlateConfig, type SlateConfigDocsReference, SlateContext, SlateDeclarationError, SlateDefaultPollingIntervalSeconds, type SlateDirectUploadInput, type SlateDocsReference, SlateError, type SlateErrorInput, type SlateErrorIssue, type SlateErrorKind, type SlateErrorProviderInfo, type SlateErrorResponse, type SlateErrorUpstreamInfo, type SlateGatewayEvent, type SlateLiveInvocationInfo, type SlateLogEntry, type SlateLogFields, type SlateLogListener, type SlateLogMessageInput, type SlateLogType, SlateLogger, type SlateProviderDocsReference, SlatePublicContext, SlatePublicTool, type SlatePublicToolInvocationHandler, type SlatePublicToolParameters, type SlateServiceErrorData, SlateSpecification, type SlateSpecificationCreateParameters, type SlateSpecificationParameters, SlateTool, type SlateToolInvocationHandler, type SlateToolParameters, SlateTrigger, SlateTriggerGroup, SlateTriggerGroupBuilder, type SlateTriggerGroupCreateParameters, type SlateTriggerGroupGatewayConnectHandler, type SlateTriggerGroupGatewayParameters, type SlateTriggerGroupGatewayReceiveHandler, type SlateTriggerGroupParameters, type SlateTriggerGroupPollHandler, type SlateTriggerGroupPollingParameters, type SlateTriggerGroupRoutingMatchersHandler, type SlateTriggerGroupWebhookAutoRegistrationParameters, type SlateTriggerGroupWebhookManualRegistrationParameters, type SlateTriggerGroupWebhookParameters, type SlateTriggerMappingHandler, type SlateTriggerMatchesHandler, type SlateTriggerParameters, type SlateTriggerRoutingMatcher, type SlateTypedDocsReference, type SlateWebhookHttpResponseInit, type SlateWebhookManualFinishHandler, type SlateWebhookManualSetupHandler, type SlateWebhookProcessHandler, type SlateWebhookRegisterHandler, type SlateWebhookSkipped, type SlateWebhookTarget, type SlateWebhookTargetListHandler, type SlateWebhookTargetOwnership, type SlateWebhookUnregisterHandler, type VerifyHmacSignatureOptions, adapterSpec, allOf, anyOf, auth, axios, buildApiServiceError, collectApiErrorDetails, config, createApiServiceError, createAuthenticatedAxios, createAxios, createBase64Attachment, createHmacSignature, createSlateError, createTextAttachment, createUrlAttachment, extractApiErrorMessage, getApiErrorResponse, getApiErrorStatus, getBase64ByteLength, getCurrentContext, getFileUrlTool, getFileUrlToolInputSchema, getFileUrlToolOutputSchema, getGraphWebhookValidationResponse, getMetaWebhookVerificationResponse, getOAuthExpiresAtFromExpiresIn, getResponseHeaderValue, getServiceErrorData, graphWebhookHttp, inferSlateErrorFromAxios, isApiErrorRecord, isAxiosErrorLike, isServiceErrorData, isUrlEmbeddedCredential, mapServiceErrorCode, mapServiceErrorToSlateErrorInput, mergeScopes, metaWebhookHttp, normalizeOAuthTokenResponse, pickDefined, publicTool, redactUrlAttachmentSecrets, requestAxios, requestAxiosData, runWithContext, scopeClause, setIfDefined, skipWebhook, spec, statusLabelForApiError, tool, trigger, triggerGroup, uploadAttachmentDirect, validateScopes, verifyHmacSignature };
|
package/dist/index.d.ts
CHANGED
|
@@ -50,15 +50,17 @@ declare class AuthConfigSecretRedactor {
|
|
|
50
50
|
private readonly secretToPlaceholder;
|
|
51
51
|
constructor(authConfig: Record<string, unknown> | undefined);
|
|
52
52
|
redact<T>(value: T): T;
|
|
53
|
-
|
|
53
|
+
/** `embeddable` limits which secrets are also replaced inside longer strings. */
|
|
54
|
+
redactEmbedded<T>(value: T, embeddable?: (secret: string, path: string) => boolean): T;
|
|
54
55
|
private buildSecretMap;
|
|
55
56
|
private transform;
|
|
56
57
|
private isPlainObject;
|
|
57
58
|
}
|
|
59
|
+
declare let isUrlEmbeddedCredential: (secret: string, path: string) => boolean;
|
|
58
60
|
/**
|
|
59
61
|
* Applied to every finalized attachment list right before it's sent over
|
|
60
62
|
* `slates/action.tool.invoke` (see @slates/provider-handler). Only `type: 'url'` attachments
|
|
61
|
-
* carry
|
|
63
|
+
* carry credentials -- content/upload_reference attachments pass through untouched.
|
|
62
64
|
*/
|
|
63
65
|
declare let redactUrlAttachmentSecrets: (attachments: SlateAttachment[] | undefined, authConfig: Record<string, unknown> | undefined) => SlateAttachment[] | undefined;
|
|
64
66
|
|
|
@@ -523,6 +525,41 @@ type SlateTriggerGroupPollHandler<ConfigType extends {}, AuthType extends {}> =
|
|
|
523
525
|
}[];
|
|
524
526
|
updatedState?: any;
|
|
525
527
|
}>;
|
|
528
|
+
interface SlateGatewayEvent {
|
|
529
|
+
payload: any;
|
|
530
|
+
idempotencyKey?: string;
|
|
531
|
+
}
|
|
532
|
+
type SlateTriggerGroupGatewayConnectHandler<ConfigType extends {}, AuthType extends {}> = (context: SlateContext<ConfigType, AuthType, {
|
|
533
|
+
state: any | null;
|
|
534
|
+
}>) => Promise<{
|
|
535
|
+
url: string;
|
|
536
|
+
state?: any;
|
|
537
|
+
}>;
|
|
538
|
+
/** `closed` is set, with no frames, when the socket closed unexpectedly. */
|
|
539
|
+
type SlateTriggerGroupGatewayReceiveHandler<ConfigType extends {}, AuthType extends {}> = (context: SlateContext<ConfigType, AuthType, {
|
|
540
|
+
state: any | null;
|
|
541
|
+
frames: string[];
|
|
542
|
+
closed?: {
|
|
543
|
+
code: number;
|
|
544
|
+
reason: string;
|
|
545
|
+
} | null;
|
|
546
|
+
}>) => Promise<{
|
|
547
|
+
state?: any;
|
|
548
|
+
send?: string[];
|
|
549
|
+
events?: SlateGatewayEvent[];
|
|
550
|
+
/** With `expectsAck`, the hub reconnects when no `heartbeatAcked` arrives before the next beat. */
|
|
551
|
+
heartbeat?: {
|
|
552
|
+
intervalMs: number;
|
|
553
|
+
frame: string;
|
|
554
|
+
expectsAck?: boolean;
|
|
555
|
+
} | null;
|
|
556
|
+
/** Set when `frames` included the provider's heartbeat acknowledgement. */
|
|
557
|
+
heartbeatAcked?: boolean;
|
|
558
|
+
close?: {
|
|
559
|
+
reconnect: boolean;
|
|
560
|
+
reason?: string;
|
|
561
|
+
} | null;
|
|
562
|
+
}>;
|
|
526
563
|
type SlateWebhookTargetListHandler<ConfigType extends {}, AuthType extends {}> = (context: SlateContext<ConfigType, AuthType, {
|
|
527
564
|
pageToken: any | null;
|
|
528
565
|
}>) => Promise<{
|
|
@@ -574,6 +611,10 @@ interface SlateTriggerGroupPollingParameters<ConfigType extends {}, AuthType ext
|
|
|
574
611
|
intervalSeconds: number;
|
|
575
612
|
pollEvents: SlateTriggerGroupPollHandler<ConfigType, AuthType>;
|
|
576
613
|
}
|
|
614
|
+
interface SlateTriggerGroupGatewayParameters<ConfigType extends {}, AuthType extends {}> {
|
|
615
|
+
connect: SlateTriggerGroupGatewayConnectHandler<ConfigType, AuthType>;
|
|
616
|
+
receive: SlateTriggerGroupGatewayReceiveHandler<ConfigType, AuthType>;
|
|
617
|
+
}
|
|
577
618
|
interface SlateTriggerGroupWebhookAutoRegistrationParameters<ConfigType extends {}, AuthType extends {}> {
|
|
578
619
|
webhookTargetList: SlateWebhookTargetListHandler<ConfigType, AuthType>;
|
|
579
620
|
webhookRegister: SlateWebhookRegisterHandler<ConfigType, AuthType>;
|
|
@@ -598,9 +639,10 @@ interface SlateTriggerGroupCreateParameters<InputType extends {} = Record<string
|
|
|
598
639
|
eventSchema?: z$1.ZodType<InputType>;
|
|
599
640
|
}
|
|
600
641
|
interface SlateTriggerGroupParameters<ConfigType extends {}, AuthType extends {}, InputType extends {} = Record<string, unknown>> extends SlateTriggerGroupCreateParameters<InputType> {
|
|
601
|
-
source: 'polling' | 'webhook';
|
|
642
|
+
source: 'polling' | 'webhook' | 'gateway';
|
|
602
643
|
polling?: SlateTriggerGroupPollingParameters<ConfigType, AuthType>;
|
|
603
644
|
webhook?: SlateTriggerGroupWebhookParameters<ConfigType, AuthType>;
|
|
645
|
+
gateway?: SlateTriggerGroupGatewayParameters<ConfigType, AuthType>;
|
|
604
646
|
routingMatchers: SlateTriggerGroupRoutingMatchersHandler<ConfigType, AuthType>;
|
|
605
647
|
}
|
|
606
648
|
declare class SlateTriggerGroup<ConfigType extends {}, AuthType extends {}, InputType extends {} = Record<string, unknown>> {
|
|
@@ -614,9 +656,10 @@ declare class SlateTriggerGroup<ConfigType extends {}, AuthType extends {}, Inpu
|
|
|
614
656
|
get description(): string | undefined;
|
|
615
657
|
get metadata(): Record<string, any> | undefined;
|
|
616
658
|
get eventSchema(): z$1.ZodType<InputType, unknown, z$1.core.$ZodTypeInternals<InputType, unknown>>;
|
|
617
|
-
get source(): "polling" | "webhook";
|
|
659
|
+
get source(): "polling" | "webhook" | "gateway";
|
|
618
660
|
get polling(): SlateTriggerGroupPollingParameters<ConfigType, AuthType> | undefined;
|
|
619
661
|
get webhook(): SlateTriggerGroupWebhookParameters<ConfigType, AuthType> | undefined;
|
|
662
|
+
get gateway(): SlateTriggerGroupGatewayParameters<ConfigType, AuthType> | undefined;
|
|
620
663
|
get routingMatchers(): SlateTriggerGroupRoutingMatchersHandler<ConfigType, AuthType>;
|
|
621
664
|
}
|
|
622
665
|
declare class SlateTriggerGroupBuilder<ConfigType extends {}, AuthType extends {}, InputType extends {} = Record<string, unknown>> {
|
|
@@ -634,6 +677,8 @@ declare class SlateTriggerGroupBuilder<ConfigType extends {}, AuthType extends {
|
|
|
634
677
|
manualRegistration?: SlateTriggerGroupWebhookManualRegistrationParameters<UserConfigSchema, FullConfigSchema>;
|
|
635
678
|
process: SlateWebhookProcessHandler;
|
|
636
679
|
}): SlateTriggerGroupBuilder<ConfigType, AuthType, InputType>;
|
|
680
|
+
/** Receive events over a platform-managed persistent connection (e.g. a WebSocket gateway). */
|
|
681
|
+
gateway(props: SlateTriggerGroupGatewayParameters<ConfigType, AuthType>): SlateTriggerGroupBuilder<ConfigType, AuthType, InputType>;
|
|
637
682
|
routingMatchers(handler: SlateTriggerGroupRoutingMatchersHandler<ConfigType, AuthType>): SlateTriggerGroupBuilder<ConfigType, AuthType, InputType>;
|
|
638
683
|
build(): SlateTriggerGroup<ConfigType, AuthType, InputType>;
|
|
639
684
|
}
|
|
@@ -1094,4 +1139,4 @@ declare let skipWebhook: (reason: string, response?: Response | SlateWebhookHttp
|
|
|
1094
1139
|
response: Response | SlateWebhookHttpResponseInit;
|
|
1095
1140
|
};
|
|
1096
1141
|
|
|
1097
|
-
export { AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX, type ApiErrorBuildHelpers, type ApiErrorDetailOptions, type ApiErrorResponse, type ApiErrorStatus, type ApiServiceError, AuthConfigSecretRedactor, type BuildApiServiceErrorOptions, type CreateHmacSignatureOptions, GET_FILE_URL_TOOL_ID, type GetFileUrlHandler, type GetFileUrlToolInput, type GetFileUrlToolOutput, type NormalizeOAuthTokenResponseOptions, type OAuthExpiresAtOptions, type OAuthRefreshTokenFallbackMode, type OAuthTokenResponse, Slate, SlateAction, SlateActionBuilder, type SlateActionCreateParameters, type SlateActionDocsReference, type SlateActionParameters, type SlateActionParametersAny, type SlateActionParametersTool, type SlateActionParametersTrigger, type SlateActionScopeClause, type SlateActionScopeClauseInput, type SlateActionScopeValue, type SlateActionScopes, type SlateActionScopesInput, type SlateActionType, SlateAdapter, type SlateAdapterCapability, SlateAdapterSpec, type SlateAdapterSpecParameters, type SlateAddAttachmentContent, type SlateAddAttachmentInput, type SlateAttachment, type SlateAttachmentInlineContent, type SlateAttachmentUploadReferenceContent, type SlateAttachmentUrlContent, SlateAuth, type SlateAuthDocsReference, type SlateAuthType, type SlateAuthWithCustomData, type SlateAuthWithNone, type SlateAuthWithOauth, type SlateAuthWithServiceAccount, type SlateAuthWithToken, type SlateAuthenticatedAxiosDefaults, type SlateAxiosDefaults, type SlateAxiosErrorAdapter, type SlateAxiosErrorOptions, SlateConfig, type SlateConfigDocsReference, SlateContext, SlateDeclarationError, SlateDefaultPollingIntervalSeconds, type SlateDirectUploadInput, type SlateDocsReference, SlateError, type SlateErrorInput, type SlateErrorIssue, type SlateErrorKind, type SlateErrorProviderInfo, type SlateErrorResponse, type SlateErrorUpstreamInfo, type SlateLiveInvocationInfo, type SlateLogEntry, type SlateLogFields, type SlateLogListener, type SlateLogMessageInput, type SlateLogType, SlateLogger, type SlateProviderDocsReference, SlatePublicContext, SlatePublicTool, type SlatePublicToolInvocationHandler, type SlatePublicToolParameters, type SlateServiceErrorData, SlateSpecification, type SlateSpecificationCreateParameters, type SlateSpecificationParameters, SlateTool, type SlateToolInvocationHandler, type SlateToolParameters, SlateTrigger, SlateTriggerGroup, SlateTriggerGroupBuilder, type SlateTriggerGroupCreateParameters, type SlateTriggerGroupParameters, type SlateTriggerGroupPollHandler, type SlateTriggerGroupPollingParameters, type SlateTriggerGroupRoutingMatchersHandler, type SlateTriggerGroupWebhookAutoRegistrationParameters, type SlateTriggerGroupWebhookManualRegistrationParameters, type SlateTriggerGroupWebhookParameters, type SlateTriggerMappingHandler, type SlateTriggerMatchesHandler, type SlateTriggerParameters, type SlateTriggerRoutingMatcher, type SlateTypedDocsReference, type SlateWebhookHttpResponseInit, type SlateWebhookManualFinishHandler, type SlateWebhookManualSetupHandler, type SlateWebhookProcessHandler, type SlateWebhookRegisterHandler, type SlateWebhookSkipped, type SlateWebhookTarget, type SlateWebhookTargetListHandler, type SlateWebhookTargetOwnership, type SlateWebhookUnregisterHandler, type VerifyHmacSignatureOptions, adapterSpec, allOf, anyOf, auth, axios, buildApiServiceError, collectApiErrorDetails, config, createApiServiceError, createAuthenticatedAxios, createAxios, createBase64Attachment, createHmacSignature, createSlateError, createTextAttachment, createUrlAttachment, extractApiErrorMessage, getApiErrorResponse, getApiErrorStatus, getBase64ByteLength, getCurrentContext, getFileUrlTool, getFileUrlToolInputSchema, getFileUrlToolOutputSchema, getGraphWebhookValidationResponse, getMetaWebhookVerificationResponse, getOAuthExpiresAtFromExpiresIn, getResponseHeaderValue, getServiceErrorData, graphWebhookHttp, inferSlateErrorFromAxios, isApiErrorRecord, isAxiosErrorLike, isServiceErrorData, mapServiceErrorCode, mapServiceErrorToSlateErrorInput, mergeScopes, metaWebhookHttp, normalizeOAuthTokenResponse, pickDefined, publicTool, redactUrlAttachmentSecrets, requestAxios, requestAxiosData, runWithContext, scopeClause, setIfDefined, skipWebhook, spec, statusLabelForApiError, tool, trigger, triggerGroup, uploadAttachmentDirect, validateScopes, verifyHmacSignature };
|
|
1142
|
+
export { AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX, type ApiErrorBuildHelpers, type ApiErrorDetailOptions, type ApiErrorResponse, type ApiErrorStatus, type ApiServiceError, AuthConfigSecretRedactor, type BuildApiServiceErrorOptions, type CreateHmacSignatureOptions, GET_FILE_URL_TOOL_ID, type GetFileUrlHandler, type GetFileUrlToolInput, type GetFileUrlToolOutput, type NormalizeOAuthTokenResponseOptions, type OAuthExpiresAtOptions, type OAuthRefreshTokenFallbackMode, type OAuthTokenResponse, Slate, SlateAction, SlateActionBuilder, type SlateActionCreateParameters, type SlateActionDocsReference, type SlateActionParameters, type SlateActionParametersAny, type SlateActionParametersTool, type SlateActionParametersTrigger, type SlateActionScopeClause, type SlateActionScopeClauseInput, type SlateActionScopeValue, type SlateActionScopes, type SlateActionScopesInput, type SlateActionType, SlateAdapter, type SlateAdapterCapability, SlateAdapterSpec, type SlateAdapterSpecParameters, type SlateAddAttachmentContent, type SlateAddAttachmentInput, type SlateAttachment, type SlateAttachmentInlineContent, type SlateAttachmentUploadReferenceContent, type SlateAttachmentUrlContent, SlateAuth, type SlateAuthDocsReference, type SlateAuthType, type SlateAuthWithCustomData, type SlateAuthWithNone, type SlateAuthWithOauth, type SlateAuthWithServiceAccount, type SlateAuthWithToken, type SlateAuthenticatedAxiosDefaults, type SlateAxiosDefaults, type SlateAxiosErrorAdapter, type SlateAxiosErrorOptions, SlateConfig, type SlateConfigDocsReference, SlateContext, SlateDeclarationError, SlateDefaultPollingIntervalSeconds, type SlateDirectUploadInput, type SlateDocsReference, SlateError, type SlateErrorInput, type SlateErrorIssue, type SlateErrorKind, type SlateErrorProviderInfo, type SlateErrorResponse, type SlateErrorUpstreamInfo, type SlateGatewayEvent, type SlateLiveInvocationInfo, type SlateLogEntry, type SlateLogFields, type SlateLogListener, type SlateLogMessageInput, type SlateLogType, SlateLogger, type SlateProviderDocsReference, SlatePublicContext, SlatePublicTool, type SlatePublicToolInvocationHandler, type SlatePublicToolParameters, type SlateServiceErrorData, SlateSpecification, type SlateSpecificationCreateParameters, type SlateSpecificationParameters, SlateTool, type SlateToolInvocationHandler, type SlateToolParameters, SlateTrigger, SlateTriggerGroup, SlateTriggerGroupBuilder, type SlateTriggerGroupCreateParameters, type SlateTriggerGroupGatewayConnectHandler, type SlateTriggerGroupGatewayParameters, type SlateTriggerGroupGatewayReceiveHandler, type SlateTriggerGroupParameters, type SlateTriggerGroupPollHandler, type SlateTriggerGroupPollingParameters, type SlateTriggerGroupRoutingMatchersHandler, type SlateTriggerGroupWebhookAutoRegistrationParameters, type SlateTriggerGroupWebhookManualRegistrationParameters, type SlateTriggerGroupWebhookParameters, type SlateTriggerMappingHandler, type SlateTriggerMatchesHandler, type SlateTriggerParameters, type SlateTriggerRoutingMatcher, type SlateTypedDocsReference, type SlateWebhookHttpResponseInit, type SlateWebhookManualFinishHandler, type SlateWebhookManualSetupHandler, type SlateWebhookProcessHandler, type SlateWebhookRegisterHandler, type SlateWebhookSkipped, type SlateWebhookTarget, type SlateWebhookTargetListHandler, type SlateWebhookTargetOwnership, type SlateWebhookUnregisterHandler, type VerifyHmacSignatureOptions, adapterSpec, allOf, anyOf, auth, axios, buildApiServiceError, collectApiErrorDetails, config, createApiServiceError, createAuthenticatedAxios, createAxios, createBase64Attachment, createHmacSignature, createSlateError, createTextAttachment, createUrlAttachment, extractApiErrorMessage, getApiErrorResponse, getApiErrorStatus, getBase64ByteLength, getCurrentContext, getFileUrlTool, getFileUrlToolInputSchema, getFileUrlToolOutputSchema, getGraphWebhookValidationResponse, getMetaWebhookVerificationResponse, getOAuthExpiresAtFromExpiresIn, getResponseHeaderValue, getServiceErrorData, graphWebhookHttp, inferSlateErrorFromAxios, isApiErrorRecord, isAxiosErrorLike, isServiceErrorData, isUrlEmbeddedCredential, mapServiceErrorCode, mapServiceErrorToSlateErrorInput, mergeScopes, metaWebhookHttp, normalizeOAuthTokenResponse, pickDefined, publicTool, redactUrlAttachmentSecrets, requestAxios, requestAxiosData, runWithContext, scopeClause, setIfDefined, skipWebhook, spec, statusLabelForApiError, tool, trigger, triggerGroup, uploadAttachmentDirect, validateScopes, verifyHmacSignature };
|
package/dist/index.module.js
CHANGED
|
@@ -961,10 +961,14 @@ var AuthConfigSecretRedactor = class {
|
|
|
961
961
|
return this.secretToPlaceholder.get(stringValue) ?? stringValue;
|
|
962
962
|
});
|
|
963
963
|
}
|
|
964
|
-
|
|
965
|
-
|
|
964
|
+
/** `embeddable` limits which secrets are also replaced inside longer strings. */
|
|
965
|
+
redactEmbedded(value, embeddable = () => true) {
|
|
966
|
+
let secrets = [...this.secretToPlaceholder.entries()].filter(
|
|
967
|
+
([secret, placeholder]) => embeddable(secret, placeholder.slice(AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX.length))
|
|
968
|
+
).map(([secret]) => secret);
|
|
969
|
+
if (secrets.length === 0) return this.redact(value);
|
|
966
970
|
let pattern = new RegExp(
|
|
967
|
-
|
|
971
|
+
secrets.sort((a, b) => b.length - a.length).map((secret) => secret.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|"),
|
|
968
972
|
"g"
|
|
969
973
|
);
|
|
970
974
|
return this.transform(value, (stringValue) => {
|
|
@@ -1017,18 +1021,21 @@ var AuthConfigSecretRedactor = class {
|
|
|
1017
1021
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1018
1022
|
}
|
|
1019
1023
|
};
|
|
1024
|
+
var URL_CREDENTIAL_KEY = /^(?:.*[-_])?(?:token|secret|password|api[-_]?key)$/i;
|
|
1025
|
+
var isUrlEmbeddedCredential = (secret, path) => secret.length >= 8 && URL_CREDENTIAL_KEY.test(path.split(".").pop() ?? "");
|
|
1020
1026
|
var redactUrlAttachmentSecrets = (attachments, authConfig) => {
|
|
1021
1027
|
if (!authConfig || !attachments) return attachments;
|
|
1022
1028
|
let redactor = new AuthConfigSecretRedactor(authConfig);
|
|
1023
1029
|
return attachments.map((attachment) => {
|
|
1024
1030
|
if (attachment.content.type !== "url") return attachment;
|
|
1025
|
-
|
|
1031
|
+
let { url, headers, query } = attachment.content;
|
|
1026
1032
|
return {
|
|
1027
1033
|
...attachment,
|
|
1028
1034
|
content: {
|
|
1029
1035
|
...attachment.content,
|
|
1030
|
-
|
|
1031
|
-
|
|
1036
|
+
url: redactor.redactEmbedded(url, isUrlEmbeddedCredential),
|
|
1037
|
+
...headers ? { headers: redactor.redactEmbedded(headers) } : {},
|
|
1038
|
+
...query ? { query: redactor.redactEmbedded(query) } : {}
|
|
1032
1039
|
}
|
|
1033
1040
|
};
|
|
1034
1041
|
});
|
|
@@ -1078,6 +1085,7 @@ var getFileUrlTool = (spec2, handleGetFileUrl) => tool(spec2, {
|
|
|
1078
1085
|
return {
|
|
1079
1086
|
output: {
|
|
1080
1087
|
...output,
|
|
1088
|
+
url: redactor.redactEmbedded(output.url, isUrlEmbeddedCredential),
|
|
1081
1089
|
...output.headers ? { headers: redactor.redactEmbedded(output.headers) } : {},
|
|
1082
1090
|
...output.query ? { query: redactor.redactEmbedded(output.query) } : {}
|
|
1083
1091
|
},
|
|
@@ -1175,6 +1183,9 @@ var SlateTriggerGroup = class _SlateTriggerGroup {
|
|
|
1175
1183
|
get webhook() {
|
|
1176
1184
|
return this._params.webhook;
|
|
1177
1185
|
}
|
|
1186
|
+
get gateway() {
|
|
1187
|
+
return this._params.gateway;
|
|
1188
|
+
}
|
|
1178
1189
|
get routingMatchers() {
|
|
1179
1190
|
return this._params.routingMatchers;
|
|
1180
1191
|
}
|
|
@@ -1191,6 +1202,7 @@ var SlateTriggerGroupBuilder = class {
|
|
|
1191
1202
|
#source = null;
|
|
1192
1203
|
#polling = null;
|
|
1193
1204
|
#webhook = null;
|
|
1205
|
+
#gateway = null;
|
|
1194
1206
|
#routingMatchers = null;
|
|
1195
1207
|
polling(props) {
|
|
1196
1208
|
if (this.#source) {
|
|
@@ -1220,6 +1232,15 @@ var SlateTriggerGroupBuilder = class {
|
|
|
1220
1232
|
};
|
|
1221
1233
|
return this;
|
|
1222
1234
|
}
|
|
1235
|
+
/** Receive events over a platform-managed persistent connection (e.g. a WebSocket gateway). */
|
|
1236
|
+
gateway(props) {
|
|
1237
|
+
if (this.#source) {
|
|
1238
|
+
throw new SlateDeclarationError("Trigger group invocation is already defined");
|
|
1239
|
+
}
|
|
1240
|
+
this.#source = "gateway";
|
|
1241
|
+
this.#gateway = { connect: props.connect, receive: props.receive };
|
|
1242
|
+
return this;
|
|
1243
|
+
}
|
|
1223
1244
|
routingMatchers(handler) {
|
|
1224
1245
|
this.#routingMatchers = handler;
|
|
1225
1246
|
return this;
|
|
@@ -1227,7 +1248,7 @@ var SlateTriggerGroupBuilder = class {
|
|
|
1227
1248
|
build() {
|
|
1228
1249
|
if (!this.#source) {
|
|
1229
1250
|
throw new SlateDeclarationError(
|
|
1230
|
-
"Trigger group invocation (polling or
|
|
1251
|
+
"Trigger group invocation (polling, webhook, or gateway) is not defined"
|
|
1231
1252
|
);
|
|
1232
1253
|
}
|
|
1233
1254
|
if (!this.#routingMatchers) {
|
|
@@ -1238,6 +1259,7 @@ var SlateTriggerGroupBuilder = class {
|
|
|
1238
1259
|
source: this.#source,
|
|
1239
1260
|
polling: this.#polling ?? void 0,
|
|
1240
1261
|
webhook: this.#webhook ?? void 0,
|
|
1262
|
+
gateway: this.#gateway ?? void 0,
|
|
1241
1263
|
routingMatchers: this.#routingMatchers
|
|
1242
1264
|
});
|
|
1243
1265
|
}
|
|
@@ -2027,6 +2049,7 @@ var redactHashFragment = (hash, redactor) => {
|
|
|
2027
2049
|
);
|
|
2028
2050
|
return redacted ? `#${redacted}` : "";
|
|
2029
2051
|
};
|
|
2052
|
+
var isEmbeddedPathSecret = (secret, path) => secret.length >= 8 && isSecretKeyName(path.split(".").pop() ?? "");
|
|
2030
2053
|
var sanitizeUrl = (value, redactor) => {
|
|
2031
2054
|
if (!value) return value;
|
|
2032
2055
|
try {
|
|
@@ -2035,6 +2058,7 @@ var sanitizeUrl = (value, redactor) => {
|
|
|
2035
2058
|
url.username = "";
|
|
2036
2059
|
url.password = "";
|
|
2037
2060
|
}
|
|
2061
|
+
if (redactor) url.pathname = redactor.redactEmbedded(url.pathname, isEmbeddedPathSecret);
|
|
2038
2062
|
for (let key of Array.from(url.searchParams.keys())) {
|
|
2039
2063
|
if (isUrlFormSecretKeyName(key)) {
|
|
2040
2064
|
url.searchParams.set(key, REDACTED_VALUE);
|
|
@@ -2047,7 +2071,7 @@ var sanitizeUrl = (value, redactor) => {
|
|
|
2047
2071
|
url.hash = redactHashFragment(url.hash, redactor);
|
|
2048
2072
|
return decodeRedactedMarker(url.toString());
|
|
2049
2073
|
} catch {
|
|
2050
|
-
let text = redactor ? redactor.
|
|
2074
|
+
let text = redactor ? redactor.redactEmbedded(value, isEmbeddedPathSecret) : value;
|
|
2051
2075
|
return text.replace(
|
|
2052
2076
|
/([?&]([^=&#]+)=)([^&#]+)/g,
|
|
2053
2077
|
(_match, prefix, key, rawValue) => isUrlFormSecretKeyName(key) ? `${prefix}${REDACTED_VALUE}` : `${prefix}${rawValue}`
|
|
@@ -2898,6 +2922,7 @@ export {
|
|
|
2898
2922
|
isApiErrorRecord,
|
|
2899
2923
|
isAxiosErrorLike,
|
|
2900
2924
|
isServiceErrorData,
|
|
2925
|
+
isUrlEmbeddedCredential,
|
|
2901
2926
|
mapServiceErrorCode,
|
|
2902
2927
|
mapServiceErrorToSlateErrorInput,
|
|
2903
2928
|
mergeScopes,
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { AuthConfigSecretRedactor } from '../auth/redact';
|
|
2
|
+
import { AuthConfigSecretRedactor, isUrlEmbeddedCredential } from '../auth/redact';
|
|
3
3
|
import type { SlateContext } from '../context/context';
|
|
4
4
|
import type { SlateSpecification } from '../specification/specification';
|
|
5
5
|
import { tool } from './tool';
|
|
@@ -42,6 +42,7 @@ export let getFileUrlTool = <ConfigType extends {}, AuthType extends {}>(
|
|
|
42
42
|
return {
|
|
43
43
|
output: {
|
|
44
44
|
...output,
|
|
45
|
+
url: redactor.redactEmbedded(output.url, isUrlEmbeddedCredential),
|
|
45
46
|
...(output.headers ? { headers: redactor.redactEmbedded(output.headers) } : {}),
|
|
46
47
|
...(output.query ? { query: redactor.redactEmbedded(output.query) } : {})
|
|
47
48
|
},
|
|
@@ -31,6 +31,39 @@ export type SlateTriggerGroupPollHandler<ConfigType extends {}, AuthType extends
|
|
|
31
31
|
updatedState?: any;
|
|
32
32
|
}>;
|
|
33
33
|
|
|
34
|
+
export interface SlateGatewayEvent {
|
|
35
|
+
payload: any;
|
|
36
|
+
idempotencyKey?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type SlateTriggerGroupGatewayConnectHandler<
|
|
40
|
+
ConfigType extends {},
|
|
41
|
+
AuthType extends {}
|
|
42
|
+
> = (
|
|
43
|
+
context: SlateContext<ConfigType, AuthType, { state: any | null }>
|
|
44
|
+
) => Promise<{ url: string; state?: any }>;
|
|
45
|
+
|
|
46
|
+
/** `closed` is set, with no frames, when the socket closed unexpectedly. */
|
|
47
|
+
export type SlateTriggerGroupGatewayReceiveHandler<
|
|
48
|
+
ConfigType extends {},
|
|
49
|
+
AuthType extends {}
|
|
50
|
+
> = (
|
|
51
|
+
context: SlateContext<
|
|
52
|
+
ConfigType,
|
|
53
|
+
AuthType,
|
|
54
|
+
{ state: any | null; frames: string[]; closed?: { code: number; reason: string } | null }
|
|
55
|
+
>
|
|
56
|
+
) => Promise<{
|
|
57
|
+
state?: any;
|
|
58
|
+
send?: string[];
|
|
59
|
+
events?: SlateGatewayEvent[];
|
|
60
|
+
/** With `expectsAck`, the hub reconnects when no `heartbeatAcked` arrives before the next beat. */
|
|
61
|
+
heartbeat?: { intervalMs: number; frame: string; expectsAck?: boolean } | null;
|
|
62
|
+
/** Set when `frames` included the provider's heartbeat acknowledgement. */
|
|
63
|
+
heartbeatAcked?: boolean;
|
|
64
|
+
close?: { reconnect: boolean; reason?: string } | null;
|
|
65
|
+
}>;
|
|
66
|
+
|
|
34
67
|
export type SlateWebhookTargetListHandler<ConfigType extends {}, AuthType extends {}> = (
|
|
35
68
|
context: SlateContext<ConfigType, AuthType, { pageToken: any | null }>
|
|
36
69
|
) => Promise<{
|
|
@@ -121,6 +154,14 @@ export interface SlateTriggerGroupPollingParameters<
|
|
|
121
154
|
pollEvents: SlateTriggerGroupPollHandler<ConfigType, AuthType>;
|
|
122
155
|
}
|
|
123
156
|
|
|
157
|
+
export interface SlateTriggerGroupGatewayParameters<
|
|
158
|
+
ConfigType extends {},
|
|
159
|
+
AuthType extends {}
|
|
160
|
+
> {
|
|
161
|
+
connect: SlateTriggerGroupGatewayConnectHandler<ConfigType, AuthType>;
|
|
162
|
+
receive: SlateTriggerGroupGatewayReceiveHandler<ConfigType, AuthType>;
|
|
163
|
+
}
|
|
164
|
+
|
|
124
165
|
export interface SlateTriggerGroupWebhookAutoRegistrationParameters<
|
|
125
166
|
ConfigType extends {},
|
|
126
167
|
AuthType extends {}
|
|
@@ -164,9 +205,10 @@ export interface SlateTriggerGroupParameters<
|
|
|
164
205
|
AuthType extends {},
|
|
165
206
|
InputType extends {} = Record<string, unknown>
|
|
166
207
|
> extends SlateTriggerGroupCreateParameters<InputType> {
|
|
167
|
-
source: 'polling' | 'webhook';
|
|
208
|
+
source: 'polling' | 'webhook' | 'gateway';
|
|
168
209
|
polling?: SlateTriggerGroupPollingParameters<ConfigType, AuthType>;
|
|
169
210
|
webhook?: SlateTriggerGroupWebhookParameters<ConfigType, AuthType>;
|
|
211
|
+
gateway?: SlateTriggerGroupGatewayParameters<ConfigType, AuthType>;
|
|
170
212
|
routingMatchers: SlateTriggerGroupRoutingMatchersHandler<ConfigType, AuthType>;
|
|
171
213
|
}
|
|
172
214
|
|
|
@@ -227,6 +269,10 @@ export class SlateTriggerGroup<
|
|
|
227
269
|
return this._params.webhook;
|
|
228
270
|
}
|
|
229
271
|
|
|
272
|
+
get gateway() {
|
|
273
|
+
return this._params.gateway;
|
|
274
|
+
}
|
|
275
|
+
|
|
230
276
|
get routingMatchers() {
|
|
231
277
|
return this._params.routingMatchers;
|
|
232
278
|
}
|
|
@@ -237,9 +283,10 @@ export class SlateTriggerGroupBuilder<
|
|
|
237
283
|
AuthType extends {},
|
|
238
284
|
InputType extends {} = Record<string, unknown>
|
|
239
285
|
> {
|
|
240
|
-
#source: 'polling' | 'webhook' | null = null;
|
|
286
|
+
#source: 'polling' | 'webhook' | 'gateway' | null = null;
|
|
241
287
|
#polling: SlateTriggerGroupPollingParameters<ConfigType, AuthType> | null = null;
|
|
242
288
|
#webhook: SlateTriggerGroupWebhookParameters<ConfigType, AuthType> | null = null;
|
|
289
|
+
#gateway: SlateTriggerGroupGatewayParameters<ConfigType, AuthType> | null = null;
|
|
243
290
|
#routingMatchers: SlateTriggerGroupRoutingMatchersHandler<ConfigType, AuthType> | null =
|
|
244
291
|
null;
|
|
245
292
|
|
|
@@ -302,6 +349,20 @@ export class SlateTriggerGroupBuilder<
|
|
|
302
349
|
return this;
|
|
303
350
|
}
|
|
304
351
|
|
|
352
|
+
/** Receive events over a platform-managed persistent connection (e.g. a WebSocket gateway). */
|
|
353
|
+
gateway(
|
|
354
|
+
props: SlateTriggerGroupGatewayParameters<ConfigType, AuthType>
|
|
355
|
+
): SlateTriggerGroupBuilder<ConfigType, AuthType, InputType> {
|
|
356
|
+
if (this.#source) {
|
|
357
|
+
throw new SlateDeclarationError('Trigger group invocation is already defined');
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
this.#source = 'gateway';
|
|
361
|
+
this.#gateway = { connect: props.connect, receive: props.receive };
|
|
362
|
+
|
|
363
|
+
return this;
|
|
364
|
+
}
|
|
365
|
+
|
|
305
366
|
routingMatchers(
|
|
306
367
|
handler: SlateTriggerGroupRoutingMatchersHandler<ConfigType, AuthType>
|
|
307
368
|
): SlateTriggerGroupBuilder<ConfigType, AuthType, InputType> {
|
|
@@ -312,7 +373,7 @@ export class SlateTriggerGroupBuilder<
|
|
|
312
373
|
build(): SlateTriggerGroup<ConfigType, AuthType, InputType> {
|
|
313
374
|
if (!this.#source) {
|
|
314
375
|
throw new SlateDeclarationError(
|
|
315
|
-
'Trigger group invocation (polling or
|
|
376
|
+
'Trigger group invocation (polling, webhook, or gateway) is not defined'
|
|
316
377
|
);
|
|
317
378
|
}
|
|
318
379
|
if (!this.#routingMatchers) {
|
|
@@ -324,6 +385,7 @@ export class SlateTriggerGroupBuilder<
|
|
|
324
385
|
source: this.#source,
|
|
325
386
|
polling: this.#polling ?? undefined,
|
|
326
387
|
webhook: this.#webhook ?? undefined,
|
|
388
|
+
gateway: this.#gateway ?? undefined,
|
|
327
389
|
routingMatchers: this.#routingMatchers
|
|
328
390
|
});
|
|
329
391
|
}
|
package/src/auth/redact.test.ts
CHANGED
|
@@ -167,7 +167,7 @@ describe('redactUrlAttachmentSecrets', () => {
|
|
|
167
167
|
]);
|
|
168
168
|
});
|
|
169
169
|
|
|
170
|
-
it('only changes
|
|
170
|
+
it('only changes credential values, preserving metadata and the original attachment', () => {
|
|
171
171
|
let attachment: SlateAttachment = {
|
|
172
172
|
mimeType: 'application/pdf',
|
|
173
173
|
attachmentHash: 'file-hash',
|
|
@@ -187,6 +187,7 @@ describe('redactUrlAttachmentSecrets', () => {
|
|
|
187
187
|
...original,
|
|
188
188
|
content: {
|
|
189
189
|
...original.content,
|
|
190
|
+
url: 'https://example.com/$$MT$secret$authConfig$token$$/file.pdf',
|
|
190
191
|
headers: { Authorization: 'Bearer $$MT$secret$authConfig$token$$' },
|
|
191
192
|
query: { key: '$$MT$secret$authConfig$nested.token2$$-suffix' }
|
|
192
193
|
}
|
|
@@ -195,7 +196,35 @@ describe('redactUrlAttachmentSecrets', () => {
|
|
|
195
196
|
expect(attachment).toEqual(original);
|
|
196
197
|
});
|
|
197
198
|
|
|
198
|
-
it('
|
|
199
|
+
it('redacts a bot token embedded in the url path', () => {
|
|
200
|
+
let attachments = [
|
|
201
|
+
urlAttachment({ url: 'https://api.telegram.org/file/bot123:ABCDEFGH/photos/a.jpg' })
|
|
202
|
+
];
|
|
203
|
+
|
|
204
|
+
expect(
|
|
205
|
+
redactUrlAttachmentSecrets(attachments, { token: '123:ABCDEFGH', botId: '12345678' })
|
|
206
|
+
).toEqual([
|
|
207
|
+
urlAttachment({
|
|
208
|
+
url: 'https://api.telegram.org/file/bot$$MT$secret$authConfig$token$$/photos/a.jpg'
|
|
209
|
+
})
|
|
210
|
+
]);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('keeps non-credential and short auth values in the url', () => {
|
|
214
|
+
let attachments = [
|
|
215
|
+
urlAttachment({ url: 'https://example.com/AC12345678/12345678/abc/file.pdf' })
|
|
216
|
+
];
|
|
217
|
+
|
|
218
|
+
expect(
|
|
219
|
+
redactUrlAttachmentSecrets(attachments, {
|
|
220
|
+
account_sid: 'AC12345678',
|
|
221
|
+
botId: '12345678',
|
|
222
|
+
token: 'abc'
|
|
223
|
+
})
|
|
224
|
+
).toEqual(attachments);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('leaves url attachments with no credentials untouched', () => {
|
|
199
228
|
let attachments = [urlAttachment()];
|
|
200
229
|
expect(redactUrlAttachmentSecrets(attachments, authConfig)).toEqual(attachments);
|
|
201
230
|
});
|
package/src/auth/redact.ts
CHANGED
|
@@ -25,11 +25,20 @@ export class AuthConfigSecretRedactor {
|
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
/** `embeddable` limits which secrets are also replaced inside longer strings. */
|
|
29
|
+
public redactEmbedded<T>(
|
|
30
|
+
value: T,
|
|
31
|
+
embeddable: (secret: string, path: string) => boolean = () => true
|
|
32
|
+
): T {
|
|
33
|
+
let secrets = [...this.secretToPlaceholder.entries()]
|
|
34
|
+
.filter(([secret, placeholder]) =>
|
|
35
|
+
embeddable(secret, placeholder.slice(AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX.length))
|
|
36
|
+
)
|
|
37
|
+
.map(([secret]) => secret);
|
|
38
|
+
if (secrets.length === 0) return this.redact(value);
|
|
30
39
|
|
|
31
40
|
let pattern = new RegExp(
|
|
32
|
-
|
|
41
|
+
secrets
|
|
33
42
|
.sort((a, b) => b.length - a.length)
|
|
34
43
|
// Escape regex metacharacters so values match literally; $& inserts the matched character.
|
|
35
44
|
.map(secret => secret.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
|
|
@@ -102,10 +111,17 @@ export class AuthConfigSecretRedactor {
|
|
|
102
111
|
}
|
|
103
112
|
}
|
|
104
113
|
|
|
114
|
+
// Credentials replaced inside URLs (e.g. Telegram's `/file/bot<token>/` path). Kept narrow:
|
|
115
|
+
// a placeholder in a URL makes the hub proxy the download instead of handing out the link.
|
|
116
|
+
let URL_CREDENTIAL_KEY = /^(?:.*[-_])?(?:token|secret|password|api[-_]?key)$/i;
|
|
117
|
+
|
|
118
|
+
export let isUrlEmbeddedCredential = (secret: string, path: string) =>
|
|
119
|
+
secret.length >= 8 && URL_CREDENTIAL_KEY.test(path.split('.').pop() ?? '');
|
|
120
|
+
|
|
105
121
|
/**
|
|
106
122
|
* Applied to every finalized attachment list right before it's sent over
|
|
107
123
|
* `slates/action.tool.invoke` (see @slates/provider-handler). Only `type: 'url'` attachments
|
|
108
|
-
* carry
|
|
124
|
+
* carry credentials -- content/upload_reference attachments pass through untouched.
|
|
109
125
|
*/
|
|
110
126
|
export let redactUrlAttachmentSecrets = (
|
|
111
127
|
attachments: SlateAttachment[] | undefined,
|
|
@@ -117,18 +133,15 @@ export let redactUrlAttachmentSecrets = (
|
|
|
117
133
|
|
|
118
134
|
return attachments.map(attachment => {
|
|
119
135
|
if (attachment.content.type !== 'url') return attachment;
|
|
120
|
-
if (!attachment.content.headers && !attachment.content.query) return attachment;
|
|
121
136
|
|
|
137
|
+
let { url, headers, query } = attachment.content;
|
|
122
138
|
return {
|
|
123
139
|
...attachment,
|
|
124
140
|
content: {
|
|
125
141
|
...attachment.content,
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
query: attachment.content.query
|
|
130
|
-
? redactor.redactEmbedded(attachment.content.query)
|
|
131
|
-
: undefined
|
|
142
|
+
url: redactor.redactEmbedded(url, isUrlEmbeddedCredential),
|
|
143
|
+
...(headers ? { headers: redactor.redactEmbedded(headers) } : {}),
|
|
144
|
+
...(query ? { query: redactor.redactEmbedded(query) } : {})
|
|
132
145
|
}
|
|
133
146
|
};
|
|
134
147
|
});
|
package/src/axios/trace.test.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { AuthConfigSecretRedactor } from '../auth/redact';
|
|
2
3
|
import { __traceInternals } from './trace';
|
|
3
4
|
|
|
4
5
|
let {
|
|
@@ -272,6 +273,26 @@ describe('sanitizeUrl', () => {
|
|
|
272
273
|
expect(out).toContain('expires_in=3600');
|
|
273
274
|
});
|
|
274
275
|
|
|
276
|
+
it('redacts long auth-config secrets embedded in the path', () => {
|
|
277
|
+
let redactor = new AuthConfigSecretRedactor({
|
|
278
|
+
token: '123456:ABCdefGHIjklMNOpqrSTU',
|
|
279
|
+
botId: '123456',
|
|
280
|
+
applicationId: '1503442063478362305'
|
|
281
|
+
});
|
|
282
|
+
expect(
|
|
283
|
+
sanitizeUrl('https://api.telegram.org/bot123456:ABCdefGHIjklMNOpqrSTU/getMe', redactor)
|
|
284
|
+
).toBe('https://api.telegram.org/bot$$MT$secret$authConfig$token$$/getMe');
|
|
285
|
+
expect(sanitizeUrl('https://example.com/bots/123456/info', redactor)).toBe(
|
|
286
|
+
'https://example.com/bots/123456/info'
|
|
287
|
+
);
|
|
288
|
+
expect(
|
|
289
|
+
sanitizeUrl(
|
|
290
|
+
'https://discord.com/api/applications/1503442063478362305/commands',
|
|
291
|
+
redactor
|
|
292
|
+
)
|
|
293
|
+
).toBe('https://discord.com/api/applications/1503442063478362305/commands');
|
|
294
|
+
});
|
|
295
|
+
|
|
275
296
|
it('leaves innocuous URLs unchanged', () => {
|
|
276
297
|
expect(sanitizeUrl('https://example.com/api?page=2&limit=10')).toBe(
|
|
277
298
|
'https://example.com/api?page=2&limit=10'
|
package/src/axios/trace.ts
CHANGED
|
@@ -563,6 +563,10 @@ let redactHashFragment = (hash: string, redactor?: AuthConfigSecretRedactor) =>
|
|
|
563
563
|
return redacted ? `#${redacted}` : '';
|
|
564
564
|
};
|
|
565
565
|
|
|
566
|
+
// Redacts secret-keyed auth values embedded in URL paths (e.g. Telegram's `/bot<token>/...`).
|
|
567
|
+
let isEmbeddedPathSecret = (secret: string, path: string) =>
|
|
568
|
+
secret.length >= 8 && isSecretKeyName(path.split('.').pop() ?? '');
|
|
569
|
+
|
|
566
570
|
let sanitizeUrl = (value: string, redactor?: AuthConfigSecretRedactor) => {
|
|
567
571
|
if (!value) return value;
|
|
568
572
|
|
|
@@ -574,6 +578,8 @@ let sanitizeUrl = (value: string, redactor?: AuthConfigSecretRedactor) => {
|
|
|
574
578
|
url.password = '';
|
|
575
579
|
}
|
|
576
580
|
|
|
581
|
+
if (redactor) url.pathname = redactor.redactEmbedded(url.pathname, isEmbeddedPathSecret);
|
|
582
|
+
|
|
577
583
|
for (let key of Array.from(url.searchParams.keys())) {
|
|
578
584
|
if (isUrlFormSecretKeyName(key)) {
|
|
579
585
|
url.searchParams.set(key, REDACTED_VALUE);
|
|
@@ -590,7 +596,7 @@ let sanitizeUrl = (value: string, redactor?: AuthConfigSecretRedactor) => {
|
|
|
590
596
|
|
|
591
597
|
return decodeRedactedMarker(url.toString());
|
|
592
598
|
} catch {
|
|
593
|
-
let text = redactor ? redactor.
|
|
599
|
+
let text = redactor ? redactor.redactEmbedded(value, isEmbeddedPathSecret) : value;
|
|
594
600
|
return text.replace(
|
|
595
601
|
/([?&]([^=&#]+)=)([^&#]+)/g,
|
|
596
602
|
(_match, prefix: string, key: string, rawValue: string) =>
|