feat(trust): Phase 1 (slack) — L3 identity via shared gate#1363
Conversation
Wire Slack into the PlatformTrustConfigs registry and call the shared ingress trust gate from the Slack message path, mirroring the Discord wiring from #1270. Slack was the only configured platform absent from the registry — the gate would have fallen back to the deny-all default had it ever run for slack events. - main.rs: insert "slack" TrustConfig — L2 open (Slack's own channel allowlist stays authoritative in the adapter), L3 mirrors the resolved [slack].allow_all_users/allowed_users, so the gate agrees with Slack's existing user check (behavior-preserving). - slack.rs: thread Arc<AdapterRouter> through run_slack_adapter into handle_message; evaluate gate_incoming after the existing user check (redundant-but-matching, non-regressive). Bots bypass L3 — same rationale as Discord (#1270 review F1): bot admission is allow_bot_messages + trusted_bot_ids, and L3 is human-identity only. - is_dm passed truthfully via Slack conversation-ID prefix (D… = DM), cf. #1270 review F2; decision is identical either way today since the entry is L2-open with allow_dm=true. - tests: pin the L3 bot-bypass and the DM prefix classification. Refs #1361 (first task), umbrella #1356, ADR #1291.
This comment has been minimized.
This comment has been minimized.
Self-review finding: the Slack wiring copy-pasted l3_gate_applies from discord.rs (identical 3-line fn + doc). Move the single definition next to Decision in trust.rs and import it from both gate call sites. Each adapter keeps its own pinning test against the shared fn.
This comment has been minimized.
This comment has been minimized.
The platform-facts KB (#1295) landed on main after this branch was cut and records 'Slack does NOT use the shared gate' — which this PR makes stale. Update the trust_gate feature entry (partial → implemented, mirroring discord.toml's phrasing) and the Native-trust-divergence quirk. Conformance suite passes against this branch's code refs.
|
Note LGTM ✅ — Slack joins the shared L3 identity gate with a clean, behavior-preserving wiring that mirrors the accepted Discord Phase 1 pattern. What This PR DoesSlack was the only configured platform absent from the How It Works
Findings
Finding Details🟢 F1: Registry agrees with inline check by constructionThe registry entry uses 🟢 F2: Shared
|
What problem does this solve?
Slack is the only configured platform absent from the
PlatformTrustConfigsregistry:src/main.rsinserts the six gateway platforms, Discord (#1270), and Telegram — but never Slack. Slack trust relies entirely on the adapter's inline checks, and the registry's fallback for unregistered platforms is the deny-all default, so the shared ingress gate could never be made authoritative for Slack (Phase 1c) without this wiring.This implements the first task of #1361 (umbrella #1356), mirroring the Discord Phase 1 pattern from #1270.
At a Glance
Phase 1c (future) flips the gate from redundant-but-matching to authoritative and removes the scattered inline checks — this PR makes that possible for Slack.
Proposed Solution
src/main.rs— insert a"slack"entry into the registry: L2 open (Slack's own channel allowlist stays authoritative in the adapter), L3 mirrors the resolved[slack].allow_all_users/allowed_usersviaconfig::resolve_allow_all, so the gate agrees exactly with Slack's existing user check.crates/openab-core/src/slack.rs— threadArc<AdapterRouter>throughrun_slack_adapterintohandle_message, and evaluategate_incoming("slack", …)after the existing user check. The gate is redundant-but-matching: it cannot deny anything the inline check already admitted (non-regressive), and the existing 🚫-reaction deny UX is unchanged.l3_gate_applies(is_bot_msg)skips the gate for bot senders, mirroring the inline check's!is_bot_msgbypass and Discord's rationale (feat(trust): Phase 1 (discord) — L3 identity via shared gate [DRAFT: canary before merge] #1270 review F1): bot admission isallow_bot_messages+trusted_bot_ids; L3 is a human-identity allowlist. Running it on bots would wrongly drop trusted bot-to-bot messages whenallow_all_users = false(multi-agent).is_dm— passed via Slack conversation-ID prefix (D…= DM,C…/G…= channel/group), cf. feat(trust): Phase 1 (discord) — L3 identity via shared gate [DRAFT: canary before merge] #1270 review F2. Informational today: the registry entry is L2-open withallow_dm = true, so the decision is identical either way.crates/openab-core/src/trust.rs(added in7908cb7after self-review) —l3_gate_appliesnow has a single definition next toDecision, imported by both the Discord and Slack gate call sites, instead of being copy-pasted per adapter.Why this approach?
It is the exact shape of the accepted Discord Phase 1 change (#1270: registry insert + redundant-but-matching gate call + bot bypass + tests), keeping the two core platforms symmetrical ahead of Phase 1c (gate becomes authoritative, scattered checks removed). Behavior-preserving by construction — no config field changes, no default changes.
Self-review
Reviewed with the standard SOP after opening:
dispatcher.submitsite in slack.rs is insidehandle_message, and both event paths (app_mention,message) route through it — no Slack dispatch path bypasses the new gate.identity_allowed's empty-sender fail-closed cannot fire (handle_messagereturns early when the event has nouser/bot_id).l3_gate_appliesduplication: the original commit copy-pasted the helper from discord.rs. Consolidated intotrust.rsin7908cb7; both adapters now import the shared definition, each keeping its own pinning test.Platform-facts KB sync
maingained the schema-driven platform facts KB (#1295) after this branch was cut;docs/platforms/schema/slack.tomlrecorded "Slack does NOT use the shared gate," which this PR makes stale. Commitf6606e1updates thetrust_gateentry (partial → implemented, phrasing mirrors discord.toml) and the Native-trust-divergence quirk. TheconformanceCI check now runs on this PR and passes.Validation
At
7908cb7(macOS arm64):cargo clippy --workspace --all-features -- -D warnings— cleancargo clippy --workspace -- -D warnings(default features) — cleancargo check -p openab-core --no-default-features— passcargo check --no-default-features --features discord(slack feature off) — pass (1 pre-existingsession_ttl_durwarning, present on unmodifiedmain)cargo test -p openab-core --all-features— 656 passed, 1 failed:secrets::tests::resolve_exec_nonzero_exit, the known pre-existing macOS-only failure (also fails on unmodifiedmain)l3_gate*) — 2/2 across both adaptersrustfmt --check— no new drift introduced (per-file diff counts identical tomainbaseline: trust.rs 8→8, slack.rs 25→25, discord.rs 55→55, main.rs 4→4)Tests
slack::tests::l3_gate_skips_bots_applies_to_humans— pins the L3 bot-bypass (mirrors Discord's feat(trust): Phase 1 (discord) — L3 identity via shared gate [DRAFT: canary before merge] #1270 F4 test)slack::tests::is_dm_channel_by_prefix— pins theD…/C…/G…conversation-ID classificationdiscord.rskeeps its existingl3_gate_skips_bots_admits_humanspin, now exercising the sharedtrust::l3_gate_appliesRefs #1361 (first task — Enterprise Grid
workspace_usersremains), umbrella #1356, ADR #1291.