@open-everywhere/provider-slack 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/agent/app-manifest.ts +49 -7
  2. package/agent/channels/slack-events.ts +31 -19
  3. package/agent/channels/slack-front.ts +209 -11
  4. package/agent/channels/slack-home.ts +511 -0
  5. package/agent/channels/slack-memory-canvas.ts +382 -0
  6. package/agent/channels/slack-offboarding.ts +89 -0
  7. package/agent/channels/slack-origin-codec.ts +8 -0
  8. package/agent/channels/slack-step-label.ts +177 -0
  9. package/agent/channels/slack-wake-backscroll.ts +3 -2
  10. package/agent/channels/slack.ts +31 -18
  11. package/agent/docs-generated.ts +1 -1
  12. package/agent/ops.ts +5 -0
  13. package/agent/provider-events.ts +1 -1
  14. package/agent/register.ts +9 -0
  15. package/agent/setup/page.ts +3 -1
  16. package/agent/slack-as-you.ts +107 -0
  17. package/agent/surface-parity.ts +3 -0
  18. package/dist/agent/app-manifest.d.ts +11 -0
  19. package/dist/agent/app-manifest.d.ts.map +1 -1
  20. package/dist/agent/app-manifest.js +40 -7
  21. package/dist/agent/app-manifest.js.map +1 -1
  22. package/dist/agent/channels/slack-events.d.ts +13 -5
  23. package/dist/agent/channels/slack-events.d.ts.map +1 -1
  24. package/dist/agent/channels/slack-events.js +28 -17
  25. package/dist/agent/channels/slack-events.js.map +1 -1
  26. package/dist/agent/channels/slack-front.d.ts +52 -0
  27. package/dist/agent/channels/slack-front.d.ts.map +1 -1
  28. package/dist/agent/channels/slack-front.js +142 -11
  29. package/dist/agent/channels/slack-front.js.map +1 -1
  30. package/dist/agent/channels/slack-home.d.ts +95 -0
  31. package/dist/agent/channels/slack-home.d.ts.map +1 -0
  32. package/dist/agent/channels/slack-home.js +445 -0
  33. package/dist/agent/channels/slack-home.js.map +1 -0
  34. package/dist/agent/channels/slack-memory-canvas.d.ts +65 -0
  35. package/dist/agent/channels/slack-memory-canvas.d.ts.map +1 -0
  36. package/dist/agent/channels/slack-memory-canvas.js +325 -0
  37. package/dist/agent/channels/slack-memory-canvas.js.map +1 -0
  38. package/dist/agent/channels/slack-offboarding.d.ts +31 -0
  39. package/dist/agent/channels/slack-offboarding.d.ts.map +1 -0
  40. package/dist/agent/channels/slack-offboarding.js +75 -0
  41. package/dist/agent/channels/slack-offboarding.js.map +1 -0
  42. package/dist/agent/channels/slack-origin-codec.d.ts.map +1 -1
  43. package/dist/agent/channels/slack-origin-codec.js +8 -0
  44. package/dist/agent/channels/slack-origin-codec.js.map +1 -1
  45. package/dist/agent/channels/slack-step-label.d.ts +17 -0
  46. package/dist/agent/channels/slack-step-label.d.ts.map +1 -0
  47. package/dist/agent/channels/slack-step-label.js +170 -0
  48. package/dist/agent/channels/slack-step-label.js.map +1 -0
  49. package/dist/agent/channels/slack-wake-backscroll.d.ts +2 -2
  50. package/dist/agent/channels/slack-wake-backscroll.d.ts.map +1 -1
  51. package/dist/agent/channels/slack-wake-backscroll.js +3 -3
  52. package/dist/agent/channels/slack-wake-backscroll.js.map +1 -1
  53. package/dist/agent/channels/slack.d.ts.map +1 -1
  54. package/dist/agent/channels/slack.js +31 -18
  55. package/dist/agent/channels/slack.js.map +1 -1
  56. package/dist/agent/docs-generated.js +1 -1
  57. package/dist/agent/docs-generated.js.map +1 -1
  58. package/dist/agent/ops.d.ts.map +1 -1
  59. package/dist/agent/ops.js +5 -1
  60. package/dist/agent/ops.js.map +1 -1
  61. package/dist/agent/provider-events.js +1 -1
  62. package/dist/agent/provider-events.js.map +1 -1
  63. package/dist/agent/register.d.ts.map +1 -1
  64. package/dist/agent/register.js +9 -1
  65. package/dist/agent/register.js.map +1 -1
  66. package/dist/agent/setup/page.d.ts.map +1 -1
  67. package/dist/agent/setup/page.js +3 -1
  68. package/dist/agent/setup/page.js.map +1 -1
  69. package/dist/agent/slack-as-you.d.ts +38 -0
  70. package/dist/agent/slack-as-you.d.ts.map +1 -0
  71. package/dist/agent/slack-as-you.js +82 -0
  72. package/dist/agent/slack-as-you.js.map +1 -0
  73. package/dist/agent/surface-parity.d.ts.map +1 -1
  74. package/dist/agent/surface-parity.js +3 -0
  75. package/dist/agent/surface-parity.js.map +1 -1
  76. package/package.json +27 -3
@@ -1,6 +1,9 @@
1
+ import { type SlackUserDeactivation } from "./slack-offboarding.js";
2
+ import type { OffboardOutcome } from "@open-everywhere/core/agent/adapter-api.js";
1
3
  import { type Channel, type RouteHandlerArgs } from "eve/channels";
2
4
  import { liveSupervisorDeps, type SlackEventEnvelope } from "./slack-events.js";
3
5
  import { EventDedupe, ThreadFifo, type SingleWindowMentionPolicy, type DmSeat, type SetKeyViewResult } from "@open-everywhere/core/agent/adapter-api.js";
6
+ import { type ParsedHomeClick, type ParsedHomeOpen, type ParsedHomeSubmission } from "./slack-home.js";
4
7
  import { type ParsedSlackShortcut } from "./slack-shortcut.js";
5
8
  /** An HTTP route handler — `RouteHandler` isn't a public eve export, so we mirror its shape. */
6
9
  type RouteHandler = (req: Request, args: RouteHandlerArgs) => Promise<Response>;
@@ -22,6 +25,13 @@ export type FrontDecision = {
22
25
  readonly kind: "join";
23
26
  readonly reason: string;
24
27
  readonly env: SlackEventEnvelope;
28
+ }
29
+ /** OPE-2423 — a `user_change` event. Ours: a `deleted` user is a deactivation report for core's
30
+ * offboarding lever (slack-offboarding.ts); every other profile edit is acked with no work. */
31
+ | {
32
+ readonly kind: "user-change";
33
+ readonly reason: string;
34
+ readonly env: SlackEventEnvelope;
25
35
  } | {
26
36
  readonly kind: "reaction";
27
37
  readonly reason: string;
@@ -91,6 +101,31 @@ export type FrontDecision = {
91
101
  readonly kind: "shortcut";
92
102
  readonly reason: string;
93
103
  readonly shortcut: ParsedSlackShortcut;
104
+ }
105
+ /** A `channel_shared` (the channel became Slack Connect shared) — ours: re-run the memory canvas gate
106
+ * on that channel, which clears the app's canvas when the channel no longer passes (OPE-2451). */
107
+ | {
108
+ readonly kind: "channel-shared";
109
+ readonly reason: string;
110
+ readonly env: SlackEventEnvelope;
111
+ }
112
+ /** An `app_home_opened` for the HOME tab (OPE-2451) — ours: publish the person's own page. */
113
+ | {
114
+ readonly kind: "home-open";
115
+ readonly reason: string;
116
+ readonly open: ParsedHomeOpen;
117
+ }
118
+ /** An `oe_home:` click on the Home tab (OPE-2451) — ours: run a button, or open an item's modal. */
119
+ | {
120
+ readonly kind: "home-click";
121
+ readonly reason: string;
122
+ readonly click: ParsedHomeClick;
123
+ }
124
+ /** A submission of the Home tab's own modal (OPE-2451) — ours: run the action, republish the page. */
125
+ | {
126
+ readonly kind: "home-submit";
127
+ readonly reason: string;
128
+ readonly submission: ParsedHomeSubmission;
94
129
  };
95
130
  /**
96
131
  * Decide how the front route handles a raw inbound body. FORWARD is the fail-safe default:
@@ -180,10 +215,27 @@ export interface FrontOptions {
180
215
  * re-verifies standing host-side, then mints an ephemeral OAuth URL / opens the api-key intake.
181
216
  * Injectable for tests. */
182
217
  readonly handleConnectClick?: (payload: unknown) => Promise<boolean>;
218
+ /** OPE-2423 — hand one deactivation report to core's offboarding lever. Defaults to
219
+ * {@link routeSlackUserDeactivation} with a live `users.info` re-read. Injectable for tests. */
220
+ readonly routeUserDeactivation?: (d: SlackUserDeactivation) => Promise<OffboardOutcome>;
183
221
  /** Injected in tests; the live default is core's `handleGrantCardClick`. The signed grant-click
184
222
  * branch schedules it through the route's `waitUntil`, so this handler may outlive the empty
185
223
  * Slack acknowledgement. */
186
224
  readonly handleGrantCardClick?: (payload: unknown) => Promise<boolean>;
225
+ /** The three Home-tab handlers (OPE-2451). Injected in tests; the live defaults are slack-home.ts's,
226
+ * over the live Slack deps. Each runs after the empty acknowledgement, through `waitUntil`. */
227
+ readonly handleHomeOpened?: (open: ParsedHomeOpen) => Promise<boolean>;
228
+ readonly handleHomeClick?: (click: ParsedHomeClick) => Promise<boolean>;
229
+ readonly handleHomeSubmission?: (submission: ParsedHomeSubmission) => Promise<boolean>;
230
+ /** The domain memory canvas recheck a trust event runs (OPE-2451): a person joined the channel, or it
231
+ * was shared. Injected in tests; the live default is slack-memory-canvas.ts's, over the live deps. */
232
+ readonly recheckChannelCanvas?: (input: {
233
+ org: string;
234
+ teamId: string;
235
+ channelId: string;
236
+ trigger: "member-joined" | "channel-shared";
237
+ joinedUserId?: string;
238
+ }) => Promise<unknown>;
187
239
  /** SINGLE-WINDOW mention policy for one (channel, surface) — should the unified window own an
188
240
  * @mention here (suppress the native forward + keep the sibling as an addressed wake)?
189
241
  * Defaults to the live {@link slackSingleWindowMentionPolicy} (grain + fail-closed
@@ -1 +1 @@
1
- {"version":3,"file":"slack-front.d.ts","sourceRoot":"","sources":["../../../agent/channels/slack-front.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"slack-front.d.ts","sourceRoot":"","sources":["../../../agent/channels/slack-front.ts"],"names":[],"mappings":"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"}
@@ -38,6 +38,7 @@
38
38
  // urlencoded body (Eve's own `eve_input:` HITL clicks, view_submission, slash
39
39
  // commands) still forwards exactly as before.
40
40
  // 4. Idempotency + per-thread FIFO guard the wake (see EventDedupe / ThreadFifo below).
41
+ import { parseSlackUserDeactivation, routeSlackUserDeactivation } from "./slack-offboarding.js";
41
42
  import { POST } from "eve/channels";
42
43
  import { SLACK_SIGNATURE_HEADER, SLACK_TIMESTAMP_HEADER, slackSignature, slackSignatureMatches } from "./slack-signature.js";
43
44
  import { slackSigningSecret } from "../setup/credentials.js";
@@ -46,9 +47,11 @@ import { callSlackWebApi } from "./slack-web-api.js";
46
47
  import { auditDmBotAuthorDrop, auditDmDriverAdmitted, dmDoorAdmitsDriver, parseMessageEvent, routeMessageEvent, liveDeps, routeNameDropEvent, liveNameDropDeps, parseChannelJoinEvent, routeChannelJoinEvent, liveChannelJoinDeps, parseSlackReactionEvent, routeReactionEvent, liveReactionDeps, routeSupervisorEvent, liveSupervisorDeps, supervisorFifoKey, bindableFor, bindableForJoin, bindableForReaction, slackSingleWindowMentionPolicy, slackDomainUsesUnifiedWindow, slackFrontTenantFenceDeclined, slackInteractivityTenantFenceDeclined, } from "./slack-events.js";
47
48
  import { slackInteractivityTenantIds } from "./slack-tenant-fence.js";
48
49
  import { EventDedupe, ThreadFifo, getOrCreateDmSeat as liveGetOrCreateDmSeat, touchDmSeat as liveTouchDmSeat, resolvePartition, domainKeyOf, isThreadEngaged, divertInboundToUnifiedWindow, isPrunedDeploymentWakeError, markUndeliveredAfterHeal, isUndeliveredAfterHeal, healPrunedDeploymentStrand, mintWakeId, slackVendorEventTime, spreadVendorTs, resolveWakeTrust, ambientSupervisorEnabled, getConfig, getOperationalStore, OE_APPROVAL_PREFIX, handleApprovalPayload as liveHandleApprovalPayload, OE_SETKEY_ACTION_PREFIX, OE_SETKEY_MODAL_CALLBACK, handleSetKeyClick as liveHandleSetKeyClick, handleSetKeyViewSubmission as liveHandleSetKeyViewSubmission, OE_CONNECT_ACTION_PREFIX, handleConnectClick as liveHandleConnectClick, OE_GRANT_ACTION_PREFIX, handleGrantCardClick as liveHandleGrantCardClick, buildRecord, enqueue as enqueueLogRecord, flushLogShip, stampNonMemberChatAuth, externalPolicyIsInert, recordWakeTail, tailAuthorGrain, dmWindowRegistryKey, stampSurfaceEventVerified, } from "@open-everywhere/core/agent/adapter-api.js";
49
- import { renderWakeMessage, slackChannelFactsFor, slackAuthorIsMember, slackClickerIsGuest, slackWakeAuthorFacts, slackExternalPolicyForRoom, applySlackExternalPolicy, stripUnfencedSlackAttachments, slackEnterpriseIdFromEnvelope, _resetAuthorMemberCache, } from "./slack-events.js";
50
+ import { renderWakeMessage, slackChannelFactsFor, slackAuthorIsMember, slackClickerIsGuest, slackWakeAuthorFacts, slackExternalPolicyForRoom, applySlackExternalPolicy, stripUnfencedSlackAttachments, slackEnterpriseIdFromEnvelope, slackForm, _resetAuthorMemberCache, } from "./slack-events.js";
50
51
  import { buildSlackAuth, withForwardedSlackEnvelope } from "./slack-identity.js";
51
52
  import { holdRouteWork, routeHoldQuiesced, withSlackRouteHold } from "./slack-route-hold.js";
53
+ import { liveMemoryCanvasDeps, recheckChannelCanvas } from "./slack-memory-canvas.js";
54
+ import { handleHomeClick, handleHomeOpened, handleHomeSubmission, liveSlackHomeDeps, parseHomeClick, parseHomeOpened, parseHomeSubmission, } from "./slack-home.js";
52
55
  import { persistSlackAttachment, registerSlackAttachment } from "./slack-attachments.js";
53
56
  import { parseSlackShortcutPayload, shortcutMessageEvent, shortcutWakeKey, } from "./slack-shortcut.js";
54
57
  /** The public URL Slack POSTs every subscribed event to (Event Subscriptions Request URL). */
@@ -213,6 +216,17 @@ export function classifyEnvelope(rawBody, contentType) {
213
216
  if (grantClick !== undefined) {
214
217
  return { kind: "grant-click", reason: "block_actions oe_grant: click — ours, never forwarded", payload: grantClick };
215
218
  }
219
+ // THE HOME TAB (OPE-2451). Its clicks carry an `oe_home:` action id and its one modal a callback
220
+ // id of its own, so neither can be mistaken for another door's payload, nor for eve's.
221
+ const homePayload = decodeInteractivityPayload(rawBody);
222
+ const homeClick = parseHomeClick(homePayload);
223
+ if (homeClick !== undefined) {
224
+ return { kind: "home-click", reason: `block_actions oe_home: ${homeClick.action} — ours, never forwarded`, click: homeClick };
225
+ }
226
+ const homeSubmission = parseHomeSubmission(homePayload);
227
+ if (homeSubmission !== undefined) {
228
+ return { kind: "home-submit", reason: `view_submission for the Home tab modal (${homeSubmission.action}) — ours, never forwarded`, submission: homeSubmission };
229
+ }
216
230
  // A SHORTCUT (OPE-1376) — a `message_action` or `shortcut` payload. Ours, never forwarded; see
217
231
  // the `shortcut` arm of FrontDecision for why a forward could not do anything with it. It is
218
232
  // matched LAST among the urlencoded branches and cannot race any of them: every branch above
@@ -246,6 +260,21 @@ export function classifyEnvelope(rawBody, contentType) {
246
260
  if (eventType === "member_joined_channel") {
247
261
  return { kind: "join", reason: "member_joined_channel — channel-join intro candidate", env };
248
262
  }
263
+ if (eventType === "channel_shared") {
264
+ return { kind: "channel-shared", reason: "channel_shared — recheck the domain memory canvas", env };
265
+ }
266
+ if (eventType === "app_home_opened") {
267
+ // Only the HOME tab is ours (OPE-2451). The same event fires for the Messages tab, which has no
268
+ // page to publish, so that one forwards — eve acknowledges an event it has no handler for.
269
+ const open = parseHomeOpened(env);
270
+ if (open)
271
+ return { kind: "home-open", reason: "app_home_opened (home tab) — publish the person's page", open };
272
+ return { kind: "forward", reason: "app_home_opened for a tab other than home — nothing to publish" };
273
+ }
274
+ if (eventType === "user_change") {
275
+ // OPE-2423: slackChannel drops it, and a DEACTIVATED user is ours — automatic offboarding.
276
+ return { kind: "user-change", reason: "user_change — a deactivation report candidate", env };
277
+ }
249
278
  if (eventType === "reaction_added" || eventType === "reaction_removed") {
250
279
  // Inbound reactions: slackChannel drops them (no handler), so they're ours to ingest
251
280
  // (reaction-ingest.ts — a feedback signal on the bot's own replies + volume telemetry).
@@ -704,7 +733,12 @@ export function buildFrontHandler(innerHandler, opts = {}) {
704
733
  const handleSetKeyClick = opts.handleSetKeyClick ?? liveHandleSetKeyClick;
705
734
  const handleSetKeyViewSubmission = opts.handleSetKeyViewSubmission ?? liveHandleSetKeyViewSubmission;
706
735
  const handleConnectClick = opts.handleConnectClick ?? liveHandleConnectClick;
736
+ const routeUserDeactivation = opts.routeUserDeactivation ?? ((d) => routeSlackUserDeactivation(d, { usersInfo: (userId) => slackForm("users.info", `user=${encodeURIComponent(userId)}`) }));
707
737
  const handleGrantCardClick = opts.handleGrantCardClick ?? liveHandleGrantCardClick;
738
+ const homeOpened = opts.handleHomeOpened ?? ((open) => handleHomeOpened(open, liveSlackHomeDeps()));
739
+ const homeClicked = opts.handleHomeClick ?? ((click) => handleHomeClick(click, liveSlackHomeDeps()));
740
+ const recheckCanvas = opts.recheckChannelCanvas ?? ((input) => recheckChannelCanvas(input, liveMemoryCanvasDeps()));
741
+ const homeSubmitted = opts.handleHomeSubmission ?? ((submission) => handleHomeSubmission(submission, liveSlackHomeDeps()));
708
742
  const ambientEnabledFor = opts.ambientEnabledFor ?? ((surfaceKey) => ambientSupervisorEnabled(surfaceKey, getConfig().loadDomains()));
709
743
  const seatedSurface = opts.seatedSurfaceFor ?? slackDomainUsesUnifiedWindow;
710
744
  const mentionPolicyFor = opts.mentionPolicyFor ?? slackSingleWindowMentionPolicy;
@@ -859,16 +893,16 @@ export function buildFrontHandler(innerHandler, opts = {}) {
859
893
  /** The Events API form: key one `event_id` (falling back to `channel:ts`). Every existing wake
860
894
  * route reads this one; only the shortcut branch keys itself. */
861
895
  const notYetSeen = (env, ev) => notYetSeenKey(wakeKey(env, ev.channelId, ev.ts), ev);
862
- // UNOWNED message dispatch (top-level, or in-thread but not engaged): today's default is the
863
- // name-drop path (per-domain opt-in, fail-closed). When the channel's domain opts into
864
- // ambientSupervisor, the SAME unowned traffic routes to the channel-supervisor session instead
896
+ // UNOWNED message dispatch (top-level, or in-thread but not engaged): the fallback is the
897
+ // name-drop path (per-domain opt-in, fail-closed). When the channel's domain has
898
+ // ambientSupervisor on (the default since OPE-2409), the SAME unowned traffic routes to the channel-supervisor session instead
865
899
  // (slack-events.ts routeSupervisorEvent) — the "always-on teammate" leg. `directMention` is the
866
900
  // SINGLE-WINDOW addressed-mention divert (an app_mention event routed here from the mention
867
901
  // branch): it forces the supervisor path (the only road into the unified window) and renders an
868
902
  // addressed `direct-mention` wake. The supervisor wake serializes on its OWN FIFO key (the
869
903
  // supervisor token), never shared with a thread FIFO. Fail-closed: any partition/config error,
870
904
  // or the flag off, falls through to the UNCHANGED name-drop dispatch — so ambientSupervisor-off
871
- // is byte-identical to today. Parametrised on `ev` so both the app_mention divert and a plain
905
+ // is byte-identical to the pre-ambient path. Parametrised on `ev` so both the app_mention divert and a plain
872
906
  // message.channels wake feed one dispatcher.
873
907
  // `onWake` runs SYNCHRONOUSLY, once, immediately before a wake is scheduled — and never on the
874
908
  // addressed-drop path below. The shortcut route (OPE-1442) uses it to seed the attachment
@@ -1109,10 +1143,9 @@ export function buildFrontHandler(innerHandler, opts = {}) {
1109
1143
  // 🔴 A GROUP DM IS SUPPRESSIBLE ON THE AUTHOR GRAIN TOO (OPE-1486). It was not before, because
1110
1144
  // an mpim resolved no refutation at all — the limit the old note here recorded. The author leg
1111
1145
  // above now resolves one from the same probe a channel uses, so an operator who set
1112
- // `externalPolicy.authorGrain: "withhold"` gets that rule in a group DM as well. Nothing moves
1113
- // on the SUPPRESSION PATH for a default deployment: `withholdsBody` is inert under the shipped
1114
- // `taint` grain, so only a deployment that explicitly excluded refuted authors is suppressed
1115
- // here — which is the rule it asked for. That is a claim about SUPPRESSION alone: on `taint`
1146
+ // `externalPolicy.authorGrain: "withhold"` (shipped since 2026-10-10) gets that rule in a group
1147
+ // DM as well. `withholdsBody` is inert only under the `taint` opt-out, so a deployment that opted
1148
+ // out is never suppressed here. That is a claim about SUPPRESSION alone: on `taint`
1116
1149
  // the same refutation still newly stamps `oe_chat_nonmember` and still newly fences the body,
1117
1150
  // which is the fix. The room leg stays off for the whole DM family by the note above: on a DM
1118
1151
  // the trust plane asks about the PARTNER, not about the room.
@@ -1617,7 +1650,7 @@ export function buildFrontHandler(innerHandler, opts = {}) {
1617
1650
  //
1618
1651
  // 🔴 IT COSTS A PROBE, SO IT IS SKIPPED WHEN IT CANNOT MATTER. Unlike the three routes, this
1619
1652
  // leg resolves no author facts of its own, so gating it means one `users.info` call. The inert
1620
- // check runs first: on the shipped `taint` / `engage` pair no evidence is resolved at all and
1653
+ // check runs first: on the `taint` / `engage` opt-out pair no evidence is resolved at all and
1621
1654
  // this whole block is a single config read. The probe is TTL-cached per author on top of that.
1622
1655
  //
1623
1656
  // FAIL-OPEN on anything unreadable — an unparseable event, an unresolvable partition, a probe
@@ -1743,6 +1776,32 @@ export function buildFrontHandler(innerHandler, opts = {}) {
1743
1776
  }));
1744
1777
  return new Response(null, { status: 200 });
1745
1778
  }
1779
+ if (decision.kind === "home-open" || decision.kind === "home-click" || decision.kind === "home-submit") {
1780
+ // THE HOME TAB (OPE-2451). THE TENANT FENCE FIRST (OPE-1680), for the reason the approval branch
1781
+ // states: the page reads and changes a person's memory, keyed to a bare per-workspace member id,
1782
+ // so an unadmitted workspace reaching it is a foreign tenant reading our store.
1783
+ const ids = decision.kind === "home-open" ? decision.open : decision.kind === "home-click" ? decision.click : decision.submission;
1784
+ const fenceIds = {
1785
+ ...(ids.teamId === undefined ? {} : { teamId: ids.teamId }),
1786
+ ...(ids.enterpriseId === undefined ? {} : { enterpriseId: ids.enterpriseId }),
1787
+ userId: ids.userId,
1788
+ };
1789
+ if (slackInteractivityTenantFenceDeclined(fenceIds, decision.kind, decision.kind === "home-open" ? "front-home-event-branch" : "front-interactivity-branch")) {
1790
+ return fencedAck(new Response(null, { status: 200 }));
1791
+ }
1792
+ // ACK FIRST, WORK AFTER. Building the page reads memory and asks Slack who the person is and
1793
+ // which channels they sit in, which can cross Slack's three-second budget. An empty 200 also
1794
+ // CLOSES a submitted modal, which is what the person expects after Save or Forget; the page
1795
+ // they return to is republished with a one-line notice saying what happened.
1796
+ const run = decision.kind === "home-open" ? homeOpened(decision.open) : decision.kind === "home-click" ? homeClicked(decision.click) : homeSubmitted(decision.submission);
1797
+ args.waitUntil(run
1798
+ .then((handled) => {
1799
+ if (!handled)
1800
+ console.log(`[open-everywhere:slack-front] ${decision.kind} for ${ids.userId} did not complete`);
1801
+ })
1802
+ .catch(() => console.warn(`[open-everywhere:slack-front] ${decision.kind} failed after acknowledgement`)));
1803
+ return new Response(null, { status: 200 });
1804
+ }
1746
1805
  if (decision.kind === "setkey-submit") {
1747
1806
  // THE TENANT FENCE (OPE-1680), above the handler — this is the branch that WRITES A SECRET into
1748
1807
  // this deployment's store, keyed to the intake the payload names. A `view_submission` carries
@@ -1764,6 +1823,34 @@ export function buildFrontHandler(innerHandler, opts = {}) {
1764
1823
  }
1765
1824
  return forwardNative();
1766
1825
  }
1826
+ if (decision.kind === "channel-shared") {
1827
+ // THE CHANNEL WAS SHARED (OPE-2451): re-run the memory canvas gate at once, which clears the app's
1828
+ // own canvas there. The canvas reads the room verdict fresh, so the wake path's cached "internal"
1829
+ // cannot carry a pre-share answer into this decision.
1830
+ const ev = decision.env.event;
1831
+ const channelId = typeof ev?.channel === "string" ? ev.channel : undefined;
1832
+ const teamId = typeof decision.env.team_id === "string" ? decision.env.team_id : undefined;
1833
+ if (!channelId || !teamId)
1834
+ return OK();
1835
+ const sharedEnterpriseId = slackEnterpriseIdFromEnvelope(decision.env);
1836
+ if (slackInteractivityTenantFenceDeclined({ teamId, ...(sharedEnterpriseId === undefined ? {} : { enterpriseId: sharedEnterpriseId }), channelId }, "channel-shared", "front-channel-shared-branch")) {
1837
+ return fencedAck(OK());
1838
+ }
1839
+ let sharedOrg;
1840
+ try {
1841
+ sharedOrg = resolvePartition({
1842
+ channel: { kind: "slack" },
1843
+ session: { auth: { current: { attributes: { team_id: teamId, channel_id: channelId }, principalId: "", principalType: "slack-user" } } },
1844
+ }).org;
1845
+ }
1846
+ catch {
1847
+ sharedOrg = undefined;
1848
+ }
1849
+ if (sharedOrg !== undefined) {
1850
+ args.waitUntil(recheckCanvas({ org: sharedOrg, teamId, channelId, trigger: "channel-shared" }).catch(() => console.warn("[open-everywhere:slack-front] memory canvas recheck after a share failed")));
1851
+ }
1852
+ return OK();
1853
+ }
1767
1854
  if (decision.kind === "join") {
1768
1855
  // Channel-join intro. Only the BOT's own join is an invitation — a human joining a
1769
1856
  // channel we're in fires the same event and must be dropped. Fail-CLOSED here, the
@@ -1774,8 +1861,30 @@ export function buildFrontHandler(innerHandler, opts = {}) {
1774
1861
  if (!jev)
1775
1862
  return OK();
1776
1863
  const { userId: joinBotUserId } = await getBotIdentity();
1777
- if (!joinBotUserId || jev.userId !== joinBotUserId)
1864
+ if (!joinBotUserId || jev.userId !== joinBotUserId) {
1865
+ // A PERSON JOINED (OPE-2451). No intro, but the domain memory canvas re-runs its gate: the
1866
+ // newcomer may be a guest, and a canvas written before they joined would show them every line
1867
+ // of the domain's memory. The recheck can only CLEAR the app's own canvas, never write memory,
1868
+ // so an unresolved bot identity rechecks too. Fenced like every other door: a foreign tenant
1869
+ // never reaches this deployment's Slack calls.
1870
+ if (jev.teamId === undefined)
1871
+ return OK();
1872
+ if (slackInteractivityTenantFenceDeclined({ teamId: jev.teamId, ...(jev.enterpriseId === undefined ? {} : { enterpriseId: jev.enterpriseId }), channelId: jev.channelId, userId: jev.userId }, "member-joined", "front-join-branch")) {
1873
+ return fencedAck(OK());
1874
+ }
1875
+ let joinOrg;
1876
+ try {
1877
+ joinOrg = resolvePartition(bindableForJoin(jev)).org;
1878
+ }
1879
+ catch {
1880
+ joinOrg = undefined;
1881
+ }
1882
+ if (joinOrg !== undefined) {
1883
+ const teamId = jev.teamId;
1884
+ args.waitUntil(recheckCanvas({ org: joinOrg, teamId, channelId: jev.channelId, trigger: "member-joined", joinedUserId: jev.userId }).catch(() => console.warn("[open-everywhere:slack-front] memory canvas recheck after a join failed")));
1885
+ }
1778
1886
  return OK();
1887
+ }
1779
1888
  // Same two-layer idempotency as the message wake: Slack retries a slow ack, and a
1780
1889
  // double intro is exactly the annoyance the durable half exists to prevent.
1781
1890
  const joinKey = wakeKey(decision.env, jev.channelId, jev.ts);
@@ -1796,6 +1905,28 @@ export function buildFrontHandler(innerHandler, opts = {}) {
1796
1905
  args.waitUntil(routeChannelJoinEvent(jev, liveChannelJoinDeps(joinSend)).then(logOutcome("channel-join", jev.channelId, jev.ts)));
1797
1906
  return OK();
1798
1907
  }
1908
+ if (decision.kind === "user-change") {
1909
+ // AUTOMATIC OFFBOARDING (OPE-2423). The signature above has authenticated the envelope, so its
1910
+ // `team_id` is the workspace that delivered this report. Every other decision — the
1911
+ // same-workspace gate, the tenant fence, the live users.info re-read, the terminal revoke and
1912
+ // its audit row — runs in core's offboardDeactivatedAccount, AFTER the ack: Slack wants a quick
1913
+ // 200, and a revoke is idempotent, so a Slack retry that races it changes nothing.
1914
+ const deactivation = parseSlackUserDeactivation(decision.env);
1915
+ if (!deactivation)
1916
+ return OK();
1917
+ // THE TENANT FENCE (OPE-1680), the same front-door refusal every other deciding branch takes.
1918
+ // Core's gate 2 ALSO requires a positive admission, because this fence is inert when config
1919
+ // declares no tenant — and a terminal revoke must not run on an inert answer.
1920
+ if (slackInteractivityTenantFenceDeclined({
1921
+ teamId: deactivation.deliveringTeamId,
1922
+ ...(deactivation.enterpriseId === undefined ? {} : { enterpriseId: deactivation.enterpriseId }),
1923
+ userId: deactivation.userId,
1924
+ }, "user-change", "front-user-change-branch")) {
1925
+ return fencedAck(OK());
1926
+ }
1927
+ args.waitUntil(routeUserDeactivation(deactivation).then((outcome) => console.log(`[open-everywhere:slack-front] user_change ${deactivation.userId}: offboarding ${outcome.kind}${outcome.kind === "refused" ? ` (${outcome.reason})` : ""}`)));
1928
+ return OK();
1929
+ }
1799
1930
  if (decision.kind === "reaction") {
1800
1931
  // Inbound reaction (feedback signal). Parse it; an unusable envelope is a no-op 200.
1801
1932
  const rev = parseSlackReactionEvent(decision.env);