@cuylabs/channel-slack 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -200,6 +200,48 @@ async function inspectSlackTokenScopes(options = {}) {
200
200
  errors
201
201
  };
202
202
  }
203
+ function normalizeSlackAuthTestIdentity(payload) {
204
+ const record = readRecord(payload);
205
+ const identity = {};
206
+ const url = readString(record?.url);
207
+ const team = readString(record?.team);
208
+ const teamId = readString(record?.team_id) ?? readString(record?.teamId);
209
+ const userId = readString(record?.user_id) ?? readString(record?.userId);
210
+ const botUserId = readString(record?.botUserId) ?? userId;
211
+ const botId = readString(record?.bot_id) ?? readString(record?.botId);
212
+ if (url) identity.url = url;
213
+ if (team) identity.team = team;
214
+ if (teamId) identity.teamId = teamId;
215
+ if (userId) identity.userId = userId;
216
+ if (botUserId) identity.botUserId = botUserId;
217
+ if (botId) identity.botId = botId;
218
+ return identity;
219
+ }
220
+ function compareSlackIdentity(identity, expected) {
221
+ const mismatches = [];
222
+ addIdentityMismatch(mismatches, {
223
+ actual: identity.teamId,
224
+ expected: expected.teamId,
225
+ field: "teamId",
226
+ label: "team"
227
+ });
228
+ addIdentityMismatch(mismatches, {
229
+ actual: identity.botUserId ?? identity.userId,
230
+ expected: expected.botUserId,
231
+ field: "botUserId",
232
+ label: "bot user"
233
+ });
234
+ addIdentityMismatch(mismatches, {
235
+ actual: identity.botId,
236
+ expected: expected.botId,
237
+ field: "botId",
238
+ label: "bot"
239
+ });
240
+ return mismatches;
241
+ }
242
+ function formatSlackIdentityMismatches(mismatches) {
243
+ return mismatches.map((mismatch) => mismatch.message);
244
+ }
203
245
  async function resolveDiagnosticsClient(options) {
204
246
  const explicitToken = normalizeToken(options.token);
205
247
  if (options.client) {
@@ -398,8 +440,227 @@ function readBoolean(value) {
398
440
  function elapsed(startedAt) {
399
441
  return Date.now() - startedAt;
400
442
  }
443
+ function addIdentityMismatch(mismatches, {
444
+ actual,
445
+ expected,
446
+ field,
447
+ label
448
+ }) {
449
+ if (!expected || expected === actual) {
450
+ return;
451
+ }
452
+ mismatches.push({
453
+ actual,
454
+ expected,
455
+ field,
456
+ label,
457
+ message: `Expected Slack ${label} identity ${expected}, but the token resolved ${actual ?? "no value"}`
458
+ });
459
+ }
460
+
461
+ // src/diagnostics/payload-debug.ts
462
+ function summarizeSlackPayloadDebug({
463
+ rawArgs,
464
+ slackActivity,
465
+ threadContext
466
+ }) {
467
+ const selectedRawArgs = selectSlackRawArgsForDebug(rawArgs);
468
+ return {
469
+ slackActivity: redactSlackDebugValue(slackActivity),
470
+ threadContext: redactSlackDebugValue(threadContext),
471
+ rawArgs: redactSlackDebugValue(selectedRawArgs),
472
+ rawArgsKeyPaths: collectJsonKeyPaths(selectedRawArgs),
473
+ rawArgsActionTokenPaths: findJsonKeyPaths(
474
+ selectedRawArgs,
475
+ (key) => ["action_token", "actiontoken"].includes(key.toLowerCase())
476
+ ),
477
+ rawArgsTokenLikePaths: findJsonKeyPaths(
478
+ selectedRawArgs,
479
+ (key) => key.toLowerCase().includes("token")
480
+ )
481
+ };
482
+ }
483
+ function selectSlackRawArgsForDebug(rawArgs) {
484
+ const raw = rawArgs;
485
+ return {
486
+ body: selectSlackBodyForDebug(raw?.body),
487
+ payload: raw?.payload,
488
+ event: raw?.event,
489
+ message: raw?.message,
490
+ context: raw?.context
491
+ };
492
+ }
493
+ function selectSlackBodyForDebug(body) {
494
+ const raw = body;
495
+ return {
496
+ type: raw?.type,
497
+ team_id: raw?.team_id,
498
+ enterprise_id: raw?.enterprise_id,
499
+ api_app_id: raw?.api_app_id,
500
+ event: raw?.event,
501
+ event_id: raw?.event_id,
502
+ event_time: raw?.event_time,
503
+ event_context: raw?.event_context
504
+ };
505
+ }
506
+ function redactSlackDebugValue(value, depth = 0) {
507
+ if (value === null || value === void 0) {
508
+ return value;
509
+ }
510
+ if (typeof value === "string") {
511
+ return { type: "string", length: value.length };
512
+ }
513
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
514
+ return value;
515
+ }
516
+ if (Array.isArray(value)) {
517
+ return {
518
+ type: "array",
519
+ length: value.length,
520
+ sample: value.slice(0, 3).map((entry) => redactSlackDebugValue(entry, depth + 1))
521
+ };
522
+ }
523
+ if (typeof value !== "object") {
524
+ return { type: typeof value };
525
+ }
526
+ const entries = Object.entries(value);
527
+ if (depth >= 4) {
528
+ return {
529
+ type: "object",
530
+ keys: entries.map(([key]) => key)
531
+ };
532
+ }
533
+ return Object.fromEntries(
534
+ entries.map(([key, entry]) => [
535
+ key,
536
+ redactSlackDebugEntry(key, entry, depth)
537
+ ])
538
+ );
539
+ }
540
+ function collectJsonKeyPaths(value) {
541
+ return collectJsonKeyPathsInternal(value, {
542
+ maxDepth: 7,
543
+ maxPaths: 300
544
+ });
545
+ }
546
+ function findJsonKeyPaths(value, predicate) {
547
+ return collectJsonKeyPathsInternal(value, {
548
+ maxDepth: 8,
549
+ maxPaths: 100,
550
+ predicate
551
+ });
552
+ }
553
+ function redactSlackDebugEntry(key, value, depth) {
554
+ const normalized = key.toLowerCase();
555
+ if (normalized.includes("token") || normalized.includes("secret") || normalized.includes("authorization") || normalized.includes("password")) {
556
+ return {
557
+ present: typeof value === "string" ? value.length > 0 : value !== void 0,
558
+ redacted: true
559
+ };
560
+ }
561
+ if (normalized === "text" || normalized === "markdown_text") {
562
+ return {
563
+ type: typeof value,
564
+ length: typeof value === "string" ? value.length : void 0,
565
+ redacted: true
566
+ };
567
+ }
568
+ if (typeof value === "string" && STRUCTURAL_SLACK_DEBUG_KEYS.has(normalized)) {
569
+ return value;
570
+ }
571
+ return redactSlackDebugValue(value, depth + 1);
572
+ }
573
+ var STRUCTURAL_SLACK_DEBUG_KEYS = /* @__PURE__ */ new Set([
574
+ "app_id",
575
+ "api_app_id",
576
+ "bot_id",
577
+ "botid",
578
+ "channel",
579
+ "channel_id",
580
+ "channelid",
581
+ "channel_type",
582
+ "channeltype",
583
+ "enterprise_id",
584
+ "enterpriseid",
585
+ "event_ts",
586
+ "eventts",
587
+ "messagets",
588
+ "team",
589
+ "team_id",
590
+ "teamid",
591
+ "thread_ts",
592
+ "threadts",
593
+ "ts",
594
+ "type",
595
+ "subtype",
596
+ "user",
597
+ "user_id",
598
+ "userid"
599
+ ]);
600
+ function collectJsonKeyPathsInternal(value, {
601
+ maxDepth,
602
+ maxPaths,
603
+ predicate
604
+ }) {
605
+ const paths = [];
606
+ const seen = /* @__PURE__ */ new WeakSet();
607
+ function visit(current, prefix, depth) {
608
+ if (paths.length >= maxPaths || current === null || current === void 0) {
609
+ return;
610
+ }
611
+ if (typeof current !== "object") {
612
+ return;
613
+ }
614
+ if (seen.has(current)) {
615
+ return;
616
+ }
617
+ seen.add(current);
618
+ if (Array.isArray(current)) {
619
+ if (current.length === 0) {
620
+ const path = `${prefix}[]`;
621
+ if (!predicate) {
622
+ paths.push(path);
623
+ }
624
+ return;
625
+ }
626
+ if (depth >= maxDepth) {
627
+ return;
628
+ }
629
+ for (const entry of current.slice(0, 3)) {
630
+ visit(entry, `${prefix}[]`, depth + 1);
631
+ }
632
+ return;
633
+ }
634
+ if (depth >= maxDepth) {
635
+ return;
636
+ }
637
+ for (const [key, entry] of Object.entries(
638
+ current
639
+ )) {
640
+ if (paths.length >= maxPaths) {
641
+ return;
642
+ }
643
+ const path = prefix ? `${prefix}.${key}` : key;
644
+ if (!predicate || predicate(key)) {
645
+ paths.push(path);
646
+ }
647
+ visit(entry, path, depth + 1);
648
+ }
649
+ }
650
+ visit(value, "", 0);
651
+ return paths;
652
+ }
401
653
 
402
654
  export {
403
655
  inspectSlackConnection,
404
- inspectSlackTokenScopes
656
+ inspectSlackTokenScopes,
657
+ normalizeSlackAuthTestIdentity,
658
+ compareSlackIdentity,
659
+ formatSlackIdentityMismatches,
660
+ summarizeSlackPayloadDebug,
661
+ selectSlackRawArgsForDebug,
662
+ selectSlackBodyForDebug,
663
+ redactSlackDebugValue,
664
+ collectJsonKeyPaths,
665
+ findJsonKeyPaths
405
666
  };
@@ -1,105 +1,22 @@
1
- type SlackScopeInspectionMethod = "auth.test" | "auth.scopes" | "apps.permissions.info";
2
- type SlackConnectionInspectionFindingSeverity = "info" | "warning" | "error";
3
- type SlackTokenSource = "provided" | "environment" | "client" | "none";
4
- interface SlackDiagnosticsClient {
5
- auth: {
6
- test(args?: {
7
- token?: string;
8
- }): Promise<unknown>;
9
- };
10
- apiCall(method: string, args?: Record<string, unknown>): Promise<unknown>;
11
- }
12
- interface SlackApiInspectionError {
13
- message: string;
14
- code?: string;
15
- method?: string;
16
- needed?: string;
17
- providedScopes?: string[];
18
- acceptedScopes?: string[];
19
- statusCode?: number;
20
- }
21
- interface SlackScopeInspectionMethodError {
22
- method: SlackScopeInspectionMethod;
23
- error: SlackApiInspectionError;
24
- }
25
- interface SlackScopeInspection {
26
- ok: boolean;
27
- scopes: string[];
28
- source?: SlackScopeInspectionMethod;
29
- errors: SlackScopeInspectionMethodError[];
30
- }
31
- interface SlackConnectionInspectionFinding {
32
- severity: SlackConnectionInspectionFindingSeverity;
33
- code: string;
34
- message: string;
35
- }
36
- interface SlackConnectionAuthInfo {
37
- ok: boolean;
38
- url?: string;
39
- team?: string;
40
- teamId?: string;
41
- user?: string;
42
- userId?: string;
43
- botId?: string;
44
- enterpriseId?: string;
45
- isEnterpriseInstall?: boolean;
46
- }
47
- interface SlackConnectionInspection {
48
- ok: boolean;
49
- tokenSource: SlackTokenSource;
50
- elapsedMs: number;
51
- auth?: SlackConnectionAuthInfo;
52
- scopes?: SlackScopeInspection;
53
- requiredScopes: string[];
54
- optionalScopes: string[];
55
- missingRequiredScopes: string[];
56
- missingOptionalScopes: string[];
57
- findings: SlackConnectionInspectionFinding[];
58
- error?: SlackApiInspectionError;
59
- }
60
- interface InspectSlackTokenScopesOptions {
61
- /**
62
- * Slack bot or user OAuth token. When omitted, the injected client is used
63
- * as-is and no token override is passed to Slack API calls.
64
- */
65
- token?: string;
66
- /** Inject a preconfigured Slack Web API client, useful for OAuth stores/tests. */
67
- client?: SlackDiagnosticsClient;
68
- /**
69
- * Maximum time for each Slack API request in milliseconds. Set `0` to
70
- * disable the local timeout wrapper.
71
- *
72
- * @default 2500
73
- */
74
- requestTimeoutMs?: number;
75
- /**
76
- * Scope-bearing methods to try in order.
77
- *
78
- * @default ["auth.test", "auth.scopes", "apps.permissions.info"]
79
- */
80
- methods?: readonly SlackScopeInspectionMethod[];
81
- }
82
- interface InspectSlackConnectionOptions extends Omit<InspectSlackTokenScopesOptions, "methods"> {
83
- /**
84
- * Slack OAuth scopes that must be present for this installation to be
85
- * considered usable by the caller.
86
- */
87
- requiredScopes?: readonly string[];
88
- /**
89
- * Slack OAuth scopes that are useful but not mandatory. Missing optional
90
- * scopes are returned as warnings.
91
- */
92
- optionalScopes?: readonly string[];
93
- /**
94
- * Whether to inspect token scopes after `auth.test` succeeds.
95
- *
96
- * @default true
97
- */
98
- inspectScopes?: boolean;
99
- /** Override the scope-inspection method order. */
100
- scopeMethods?: readonly SlackScopeInspectionMethod[];
101
- }
102
- declare function inspectSlackConnection(options?: InspectSlackConnectionOptions): Promise<SlackConnectionInspection>;
103
- declare function inspectSlackTokenScopes(options?: InspectSlackTokenScopesOptions): Promise<SlackScopeInspection>;
1
+ export { I as InspectSlackConnectionOptions, a as InspectSlackTokenScopesOptions, S as SlackApiInspectionError, b as SlackAuthTestIdentity, c as SlackConnectionInspection, d as SlackConnectionInspectionFinding, e as SlackConnectionInspectionFindingSeverity, f as SlackDiagnosticsClient, g as SlackIdentityExpectations, h as SlackIdentityMismatch, i as SlackScopeInspection, j as SlackScopeInspectionMethod, k as SlackScopeInspectionMethodError, l as SlackTokenSource, m as compareSlackIdentity, n as formatSlackIdentityMismatches, o as inspectSlackConnection, p as inspectSlackTokenScopes, q as normalizeSlackAuthTestIdentity } from './inspect-BpY5JA0K.js';
2
+
3
+ interface SlackPayloadDebugSummary {
4
+ rawArgs: unknown;
5
+ rawArgsActionTokenPaths: string[];
6
+ rawArgsKeyPaths: string[];
7
+ rawArgsTokenLikePaths: string[];
8
+ slackActivity: unknown;
9
+ threadContext: unknown;
10
+ }
11
+ declare function summarizeSlackPayloadDebug({ rawArgs, slackActivity, threadContext, }: {
12
+ rawArgs?: unknown;
13
+ slackActivity: unknown;
14
+ threadContext: unknown;
15
+ }): SlackPayloadDebugSummary;
16
+ declare function selectSlackRawArgsForDebug(rawArgs: unknown): unknown;
17
+ declare function selectSlackBodyForDebug(body: unknown): unknown;
18
+ declare function redactSlackDebugValue(value: unknown, depth?: number): unknown;
19
+ declare function collectJsonKeyPaths(value: unknown): string[];
20
+ declare function findJsonKeyPaths(value: unknown, predicate: (key: string) => boolean): string[];
104
21
 
105
- export { type InspectSlackConnectionOptions, type InspectSlackTokenScopesOptions, type SlackApiInspectionError, type SlackConnectionInspection, type SlackConnectionInspectionFinding, type SlackConnectionInspectionFindingSeverity, type SlackDiagnosticsClient, type SlackScopeInspection, type SlackScopeInspectionMethod, type SlackScopeInspectionMethodError, type SlackTokenSource, inspectSlackConnection, inspectSlackTokenScopes };
22
+ export { type SlackPayloadDebugSummary, collectJsonKeyPaths, findJsonKeyPaths, redactSlackDebugValue, selectSlackBodyForDebug, selectSlackRawArgsForDebug, summarizeSlackPayloadDebug };
@@ -1,8 +1,26 @@
1
1
  import {
2
+ collectJsonKeyPaths,
3
+ compareSlackIdentity,
4
+ findJsonKeyPaths,
5
+ formatSlackIdentityMismatches,
2
6
  inspectSlackConnection,
3
- inspectSlackTokenScopes
4
- } from "./chunk-FX2JOVX5.js";
7
+ inspectSlackTokenScopes,
8
+ normalizeSlackAuthTestIdentity,
9
+ redactSlackDebugValue,
10
+ selectSlackBodyForDebug,
11
+ selectSlackRawArgsForDebug,
12
+ summarizeSlackPayloadDebug
13
+ } from "./chunk-IDVDMJ5U.js";
5
14
  export {
15
+ collectJsonKeyPaths,
16
+ compareSlackIdentity,
17
+ findJsonKeyPaths,
18
+ formatSlackIdentityMismatches,
6
19
  inspectSlackConnection,
7
- inspectSlackTokenScopes
20
+ inspectSlackTokenScopes,
21
+ normalizeSlackAuthTestIdentity,
22
+ redactSlackDebugValue,
23
+ selectSlackBodyForDebug,
24
+ selectSlackRawArgsForDebug,
25
+ summarizeSlackPayloadDebug
8
26
  };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { S as SlackActivityInfo, a as SlackChannelType, b as SlackUserIdentity } from './activity-ByrD9Ftr.js';
2
2
  export { ExtractSlackMessageTextOptions, RawSlackActionTokenPayload, RawSlackAppMentionPayload, RawSlackAssistantThreadPayload, RawSlackMessagePayload, SlackAmbientTurnContext, SlackApprovalRequest, SlackAssistantStatusUpdate, SlackAssistantSuggestedPrompt, SlackAssistantSuggestedPrompts, SlackAssistantTaskDisplayMode, SlackAssistantThreadContext, SlackAssistantUtilities, SlackAuthContext, SlackChatStreamStartArgs, SlackEventInteractiveRequestHandler, SlackHumanInputRequest, SlackInteractiveMessage, SlackInteractiveMessageRef, SlackInteractiveRequest, SlackInteractiveRequestBaseContext, SlackInteractiveRequestContext, SlackInteractiveRequestHandler, SlackInteractiveRequestKind, SlackInteractiveResponder, SlackMessageAuthorshipOptions, SlackMessageFormatter, SlackMessageFormattingOptions, SlackMessageTextPayload, SlackThreadStatusSetter, SlackTurnPreparation, SlackTurnRequestContext, currentSlackTurnContext, extractSlackActionToken, extractSlackAttachmentsText, extractSlackAuthContext, extractSlackBlocksText, extractSlackMessageText, extractSlackUserIdentity, formatSlackAttributedFollowUp, isProcessableMessage, markdownToSlackMrkdwn, parseSlackMentionActivity, parseSlackMessageActivity, resolveSlackChannelType, resolveSlackMessageFormatter, resolveThreadAwareSlackSessionId, runWithSlackTurnContext, stripLeadingMentions } from './core.js';
3
- export { SlackAsyncMessagePolicyConfig, SlackAsyncMessagePolicyResolver, SlackChannelMessagePolicy, SlackMentionedThreadState, SlackMessagePolicyAcceptReason, SlackMessagePolicyAcceptedDecision, SlackMessagePolicyConfig, SlackMessagePolicyDecision, SlackMessagePolicyRejectReason, SlackMessagePolicyRejectedDecision, SlackMessagePolicyResolver, SlackMessagePolicyStateContext, SlackMessagePolicyStateStore, SlackSyncMessagePolicyStateStore, SlackThreadReplyPolicy, createAsyncSlackMessagePolicyResolver, createInMemorySlackMessagePolicyStateStore, createSlackMessagePolicyMessageKey, createSlackMessagePolicyResolver, createSlackMessagePolicyThreadKey, shouldRegisterSlackPassiveChannelMessages } from './policy.js';
3
+ export { PostgresSlackMessagePolicyPruneResult, PostgresSlackMessagePolicyStateStore, PostgresSlackMessagePolicyStateStoreOptions, SlackAsyncMessagePolicyConfig, SlackAsyncMessagePolicyResolver, SlackChannelMessagePolicy, SlackMentionedThreadState, SlackMessagePolicyAcceptReason, SlackMessagePolicyAcceptedDecision, SlackMessagePolicyConfig, SlackMessagePolicyDecision, SlackMessagePolicyPostgresClient, SlackMessagePolicyRejectReason, SlackMessagePolicyRejectedDecision, SlackMessagePolicyResolver, SlackMessagePolicyStateContext, SlackMessagePolicyStateStore, SlackSyncMessagePolicyStateStore, SlackThreadReplyPolicy, createAsyncSlackMessagePolicyResolver, createInMemorySlackMessagePolicyStateStore, createPostgresSlackMessagePolicyStateStore, createSlackMessagePolicyMessageKey, createSlackMessagePolicyResolver, createSlackMessagePolicyThreadKey, initializePostgresSlackMessagePolicyState, prunePostgresSlackMessagePolicyState, shouldRegisterSlackPassiveChannelMessages } from './policy.js';
4
4
  export { L as Logger } from './logging-Bl3HfcC8.js';
package/dist/index.js CHANGED
@@ -25,14 +25,18 @@ import {
25
25
  import {
26
26
  createAsyncSlackMessagePolicyResolver,
27
27
  createInMemorySlackMessagePolicyStateStore,
28
+ createPostgresSlackMessagePolicyStateStore,
28
29
  createSlackMessagePolicyMessageKey,
29
30
  createSlackMessagePolicyResolver,
30
31
  createSlackMessagePolicyThreadKey,
32
+ initializePostgresSlackMessagePolicyState,
33
+ prunePostgresSlackMessagePolicyState,
31
34
  shouldRegisterSlackPassiveChannelMessages
32
- } from "./chunk-BODPT4I6.js";
35
+ } from "./chunk-CMR6B76C.js";
33
36
  export {
34
37
  createAsyncSlackMessagePolicyResolver,
35
38
  createInMemorySlackMessagePolicyStateStore,
39
+ createPostgresSlackMessagePolicyStateStore,
36
40
  createSlackMessagePolicyMessageKey,
37
41
  createSlackMessagePolicyResolver,
38
42
  createSlackMessagePolicyThreadKey,
@@ -44,10 +48,12 @@ export {
44
48
  extractSlackMessageText,
45
49
  extractSlackUserIdentity,
46
50
  formatSlackAttributedFollowUp,
51
+ initializePostgresSlackMessagePolicyState,
47
52
  isProcessableMessage,
48
53
  markdownToSlackMrkdwn,
49
54
  parseSlackMentionActivity,
50
55
  parseSlackMessageActivity,
56
+ prunePostgresSlackMessagePolicyState,
51
57
  resolveSlackChannelType,
52
58
  resolveSlackMessageFormatter,
53
59
  resolveThreadAwareSlackSessionId,
@@ -0,0 +1,128 @@
1
+ type SlackScopeInspectionMethod = "auth.test" | "auth.scopes" | "apps.permissions.info";
2
+ type SlackConnectionInspectionFindingSeverity = "info" | "warning" | "error";
3
+ type SlackTokenSource = "provided" | "environment" | "client" | "none";
4
+ interface SlackDiagnosticsClient {
5
+ auth: {
6
+ test(args?: {
7
+ token?: string;
8
+ }): Promise<unknown>;
9
+ };
10
+ apiCall(method: string, args?: Record<string, unknown>): Promise<unknown>;
11
+ }
12
+ interface SlackApiInspectionError {
13
+ message: string;
14
+ code?: string;
15
+ method?: string;
16
+ needed?: string;
17
+ providedScopes?: string[];
18
+ acceptedScopes?: string[];
19
+ statusCode?: number;
20
+ }
21
+ interface SlackScopeInspectionMethodError {
22
+ method: SlackScopeInspectionMethod;
23
+ error: SlackApiInspectionError;
24
+ }
25
+ interface SlackScopeInspection {
26
+ ok: boolean;
27
+ scopes: string[];
28
+ source?: SlackScopeInspectionMethod;
29
+ errors: SlackScopeInspectionMethodError[];
30
+ }
31
+ interface SlackConnectionInspectionFinding {
32
+ severity: SlackConnectionInspectionFindingSeverity;
33
+ code: string;
34
+ message: string;
35
+ }
36
+ interface SlackConnectionAuthInfo {
37
+ ok: boolean;
38
+ url?: string;
39
+ team?: string;
40
+ teamId?: string;
41
+ user?: string;
42
+ userId?: string;
43
+ botId?: string;
44
+ enterpriseId?: string;
45
+ isEnterpriseInstall?: boolean;
46
+ }
47
+ interface SlackAuthTestIdentity {
48
+ botId?: string;
49
+ botUserId?: string;
50
+ team?: string;
51
+ teamId?: string;
52
+ url?: string;
53
+ userId?: string;
54
+ }
55
+ interface SlackIdentityExpectations {
56
+ botId?: string;
57
+ botUserId?: string;
58
+ teamId?: string;
59
+ }
60
+ interface SlackIdentityMismatch {
61
+ actual?: string;
62
+ expected: string;
63
+ field: "botId" | "botUserId" | "teamId";
64
+ label: string;
65
+ message: string;
66
+ }
67
+ interface SlackConnectionInspection {
68
+ ok: boolean;
69
+ tokenSource: SlackTokenSource;
70
+ elapsedMs: number;
71
+ auth?: SlackConnectionAuthInfo;
72
+ scopes?: SlackScopeInspection;
73
+ requiredScopes: string[];
74
+ optionalScopes: string[];
75
+ missingRequiredScopes: string[];
76
+ missingOptionalScopes: string[];
77
+ findings: SlackConnectionInspectionFinding[];
78
+ error?: SlackApiInspectionError;
79
+ }
80
+ interface InspectSlackTokenScopesOptions {
81
+ /**
82
+ * Slack bot or user OAuth token. When omitted, the injected client is used
83
+ * as-is and no token override is passed to Slack API calls.
84
+ */
85
+ token?: string;
86
+ /** Inject a preconfigured Slack Web API client, useful for OAuth stores/tests. */
87
+ client?: SlackDiagnosticsClient;
88
+ /**
89
+ * Maximum time for each Slack API request in milliseconds. Set `0` to
90
+ * disable the local timeout wrapper.
91
+ *
92
+ * @default 2500
93
+ */
94
+ requestTimeoutMs?: number;
95
+ /**
96
+ * Scope-bearing methods to try in order.
97
+ *
98
+ * @default ["auth.test", "auth.scopes", "apps.permissions.info"]
99
+ */
100
+ methods?: readonly SlackScopeInspectionMethod[];
101
+ }
102
+ interface InspectSlackConnectionOptions extends Omit<InspectSlackTokenScopesOptions, "methods"> {
103
+ /**
104
+ * Slack OAuth scopes that must be present for this installation to be
105
+ * considered usable by the caller.
106
+ */
107
+ requiredScopes?: readonly string[];
108
+ /**
109
+ * Slack OAuth scopes that are useful but not mandatory. Missing optional
110
+ * scopes are returned as warnings.
111
+ */
112
+ optionalScopes?: readonly string[];
113
+ /**
114
+ * Whether to inspect token scopes after `auth.test` succeeds.
115
+ *
116
+ * @default true
117
+ */
118
+ inspectScopes?: boolean;
119
+ /** Override the scope-inspection method order. */
120
+ scopeMethods?: readonly SlackScopeInspectionMethod[];
121
+ }
122
+ declare function inspectSlackConnection(options?: InspectSlackConnectionOptions): Promise<SlackConnectionInspection>;
123
+ declare function inspectSlackTokenScopes(options?: InspectSlackTokenScopesOptions): Promise<SlackScopeInspection>;
124
+ declare function normalizeSlackAuthTestIdentity(payload: unknown): SlackAuthTestIdentity;
125
+ declare function compareSlackIdentity(identity: SlackAuthTestIdentity, expected: SlackIdentityExpectations): SlackIdentityMismatch[];
126
+ declare function formatSlackIdentityMismatches(mismatches: readonly SlackIdentityMismatch[]): string[];
127
+
128
+ export { type InspectSlackConnectionOptions as I, type SlackApiInspectionError as S, type InspectSlackTokenScopesOptions as a, type SlackAuthTestIdentity as b, type SlackConnectionInspection as c, type SlackConnectionInspectionFinding as d, type SlackConnectionInspectionFindingSeverity as e, type SlackDiagnosticsClient as f, type SlackIdentityExpectations as g, type SlackIdentityMismatch as h, type SlackScopeInspection as i, type SlackScopeInspectionMethod as j, type SlackScopeInspectionMethodError as k, type SlackTokenSource as l, compareSlackIdentity as m, formatSlackIdentityMismatches as n, inspectSlackConnection as o, inspectSlackTokenScopes as p, normalizeSlackAuthTestIdentity as q };
package/dist/policy.d.ts CHANGED
@@ -118,6 +118,52 @@ declare function createAsyncSlackMessagePolicyResolver(config?: SlackAsyncMessag
118
118
  declare function createSlackMessagePolicyMessageKey(activity: SlackActivityInfo): string | undefined;
119
119
  declare function createSlackMessagePolicyThreadKey(activity: SlackActivityInfo): string;
120
120
 
121
+ interface SlackMessagePolicyPostgresClient {
122
+ end?: () => Promise<void>;
123
+ query<T = unknown>(sql: string, values?: readonly unknown[]): Promise<{
124
+ rows: T[];
125
+ rowCount?: number | null;
126
+ }>;
127
+ }
128
+ interface PostgresSlackMessagePolicyStateStoreOptions {
129
+ acceptedMessageRetentionMs?: number;
130
+ acceptedMessagesTableName?: string;
131
+ client?: SlackMessagePolicyPostgresClient;
132
+ connectionString?: string;
133
+ ensureSchema?: boolean;
134
+ mentionedThreadRetentionMs?: number;
135
+ mentionedThreadsTableName?: string;
136
+ onPruneError?: (error: unknown) => void;
137
+ pruneBatchSize?: number;
138
+ pruneIntervalMs?: number;
139
+ schema?: string;
140
+ }
141
+ interface PostgresSlackMessagePolicyStateStore extends SlackMessagePolicyStateStore {
142
+ close(): Promise<void>;
143
+ prune(): Promise<PostgresSlackMessagePolicyPruneResult>;
144
+ }
145
+ interface PostgresSlackMessagePolicyPruneResult {
146
+ acceptedMessagesDeleted: number;
147
+ mentionedThreadsDeleted: number;
148
+ }
149
+ declare function createPostgresSlackMessagePolicyStateStore({ acceptedMessageRetentionMs, acceptedMessagesTableName, client, connectionString, ensureSchema, mentionedThreadRetentionMs, mentionedThreadsTableName, onPruneError, pruneBatchSize, pruneIntervalMs, schema, }: PostgresSlackMessagePolicyStateStoreOptions): PostgresSlackMessagePolicyStateStore;
150
+ declare function initializePostgresSlackMessagePolicyState({ acceptedMessagesTableName, client, ensureSchema, mentionedThreadsTableName, schema, }: {
151
+ acceptedMessagesTableName?: string;
152
+ client: SlackMessagePolicyPostgresClient;
153
+ ensureSchema?: boolean;
154
+ mentionedThreadsTableName?: string;
155
+ schema?: string;
156
+ }): Promise<void>;
157
+ declare function prunePostgresSlackMessagePolicyState({ acceptedMessageRetentionMs, acceptedMessagesTableName, client, mentionedThreadRetentionMs, mentionedThreadsTableName, pruneBatchSize, schema, }: {
158
+ acceptedMessageRetentionMs?: number;
159
+ acceptedMessagesTableName?: string;
160
+ client: SlackMessagePolicyPostgresClient;
161
+ mentionedThreadRetentionMs?: number;
162
+ mentionedThreadsTableName?: string;
163
+ pruneBatchSize?: number;
164
+ schema?: string;
165
+ }): Promise<PostgresSlackMessagePolicyPruneResult>;
166
+
121
167
  declare function shouldRegisterSlackPassiveChannelMessages(config?: SlackMessagePolicyConfig): boolean;
122
168
 
123
169
  declare function createSlackMessagePolicyResolver(config?: SlackMessagePolicyConfig): SlackMessagePolicyResolver;
@@ -127,4 +173,4 @@ declare function createInMemorySlackMessagePolicyStateStore({ maxAcceptedMessage
127
173
  maxMentionedThreads?: number;
128
174
  }): SlackSyncMessagePolicyStateStore;
129
175
 
130
- export { type SlackAsyncMessagePolicyConfig, type SlackAsyncMessagePolicyResolver, type SlackChannelMessagePolicy, type SlackMentionedThreadState, type SlackMessagePolicyAcceptReason, type SlackMessagePolicyAcceptedDecision, type SlackMessagePolicyConfig, type SlackMessagePolicyDecision, type SlackMessagePolicyRejectReason, type SlackMessagePolicyRejectedDecision, type SlackMessagePolicyResolver, type SlackMessagePolicyStateContext, type SlackMessagePolicyStateStore, type SlackSyncMessagePolicyStateStore, type SlackThreadReplyPolicy, createAsyncSlackMessagePolicyResolver, createInMemorySlackMessagePolicyStateStore, createSlackMessagePolicyMessageKey, createSlackMessagePolicyResolver, createSlackMessagePolicyThreadKey, shouldRegisterSlackPassiveChannelMessages };
176
+ export { type PostgresSlackMessagePolicyPruneResult, type PostgresSlackMessagePolicyStateStore, type PostgresSlackMessagePolicyStateStoreOptions, type SlackAsyncMessagePolicyConfig, type SlackAsyncMessagePolicyResolver, type SlackChannelMessagePolicy, type SlackMentionedThreadState, type SlackMessagePolicyAcceptReason, type SlackMessagePolicyAcceptedDecision, type SlackMessagePolicyConfig, type SlackMessagePolicyDecision, type SlackMessagePolicyPostgresClient, type SlackMessagePolicyRejectReason, type SlackMessagePolicyRejectedDecision, type SlackMessagePolicyResolver, type SlackMessagePolicyStateContext, type SlackMessagePolicyStateStore, type SlackSyncMessagePolicyStateStore, type SlackThreadReplyPolicy, createAsyncSlackMessagePolicyResolver, createInMemorySlackMessagePolicyStateStore, createPostgresSlackMessagePolicyStateStore, createSlackMessagePolicyMessageKey, createSlackMessagePolicyResolver, createSlackMessagePolicyThreadKey, initializePostgresSlackMessagePolicyState, prunePostgresSlackMessagePolicyState, shouldRegisterSlackPassiveChannelMessages };