Commit 0c6f0c5
authored
channels: add Slack HTTP receiver for distributed-app mode (#93)
* channels: add Slack HTTP receiver for distributed-app mode
Phantom Cloud tenants flip SLACK_TRANSPORT=http to receive Slack events
via the central phantom-slack-events gateway instead of opening a
Socket Mode WebSocket out to Slack themselves. Self-hosters keep the
Socket Mode flow at slack.ts unchanged.
The hybrid metadata pattern is locked: identity (team_id,
installer_user_id, team_name) flows through /v1/identity.slack on the
phantomd metadata gateway; secrets (slack_bot_token,
slack_gateway_signing_secret) flow through /v1/secrets/<name> via the
Phase C path. The new MetadataIdentityFetcher mirrors the existing
MetadataSecretFetcher and parses the optional slack subfield.
SlackHttpChannel reuses Bolt's App with an ExpressReceiver and
signatureVerification: false. A custom Express middleware verifies the
gateway's HMAC over <forwardedAt>:<eventId>:<rawBody> with a 5-minute
replay window, then enforces a defense-in-depth team_id match against
this.teamId before Bolt sees the body. Failures return 401 (HMAC) or
403 (team_id) before any handler runs. The existing slack-actions.ts,
slack-formatter.ts, feedback.ts, progress-stream.ts, and
status-reactions.ts are receiver-agnostic and reused via the same
app.action()/app.event() registrations.
Owner access control redesigns for HTTP mode per plan section 6.4:
"any user from this.teamId" replaces the strict OWNER_SLACK_USER_ID
check. The Socket Mode rejection DM is intentionally not replicated;
HTTP-mode tenants are multi-user.
Test count: +88 new tests (1922 vs 1834 baseline), zero plaintext bot
token in any log line, error message, or test assertion.
* channels: wire SLACK_TRANSPORT dispatch into Phantom boot
The new factory at slack-channel-factory.ts picks SlackChannel or
SlackHttpChannel based on SLACK_TRANSPORT (default "socket", "http"
opts a tenant into the distributed-app flow). The factory is the one
place that depends on both classes; everywhere else takes the
structural SlackTransport union from slack-transport.ts.
The 5-line constructor guard in slack.ts rejects transport: "http" up
front so a misconfigured tenant fails loudly at construction instead
of silently running Socket Mode.
Scheduler delivery, /trigger endpoint, and the onboarding flow widen
their type signatures from SlackChannel to SlackTransport. Both
classes share the same method surface (sendDm, postToChannel,
isConnected, getClient, etc.) so the call sites are byte-identical.
Default SLACK_TRANSPORT=socket path is byte-identical to today's
behaviour: the existing 30 SlackChannel tests pass unchanged.
* channels: tighten Slack 5b team_id defense-in-depth and address review findings
Closes the team_id defense-in-depth gap (Critical findings 1-2 plus Major 7)
by rejecting events without parseable team_id at all three layers (middleware,
per-event app_mention/message handlers, and the previously-unguarded
reaction_added handler), with the single allowed exception being Slack's
url_verification challenge ping. Splits Slack API egress methods into
slack-egress.ts and Express helpers into slack-http-utils.ts so
slack-http-receiver.ts lands at 295 lines (under the 300-line cap), and
delegates the same egress helpers from slack.ts to DRY the duplicate
methods. Adds redactTokens on the auth.test() failure log path so a future
Bolt SDK change cannot leak a token via err.message. Aligns the identity
fetcher's tenant_slug to phantomd's omitempty wire shape and documents the
schema-drift policy for the hand-rolled guards. Plus four Minor cleanups:
adds the slack.ts constructor-guard test (M-4), drops the dead hex-decode
try/catch in the verifier (m-9), uses the SlackTransport alias in
index.ts (m-12), and pins the redaction contract with a token-bearing
auth.test() failure test (m-16).1 parent 47137eb commit 0c6f0c5
20 files changed
Lines changed: 2572 additions & 141 deletions
File tree
- src
- channels
- __tests__
- config
- __tests__
- core
- onboarding
- scheduler
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
0 commit comments