@open-everywhere/provider-slack 0.1.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.
Files changed (151) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +21 -0
  3. package/README.md +47 -0
  4. package/agent/access/slack-attachment-fetch.ts +168 -0
  5. package/agent/app-manifest.ts +149 -0
  6. package/agent/channels/slack-approval-card.ts +275 -0
  7. package/agent/channels/slack-attachments.ts +195 -0
  8. package/agent/channels/slack-commands.ts +227 -0
  9. package/agent/channels/slack-context.ts +185 -0
  10. package/agent/channels/slack-events.ts +5406 -0
  11. package/agent/channels/slack-front.ts +2349 -0
  12. package/agent/channels/slack-identity.ts +520 -0
  13. package/agent/channels/slack-input-response.ts +162 -0
  14. package/agent/channels/slack-mrkdwn.ts +61 -0
  15. package/agent/channels/slack-origin-codec.ts +62 -0
  16. package/agent/channels/slack-post-arm.ts +314 -0
  17. package/agent/channels/slack-read.ts +248 -0
  18. package/agent/channels/slack-route-hold.ts +107 -0
  19. package/agent/channels/slack-shortcut.ts +336 -0
  20. package/agent/channels/slack-signature.ts +53 -0
  21. package/agent/channels/slack-spend-gate.ts +62 -0
  22. package/agent/channels/slack-tenant-fence.ts +99 -0
  23. package/agent/channels/slack-wake-backscroll.ts +604 -0
  24. package/agent/channels/slack-web-api.ts +178 -0
  25. package/agent/channels/slack-webhook-verifier.ts +116 -0
  26. package/agent/channels/slack.ts +1266 -0
  27. package/agent/contributions.ts +32 -0
  28. package/agent/docs-generated.ts +15 -0
  29. package/agent/ops.ts +50 -0
  30. package/agent/provider-events.ts +91 -0
  31. package/agent/register.ts +144 -0
  32. package/agent/surface-parity.ts +99 -0
  33. package/dist/agent/access/slack-attachment-fetch.d.ts +15 -0
  34. package/dist/agent/access/slack-attachment-fetch.d.ts.map +1 -0
  35. package/dist/agent/access/slack-attachment-fetch.js +151 -0
  36. package/dist/agent/access/slack-attachment-fetch.js.map +1 -0
  37. package/dist/agent/app-manifest.d.ts +15 -0
  38. package/dist/agent/app-manifest.d.ts.map +1 -0
  39. package/dist/agent/app-manifest.js +141 -0
  40. package/dist/agent/app-manifest.js.map +1 -0
  41. package/dist/agent/channels/slack-approval-card.d.ts +71 -0
  42. package/dist/agent/channels/slack-approval-card.d.ts.map +1 -0
  43. package/dist/agent/channels/slack-approval-card.js +232 -0
  44. package/dist/agent/channels/slack-approval-card.js.map +1 -0
  45. package/dist/agent/channels/slack-attachments.d.ts +66 -0
  46. package/dist/agent/channels/slack-attachments.d.ts.map +1 -0
  47. package/dist/agent/channels/slack-attachments.js +174 -0
  48. package/dist/agent/channels/slack-attachments.js.map +1 -0
  49. package/dist/agent/channels/slack-commands.d.ts +27 -0
  50. package/dist/agent/channels/slack-commands.d.ts.map +1 -0
  51. package/dist/agent/channels/slack-commands.js +208 -0
  52. package/dist/agent/channels/slack-commands.js.map +1 -0
  53. package/dist/agent/channels/slack-context.d.ts +26 -0
  54. package/dist/agent/channels/slack-context.d.ts.map +1 -0
  55. package/dist/agent/channels/slack-context.js +178 -0
  56. package/dist/agent/channels/slack-context.js.map +1 -0
  57. package/dist/agent/channels/slack-events.d.ts +1654 -0
  58. package/dist/agent/channels/slack-events.d.ts.map +1 -0
  59. package/dist/agent/channels/slack-events.js +4240 -0
  60. package/dist/agent/channels/slack-events.js.map +1 -0
  61. package/dist/agent/channels/slack-front.d.ts +387 -0
  62. package/dist/agent/channels/slack-front.d.ts.map +1 -0
  63. package/dist/agent/channels/slack-front.js +1958 -0
  64. package/dist/agent/channels/slack-front.js.map +1 -0
  65. package/dist/agent/channels/slack-identity.d.ts +245 -0
  66. package/dist/agent/channels/slack-identity.d.ts.map +1 -0
  67. package/dist/agent/channels/slack-identity.js +405 -0
  68. package/dist/agent/channels/slack-identity.js.map +1 -0
  69. package/dist/agent/channels/slack-input-response.d.ts +26 -0
  70. package/dist/agent/channels/slack-input-response.d.ts.map +1 -0
  71. package/dist/agent/channels/slack-input-response.js +127 -0
  72. package/dist/agent/channels/slack-input-response.js.map +1 -0
  73. package/dist/agent/channels/slack-mrkdwn.d.ts +3 -0
  74. package/dist/agent/channels/slack-mrkdwn.d.ts.map +1 -0
  75. package/dist/agent/channels/slack-mrkdwn.js +53 -0
  76. package/dist/agent/channels/slack-mrkdwn.js.map +1 -0
  77. package/dist/agent/channels/slack-origin-codec.d.ts +7 -0
  78. package/dist/agent/channels/slack-origin-codec.d.ts.map +1 -0
  79. package/dist/agent/channels/slack-origin-codec.js +55 -0
  80. package/dist/agent/channels/slack-origin-codec.js.map +1 -0
  81. package/dist/agent/channels/slack-post-arm.d.ts +54 -0
  82. package/dist/agent/channels/slack-post-arm.d.ts.map +1 -0
  83. package/dist/agent/channels/slack-post-arm.js +268 -0
  84. package/dist/agent/channels/slack-post-arm.js.map +1 -0
  85. package/dist/agent/channels/slack-read.d.ts +84 -0
  86. package/dist/agent/channels/slack-read.d.ts.map +1 -0
  87. package/dist/agent/channels/slack-read.js +205 -0
  88. package/dist/agent/channels/slack-read.js.map +1 -0
  89. package/dist/agent/channels/slack-route-hold.d.ts +34 -0
  90. package/dist/agent/channels/slack-route-hold.d.ts.map +1 -0
  91. package/dist/agent/channels/slack-route-hold.js +97 -0
  92. package/dist/agent/channels/slack-route-hold.js.map +1 -0
  93. package/dist/agent/channels/slack-shortcut.d.ts +162 -0
  94. package/dist/agent/channels/slack-shortcut.d.ts.map +1 -0
  95. package/dist/agent/channels/slack-shortcut.js +262 -0
  96. package/dist/agent/channels/slack-shortcut.js.map +1 -0
  97. package/dist/agent/channels/slack-signature.d.ts +19 -0
  98. package/dist/agent/channels/slack-signature.d.ts.map +1 -0
  99. package/dist/agent/channels/slack-signature.js +50 -0
  100. package/dist/agent/channels/slack-signature.js.map +1 -0
  101. package/dist/agent/channels/slack-spend-gate.d.ts +22 -0
  102. package/dist/agent/channels/slack-spend-gate.d.ts.map +1 -0
  103. package/dist/agent/channels/slack-spend-gate.js +48 -0
  104. package/dist/agent/channels/slack-spend-gate.js.map +1 -0
  105. package/dist/agent/channels/slack-tenant-fence.d.ts +61 -0
  106. package/dist/agent/channels/slack-tenant-fence.d.ts.map +1 -0
  107. package/dist/agent/channels/slack-tenant-fence.js +88 -0
  108. package/dist/agent/channels/slack-tenant-fence.js.map +1 -0
  109. package/dist/agent/channels/slack-wake-backscroll.d.ts +188 -0
  110. package/dist/agent/channels/slack-wake-backscroll.d.ts.map +1 -0
  111. package/dist/agent/channels/slack-wake-backscroll.js +473 -0
  112. package/dist/agent/channels/slack-wake-backscroll.js.map +1 -0
  113. package/dist/agent/channels/slack-web-api.d.ts +46 -0
  114. package/dist/agent/channels/slack-web-api.d.ts.map +1 -0
  115. package/dist/agent/channels/slack-web-api.js +147 -0
  116. package/dist/agent/channels/slack-web-api.js.map +1 -0
  117. package/dist/agent/channels/slack-webhook-verifier.d.ts +5 -0
  118. package/dist/agent/channels/slack-webhook-verifier.d.ts.map +1 -0
  119. package/dist/agent/channels/slack-webhook-verifier.js +112 -0
  120. package/dist/agent/channels/slack-webhook-verifier.js.map +1 -0
  121. package/dist/agent/channels/slack.d.ts +37 -0
  122. package/dist/agent/channels/slack.d.ts.map +1 -0
  123. package/dist/agent/channels/slack.js +1169 -0
  124. package/dist/agent/channels/slack.js.map +1 -0
  125. package/dist/agent/contributions.d.ts +17 -0
  126. package/dist/agent/contributions.d.ts.map +1 -0
  127. package/dist/agent/contributions.js +32 -0
  128. package/dist/agent/contributions.js.map +1 -0
  129. package/dist/agent/docs-generated.d.ts +3 -0
  130. package/dist/agent/docs-generated.d.ts.map +1 -0
  131. package/dist/agent/docs-generated.js +13 -0
  132. package/dist/agent/docs-generated.js.map +1 -0
  133. package/dist/agent/ops.d.ts +3 -0
  134. package/dist/agent/ops.d.ts.map +1 -0
  135. package/dist/agent/ops.js +38 -0
  136. package/dist/agent/ops.js.map +1 -0
  137. package/dist/agent/provider-events.d.ts +3 -0
  138. package/dist/agent/provider-events.d.ts.map +1 -0
  139. package/dist/agent/provider-events.js +84 -0
  140. package/dist/agent/provider-events.js.map +1 -0
  141. package/dist/agent/register.d.ts +5 -0
  142. package/dist/agent/register.d.ts.map +1 -0
  143. package/dist/agent/register.js +118 -0
  144. package/dist/agent/register.js.map +1 -0
  145. package/dist/agent/surface-parity.d.ts +3 -0
  146. package/dist/agent/surface-parity.d.ts.map +1 -0
  147. package/dist/agent/surface-parity.js +95 -0
  148. package/dist/agent/surface-parity.js.map +1 -0
  149. package/package.json +209 -0
  150. package/tsconfig.build.json +22 -0
  151. package/tsconfig.json +15 -0
@@ -0,0 +1,387 @@
1
+ import { type Channel, type RouteHandlerArgs } from "eve/channels";
2
+ import { liveSupervisorDeps, type SlackEventEnvelope } from "./slack-events.js";
3
+ import { EventDedupe, ThreadFifo, type SingleWindowMentionPolicy, type DmSeat, type SetKeyViewResult } from "@open-everywhere/core/agent/adapter-api.js";
4
+ import { type ApprovalCardClickOutcome, type ApprovalRespondFn } from "./slack-approval-card.js";
5
+ import { type ParsedSlackShortcut } from "./slack-shortcut.js";
6
+ /** An HTTP route handler — `RouteHandler` isn't a public eve export, so we mirror its shape. */
7
+ type RouteHandler = (req: Request, args: RouteHandlerArgs) => Promise<Response>;
8
+ /** The public URL Slack POSTs every subscribed event to (Event Subscriptions Request URL). */
9
+ export declare const PUBLIC_SLACK_ROUTE = "/eve/v1/slack";
10
+ /** The internal path the wrapped `slackChannel` is mounted at (never hit by Slack directly). */
11
+ export declare const INTERNAL_SLACK_ROUTE = "/eve/v1/slack/mention";
12
+ /** The decision the front route makes for one inbound request. `env` is carried on the
13
+ * wake/join branches, and the decoded `payload` on the approval-click branch, so the handler
14
+ * needn't re-parse what it already parsed to classify. */
15
+ export type FrontDecision = {
16
+ readonly kind: "forward";
17
+ readonly reason: string;
18
+ } | {
19
+ readonly kind: "wake";
20
+ readonly reason: string;
21
+ readonly env: SlackEventEnvelope;
22
+ } | {
23
+ readonly kind: "join";
24
+ readonly reason: string;
25
+ readonly env: SlackEventEnvelope;
26
+ } | {
27
+ readonly kind: "reaction";
28
+ readonly reason: string;
29
+ readonly env: SlackEventEnvelope;
30
+ } | {
31
+ readonly kind: "approval-click";
32
+ readonly reason: string;
33
+ readonly payload: unknown;
34
+ }
35
+ /** A "Set API key" button click (credentials/intake.ts) — ours: verify the clicker is the intake's
36
+ * requester, then views.open a native modal. Never forwarded. */
37
+ | {
38
+ readonly kind: "setkey-click";
39
+ readonly reason: string;
40
+ readonly payload: unknown;
41
+ }
42
+ /** A `view_submission` from our credential-intake modal — ours: encrypt + store the pasted value
43
+ * host-side, and RESPOND with the modal-close/errors JSON. A `view_submission` for anyone else's
44
+ * modal (Eve's own) still forwards. */
45
+ | {
46
+ readonly kind: "setkey-submit";
47
+ readonly reason: string;
48
+ readonly payload: unknown;
49
+ }
50
+ /** An `oe_connect:` connector-card button click (connections/connector-card.ts) — ours: re-verify
51
+ * standing host-side, then mint an ephemeral OAuth URL / open the api-key intake. Never forwarded. */
52
+ | {
53
+ readonly kind: "connect-click";
54
+ readonly reason: string;
55
+ readonly payload: unknown;
56
+ }
57
+ /** An `oe_grant:` credential-grant card button click (access/credential-grant-card.ts) — ours: the
58
+ * OWNER of the ask answered it in their own DM. Core verifies the clicker IS that owner, then
59
+ * approves or declines. Never forwarded. */
60
+ | {
61
+ readonly kind: "grant-click";
62
+ readonly reason: string;
63
+ readonly payload: unknown;
64
+ }
65
+ /** A tap on a BRIDGED APPROVAL CARD the unified post arm rendered (OPE-1720). OURS, never
66
+ * forwarded: eve's own interactivity route resolves a click against its Slack channel's state and
67
+ * session address, and this card's parked request lives on the unified window — see
68
+ * `slack-approval-card.ts`'s header for why a forward could only drop it. */
69
+ | {
70
+ readonly kind: "input-click";
71
+ readonly reason: string;
72
+ readonly payload: unknown;
73
+ }
74
+ /** An `app_mention` — the native slackChannel path owns it UNLESS the handler's single-window
75
+ * policy says the unified window does (then the forward is suppressed and the mention's
76
+ * `message.channels` sibling carries it as an addressed wake). Carries `env` so the handler
77
+ * needn't re-parse what classification already parsed — same pattern as `wake`/`join`. */
78
+ | {
79
+ readonly kind: "mention";
80
+ readonly reason: string;
81
+ readonly env: SlackEventEnvelope;
82
+ }
83
+ /** A DM-FAMILY message — a 1:1 (`message.im`, OPE-351 stage 2) or a GROUP DM (`message.mpim`,
84
+ * stage 4). OURS, never forwarded: the surface's seat is a first-class standing window, so the
85
+ * event is diverted into it (`scheduleDmWake`) instead of going to eve's native `onDirectMessage`
86
+ * (a 1:1) or being judged by the name-drop gate that refused it outright (a group DM). `dmKind`
87
+ * is the classification the envelope DID carry, so the handler needn't re-read `channel_type`;
88
+ * `env` rides along like every other wake branch. */
89
+ | {
90
+ readonly kind: "dm-wake";
91
+ readonly reason: string;
92
+ readonly env: SlackEventEnvelope;
93
+ readonly dmKind: "im" | "mpim";
94
+ }
95
+ /** A Slack SHORTCUT — a message shortcut (`message_action`) or a global one (`shortcut`),
96
+ * OPE-1376. OURS, never forwarded: eve's `onShortcut` hook is unconfigured on this channel, so
97
+ * a forward is a guaranteed no-op, and eve's shortcut context carries no session to wake from
98
+ * anyway. The decoded shortcut rides along so the handler needn't re-parse it — same pattern as
99
+ * the click branches, which carry a raw `payload` because their handlers own the decode. */
100
+ | {
101
+ readonly kind: "shortcut";
102
+ readonly reason: string;
103
+ readonly shortcut: ParsedSlackShortcut;
104
+ };
105
+ /**
106
+ * Decide how the front route handles a raw inbound body. FORWARD is the fail-safe default:
107
+ * anything slackChannel owns (the challenge handshake, `app_mention`, a `block_actions`/slash
108
+ * interaction) or anything unrecognized goes to slackChannel unchanged. The DM FAMILY is ours:
109
+ * `message.im` (OPE-351 stage 2) and `message.mpim` (stage 4) classify `dm-wake` and are diverted
110
+ * into the surface's own standing window. The other events slackChannel drops route to us too: a
111
+ * plain channel/group `message` → the engagement wake, `member_joined_channel` → the channel-join
112
+ * intro, and a urlencoded `block_actions` payload carrying an `oe_approval:` action id → the
113
+ * approval-click handler (ours alone). A urlencoded SHORTCUT payload (`message_action` /
114
+ * `shortcut`, OPE-1376) is ours too — every OTHER urlencoded body, including Eve's `eve_input:`
115
+ * clicks, its view_submissions and slash commands, still forwards. No network I/O and NO side
116
+ * effects, so every branch is unit-tested. Classification decides what a request IS; nothing here
117
+ * may write process state, because every gate that decides whether the request WAKES anything runs
118
+ * later in the handler (OPE-1442). The absence of a lookup is also why the
119
+ * GROUP-DM app_mention leg is decided in the HANDLER and not here: it needs a Slack lookup, because
120
+ * an app_mention envelope carries no `channel_type` to classify on.
121
+ */
122
+ export declare function classifyEnvelope(rawBody: string, contentType: string): FrontDecision;
123
+ /** The FIFO key a DM's wakes serialize on. Generation-INDEPENDENT (the same reasoning as
124
+ * `supervisorFifoKey`): the FIFO's job is to serialize this DM's wakes, which must hold ACROSS a
125
+ * rotation boundary too, so it keys on the channel and never on the generation-bearing token. Its
126
+ * own namespace, so a DM's queue is never shared with a channel supervisor's or a thread's. */
127
+ export declare function dmFifoKey(dmChannelId: string): string;
128
+ /**
129
+ * Verify a Slack request signature over the RAW body (the exact bytes Slack signed).
130
+ * `v0=` HMAC-SHA256 of `v0:{timestamp}:{body}` keyed by the signing secret, constant-time
131
+ * compared, with a 5-minute replay window. Fail-closed: any missing header / secret, a stale
132
+ * timestamp, or a mismatch returns false. `nowMs` is injectable so the replay window is tested.
133
+ *
134
+ * The BASESTRING AND DIGEST are `channels/slack-signature.ts`'s (OPE-197), shared verbatim with the
135
+ * webhook-registry entry for this scheme — a difference there would be a signature that verifies on
136
+ * one route and 401s on the other. What stays HERE is what the two routes legitimately differ on:
137
+ * this one reads one env-homed secret and returns a bare boolean, because a Slack Request URL has no
138
+ * failure vocabulary to report into.
139
+ */
140
+ export declare function verifySlackSignature(rawBody: string, headers: Headers, signingSecret: string | undefined, nowMs?: number): boolean;
141
+ export { EventDedupe, ThreadFifo };
142
+ export declare function resolveBotIdentity(): Promise<{
143
+ readonly userId?: string;
144
+ readonly botId?: string;
145
+ }>;
146
+ /** Reset the cached identity (tests only). */
147
+ export declare function _resetBotIdentity(): void;
148
+ /** Injectable seams so the wake path is testable without live crypto / Slack. */
149
+ export interface FrontOptions {
150
+ readonly signingSecret?: string;
151
+ readonly dedupe?: EventDedupe;
152
+ readonly fifo?: ThreadFifo;
153
+ readonly getBotIdentity?: () => Promise<{
154
+ readonly userId?: string;
155
+ readonly botId?: string;
156
+ }>;
157
+ readonly now?: () => number;
158
+ /** Durable first-sighting check (true = proceed). Defaults to the operational store. */
159
+ readonly markEventSeen?: (org: string, key: string, atIso: string) => Promise<boolean>;
160
+ /** Is ambient-supervisor mode enabled for this channel's domain? (sync config lookup.)
161
+ * Defaults to the live domain resolver (memory/domain.ts). Fail-closed off: when this
162
+ * returns false the unowned-message dispatch is BYTE-IDENTICAL to today's name-drop path. */
163
+ readonly ambientEnabledFor?: (surfaceKey: string) => boolean;
164
+ /** Does this channel have a STANDING SEAT (OPE-1695)? Defaults to the live predicate
165
+ * (slack-events.ts slackDomainUsesUnifiedWindow: the capability plus a seat domain). It decides
166
+ * ONE thing here — whether an ADDRESSED wake has a seat road to take when the chattiness flag is
167
+ * off. False keeps the pre-seat drop, so a deployment with the capability unarmed is unchanged. */
168
+ readonly seatedSurfaceFor?: (surfaceKey: string) => boolean;
169
+ /** Approval-click handler (defaults to the real `agent/approvals/flow.ts`). Injectable so
170
+ * tests can stub it without the propose/store/executor machinery it drags in.
171
+ *
172
+ * 🔴 IT TAKES THE ROUTE'S `waitUntil` (OPE-1709), for the same reason the Discord front's
173
+ * approval branch does: "Approve for session" releases the sibling cards the grant already
174
+ * covers, and each release runs a real `execute`. That work belongs off the interactivity
175
+ * response path. The handler falls back to its old awaited shape when this is absent, which is
176
+ * exactly what a stub that ignores the second argument gets. */
177
+ readonly handleApprovalPayload?: (payload: unknown, deps?: {
178
+ waitUntil?: (p: Promise<unknown>) => void;
179
+ }) => Promise<boolean>;
180
+ /** "Set API key" click handler (defaults to the real `agent/credentials/intake.ts`) — verifies the
181
+ * clicker owns the intake, then views.open the modal. Injectable for tests. */
182
+ readonly handleSetKeyClick?: (payload: unknown) => Promise<boolean>;
183
+ /** Credential-modal `view_submission` handler (defaults to `agent/credentials/intake.ts`) —
184
+ * encrypts + stores the value and returns the modal-close/errors JSON. Injectable for tests. */
185
+ readonly handleSetKeyViewSubmission?: (payload: unknown) => Promise<SetKeyViewResult>;
186
+ /** Connector-card `oe_connect:` click handler (defaults to `agent/connections/connector-card.ts`) —
187
+ * re-verifies standing host-side, then mints an ephemeral OAuth URL / opens the api-key intake.
188
+ * Injectable for tests. */
189
+ readonly handleConnectClick?: (payload: unknown) => Promise<boolean>;
190
+ /** Injected in tests; the live default is core's `handleGrantCardClick`. The signed grant-click
191
+ * branch schedules it through the route's `waitUntil`, so this handler may outlive the empty
192
+ * Slack acknowledgement. */
193
+ readonly handleGrantCardClick?: (payload: unknown) => Promise<boolean>;
194
+ /** Bridged-approval-card `oe_input:` tap handler (OPE-1720, defaults to
195
+ * `./slack-approval-card.ts`). Injectable so the classification and the branch are testable
196
+ * without a store, a Slack token or eve's `respond` primitive. */
197
+ readonly handleApprovalCardClick?: (payload: unknown, respond: ApprovalRespondFn) => Promise<ApprovalCardClickOutcome>;
198
+ /** SINGLE-WINDOW mention policy for one (channel, surface) — should the unified window own an
199
+ * @mention here (suppress the native forward + keep the sibling as an addressed wake)?
200
+ * Defaults to the live {@link slackSingleWindowMentionPolicy} (grain + fail-closed
201
+ * internal-channel confirmation). Injectable so the two mention legs are testable without a
202
+ * live config/Slack; fail-closed off: the default answers "native owns it" for every
203
+ * non-single-window domain, byte-identical to today. */
204
+ readonly mentionPolicyFor?: (channelId: string, surfaceKey: string) => Promise<SingleWindowMentionPolicy>;
205
+ /** Resolve (create/adopt/rotate/resume) the DM seat for a wake, KEYED ON THE SURFACE KEY since
206
+ * OPE-351 stage 2 (the window token and its registry row are both surface-keyed). `channelId` is
207
+ * the raw platform id the rotation distiller fetches history with; `legacyChannelId` is the
208
+ * one-time adopt-from-OPE-90 probe, supplied for a 1:1 only — a group DM never had such a row.
209
+ * Defaults to the live store-backed {@link liveGetOrCreateDmSeat} with the tail-carrying
210
+ * distiller. Injectable for tests. */
211
+ readonly resolveDmSeat?: (org: string, dm: {
212
+ surfaceKey: string;
213
+ channelId?: string;
214
+ legacyChannelId?: string;
215
+ }, atIso: string) => Promise<DmSeat>;
216
+ /** Record one wake on the DM seat (lastWakeAt/turnCount). Defaults to {@link liveTouchDmSeat}. */
217
+ readonly touchDmSeatFn?: (org: string, dmSurfaceKey: string, atIso: string) => Promise<void>;
218
+ /** DM-partner trust lookup (`users.info`) — feeds `dm_partner_trust`, which gates a 1:1 DM's SHARED
219
+ * read layer (internal ⇒ `dm` trust, external ⇒ `public`). FAIL-CLOSED: undefined ⇒ the attribute
220
+ * is omitted ⇒ the binding treats the partner as external. Defaults to the live cached lookup.
221
+ * NOT consulted for a GROUP DM — see `scheduleDmWake`'s note on why the attribute is 1:1-only. */
222
+ readonly dmPartnerTrustFor?: (userId: string, teamId: string | undefined) => Promise<"internal" | "external" | undefined>;
223
+ /** The channel FACTS the envelope doesn't carry (`conversations.info`, TTL-cached, fail-soft):
224
+ * the surface's `channelType` — the only way to tell a GROUP-DM `app_mention` from a channel's,
225
+ * since an app_mention envelope has no `channel_type` — and the trust gate's confirmed-internal
226
+ * verdict, which stands in for the DM-partner check a group DM cannot make. Defaults to the live
227
+ * {@link slackChannelFactsFor}. Injectable so both mpim legs are testable without Slack; a stub
228
+ * answering `{ internal: false }` reproduces the missing-`mpim:read` degradation exactly.
229
+ *
230
+ * `appCanRead` is the shortcut route's file gate (OPE-1442) and is FAIL-CLOSED: an omitted or
231
+ * false value withholds the target message's files. A stub that leaves it out therefore
232
+ * reproduces "the app cannot read this room", which is the safe default for a test to inherit.
233
+ *
234
+ * `extShared`/`trustChecked` are the RAW platform halves `internal` joins away (OPE-1486) — the
235
+ * group-DM wake stamps them so `bindSlack` grades an mpim on the same two facts a channel is
236
+ * graded on. Both are POSITIVE-ONLY: an omitted value stamps nothing, so a stub that leaves them
237
+ * out reproduces "the platform said nothing about sharing", which demotes no room. */
238
+ readonly channelFactsFor?: (channelId: string) => Promise<{
239
+ internal: boolean;
240
+ channelType?: string;
241
+ appCanRead?: boolean;
242
+ extShared?: boolean;
243
+ trustChecked?: boolean;
244
+ }>;
245
+ /** Open (or reuse) the 1:1 DM channel with a Slack member, returning its `D…` id — the landing
246
+ * place a GLOBAL shortcut wakes in (OPE-1376), since a global shortcut names no conversation.
247
+ * `conversations.open` is idempotent, so this is a resolve rather than a create. Needs the
248
+ * `im:write` bot scope, which the runbook and the wizard manifest already require for the
249
+ * governance DM-delivery arm. Defaults to the live call; FAIL-CLOSED: undefined ⇒ the shortcut
250
+ * wakes nothing and says so, never a wake in a guessed room. Injectable for tests. */
251
+ readonly openDirectMessageChannel?: (userId: string) => Promise<string | undefined>;
252
+ /** The trigger author's two membership facts, from ONE `users.info` probe — the exact pair every
253
+ * wake route in slack-events.ts resolves. Two readers: the native `app_mention` forward's
254
+ * external-policy gate, which calls it only when that policy is not inert (so a deployment on the
255
+ * shipped grains pays nothing there), and every GROUP-DM wake (OPE-1486), which reads its
256
+ * `refuted` half unconditionally — a guest who writes in an mpim must mark the turn whatever the
257
+ * policy grain is. Defaults to the live {@link slackWakeAuthorFacts}; injectable so both are
258
+ * testable without Slack. */
259
+ readonly authorFactsFor?: (channelInternal: boolean, userId: string | undefined, teamId: string | undefined) => Promise<{
260
+ readonly surfaceInternal: boolean;
261
+ readonly refuted: boolean;
262
+ }>;
263
+ }
264
+ /**
265
+ * Turn a swallowed FIFO wake failure into a DURABLE, queryable signal (resilience S-1 / #551
266
+ * §3.4): a log-ship "error" record (the primary win — the failure survives the ~1h console
267
+ * retention) plus a best-effort `surface.wake_failed` audit row (mirrors recordQuietFailure's
268
+ * posture). The FIFO key encodes the channel (`${channelId}:${threadTs}` for a thread wake,
269
+ * `${channelId}:oe-sup` for a supervisor wake); team is unknown at this layer, so the audit
270
+ * partition falls back to the empty-team default exactly like recordQuietFailure's own
271
+ * `teamId ?? ""` — best-effort, never blocks. Never throws.
272
+ */
273
+ /**
274
+ * Deliver a wake, and RE-DELIVER IT ONCE when the first attempt died on a pruned deployment
275
+ * (OPE-963, channels/stranded-seat.ts).
276
+ *
277
+ * The first attempt's failure is not wasted: `divertToUnifiedWindow` classified it and MARKED the
278
+ * seat's `channel_session` row for rotation before it rethrew. So the second attempt re-resolves the
279
+ * seat, `rotationTrigger` answers `operator-marked`, the seat takes its own rotate leg (fresh
280
+ * generation, carried tail), and eve opens a NEW run under the CURRENT deployment. Without this the
281
+ * member loses the message that hit the strand, even though the seat itself is healed.
282
+ *
283
+ * EXACTLY ONE retry, and only for this class. Every other failure rethrows untouched, straight to
284
+ * the FIFO's loud handler ({@link recordWakeFailure}). A second failure of the same class rethrows
285
+ * too — the seat could not be marked, so a third attempt would resume the same dead run.
286
+ *
287
+ * THE ROUTE FUNCTION MUST BE RE-RUNNABLE, and both wrapped routes are. Everything they do before
288
+ * the divert is a read or an idempotent write: TTL-cached `conversations.info` / `users.info`
289
+ * probes, a deterministic external-policy verdict (its private notice posts only on a verdict that
290
+ * RETURNS rather than throws, so a retry never reaches it), a read-only spend gate, and
291
+ * `markEngaged`, which upserts. `recordWakeTail` and `touchDmSeat`/`touchSession` all run AFTER the
292
+ * divert, so a failed attempt records nothing to duplicate. The wake id is minted fresh, which is
293
+ * correct — the retry is a new delivery.
294
+ *
295
+ * Applied only to the WINDOW-bearing routes — a thread seat has no `channel_session` row to mark,
296
+ * so a retry there could only resume the same dead run.
297
+ *
298
+ * OPE-970: when the RETRY ALSO throws, the seat is still healed for its NEXT wake — but THIS
299
+ * member's message got no answer, and that fact must not collapse into an ordinary send-failure
300
+ * row indistinguishable from a transient blip. The retry's error is tagged
301
+ * ({@link markUndeliveredAfterHeal}) before it rethrows, so {@link recordWakeFailure} can give the
302
+ * row its own reason.
303
+ */
304
+ export declare function deliverWithStrandRetry<T>(deliver: () => Promise<T>): Promise<T>;
305
+ export declare function recordWakeFailure(key: string, err: unknown): void;
306
+ /**
307
+ * Build the front route handler. Buffers the body once, verifies the signature, then forwards
308
+ * or wakes per {@link classifyEnvelope}. `innerHandler` is slackChannel's own POST handler,
309
+ * invoked with a FRESH Request (re-readable body) + the same {@link RouteHandlerArgs}, so
310
+ * slackChannel re-verifies and dispatches exactly as if it owned the URL.
311
+ */
312
+ /**
313
+ * SINGLE-WINDOW diversion (channels/unified-window.ts): layer the cross-channel hop onto the
314
+ * supervisor deps. When routeSupervisorEvent minted a `window` for a wake (the domain's
315
+ * crossSurfaceWindow gates hold — the wakeId is already rendered into the envelope), deliver it
316
+ * through eve's cross-channel `to(...).send(...)` into the synthetic `unified` channel instead of the
317
+ * Slack send: the effective token becomes `unified:<raw>`, shared with every surface in the
318
+ * domain — ONE context window. The unified channel's `receive` registers the wakeId→origin map
319
+ * entry (durably, BEFORE the send) and re-checks the gates fail-closed. This wrapper lives HERE
320
+ * because only the route handler holds `args.to` (and slack-events.ts must not import
321
+ * unified.ts — unified.ts imports it). A window-less wake passes through untouched, so flag-off
322
+ * is byte-identical. A diversion failure PROPAGATES to the FIFO's loud catch (fail-closed: a
323
+ * wake whose reply map couldn't be written is not delivered into the shared window).
324
+ *
325
+ * THREAD-OWNERSHIP ingress routing (§S2): the divert goes through the INBOUND variant
326
+ * (unified.ts divertInboundToUnifiedWindow), which — only under delegation.oneshotAgent — consults the
327
+ * durable ownership index and dispatches a wake landing in an OWNED thread to the owning task/
328
+ * thread-seat session's token instead of the standing seat's. Flag-off, and on every unowned
329
+ * thread, the inbound variant is a byte-identical passthrough to divertToUnifiedWindow.
330
+ *
331
+ * OPE-971: the `!input.window` (NATIVE, flag-off) branch below is Slack's own un-windowed
332
+ * supervisor session — the send this domain takes when it never opted into windowing at all. That
333
+ * send was completely unwrapped: a pruned-deployment strand there stranded the seat silently,
334
+ * forever (see channels/stranded-seat.ts). `deps.wake`'s own registryKey for this branch IS
335
+ * `surfaceKey` (supervisorGrainFor returns `{unified:false, registryKey:surfaceKey}` flag-off — the
336
+ * exact row `liveSupervisorDeps`'s `getOrCreateSession` already rotates), so the heal is told that
337
+ * key directly rather than trying to parse it back out of the per-channel token.
338
+ */
339
+ export declare function withSingleWindowDiversion(deps: ReturnType<typeof liveSupervisorDeps>, to: RouteHandlerArgs["to"], surfaceKey: string): ReturnType<typeof liveSupervisorDeps>;
340
+ /** Reset the cached DM-partner trust (tests only). */
341
+ export declare function _resetDmTrustCache(): void;
342
+ /**
343
+ * Does this `message` event DUPLICATE an `app_mention` Slack also fires, so the wake path must drop it?
344
+ *
345
+ * Slack sends TWO events for a new message that @mentions the bot: the `app_mention`, which the
346
+ * front's own `mention` branch owns, and a sibling carrying the same text — `message.channels` in a
347
+ * channel, `message.mpim` in a group DM. Acting on both is a double turn, so both the channel wake
348
+ * path and the group-DM leg drop the sibling through this one rule.
349
+ *
350
+ * 🔴 AN EDIT IS NEVER A SIBLING, AND SUPPRESSING ONE IS A LOST WAKE (OPE-1673). Slack delivers an
351
+ * edit ONLY as `message` with `subtype: "message_changed"`; no `app_mention` accompanies it, and
352
+ * `parseMessageEvent` reads the POST-EDIT text — so a person who edits a message in an engaged
353
+ * thread to add `<@bot>`, or who corrects the wording of a mention that is already there, matched
354
+ * this rule and was answered by nothing at all. There is no second event to prefer. The exemption is
355
+ * narrow by construction: an edit cannot reach the `app_mention` branch, because the front classifies
356
+ * the envelope on its event TYPE and a `message_changed` always arrives as a `message`.
357
+ *
358
+ * UNVERIFIED, and stated rather than assumed: Slack's docs do not say whether an edit that ADDS a
359
+ * mention also raises a fresh `app_mention`. If it does, the cost of this exemption is an occasional
360
+ * double turn — the same trade the next paragraph already takes, for the same reason.
361
+ *
362
+ * MATCH THE AUTHOR'S OWN TEXT, NEVER THE MERGED ONE (OPE-1374). `ev.text` carries forwarded and
363
+ * quoted content, so testing it would suppress a forward whose QUOTED message mentions the bot.
364
+ * UNVERIFIED for the same reason as above: whether Slack fires an `app_mention` for a mention that
365
+ * lives inside an attachment. If it does NOT — the shape we expect — testing the merged text loses
366
+ * the wake outright, because no sibling ever arrives to deliver it. If it DOES, the cost is a double
367
+ * turn. We take the double: an occasional double beats a drop, and a deaf agent on a forward is the
368
+ * failure OPE-1374 exists to prevent.
369
+ *
370
+ * Pure, so both the suppression and its exemption are unit-testable without Slack or a store. An
371
+ * unresolved bot user id suppresses nothing — there is no needle to match, and inventing one would
372
+ * drop every message.
373
+ */
374
+ export declare function mentionSiblingSuppressed(input: {
375
+ readonly authoredText: string;
376
+ readonly subtype?: string;
377
+ readonly botUserId?: string;
378
+ }): boolean;
379
+ export declare function buildFrontHandler(innerHandler: RouteHandler, opts?: FrontOptions): RouteHandler;
380
+ /**
381
+ * Compose the engagement front route with a wrapped `slackChannel`. `inner` must have been
382
+ * built with `route: INTERNAL_SLACK_ROUTE`. Returns the SAME channel value (preserving Eve's
383
+ * internal `__kind`/adapter/receive) with the public front route prepended — so Slack's URL
384
+ * hits us, and both routes share one channel name → one session namespace.
385
+ */
386
+ export declare function frontSlackChannel<C extends Channel<any, any, any>>(inner: C, opts?: FrontOptions): C;
387
+ //# sourceMappingURL=slack-front.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack-front.d.ts","sourceRoot":"","sources":["../../../agent/channels/slack-front.ts"],"names":[],"mappings":"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"}