@open-everywhere/provider-slack 0.1.3 → 0.1.5
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/NOTICE +34 -4
- package/agent/access/slack-attachment-fetch.ts +3 -1
- package/agent/app-manifest.ts +48 -10
- package/agent/channels/slack-commands.ts +5 -1
- package/agent/channels/slack-events.ts +13 -4
- package/agent/channels/slack-front.ts +44 -7
- package/agent/channels/slack-read.ts +9 -3
- package/agent/channels/slack-setup-page.ts +20 -0
- package/agent/channels/slack-web-api.ts +34 -7
- package/agent/channels/slack.ts +11 -3
- package/agent/contributions.ts +1 -0
- package/agent/docs-generated.ts +1 -1
- package/agent/ops.ts +29 -61
- package/agent/register.ts +27 -1
- package/agent/setup/claim.ts +343 -0
- package/agent/setup/credentials.ts +265 -0
- package/agent/setup/eve-credentials.ts +77 -0
- package/agent/setup/install-state.ts +248 -0
- package/agent/setup/page.ts +579 -0
- package/agent/setup/slack-api-setup.ts +176 -0
- package/agent/status.ts +94 -0
- package/dist/agent/access/slack-attachment-fetch.d.ts.map +1 -1
- package/dist/agent/access/slack-attachment-fetch.js +3 -1
- package/dist/agent/access/slack-attachment-fetch.js.map +1 -1
- package/dist/agent/app-manifest.d.ts +4 -4
- package/dist/agent/app-manifest.d.ts.map +1 -1
- package/dist/agent/app-manifest.js +48 -10
- package/dist/agent/app-manifest.js.map +1 -1
- package/dist/agent/channels/slack-commands.d.ts.map +1 -1
- package/dist/agent/channels/slack-commands.js +5 -1
- package/dist/agent/channels/slack-commands.js.map +1 -1
- package/dist/agent/channels/slack-events.d.ts +1 -1
- package/dist/agent/channels/slack-events.d.ts.map +1 -1
- package/dist/agent/channels/slack-events.js +13 -4
- package/dist/agent/channels/slack-events.js.map +1 -1
- package/dist/agent/channels/slack-front.d.ts +4 -1
- package/dist/agent/channels/slack-front.d.ts.map +1 -1
- package/dist/agent/channels/slack-front.js +40 -7
- package/dist/agent/channels/slack-front.js.map +1 -1
- package/dist/agent/channels/slack-read.d.ts +6 -1
- package/dist/agent/channels/slack-read.d.ts.map +1 -1
- package/dist/agent/channels/slack-read.js +9 -3
- package/dist/agent/channels/slack-read.js.map +1 -1
- package/dist/agent/channels/slack-setup-page.d.ts +3 -0
- package/dist/agent/channels/slack-setup-page.d.ts.map +1 -0
- package/dist/agent/channels/slack-setup-page.js +13 -0
- package/dist/agent/channels/slack-setup-page.js.map +1 -0
- package/dist/agent/channels/slack-web-api.d.ts +3 -0
- package/dist/agent/channels/slack-web-api.d.ts.map +1 -1
- package/dist/agent/channels/slack-web-api.js +26 -6
- package/dist/agent/channels/slack-web-api.js.map +1 -1
- package/dist/agent/channels/slack.d.ts.map +1 -1
- package/dist/agent/channels/slack.js +11 -3
- package/dist/agent/channels/slack.js.map +1 -1
- package/dist/agent/contributions.d.ts +5 -0
- package/dist/agent/contributions.d.ts.map +1 -1
- package/dist/agent/contributions.js +1 -0
- package/dist/agent/contributions.js.map +1 -1
- package/dist/agent/docs-generated.js +1 -1
- package/dist/agent/docs-generated.js.map +1 -1
- package/dist/agent/ops.d.ts +1 -1
- package/dist/agent/ops.d.ts.map +1 -1
- package/dist/agent/ops.js +29 -47
- package/dist/agent/ops.js.map +1 -1
- package/dist/agent/register.d.ts.map +1 -1
- package/dist/agent/register.js +26 -2
- package/dist/agent/register.js.map +1 -1
- package/dist/agent/setup/claim.d.ts +73 -0
- package/dist/agent/setup/claim.d.ts.map +1 -0
- package/dist/agent/setup/claim.js +298 -0
- package/dist/agent/setup/claim.js.map +1 -0
- package/dist/agent/setup/credentials.d.ts +56 -0
- package/dist/agent/setup/credentials.d.ts.map +1 -0
- package/dist/agent/setup/credentials.js +214 -0
- package/dist/agent/setup/credentials.js.map +1 -0
- package/dist/agent/setup/eve-credentials.d.ts +22 -0
- package/dist/agent/setup/eve-credentials.d.ts.map +1 -0
- package/dist/agent/setup/eve-credentials.js +73 -0
- package/dist/agent/setup/eve-credentials.js.map +1 -0
- package/dist/agent/setup/install-state.d.ts +139 -0
- package/dist/agent/setup/install-state.d.ts.map +1 -0
- package/dist/agent/setup/install-state.js +196 -0
- package/dist/agent/setup/install-state.js.map +1 -0
- package/dist/agent/setup/page.d.ts +29 -0
- package/dist/agent/setup/page.d.ts.map +1 -0
- package/dist/agent/setup/page.js +460 -0
- package/dist/agent/setup/page.js.map +1 -0
- package/dist/agent/setup/slack-api-setup.d.ts +62 -0
- package/dist/agent/setup/slack-api-setup.d.ts.map +1 -0
- package/dist/agent/setup/slack-api-setup.js +138 -0
- package/dist/agent/setup/slack-api-setup.js.map +1 -0
- package/dist/agent/status.d.ts +4 -0
- package/dist/agent/status.d.ts.map +1 -0
- package/dist/agent/status.js +87 -0
- package/dist/agent/status.js.map +1 -0
- package/package.json +38 -4
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
// THE TWO SLACK CALLS A `/setup` RUN MAKES (OPE-2231) — create the app, then install it.
|
|
2
|
+
//
|
|
3
|
+
// Both go through `channels/slack-web-api.ts`, the ONE seam a Slack Web API call leaves this host
|
|
4
|
+
// through (OPE-1211), so both carry the 429/`Retry-After` backoff and neither becomes a new
|
|
5
|
+
// uncovered bypass in `slack-web-api-seam-test.ts`'s inventory.
|
|
6
|
+
//
|
|
7
|
+
// 1. `apps.manifest.create` — docs.slack.dev/reference/methods/apps.manifest.create. Authenticated by
|
|
8
|
+
// an APP CONFIGURATION TOKEN the operator pastes (api.slack.com/apps → "Your App Configuration
|
|
9
|
+
// Tokens", scope `app_configurations:write`, ~12 h life). It takes the manifest this bundle ships
|
|
10
|
+
// (`agent/app-manifest.ts`) with this deployment's host substituted, and returns the app's
|
|
11
|
+
// `app_id`, `client_id`, `client_secret`, `signing_secret` and `oauth_authorize_url`.
|
|
12
|
+
//
|
|
13
|
+
// 2. `oauth.v2.access` — docs.slack.dev/reference/methods/oauth.v2.access. Exchanges the `code` the
|
|
14
|
+
// install redirect brought back for the workspace bot `access_token`, and reports `team.id` and
|
|
15
|
+
// `authed_user.id`. Authenticated by the app's CLIENT CREDENTIALS IN THE BODY, so it is the one
|
|
16
|
+
// call in this tree that sends no `Authorization` header (`unauthenticated: true` — see the seam).
|
|
17
|
+
//
|
|
18
|
+
// 🔴 NOTHING HERE LOGS, AUDITS, RETURNS IN AN ERROR, OR OTHERWISE RENDERS A VALUE IT RECEIVED. Each
|
|
19
|
+
// function returns a typed record the caller stores straight into the vault, and each failure is a
|
|
20
|
+
// {@link SlackSetupApiError} carrying Slack's own `error` CODE and nothing else. Slack's error codes
|
|
21
|
+
// are a closed vocabulary (`invalid_auth`, `token_expired`, `invalid_manifest`, …) and are the one
|
|
22
|
+
// thing an operator needs to act; the response body that carried them is dropped unread, because on
|
|
23
|
+
// the manifest call that body is the credential bundle.
|
|
24
|
+
|
|
25
|
+
import { callSlackWebApi } from "../channels/slack-web-api.js";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* A Slack call that failed. `code` is Slack's own `error` string when it gave one, else a fixed
|
|
29
|
+
* local classification — never a message assembled from a response. The page renders this; see the
|
|
30
|
+
* header on why it carries no payload.
|
|
31
|
+
*/
|
|
32
|
+
export class SlackSetupApiError extends Error {
|
|
33
|
+
readonly code: string;
|
|
34
|
+
constructor(operation: string, code: string) {
|
|
35
|
+
super(`Slack refused ${operation}: ${code}`);
|
|
36
|
+
this.name = "SlackSetupApiError";
|
|
37
|
+
this.code = code;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** What `apps.manifest.create` gives back. Three of the five fields are SECRET. */
|
|
42
|
+
export interface CreatedSlackApp {
|
|
43
|
+
readonly appId: string;
|
|
44
|
+
readonly clientId: string;
|
|
45
|
+
/** SECRET. */
|
|
46
|
+
readonly clientSecret: string;
|
|
47
|
+
/** SECRET. */
|
|
48
|
+
readonly signingSecret: string;
|
|
49
|
+
/** Where to send the installer's browser to install the app. Slack composes it. */
|
|
50
|
+
readonly oauthAuthorizeUrl: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Injectable seam for the suite — the live default is the real Slack Web API seam. */
|
|
54
|
+
export interface SlackSetupApiDeps {
|
|
55
|
+
readonly call?: typeof callSlackWebApi;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Read one non-empty string field, or throw a shaped error naming the FIELD, never the payload. */
|
|
59
|
+
function requireString(operation: string, res: Record<string, unknown>, key: string): string {
|
|
60
|
+
const v = res[key];
|
|
61
|
+
if (typeof v !== "string" || v.length === 0) throw new SlackSetupApiError(operation, `missing_field:${key}`);
|
|
62
|
+
return v;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Slack's `error` code off an `ok:false` envelope, or a fixed stand-in when it named none. */
|
|
66
|
+
function slackErrorCode(res: Record<string, unknown>): string {
|
|
67
|
+
const e = res.error;
|
|
68
|
+
return typeof e === "string" && e.length > 0 ? e : "unknown_error";
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Create the Slack app from this bundle's shipped manifest.
|
|
73
|
+
*
|
|
74
|
+
* `configToken` is the pasted app configuration token and is used ONCE, here, as the bearer. It is
|
|
75
|
+
* never stored: it expires in about 12 hours and `/setup` has no later use for it, so holding it
|
|
76
|
+
* would be a credential kept past its purpose.
|
|
77
|
+
*
|
|
78
|
+
* `manifest` is the already-substituted manifest JSON string (the caller resolves the host, so this
|
|
79
|
+
* function has no opinion about where the deployment lives).
|
|
80
|
+
*/
|
|
81
|
+
export async function createSlackApp(
|
|
82
|
+
input: { readonly configToken: string; readonly manifest: string },
|
|
83
|
+
deps: SlackSetupApiDeps = {},
|
|
84
|
+
): Promise<CreatedSlackApp> {
|
|
85
|
+
const call = deps.call ?? callSlackWebApi;
|
|
86
|
+
let res: Record<string, unknown>;
|
|
87
|
+
try {
|
|
88
|
+
res = (await call({
|
|
89
|
+
botToken: input.configToken,
|
|
90
|
+
operation: "apps.manifest.create",
|
|
91
|
+
body: { manifest: input.manifest },
|
|
92
|
+
})) as Record<string, unknown>;
|
|
93
|
+
} catch {
|
|
94
|
+
// A throw from the seam is a transport failure or a non-2xx — the caught value can carry Slack's
|
|
95
|
+
// response body, so it is dropped rather than inspected. See the header.
|
|
96
|
+
throw new SlackSetupApiError("apps.manifest.create", "request_failed");
|
|
97
|
+
}
|
|
98
|
+
if (res.ok !== true) throw new SlackSetupApiError("apps.manifest.create", slackErrorCode(res));
|
|
99
|
+
|
|
100
|
+
const credentials = res.credentials;
|
|
101
|
+
if (typeof credentials !== "object" || credentials === null) {
|
|
102
|
+
throw new SlackSetupApiError("apps.manifest.create", "missing_field:credentials");
|
|
103
|
+
}
|
|
104
|
+
const c = credentials as Record<string, unknown>;
|
|
105
|
+
return {
|
|
106
|
+
appId: requireString("apps.manifest.create", res, "app_id"),
|
|
107
|
+
clientId: requireString("apps.manifest.create", c, "client_id"),
|
|
108
|
+
clientSecret: requireString("apps.manifest.create", c, "client_secret"),
|
|
109
|
+
signingSecret: requireString("apps.manifest.create", c, "signing_secret"),
|
|
110
|
+
oauthAuthorizeUrl: requireString("apps.manifest.create", res, "oauth_authorize_url"),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** What `oauth.v2.access` gives back. `botToken` is SECRET; the three ids are not. */
|
|
115
|
+
export interface SlackOauthInstall {
|
|
116
|
+
/** SECRET — the workspace bot token (`xoxb-…`). */
|
|
117
|
+
readonly botToken: string;
|
|
118
|
+
readonly teamId: string;
|
|
119
|
+
readonly teamName?: string;
|
|
120
|
+
readonly installerUserId: string;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Exchange the install `code` for the workspace bot token.
|
|
125
|
+
*
|
|
126
|
+
* NO `Authorization` HEADER — Slack authenticates this one by `client_id` + `client_secret` in the
|
|
127
|
+
* body (see the module header and the seam's own note). The `redirect_uri` is sent back because Slack
|
|
128
|
+
* requires it to MATCH the one the authorize step used; omitting it when one was used is an
|
|
129
|
+
* `invalid_grant`-class refusal rather than a laxer check.
|
|
130
|
+
*/
|
|
131
|
+
export async function exchangeSlackOauthCode(
|
|
132
|
+
input: {
|
|
133
|
+
readonly clientId: string;
|
|
134
|
+
readonly clientSecret: string;
|
|
135
|
+
readonly code: string;
|
|
136
|
+
readonly redirectUri: string;
|
|
137
|
+
},
|
|
138
|
+
deps: SlackSetupApiDeps = {},
|
|
139
|
+
): Promise<SlackOauthInstall> {
|
|
140
|
+
const call = deps.call ?? callSlackWebApi;
|
|
141
|
+
let res: Record<string, unknown>;
|
|
142
|
+
try {
|
|
143
|
+
res = (await call({
|
|
144
|
+
unauthenticated: true,
|
|
145
|
+
operation: "oauth.v2.access",
|
|
146
|
+
body: {
|
|
147
|
+
client_id: input.clientId,
|
|
148
|
+
client_secret: input.clientSecret,
|
|
149
|
+
code: input.code,
|
|
150
|
+
redirect_uri: input.redirectUri,
|
|
151
|
+
},
|
|
152
|
+
})) as Record<string, unknown>;
|
|
153
|
+
} catch {
|
|
154
|
+
throw new SlackSetupApiError("oauth.v2.access", "request_failed");
|
|
155
|
+
}
|
|
156
|
+
if (res.ok !== true) throw new SlackSetupApiError("oauth.v2.access", slackErrorCode(res));
|
|
157
|
+
|
|
158
|
+
const team = res.team;
|
|
159
|
+
const authedUser = res.authed_user;
|
|
160
|
+
if (typeof team !== "object" || team === null) throw new SlackSetupApiError("oauth.v2.access", "missing_field:team");
|
|
161
|
+
if (typeof authedUser !== "object" || authedUser === null) {
|
|
162
|
+
throw new SlackSetupApiError("oauth.v2.access", "missing_field:authed_user");
|
|
163
|
+
}
|
|
164
|
+
const t = team as Record<string, unknown>;
|
|
165
|
+
const u = authedUser as Record<string, unknown>;
|
|
166
|
+
const teamName = typeof t.name === "string" && t.name.length > 0 ? t.name : undefined;
|
|
167
|
+
return {
|
|
168
|
+
// `access_token` on an `oauth.v2.access` response IS the bot token for a bot-scoped install —
|
|
169
|
+
// Slack puts the USER token under `authed_user.access_token`, which this flow never asks for and
|
|
170
|
+
// never reads. Taking the wrong one here would store a token with the installer's own access.
|
|
171
|
+
botToken: requireString("oauth.v2.access", res, "access_token"),
|
|
172
|
+
teamId: requireString("oauth.v2.access", t, "id"),
|
|
173
|
+
installerUserId: requireString("oauth.v2.access", u, "id"),
|
|
174
|
+
...(teamName ? { teamName } : {}),
|
|
175
|
+
};
|
|
176
|
+
}
|
package/agent/status.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// The Slack arm of the deployment-status surface (OPE-2230) — what `GET /eve/v1/oe/status` reports
|
|
2
|
+
// under `surfaces.slack`.
|
|
3
|
+
//
|
|
4
|
+
// It lives in the BUNDLE, not in core, for the same reason the telemetry credential probe does:
|
|
5
|
+
// `SLACK_BOT_TOKEN` and `SLACK_SIGNING_SECRET` are this vendor's fingerprints, and core carries
|
|
6
|
+
// none of them (`scripts/boundary-test.ts` rule 6).
|
|
7
|
+
//
|
|
8
|
+
// It lives in `status.ts` beside `register.ts` rather than in `ops.ts` because it READS THE
|
|
9
|
+
// OPERATIONAL STORE. `ops.ts` imports core through the light door so the standalone ops MCP server
|
|
10
|
+
// can register it without booting an agent; reaching the store from there would undo that.
|
|
11
|
+
//
|
|
12
|
+
// 🔴 EVERY ANSWER IS A VERDICT, AND EVERY VERDICT IS ONE THIS BUNDLE CAN DEFEND. The route is
|
|
13
|
+
// public, so nothing here returns a token, a team id, a channel key, a count, or a timestamp.
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
deploymentOrg,
|
|
17
|
+
getOperationalStore,
|
|
18
|
+
surfaceEventVerifiedAt,
|
|
19
|
+
unifiedDomainSessionKey,
|
|
20
|
+
type SurfaceStatus,
|
|
21
|
+
} from "@open-everywhere/core/agent/adapter-api.js";
|
|
22
|
+
|
|
23
|
+
const set = (v: string | undefined): boolean => v !== undefined && v.trim() !== "";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The two `channel_session` key shapes the LEGACY evidence can be found under.
|
|
27
|
+
*
|
|
28
|
+
* A session row is keyed by the supervisor grain's `registryKey`
|
|
29
|
+
* (`packages/core/agent/channels/unified-supervisor.ts` `supervisorGrainFor`), and that key is NOT
|
|
30
|
+
* the surface key whenever window topology resolves a domain for the channel:
|
|
31
|
+
*
|
|
32
|
+
* • topology off, or no domain → the fully-qualified surface key, `slack/<team>/<channel>`;
|
|
33
|
+
* • topology on, `solo` mode → `oe-domain::slack/<team>/<channel>` (the windowId IS the
|
|
34
|
+
* surface key, so the prefix still carries the platform);
|
|
35
|
+
* • topology on, `unified` mode → `oe-domain::<domain name>`;
|
|
36
|
+
* • a NAMED window group → `oe-domain::<group name>`;
|
|
37
|
+
* • a DM seat → the DM pseudo-domain's key.
|
|
38
|
+
*
|
|
39
|
+
* The last three carry no platform marker, so no prefix can find them. That is why the PRIMARY
|
|
40
|
+
* evidence is now the signature gate's own stamp (OPE-2242, below), which no key shape can hide.
|
|
41
|
+
* These prefixes stay only for a deployment whose Slack traffic all predates the stamp.
|
|
42
|
+
*/
|
|
43
|
+
// Built with core's OWN key builder, never a copied prefix literal: a change to the key shape then
|
|
44
|
+
// reaches this reporter instead of silently making it match nothing again.
|
|
45
|
+
const SLACK_SESSION_PREFIXES = ["slack/", unifiedDomainSessionKey("slack/")] as const;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Has this deployment ever VERIFIED a signed Slack event?
|
|
49
|
+
*
|
|
50
|
+
* Two kinds of evidence, checked in order:
|
|
51
|
+
*
|
|
52
|
+
* 1. THE STAMP (OPE-2242). `slack-front.ts` calls core's `stampSurfaceEventVerified("slack")`
|
|
53
|
+
* right after its `v0=` HMAC verify passes, on every delivery and before any classification.
|
|
54
|
+
* It is a deployment-level `instance_meta` row, so it reads the same for every domain topology:
|
|
55
|
+
* `unified` mode, a named window group and a DM-only deployment included.
|
|
56
|
+
* 2. A LEGACY SESSION ROW. A `channel_session` row is written by a turn, and a turn is reached only
|
|
57
|
+
* after the same gate accepts the delivery, so a row is proof too. It covers a deployment whose
|
|
58
|
+
* traffic predates the stamp, in the two key shapes above that carry the platform.
|
|
59
|
+
*
|
|
60
|
+
* Neither is proof about the CURRENT signing secret: a rotation, or a restored database, leaves
|
|
61
|
+
* both behind.
|
|
62
|
+
*
|
|
63
|
+
* 🔴 ONE-DIRECTIONAL ON PURPOSE. No evidence means NO EVIDENCE, not "no": a workspace that has not
|
|
64
|
+
* yet sent the app an event, a store that cannot be read, or a deployment whose store was just
|
|
65
|
+
* migrated writes nothing. "unknown" is the honest answer there, and reporting "no" would train the
|
|
66
|
+
* reader to ignore the field on exactly the deployments it is meant to help.
|
|
67
|
+
*/
|
|
68
|
+
async function eventsVerified(): Promise<SurfaceStatus["eventsVerified"]> {
|
|
69
|
+
if ((await surfaceEventVerifiedAt("slack")) !== null) return "yes";
|
|
70
|
+
try {
|
|
71
|
+
const store = getOperationalStore();
|
|
72
|
+
const org = deploymentOrg();
|
|
73
|
+
for (const prefix of SLACK_SESSION_PREFIXES) {
|
|
74
|
+
const rows = await store.listChannelSessions(org, prefix);
|
|
75
|
+
if (rows.length > 0) return "yes";
|
|
76
|
+
}
|
|
77
|
+
return "unknown";
|
|
78
|
+
} catch {
|
|
79
|
+
return "unknown";
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** The bundle's answer for `surfaces.slack`. */
|
|
84
|
+
export async function slackSurfaceStatus(env: NodeJS.ProcessEnv = process.env): Promise<Partial<SurfaceStatus>> {
|
|
85
|
+
const token = set(env.SLACK_BOT_TOKEN);
|
|
86
|
+
return {
|
|
87
|
+
credentials: token && set(env.SLACK_SIGNING_SECRET) ? "yes" : "no",
|
|
88
|
+
// Slack issues a bot token only when the app is installed to a workspace, so holding one is
|
|
89
|
+
// evidence of an install. It is NOT evidence that the install is still live — a revoked app
|
|
90
|
+
// leaves the stale token in place — and the detail in the contract page says so.
|
|
91
|
+
installed: token ? "yes" : "no",
|
|
92
|
+
eventsVerified: await eventsVerified(),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slack-attachment-fetch.d.ts","sourceRoot":"","sources":["../../../agent/access/slack-attachment-fetch.ts"],"names":[],"mappings":"AAmCA,OAAO,EAIL,KAAK,eAAe,EAGrB,MAAM,4CAA4C,CAAC;
|
|
1
|
+
{"version":3,"file":"slack-attachment-fetch.d.ts","sourceRoot":"","sources":["../../../agent/access/slack-attachment-fetch.ts"],"names":[],"mappings":"AAmCA,OAAO,EAIL,KAAK,eAAe,EAGrB,MAAM,4CAA4C,CAAC;AAuBpD;kFACkF;AAClF,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,sFAAsF;IACtF,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,QAAQ,CAAC,CA2F/G"}
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
// before any dispatch. The token does traverse the operator's own proxy: Tier A tunnels it
|
|
34
34
|
// undecrypted (CONNECT), Tier B decrypts with the operator's CA, which is what Tier B is for.
|
|
35
35
|
import { assertSafeFetchUrl, auditToolAction, hostCallAuditFields, } from "@open-everywhere/core/agent/adapter-api.js";
|
|
36
|
+
import { slackBotToken } from "../setup/credentials.js";
|
|
36
37
|
// THE CREDENTIAL'S IDENTITY, FOR THE AUDIT ROW (OPE-1547) — the ref NAME, never the value. This is
|
|
37
38
|
// the one host-side seam that attaches a credential, so before this ticket it was the one place
|
|
38
39
|
// where a plane both saw the call and knew whose credential rode it, and said neither on the row.
|
|
@@ -107,7 +108,8 @@ export async function fetchSlackAttachment(ctx, ref) {
|
|
|
107
108
|
});
|
|
108
109
|
throw new Error(`describe_image: refusing to send the Slack bot token to non-Slack host "${safe.url.hostname}".`);
|
|
109
110
|
}
|
|
110
|
-
|
|
111
|
+
// Resolved, not read off the env (OPE-2231) — the token may live in the credential store.
|
|
112
|
+
const token = await slackBotToken();
|
|
111
113
|
if (!token) {
|
|
112
114
|
throw new Error("describe_image: SLACK_BOT_TOKEN is not set — the bot token is required to download a Slack attachment.");
|
|
113
115
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slack-attachment-fetch.js","sourceRoot":"","sources":["../../../agent/access/slack-attachment-fetch.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,0EAA0E;AAC1E,EAAE;AACF,+FAA+F;AAC/F,iGAAiG;AACjG,8FAA8F;AAC9F,kGAAkG;AAClG,+FAA+F;AAC/F,yDAAyD;AACzD,EAAE;AACF,8FAA8F;AAC9F,iFAAiF;AACjF,4FAA4F;AAC5F,kGAAkG;AAClG,mGAAmG;AACnG,qFAAqF;AACrF,EAAE;AACF,iGAAiG;AACjG,iGAAiG;AACjG,kGAAkG;AAClG,EAAE;AACF,8EAA8E;AAC9E,gGAAgG;AAChG,gGAAgG;AAChG,oCAAoC;AACpC,EAAE;AACF,iGAAiG;AACjG,oGAAoG;AACpG,iGAAiG;AACjG,qGAAqG;AACrG,iGAAiG;AACjG,oGAAoG;AACpG,2FAA2F;AAC3F,8FAA8F;AAE9F,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,mBAAmB,GAIpB,MAAM,4CAA4C,CAAC;
|
|
1
|
+
{"version":3,"file":"slack-attachment-fetch.js","sourceRoot":"","sources":["../../../agent/access/slack-attachment-fetch.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/** The token the request URLs carry where the deployment's own host belongs. The ops plane
|
|
2
|
-
* substitutes it (packages/core/agent/ops/surface-manifest.ts); the
|
|
2
|
+
* substitutes it (packages/core/agent/ops/surface-manifest.ts); the setup check leaves it for the
|
|
3
3
|
* operator, who has usually not deployed yet when they run it. */
|
|
4
4
|
export declare const SLACK_DEPLOY_HOST_PLACEHOLDER = "YOUR-DEPLOY-URL";
|
|
5
5
|
/** The app name the manifest carries when the operator names none. */
|
|
6
6
|
export declare const SLACK_DEFAULT_APP_NAME = "Open Everywhere";
|
|
7
7
|
/** Slack's limit on an app name (`display_information.name`). A longer name fails at paste time. */
|
|
8
8
|
export declare const SLACK_APP_NAME_MAX = 35;
|
|
9
|
-
/** Why `raw` cannot name the Slack app, or `undefined` when it can. The
|
|
9
|
+
/** Why `raw` cannot name the Slack app, or `undefined` when it can. The setup CLI's
|
|
10
10
|
* `--app-name` reads this; the ops tool applies core's generic check with {@link SLACK_APP_NAME_MAX}. */
|
|
11
11
|
export declare function slackAppNameProblem(raw: string): string | undefined;
|
|
12
12
|
/** Options for {@link slackAppManifestTemplate}. */
|
|
@@ -15,8 +15,8 @@ export interface SlackAppManifestOptions {
|
|
|
15
15
|
* second install in one workspace needs its own name, or the two apps look the same. */
|
|
16
16
|
readonly appName?: string;
|
|
17
17
|
}
|
|
18
|
-
/** A ready-to-paste Slack app manifest (Slack's "create from manifest" flow) with the
|
|
19
|
-
*
|
|
18
|
+
/** A ready-to-paste Slack app manifest (Slack's "create from manifest" flow) with the scope/event
|
|
19
|
+
* set docs/deploy/surfaces/slack.md walks through by hand. */
|
|
20
20
|
export declare function slackAppManifestTemplate(opts?: SlackAppManifestOptions): string;
|
|
21
21
|
/** Where the operator pastes the manifest. */
|
|
22
22
|
export declare const SLACK_APP_CONSOLE_URL = "https://api.slack.com/apps";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-manifest.d.ts","sourceRoot":"","sources":["../../agent/app-manifest.ts"],"names":[],"mappings":"AAaA;;mEAEmE;AACnE,eAAO,MAAM,6BAA6B,oBAAoB,CAAC;AAE/D,sEAAsE;AACtE,eAAO,MAAM,sBAAsB,oBAAoB,CAAC;AAExD,oGAAoG;AACpG,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC;0GAC0G;AAC1G,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKnE;AAED,oDAAoD;AACpD,MAAM,WAAW,uBAAuB;IACtC;6FACyF;IACzF,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;
|
|
1
|
+
{"version":3,"file":"app-manifest.d.ts","sourceRoot":"","sources":["../../agent/app-manifest.ts"],"names":[],"mappings":"AAaA;;mEAEmE;AACnE,eAAO,MAAM,6BAA6B,oBAAoB,CAAC;AAE/D,sEAAsE;AACtE,eAAO,MAAM,sBAAsB,oBAAoB,CAAC;AAExD,oGAAoG;AACpG,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC;0GAC0G;AAC1G,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKnE;AAED,oDAAoD;AACpD,MAAM,WAAW,uBAAuB;IACtC;6FACyF;IACzF,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;+DAC+D;AAC/D,wBAAgB,wBAAwB,CAAC,IAAI,GAAE,uBAA4B,GAAG,MAAM,CAyJnF;AAED,8CAA8C;AAC9C,eAAO,MAAM,qBAAqB,+BAA+B,CAAC;AAElE,kFAAkF;AAClF,eAAO,MAAM,wBAAwB,EAAE,SAAS,MAAM,EAOrD,CAAC;AAEF;;8BAE8B;AAC9B,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EAKvD,CAAC"}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
// THE Slack app manifest — one definition, three readers (OPE-1603).
|
|
2
2
|
//
|
|
3
|
-
// This file is the only place the manifest exists. The
|
|
3
|
+
// This file is the only place the manifest exists. The setup check's Slack step
|
|
4
4
|
// (packages/create/src/steps/slack.ts) prints it, the ops MCP tool `surface_manifest` serves it
|
|
5
5
|
// with this deployment's host substituted, and `scripts/slack-scope-audit-test.ts` parses the bot
|
|
6
|
-
// scope array below against the runbook's documented scopes. It used to live in the
|
|
6
|
+
// scope array below against the runbook's documented scopes. It used to live in the setup CLI, where
|
|
7
7
|
// the ops server could not reach it at all.
|
|
8
8
|
//
|
|
9
|
-
// 🔴 THIS MODULE IMPORTS NOTHING, DELIBERATELY. The
|
|
9
|
+
// 🔴 THIS MODULE IMPORTS NOTHING, DELIBERATELY. The setup CLI depends on the bundle for this
|
|
10
10
|
// document alone, so a leaf module costs it no transitive weight — not the adapter-api barrel, not
|
|
11
11
|
// eve, not the Slack Web API client. `agent/ops.ts` does the typed registration; this file holds
|
|
12
12
|
// only the vendor's own knowledge.
|
|
13
13
|
/** The token the request URLs carry where the deployment's own host belongs. The ops plane
|
|
14
|
-
* substitutes it (packages/core/agent/ops/surface-manifest.ts); the
|
|
14
|
+
* substitutes it (packages/core/agent/ops/surface-manifest.ts); the setup check leaves it for the
|
|
15
15
|
* operator, who has usually not deployed yet when they run it. */
|
|
16
16
|
export const SLACK_DEPLOY_HOST_PLACEHOLDER = "YOUR-DEPLOY-URL";
|
|
17
17
|
/** The app name the manifest carries when the operator names none. */
|
|
18
18
|
export const SLACK_DEFAULT_APP_NAME = "Open Everywhere";
|
|
19
19
|
/** Slack's limit on an app name (`display_information.name`). A longer name fails at paste time. */
|
|
20
20
|
export const SLACK_APP_NAME_MAX = 35;
|
|
21
|
-
/** Why `raw` cannot name the Slack app, or `undefined` when it can. The
|
|
21
|
+
/** Why `raw` cannot name the Slack app, or `undefined` when it can. The setup CLI's
|
|
22
22
|
* `--app-name` reads this; the ops tool applies core's generic check with {@link SLACK_APP_NAME_MAX}. */
|
|
23
23
|
export function slackAppNameProblem(raw) {
|
|
24
24
|
const name = raw.trim();
|
|
@@ -28,8 +28,8 @@ export function slackAppNameProblem(raw) {
|
|
|
28
28
|
return `the app name is ${name.length} characters; Slack accepts at most ${SLACK_APP_NAME_MAX}`;
|
|
29
29
|
return undefined;
|
|
30
30
|
}
|
|
31
|
-
/** A ready-to-paste Slack app manifest (Slack's "create from manifest" flow) with the
|
|
32
|
-
*
|
|
31
|
+
/** A ready-to-paste Slack app manifest (Slack's "create from manifest" flow) with the scope/event
|
|
32
|
+
* set docs/deploy/surfaces/slack.md walks through by hand. */
|
|
33
33
|
export function slackAppManifestTemplate(opts = {}) {
|
|
34
34
|
const appName = opts.appName?.trim() || SLACK_DEFAULT_APP_NAME;
|
|
35
35
|
return JSON.stringify({
|
|
@@ -51,8 +51,10 @@ export function slackAppManifestTemplate(opts = {}) {
|
|
|
51
51
|
{
|
|
52
52
|
command: "/oe",
|
|
53
53
|
url: `https://${SLACK_DEPLOY_HOST_PLACEHOLDER}/eve/v1/slack/commands`,
|
|
54
|
-
description: "Open Everywhere control commands
|
|
55
|
-
|
|
54
|
+
description: "Open Everywhere control-plane commands (stop, status, budget) — no model turn.",
|
|
55
|
+
// Every subcommand `parseOeCommandTokens` accepts (packages/core/agent/commands/core.ts).
|
|
56
|
+
// scripts/slack-app-manifest-test.ts fails if one is missing here.
|
|
57
|
+
usage_hint: "stop | status | budget [raise <usd> | clear] | rate <n> | help",
|
|
56
58
|
should_escape: false,
|
|
57
59
|
},
|
|
58
60
|
],
|
|
@@ -81,6 +83,13 @@ export function slackAppManifestTemplate(opts = {}) {
|
|
|
81
83
|
],
|
|
82
84
|
},
|
|
83
85
|
oauth_config: {
|
|
86
|
+
// THE OAUTH REDIRECT BACK TO THIS DEPLOYMENT (OPE-2231). `/setup` installs the app by sending
|
|
87
|
+
// the installer to Slack's authorize URL and taking the `code` on the way back, and Slack
|
|
88
|
+
// refuses a redirect to a URL the app does not DECLARE — so the agent-led install needs this
|
|
89
|
+
// line in the manifest, not just in the code that handles the callback. It is harmless on the
|
|
90
|
+
// hand-paste path: an app created from this manifest and installed from the Slack console
|
|
91
|
+
// never visits the URL.
|
|
92
|
+
redirect_urls: [`https://${SLACK_DEPLOY_HOST_PLACEHOLDER}/setup/callback`],
|
|
84
93
|
scopes: {
|
|
85
94
|
bot: [
|
|
86
95
|
"app_mentions:read",
|
|
@@ -108,10 +117,20 @@ export function slackAppManifestTemplate(opts = {}) {
|
|
|
108
117
|
// asked in an ordinary room is delivered to the requester's DM, never rendered there.
|
|
109
118
|
"im:write",
|
|
110
119
|
"groups:history",
|
|
120
|
+
// Group-DM messages — the scope `message.mpim` below needs (Slack's event reference).
|
|
121
|
+
"mpim:history",
|
|
111
122
|
// The group-DM (`mpim`) half of `im:read` — same two calls, same call sites. Code-derived
|
|
112
123
|
// rather than live-proven: the roster/disclosure paths are keyed on the room, and a
|
|
113
124
|
// member-tier click or a card can land in a group DM exactly as it can in a 1:1.
|
|
114
125
|
"mpim:read",
|
|
126
|
+
// files.getUploadURLExternal + files.completeUploadExternal — the `post_file` tool's
|
|
127
|
+
// upload flow (packages/core/agent/tools/post_file.ts). Without it every file post fails
|
|
128
|
+
// with `missing_scope`.
|
|
129
|
+
"files:write",
|
|
130
|
+
// The authenticated download of a Slack file's `url_private`
|
|
131
|
+
// (access/slack-attachment-fetch.ts fetchSlackAttachment), which `describe_image` uses to
|
|
132
|
+
// read an image a person posted. Slack serves that URL only to an app with this scope.
|
|
133
|
+
"files:read",
|
|
115
134
|
"reactions:write",
|
|
116
135
|
"reactions:read",
|
|
117
136
|
"pins:read",
|
|
@@ -125,7 +144,26 @@ export function slackAppManifestTemplate(opts = {}) {
|
|
|
125
144
|
settings: {
|
|
126
145
|
event_subscriptions: {
|
|
127
146
|
request_url: `https://${SLACK_DEPLOY_HOST_PLACEHOLDER}/eve/v1/slack`,
|
|
128
|
-
|
|
147
|
+
// EVERY event the front route acts on (slack-front.ts classifyEnvelope), and each one's
|
|
148
|
+
// scope is in the bot list above, per Slack's event reference:
|
|
149
|
+
// app_mention → app_mentions:read · message.im → im:history
|
|
150
|
+
// message.channels → channels:history (an engaged thread's follow-up with no re-mention)
|
|
151
|
+
// message.groups → groups:history (the same, in private channels)
|
|
152
|
+
// message.mpim → mpim:history (group DMs; without it only an @mention there is heard)
|
|
153
|
+
// member_joined_channel → channels:read, groups:read, mpim:read (the channel-join intro)
|
|
154
|
+
// reaction_added, reaction_removed → reactions:read (reaction feedback)
|
|
155
|
+
// scripts/slack-app-manifest-test.ts derives the handled set from the code and fails if
|
|
156
|
+
// this list drops one (OPE-2223).
|
|
157
|
+
bot_events: [
|
|
158
|
+
"app_mention",
|
|
159
|
+
"message.im",
|
|
160
|
+
"message.channels",
|
|
161
|
+
"message.groups",
|
|
162
|
+
"message.mpim",
|
|
163
|
+
"member_joined_channel",
|
|
164
|
+
"reaction_added",
|
|
165
|
+
"reaction_removed",
|
|
166
|
+
],
|
|
129
167
|
},
|
|
130
168
|
// The INTERACTIVITY Request URL — the SAME public route Event Subscriptions uses. Every
|
|
131
169
|
// button click and every shortcut lands here, and the front route classifies which handler
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-manifest.js","sourceRoot":"","sources":["../../agent/app-manifest.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,
|
|
1
|
+
{"version":3,"file":"app-manifest.js","sourceRoot":"","sources":["../../agent/app-manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slack-commands.d.ts","sourceRoot":"","sources":["../../../agent/channels/slack-commands.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"slack-commands.d.ts","sourceRoot":"","sources":["../../../agent/channels/slack-commands.ts"],"names":[],"mappings":"AAqCA,OAAO,EASL,KAAK,eAAe,EACrB,MAAM,4CAA4C,CAAC;AAOpD,mGAAmG;AACnG,eAAO,MAAM,oBAAoB,2BAA2B,CAAC;AAS7D;;;;;;;;;;;;;;;;;;;+CAmB+C;AAC/C,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,eAAe,GAAG,eAAe,CAkBhF"}
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
// route below for what such a command reached before.
|
|
34
34
|
import { defineChannel, POST } from "eve/channels";
|
|
35
35
|
import { verifySlackSignature } from "./slack-front.js";
|
|
36
|
+
import { slackSigningSecret } from "../setup/credentials.js";
|
|
36
37
|
import { bindFrom, runOeCommand, parseSlackCommandText, resolvePartition, getOperationalStore, admittedTenantsFromConfig, unadmittedTenantLog, UNADMITTED_TENANT_DROP_REASON, } from "@open-everywhere/core/agent/adapter-api.js";
|
|
37
38
|
import { slackTenantAdmission } from "./slack-tenant-fence.js";
|
|
38
39
|
function log(msg) {
|
|
@@ -135,7 +136,10 @@ export default defineChannel({
|
|
|
135
136
|
// keeps stop free and working while the scope is over its spend cap.
|
|
136
137
|
POST(SLACK_COMMANDS_ROUTE, async (req, { attachSession, waitUntil }) => {
|
|
137
138
|
const rawBody = await req.text();
|
|
138
|
-
|
|
139
|
+
// Resolved, not read off the env (OPE-2231): a `/setup` run can have put the signing secret in
|
|
140
|
+
// the credential store, and `/oe stop` is the affordance a person reaches for when the agent is
|
|
141
|
+
// doing the wrong thing. An install where stop 401s is an install where stop is missing.
|
|
142
|
+
if (!verifySlackSignature(rawBody, req.headers, await slackSigningSecret())) {
|
|
139
143
|
return new Response("unauthorized", { status: 401 });
|
|
140
144
|
}
|
|
141
145
|
const params = new URLSearchParams(rawBody);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slack-commands.js","sourceRoot":"","sources":["../../../agent/channels/slack-commands.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,8FAA8F;AAC9F,uFAAuF;AACvF,iFAAiF;AACjF,EAAE;AACF,sFAAsF;AACtF,4FAA4F;AAC5F,+FAA+F;AAC/F,6FAA6F;AAC7F,8FAA8F;AAC9F,oFAAoF;AACpF,4FAA4F;AAC5F,sFAAsF;AACtF,EAAE;AACF,0FAA0F;AAC1F,8FAA8F;AAC9F,qFAAqF;AACrF,8FAA8F;AAC9F,mCAAmC;AACnC,EAAE;AACF,6FAA6F;AAC7F,6FAA6F;AAC7F,6FAA6F;AAC7F,8FAA8F;AAC9F,qFAAqF;AACrF,6FAA6F;AAC7F,EAAE;AACF,iFAAiF;AACjF,EAAE;AACF,iGAAiG;AACjG,8FAA8F;AAC9F,iGAAiG;AACjG,sDAAsD;AAEtD,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,EACnB,6BAA6B,GAE9B,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D,SAAS,GAAG,CAAC,GAAW;IACtB,OAAO,CAAC,GAAG,CAAC,oCAAoC,GAAG,EAAE,CAAC,CAAC;AACzD,CAAC;AAED,mGAAmG;AACnG,MAAM,CAAC,MAAM,oBAAoB,GAAG,wBAAwB,CAAC;AAE7D;oFACoF;AACpF,SAAS,SAAS,CAAC,MAAuB,EAAE,IAAY;IACtD,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC3B,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;;;;;;;;;;+CAmB+C;AAC/C,MAAM,UAAU,uBAAuB,CAAC,MAAuB;IAC7D,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACxD,OAAO;QACL,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;QAC1B,OAAO,EAAE;YACP,IAAI,EAAE;gBACJ,OAAO,EAAE;oBACP,UAAU,EAAE;wBACV,OAAO,EAAE,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,EAAE;wBAC3C,UAAU,EAAE,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,IAAI,EAAE;wBACjD,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;qBACzD;oBACD,WAAW,EAAE,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,EAAE;oBAC/C,aAAa,EAAE,YAAY;iBAC5B;aACF;SACF;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,KAAK,UAAU,mBAAmB,CAAC,MAA0B,EAAE,SAA6B,EAAE,MAAc,EAAE,YAAqB;IACjI,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,gBAAgB,CAAC;YACzB,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;YAC1B,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,MAAM,IAAI,EAAE,EAAE,UAAU,EAAE,SAAS,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE,EAAE,EAAE;SAClI,CAAC,CAAC;QACtB,MAAM,mBAAmB,EAAE,CAAC,WAAW,CAAC;YACtC,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC5B,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,MAAM,EAAE,sBAAsB;YAC9B,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,SAAS,IAAI,IAAI,EAAE,IAAI,EAAE,MAAM,IAAI,IAAI,EAAE,UAAU,EAAE,YAAY,IAAI,IAAI,EAAE;SAC9H,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,wBAAwB;IAC1B,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY;IACrC,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,EAAE;QACxE,MAAM,EAAE,GAAG;QACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;KAChD,CAAC,CAAC;AACL,CAAC;AAED,eAAe,aAAa,CAAC;IAC3B,MAAM,EAAE;QACN,4FAA4F;QAC5F,0FAA0F;QAC1F,qEAAqE;QACrE,IAAI,CAAC,oBAAoB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,aAAa,EAAE,SAAS,EAAE,EAAE,EAAE;YACrE,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YACjC,IAAI,CAAC,oBAAoB,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"slack-commands.js","sourceRoot":"","sources":["../../../agent/channels/slack-commands.ts"],"names":[],"mappings":"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"}
|
|
@@ -1147,7 +1147,7 @@ export declare function slackChannelFactsFor(channelId: string): Promise<{
|
|
|
1147
1147
|
* config-load error ⇒ false (fail-safe to the native per-channel split).
|
|
1148
1148
|
*/
|
|
1149
1149
|
export declare function slackDomainUsesUnifiedWindow(surfaceKey: string): boolean;
|
|
1150
|
-
export declare function slackForm(method: string, body: string, token?: string
|
|
1150
|
+
export declare function slackForm(method: string, body: string, token?: string): Promise<Record<string, unknown> | undefined>;
|
|
1151
1151
|
/**
|
|
1152
1152
|
* Render a `conversations.history` response (newest-first, raw Slack JSON — probe,
|
|
1153
1153
|
* never assume) as a compact oldest-first transcript, or undefined when there's
|