# ChannelGate — Features ## Company email domain auto-approval - Admin UI → Users → Auto-approval accepts exact company email domains, disabled by default. Authenticated inbound provider identities can gain Approved access before engine selection; this never grants Admin or bypasses channel access rules, quotas, or license admission. - Slack fetches the current human profile (requires `users:read.email`). Google Chat and Teams use provider-supplied sender email when available; missing email remains manual approval. Editable names, message text and run-API attribution cannot establish an email identity. - Unchecking Approved in the admin user editor records a manual opt-out from auto-approval; checking it clears that opt-out. Removing domains/disabling the policy retains prior approvals. - Existing known Slack users can be previewed and explicitly approved, with fresh identity, current policy and manual opt-out checks on apply. Up to 500 users per batch; lookup failures are reported and grant nothing. Policy changes and automatic approvals are audited. ## Registered inventory limits and Enterprise harness approvals - Non-Enterprise installs allow at most 20 registered channels (including DMs and the API conversation) and 20 stored human users, including unapproved accounts. Registration checks are atomic; existing records remain editable and usable when an install is already over its cap. Legacy free-license payloads cannot bypass these caps. The no-key monthly one-conversation limit and Registered 500-message monthly limit remain. Enterprise defaults to unlimited. - Enterprise organization admins can approve one or more harnesses per channel through the admin editor or Slack Settings → Agent. Unrestricted is the default. Pins, saved sessions, API overrides, automation and fallback cannot launch outside the approved set; queued work rechecks the live policy. Claude memory review is skipped when Claude is excluded. - Approval changes are audited. Restrictions remain enforced after Enterprise expiry/downgrade; changing or clearing them requires Enterprise. These approvals govern managed engine launches, not arbitrary shell commands already permitted to Worker/Admin authors. ## Channel agent directory - `search_agents` finds registered specialist channel agents by purpose, examples and effective shared skills, with channel links and bounded pagination. Current organization, template, channel-section and explicit channel grants/dependencies resolve at lookup; personal skills never contribute. Managers describe or hide their own agent with `set_channel_agent_profile`. - The always-injected `gateway-usage` guide checks the directory when a specialist may help and recommends a channel without sending messages, delegating or transferring files. Organization skills can supply company terminology; no company directory is hardcoded in the product skill. - Built-in reconciliation refreshes channel metadata at startup and nightly at 03:00 in the host local timezone without an engine turn or user schedule. Metadata caches narrow keyword searches; returned recommendations still verify live metadata/membership and fresh gateway access. The daemon registers its existing Slack lifecycle manager in the live connector registry; disconnects fail closed and reconnects resolve the current client without retaining old readers. - Visibility protects the reply's audience as well as its requester. DMs, group DMs, hidden, archived and Lean agents are excluded. Private destinations cannot appear in public/shared sources; other results require the whole current source roster to belong to the destination. A one-to-one bot DM uses its requester's access. Admin status never substitutes for membership. Slack supplies the membership interface; unsupported/disconnected platforms fail closed. ## Composio connection visibility - Slack Settings → **You** shows the viewer's personal connected Composio applications and accounts directly below their Composio credential. The channel's **MCP** page shows the shared connections and whether they use the channel or organization identity. Both lists load after the native modal opens, offer Refresh, and page through all reported accounts in compact rows. Credential forms remain undisturbed; late loads cannot overwrite newer navigation. Each read rechecks viewer ownership, current channel access and the resolved credential scope. - Admin UI user pages list that person's personal Composio applications and accounts. Channel Connections pages list the shared identity and identify channel credentials versus organization defaults; personal accounts remain on user pages. Each row shows the app, account alias/available account identity, connection ID, status, default selection and account type when provided. - Lists load on demand and have a Refresh connections button. Personal mode discovers the apps published by Composio and reads each app's account metadata; a visible caveat explains that inactive/unpublished connections may be absent. Missing or incomplete provider metadata is reported explicitly. SDK mode lists all account pages for the exact stable user/channel identity under the existing Enterprise entitlement, without creating sessions or authorizations. - Inventory reads retain personal-only and channel → organization resolution, refusal of organization defaults, and DM suppression of shared identities. Responses contain allowlisted metadata only, never connector keys, account credential payloads or business records. - Slack Settings renders populated Cloud MCP and skill pickers on the MCP, Skills and You pages without a native Slack `invalid_arguments` error; selection still saves immediately. ## Slack channel membership approvals - Managed Composio Slack join, invitation and channel-creation actions require a one-use human approval card, including direct actions and nested execution batches through either identity. Auto/Admin mode and remembered tool permissions cannot supply this decision. The card names the connection, account selectors, destinations and invitees; oversized previews fail closed. - Container and host runtime connections, including SDK sessions, traverse the same daemon check. Denial, timeout, unavailable approval, cancellation, disconnect or expired/revoked authority prevents forwarding. Ordinary structured reads and writes continue. - Opaque Composio workbench/bash/proxy/API executors are refused because arbitrary persistent code can hide a membership change. Use structured connector actions instead. This enforcement covers managed Composio; independently supplied credentials, custom MCPs and browser sessions remain outside that boundary. The always-loaded guide forbids bypass through any route and treats sharing/posting requests as separate from permission to join or change the sender. ## Google Chat native conversation controls - Google Chat `/help` now opens a compact Cards v2 guide with expandable topics, matching the Teams quick-start experience. Sections carry emoji headers; quick-start entries and commands are icon rows (Material icons) with the bold command over its description, and typed example phrases use a chat icon. The card is the whole reply, with no separate text bubble. If card delivery fails, the complete text guide is returned. - `/settings`, `/secrets` and `/model` open requester-only panels in their source space/session. General, Variables, MCPs, Skills, Automations and Resume reuse the same guarded settings policy as Teams. Channel defaults and session overrides have separate model/effort previews and Apply actions. Credential entry opens a private browser form using one-use grants, HttpOnly cookies, CSRF checks and current space membership; stored values are never displayed or prefilled. - `/files [folder]`, `/sendfile ` and the agent's `share_file` show private file controls: browse, text/Word text preview, download, and eligible browser editing/uploads. Paths remain confined to the workspace and every click/browser request repeats current authorization. Browser links require the gateway Public URL; files are not uploaded to Drive or published. - Final answers, errors and stops carry compact statistics plus **Files**, **Variables**, **Settings**, and up to three referenced-file buttons. The sealed menu survives restarts; opened panel drafts expire after 15 minutes. Google-enforced private viewers keep file and credential links visible only to the requester in the original space. - Native approval cards remain in the source conversation. Pub/Sub card and text controls use a separate durable lane so stop/status remain responsive while agent turns are running. Registered slash commands are rebuilt from Google's SLASH_COMMAND annotation (or the literal message text), because `argumentText` carries only the arguments; a numeric command ID is never mapped to a name. In a group chat or unthreaded space, a top-level `/stop`, `/status` or `/clear` that quotes the request or a bot reply targets that quoted session. The working placeholder is edited in place with a compact heartbeat (phase, run-slot position, elapsed, last activity, subagents, "Still connected") — Chat has no typing indicator — and is replaced by the final answer; if that edit fails the answer is posted and the placeholder removed. Completed space/group answers mention the requester. Approval refusals (not authorized, wrong scope, already handled) and control errors are shown privately to the clicker with the policy reason; REST bodies, system errors and host paths collapse to generic retry guidance. Deny ignores the comment field. A refused private-browser save shows a value-free reason and keeps the session. Open panel drafts and browser-settings sessions are in memory and need reopening after a restart; a restart-interrupted click is reported only to its clicker. Google Chat dialogs and typing events remain unavailable; card buttons act only with the HTTP endpoint connection (next section). - Automated coverage and pending live Claude/Codex gates: → TEST-PLAN: Google Chat native controls. ## Google Chat HTTP endpoint (working card buttons) - A Chat app has one connection setting, and Google delivers card and button clicks only to an **HTTP endpoint URL** connection — never to a Pub/Sub topic, and the Workspace Events API has no click event type. With the topic connection every card button ends in Chat's "unable to process your request". ChannelGate therefore serves `POST /api/googlechat/events` on its HTTPS listener, mounted ahead of admin auth and the Host/Origin guard like the Teams webhook: it reads no cookie and authenticates every request itself (`src/platforms/googlechat/verify.js`). - Verification fails closed: RS256 by a key in Google's published set (cached a day, one refresh per minute for an unknown `kid`), issuer `accounts.google.com`, audience equal to the configured endpoint URL (`/api/googlechat/events`), `email_verified`, and the sender exactly the configured **Chat app service account** (an add-on's `service-@gcp-sa-gsuiteaddons…`) or Google's `chat@system.gserviceaccount.com`; a standalone app with the project-number audience presents a JWT issued by that account, verified against its own key set with the configured **project number** as audience. Anything else answers `401` with no detail (the reason is logged); an endpoint without a Public URL or project number answers `503` naming the remedy; a connected transport is required (`503` otherwise). - **Typed settings commands.** `/settings