@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.
- package/LICENSE +201 -0
- package/NOTICE +21 -0
- package/README.md +47 -0
- package/agent/access/slack-attachment-fetch.ts +168 -0
- package/agent/app-manifest.ts +149 -0
- package/agent/channels/slack-approval-card.ts +275 -0
- package/agent/channels/slack-attachments.ts +195 -0
- package/agent/channels/slack-commands.ts +227 -0
- package/agent/channels/slack-context.ts +185 -0
- package/agent/channels/slack-events.ts +5406 -0
- package/agent/channels/slack-front.ts +2349 -0
- package/agent/channels/slack-identity.ts +520 -0
- package/agent/channels/slack-input-response.ts +162 -0
- package/agent/channels/slack-mrkdwn.ts +61 -0
- package/agent/channels/slack-origin-codec.ts +62 -0
- package/agent/channels/slack-post-arm.ts +314 -0
- package/agent/channels/slack-read.ts +248 -0
- package/agent/channels/slack-route-hold.ts +107 -0
- package/agent/channels/slack-shortcut.ts +336 -0
- package/agent/channels/slack-signature.ts +53 -0
- package/agent/channels/slack-spend-gate.ts +62 -0
- package/agent/channels/slack-tenant-fence.ts +99 -0
- package/agent/channels/slack-wake-backscroll.ts +604 -0
- package/agent/channels/slack-web-api.ts +178 -0
- package/agent/channels/slack-webhook-verifier.ts +116 -0
- package/agent/channels/slack.ts +1266 -0
- package/agent/contributions.ts +32 -0
- package/agent/docs-generated.ts +15 -0
- package/agent/ops.ts +50 -0
- package/agent/provider-events.ts +91 -0
- package/agent/register.ts +144 -0
- package/agent/surface-parity.ts +99 -0
- package/dist/agent/access/slack-attachment-fetch.d.ts +15 -0
- package/dist/agent/access/slack-attachment-fetch.d.ts.map +1 -0
- package/dist/agent/access/slack-attachment-fetch.js +151 -0
- package/dist/agent/access/slack-attachment-fetch.js.map +1 -0
- package/dist/agent/app-manifest.d.ts +15 -0
- package/dist/agent/app-manifest.d.ts.map +1 -0
- package/dist/agent/app-manifest.js +141 -0
- package/dist/agent/app-manifest.js.map +1 -0
- package/dist/agent/channels/slack-approval-card.d.ts +71 -0
- package/dist/agent/channels/slack-approval-card.d.ts.map +1 -0
- package/dist/agent/channels/slack-approval-card.js +232 -0
- package/dist/agent/channels/slack-approval-card.js.map +1 -0
- package/dist/agent/channels/slack-attachments.d.ts +66 -0
- package/dist/agent/channels/slack-attachments.d.ts.map +1 -0
- package/dist/agent/channels/slack-attachments.js +174 -0
- package/dist/agent/channels/slack-attachments.js.map +1 -0
- package/dist/agent/channels/slack-commands.d.ts +27 -0
- package/dist/agent/channels/slack-commands.d.ts.map +1 -0
- package/dist/agent/channels/slack-commands.js +208 -0
- package/dist/agent/channels/slack-commands.js.map +1 -0
- package/dist/agent/channels/slack-context.d.ts +26 -0
- package/dist/agent/channels/slack-context.d.ts.map +1 -0
- package/dist/agent/channels/slack-context.js +178 -0
- package/dist/agent/channels/slack-context.js.map +1 -0
- package/dist/agent/channels/slack-events.d.ts +1654 -0
- package/dist/agent/channels/slack-events.d.ts.map +1 -0
- package/dist/agent/channels/slack-events.js +4240 -0
- package/dist/agent/channels/slack-events.js.map +1 -0
- package/dist/agent/channels/slack-front.d.ts +387 -0
- package/dist/agent/channels/slack-front.d.ts.map +1 -0
- package/dist/agent/channels/slack-front.js +1958 -0
- package/dist/agent/channels/slack-front.js.map +1 -0
- package/dist/agent/channels/slack-identity.d.ts +245 -0
- package/dist/agent/channels/slack-identity.d.ts.map +1 -0
- package/dist/agent/channels/slack-identity.js +405 -0
- package/dist/agent/channels/slack-identity.js.map +1 -0
- package/dist/agent/channels/slack-input-response.d.ts +26 -0
- package/dist/agent/channels/slack-input-response.d.ts.map +1 -0
- package/dist/agent/channels/slack-input-response.js +127 -0
- package/dist/agent/channels/slack-input-response.js.map +1 -0
- package/dist/agent/channels/slack-mrkdwn.d.ts +3 -0
- package/dist/agent/channels/slack-mrkdwn.d.ts.map +1 -0
- package/dist/agent/channels/slack-mrkdwn.js +53 -0
- package/dist/agent/channels/slack-mrkdwn.js.map +1 -0
- package/dist/agent/channels/slack-origin-codec.d.ts +7 -0
- package/dist/agent/channels/slack-origin-codec.d.ts.map +1 -0
- package/dist/agent/channels/slack-origin-codec.js +55 -0
- package/dist/agent/channels/slack-origin-codec.js.map +1 -0
- package/dist/agent/channels/slack-post-arm.d.ts +54 -0
- package/dist/agent/channels/slack-post-arm.d.ts.map +1 -0
- package/dist/agent/channels/slack-post-arm.js +268 -0
- package/dist/agent/channels/slack-post-arm.js.map +1 -0
- package/dist/agent/channels/slack-read.d.ts +84 -0
- package/dist/agent/channels/slack-read.d.ts.map +1 -0
- package/dist/agent/channels/slack-read.js +205 -0
- package/dist/agent/channels/slack-read.js.map +1 -0
- package/dist/agent/channels/slack-route-hold.d.ts +34 -0
- package/dist/agent/channels/slack-route-hold.d.ts.map +1 -0
- package/dist/agent/channels/slack-route-hold.js +97 -0
- package/dist/agent/channels/slack-route-hold.js.map +1 -0
- package/dist/agent/channels/slack-shortcut.d.ts +162 -0
- package/dist/agent/channels/slack-shortcut.d.ts.map +1 -0
- package/dist/agent/channels/slack-shortcut.js +262 -0
- package/dist/agent/channels/slack-shortcut.js.map +1 -0
- package/dist/agent/channels/slack-signature.d.ts +19 -0
- package/dist/agent/channels/slack-signature.d.ts.map +1 -0
- package/dist/agent/channels/slack-signature.js +50 -0
- package/dist/agent/channels/slack-signature.js.map +1 -0
- package/dist/agent/channels/slack-spend-gate.d.ts +22 -0
- package/dist/agent/channels/slack-spend-gate.d.ts.map +1 -0
- package/dist/agent/channels/slack-spend-gate.js +48 -0
- package/dist/agent/channels/slack-spend-gate.js.map +1 -0
- package/dist/agent/channels/slack-tenant-fence.d.ts +61 -0
- package/dist/agent/channels/slack-tenant-fence.d.ts.map +1 -0
- package/dist/agent/channels/slack-tenant-fence.js +88 -0
- package/dist/agent/channels/slack-tenant-fence.js.map +1 -0
- package/dist/agent/channels/slack-wake-backscroll.d.ts +188 -0
- package/dist/agent/channels/slack-wake-backscroll.d.ts.map +1 -0
- package/dist/agent/channels/slack-wake-backscroll.js +473 -0
- package/dist/agent/channels/slack-wake-backscroll.js.map +1 -0
- package/dist/agent/channels/slack-web-api.d.ts +46 -0
- package/dist/agent/channels/slack-web-api.d.ts.map +1 -0
- package/dist/agent/channels/slack-web-api.js +147 -0
- package/dist/agent/channels/slack-web-api.js.map +1 -0
- package/dist/agent/channels/slack-webhook-verifier.d.ts +5 -0
- package/dist/agent/channels/slack-webhook-verifier.d.ts.map +1 -0
- package/dist/agent/channels/slack-webhook-verifier.js +112 -0
- package/dist/agent/channels/slack-webhook-verifier.js.map +1 -0
- package/dist/agent/channels/slack.d.ts +37 -0
- package/dist/agent/channels/slack.d.ts.map +1 -0
- package/dist/agent/channels/slack.js +1169 -0
- package/dist/agent/channels/slack.js.map +1 -0
- package/dist/agent/contributions.d.ts +17 -0
- package/dist/agent/contributions.d.ts.map +1 -0
- package/dist/agent/contributions.js +32 -0
- package/dist/agent/contributions.js.map +1 -0
- package/dist/agent/docs-generated.d.ts +3 -0
- package/dist/agent/docs-generated.d.ts.map +1 -0
- package/dist/agent/docs-generated.js +13 -0
- package/dist/agent/docs-generated.js.map +1 -0
- package/dist/agent/ops.d.ts +3 -0
- package/dist/agent/ops.d.ts.map +1 -0
- package/dist/agent/ops.js +38 -0
- package/dist/agent/ops.js.map +1 -0
- package/dist/agent/provider-events.d.ts +3 -0
- package/dist/agent/provider-events.d.ts.map +1 -0
- package/dist/agent/provider-events.js +84 -0
- package/dist/agent/provider-events.js.map +1 -0
- package/dist/agent/register.d.ts +5 -0
- package/dist/agent/register.d.ts.map +1 -0
- package/dist/agent/register.js +118 -0
- package/dist/agent/register.js.map +1 -0
- package/dist/agent/surface-parity.d.ts +3 -0
- package/dist/agent/surface-parity.d.ts.map +1 -0
- package/dist/agent/surface-parity.js +95 -0
- package/dist/agent/surface-parity.js.map +1 -0
- package/package.json +209 -0
- package/tsconfig.build.json +22 -0
- 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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"}
|