Skip to content

feat(messaging): add Google Chat channel#7317

Open
hunglp6d wants to merge 25 commits into
mainfrom
feat/messaging-channel-integration-googlechat
Open

feat(messaging): add Google Chat channel#7317
hunglp6d wants to merge 25 commits into
mainfrom
feat/messaging-channel-integration-googlechat

Conversation

@hunglp6d

@hunglp6d hunglp6d commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds Google Chat as an experimental OpenClaw messaging channel, served at /googlechat on the gateway through a dedicated Google-Chat-only cloudflared tunnel and a loopback webhook proxy. Outbound auth is minted gateway-side (OpenShell google-service-account-jwt provider) and injected by the L7 proxy, so the service-account private key never enters the sandbox. Inbound cert verification and outbound replies both route by hostname through the trusted L7 proxy (the SSRF guard's trusted-proxy modes), so the channel works in the DNS-less proxy-only sandbox — no local DNS resolve, no sentinel IP.

Scope: OpenClaw only. Hermes uses a different inbound model (Cloud Pub/Sub pull, no webhook) and a different credential path, so Hermes Google Chat is a planned follow-up rather than part of this PR.

Supersedes #6120: same change, recommitted as a single verified commit with clean history.

Architecture

Google Chat is the first bridge channel: inbound webhooks are verified inside the sandbox, but the outbound bot token is minted on the host and the service-account private key never enters the sandbox. Two JWTs run in opposite directions — Google signs one that the plugin verifies (inbound), and the gateway signs one to mint the outbound token (outbound).

INBOUND — Google → bot   (Google signs a JWT; the plugin VERIFIES it)

   [GOOGLE]   chat.googleapis.com — signs a JWT, POSTs the webhook
                  │
                  ▼
   [HOST]     cloudflared (dedicated tunnel)
                  │
                  ▼
   [HOST]     loopback webhook proxy — admits only POST /googlechat, 404s all else
                  │                    (the public URL is a webhook pinhole, not the dashboard)
                  ▼
   [HOST]     OpenClaw gateway :18789 — routes /googlechat into the sandbox
                  │
                  ▼
   [SANDBOX]  @openclaw/googlechat plugin
                  │  VERIFY the JWT — fetch Google's certs (GET www.googleapis.com, out through the
                  │  L7 proxy via trusted-proxy-fetch) → check signature + audience + appPrincipal
                  ▼
   [SANDBOX]  agent handles the message


OUTBOUND — bot → Google   (the gateway GENERATES the token; the L7 proxy swaps it in — key never in the sandbox)

   [SANDBOX]  @openclaw/googlechat plugin — builds the reply, stamps «Authorization: Bearer <placeholder>»
                  │  outbound-auth put the placeholder there → the sandbox holds no key, no real token;
                  │  trusted-proxy-fetch routes the send out through the L7 proxy (no local DNS)
                  ▼
   [HOST]     L7 egress proxy
                  │  ① swap «placeholder» → the real Bearer minted by the gateway:
                  │      GENERATE — sign an SA-JWT with private_key → Google OAuth → access token (cached ~1h)
                  │  ② policy-check — chat.googleapis.com, POST/PATCH/DELETE within /v1/spaces
                  ▼
   [GOOGLE]   chat.googleapis.com — user sees the reply

  Note — trusted-proxy-fetch is ROUTING (every plugin→Google call goes via the L7 proxy, no local DNS),
  so it appears in both flows: the inbound cert fetch and the outbound send. The token swap, the
  outbound-auth placeholder, and the JWT verify/generate are each one-directional.

OpenShell Requirement

The Google Chat service-account private key is configured through OpenShell's --secret-material-env (OpenShell#2178), which keeps it off process arguments. That flag ships in OpenShell v0.0.82+; current main pins OpenShell 0.0.85, so the requirement is already satisfied on main — no prerequisite PR.

Related Issue

Parts of #5492

Result

image

Changes

Channel

  • New googlechat manifest (inputs, enrollment notes, render) + built-in registration; served on the shared gateway dashboard port at /googlechat (no host forward — on its own dedicated tunnel, see below).
  • Enroll hooks: tunnel/audience gate (derives the public webhook URL from the cloudflared tunnel), token-paste for the SA JSON (validates the paste is parseable JSON and re-prompts before skip), config prompts (audience, appPrincipal, DM allowlist); channel template resolver + nemoclaw tunnel service wiring.
  • Dedicated webhook tunnel. A Google-Chat-only cloudflared tunnel (separate from nemoclaw tunnel start) fronts a loopback-only webhook proxy that forwards only POST /googlechat (1 MiB body cap) and returns 404 for every other method or path, so the public URL is a narrow webhook pinhole that never exposes the dashboard or control UI. NemoClaw tears down both the proxy and its cloudflared on skip, remove, and destroy.
  • Always skips in non-interactive mode (mirrors WeChat host-QR): enrollment needs manual, out-of-band Google Cloud Console + appPrincipal steps that no environment variable can satisfy, so the tunnel/audience gate skips rather than enroll a half-configured channel that silently 404s on inbound webhooks.
  • appPrincipal discovery sentinel: a blank appPrincipal renders an all-zeros placeholder so the first DM logs unexpected add-on principal: <N> (the real value to copy) instead of a numberless missing add-on principal binding; inert for Google Workspace accounts. Enrollment notes are rewritten into an always-printed capture guide with the exact logs --follow command and the persist-and-rebuild steps.

Gateway reliability

  • Renders gateway.reload.mode=off. OpenClaw rewrites its own config ~60s after boot (auto-enabling default provider plugins); with reactive hot-reload on, that self-write rebuilds the gateway's HTTP route table and drops the Google Chat inbound webhook route, so /googlechat starts returning 404 and the bot goes silent ~60s after every start. The sandbox's openclaw.json is sealed at build time (0600 + integrity hash), so disabling reactive reload is safe; NemoClaw still restarts the gateway explicitly on rebuild / gateway restart.

Inbound + outbound routing (proxy-only sandbox)

  • googlechat-trusted-proxy-fetch boot preload: rewrites the plugin's three googleapis fetch sites (inbound cert verify + all outbound sends/edits) to the SSRF guard's trusted_env_proxy/trusted_explicit_proxy modes, so they skip the local getaddrinfo and route by hostname through the L7 proxy — fixes EAI_AGAIN in the DNS-less netns, no sentinel IP. Interim; clean fix is upstream in OpenClaw (like web_fetch #50650).
  • googlechat network-policy preset scoped to the Chat spaces tree, including PATCH for streaming message edits.

Outbound auth (key out of sandbox)

  • google-chat-bridge OpenShell provider profile + googlechat-bridge-provider onboard wiring: import the profile pre-create, run provider refresh configure --strategy google-service-account-jwt post-create from the pasted SA JSON — the gateway mints/rotates the token and the L7 proxy injects Authorization: Bearer on chat.googleapis.com. The private key is supplied through --secret-material-env, so it never reaches argv; the profile authorizes only the Node runtime for the injected bearer.
  • googlechat-outbound-auth boot preload: load-time rewrite of the plugin's single token producer to emit the OpenShell credential placeholder (revision-less alias, so it resolves to the latest re-minted token and survives rotation) instead of signing in-process.
  • Drops in-sandbox SA-key file delivery for outbound; serviceAccountFile is kept only as a channel-start-gate marker (never delivered or read); keeps the BEGIN PRIVATE KEY secret scan.

Documentation

  • Adds OpenClaw-only setup, onboarding, lifecycle, and security guidance. The docs build completed with zero errors; two pre-existing warnings remain (redirect authentication and light-accent contrast).

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Quality Gates

  • Tests added or updated for changed behavior — unit tests for the two boot preloads (anchor rewrite, idempotency, drift-throw, runtime short-circuit), the bridge provider (env resolution, fail-closed refresh, Node-only credential boundary), the tunnel/audience gate (unconditional non-interactive skip, audience does not bypass), the template resolver (appPrincipal discovery sentinel when blank), and a manifest runtime-security-contract test (both boot preloads present and non-optional, gateway.reload.mode=off rendered, the non-existent serviceAccountFile sentinel, and no credentials delivered into the sandbox)
  • Existing tests cover changed behavior — justification:
  • Tests not applicable — justification:
  • Docs updated for user-facing behavior changes
  • Docs not applicable — justification:
  • Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging)
  • Sensitive-path review completed or maintainer-approved waiver recorded — nine-category review on the predecessor #6120
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Verification

  • PR description includes a Signed-off-by: line and every commit appears as Verified in GitHub
  • Normal pre-commit, commit-msg, and pre-push hooks passed, or npm run check:diff passed when hooks were skipped or unavailable
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: Hung Le hple@nvidia.com
Signed-off-by: Carlos Villela cvillela@nvidia.com

Summary by CodeRabbit

  • New Features

    • Added experimental Google Chat messaging-channel support for OpenClaw sandboxes.
    • Enabled end-to-end channel setup including service-account credential entry, required public webhook endpoint enrollment, and interactive audience gating.
    • Added Google Chat channel operations for onboarding and lifecycle flows (add/remove/pause/resume, credential rotation, and rebuild behavior).
  • Documentation

    • Added a dedicated “Set Up Google Chat” guide and updated channel-selection/onboarding instructions for Google Chat.
  • Bug Fixes

    • Improved cleanup and stop/start behavior for Google Chat webhook tunnels and bridge providers during channel and sandbox removal/rebuild.

Adds a manifest-first Google Chat channel: inbound webhook via the public tunnel, and
outbound replies authenticated by a gateway-minted service-account token. The private key
is configured through OpenShell's --secret-material-env, so it never appears in argv and
never enters the sandbox. Includes the network policy preset, appPrincipal capture flow
for personal/standalone accounts, DM allowlist, and tests.

Co-authored-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Hung Le <hple@nvidia.com>
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds experimental Google Chat support for OpenClaw sandboxes: a new built-in channel manifest, network policy, and provider profile; interactive tunnel/audience enrollment via a dedicated cloudflared webhook proxy; a generic gateway bridge-provider onboarding layer; runtime source patches for outbound auth and trusted-proxy fetch; secret-prompt masking enhancements; lifecycle wiring for add/remove/stop/start and destroy cleanup; and corresponding documentation and tests.

Changes

Google Chat Channel Cohort

Layer / File(s) Summary
Channel manifest and registry integration
src/lib/messaging/channels/googlechat/manifest.ts, .../policy/openclaw.yaml, .../provider-profile/openclaw.yaml, .../rendered-config-parser.ts, .../template-resolver.ts, .../hooks/index.ts, .../hooks/service-account-token-paste.ts, .../runtime-contract.test.ts, src/lib/messaging/channels/built-ins.ts, rendered-config-parser.ts, template-resolver.ts, manifests.test.ts, metadata.test.ts, diagnostics.test.ts, utils.test.ts, messaging-channel-config.test.ts, messaging-build-applier.mts, hooks/builtins.ts, hook-runner.test.ts, sandbox/channels.test.ts, state/openclaw-managed-extensions.test.ts, ci/reviewed-npm-lifecycle-allowlist.json
Registers googlechatManifest as a built-in channel with network policy (POST/PATCH/DELETE for Chat API, GET for JWT cert verification), outbound-auth bridge provider profile, rendered-config and template resolvers, token-paste and audience-gate hooks, and wires into channel/hook/manifest registries and trusted-package lists. Updates test expectations across manifests, metadata, diagnostics, and plugin integrity pins.
Secret prompt masking and token-paste validation
src/lib/credentials/store.ts, src/lib/messaging/hooks/common/token-paste.ts, .../config-prompt.ts, src/lib/messaging/manifest/types.ts
Adds optional maskCap parameter to promptSecret/prompt to cap displayed asterisks for long pasted secrets; adds maskCap, maxTokenAttempts, and validate options to TokenPasteField and manifest secret input specs, enabling interactive retry loops and custom validation for Google Chat service-account JSON paste.
Webhook enrollment and tunnel runtime
googlechat/hooks/tunnel-audience-gate.ts, .../hooks/tunnel-runtime.ts, .../tunnel/lifecycle.ts, .../tunnel/proxy.ts, src/lib/tunnel/services.ts, and matching *.test.ts
Implements an interactive audience-gate hook (prompts for webhook audience or starts dedicated cloudflared tunnel), a route-restricted webhook proxy (accepts only POST /googlechat), coordinated tunnel lifecycle with lazy-loaded services, and helpers to compute/derive Google Chat PID directories and manage tunnel state. Tests validate tunnel start/stop, proxy routing, body-size enforcement, and readiness detection.
Gateway bridge provider provisioning
src/lib/onboard/messaging-bridge-provider.ts, src/lib/onboard/messaging-prep.ts, src/lib/onboard/providers.ts, src/lib/actions/sandbox/policy-channel.ts, and matching tests including test/channels-add-bridge-lifecycle.test.ts
Adds discovery and collection of bridge token definitions from per-channel/agent YAML profiles, idempotent profile import via OpenShell, gateway-side token refresh configuration with secret material passed via ephemeral env vars (never CLI args), provider reuse detection when secrets are unavailable, and integration of bridge add/remove/reuse into channel add/remove flows with fail-closed error handling. Tests validate token collection, refresh configuration, profile discovery, provider naming, and end-to-end add/remove/stop/start lifecycle.
Runtime patches, cleanup, documentation, and validation
googlechat/runtime/googlechat-outbound-auth.ts, .../runtime/googlechat-trusted-proxy-fetch.ts, src/lib/actions/sandbox/destroy.ts, .../policy-channel-dependencies.ts, docs/manage-sandboxes/*.mdx, docs/index.yml, test/e2e/live/*, test/onboard-readiness.test.ts, test/messaging-build-applier-integrity.test.ts
Patches the bundled @openclaw/googlechat plugin at load time to short-circuit outbound token minting (returns gateway-minted GOOGLE_CHAT_ACCESS_TOKEN placeholder) and route Google API fetches through a trusted SSRF guard proxy; wires webhook tunnel teardown (stopGooglechatWebhookTunnel) into sandbox destroy cleanup with PID directory removal; adds comprehensive setup, lifecycle, credential rotation, and verification documentation with OpenClaw-only callouts; provides E2E progress reporting for long-running tunnel tests; and includes runtime security contract and bridge-lifecycle regression tests.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant ChannelsAddCLI
  participant AudienceGateHook
  participant TunnelRuntime
  participant BridgeProvider
  participant Gateway

  Operator->>ChannelsAddCLI: channels add googlechat
  ChannelsAddCLI->>AudienceGateHook: run tunnelAudienceGate hook
  AudienceGateHook->>TunnelRuntime: startTunnel (cloudflared + webhook proxy)
  TunnelRuntime-->>AudienceGateHook: public tunnel URL
  AudienceGateHook-->>ChannelsAddCLI: GOOGLECHAT_AUDIENCE
  ChannelsAddCLI->>BridgeProvider: collectMessagingBridgeTokenDefs + ensureMessagingBridgeProfiles
  BridgeProvider->>Gateway: provider profile import / refresh configure
  ChannelsAddCLI->>Gateway: upsert bridge provider (bestEffort)
  Gateway-->>ChannelsAddCLI: registration result
  ChannelsAddCLI-->>Operator: channel enabled
Loading

Suggested labels: v0.0.94

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 24.53% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding Google Chat as a messaging channel.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/messaging-channel-integration-googlechat

Comment @coderabbitai help to get the list of available commands.

@github-code-quality

github-code-quality Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit f233693 in the feat/messaging-chann... branch remains at 96%, unchanged from commit dbac677 in the main branch.

TypeScript / code-coverage/cli

The overall coverage in commit f233693 in the feat/messaging-chann... branch is 81%. The coverage in commit dbac677 in the main branch is 80%.

Show a code coverage summary of the most impacted files.
File main dbac677 feat/messaging-chann... f233693 +/-
src/lib/credentials/store.ts 59% 53% -6%
src/lib/tunnel/services.ts 73% 79% +6%
src/lib/messagi...-proxy-fetch.ts 0% 72% +72%
src/lib/messagi...utbound-auth.ts 0% 76% +76%
src/lib/messagi...nnel-runtime.ts 0% 77% +77%
src/lib/messagi...tunnel/proxy.ts 0% 89% +89%
src/lib/messagi...udience-gate.ts 0% 90% +90%
src/lib/onboard...dge-provider.ts 0% 99% +99%
src/lib/messagi...-token-paste.ts 0% 100% +100%
src/lib/messagi...ate-resolver.ts 0% 100% +100%

Updated July 25, 2026 17:43 UTC

Comment thread src/lib/tunnel/googlechat-webhook-proxy.ts Fixed
Comment thread src/lib/tunnel/googlechat-webhook-proxy.ts Fixed
@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Informational

Advisor assessment: Informational / high confidence
Next action: No advisor follow-up needed.
Findings: 0 blockers · 0 warnings · 0 suggestions
Status: No actionable findings remain in the canonical review ledger.

Model lanes

  • GPT-5.6 Terra (primary): Completed · high confidence · 0 blockers · 0 warnings · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Completed · high confidence · 0 blockers · 1 warning · 0 suggestions
  • Model comparison: normalized findings differ; normalized E2E selections differ; Nemotron reported the same number of blockers, 1 more warning, the same number of suggestions.

Nemotron output stays in workflow artifacts and does not change the assessment above.

E2E guidance

Advisory only. E2E / PR Gate selects and runs jobs independently.

Recommended E2E: cloud-onboard, credential-sanitization, security-posture, channels-add-remove, channels-stop-start, inference-routing, network-policy, onboard-repair, onboard-resume

1 optional E2E recommendation
  • ubuntu-repo-cloud-openclaw

Workflow run details

This automated review informs maintainers. Warnings and suggestions do not require a response. A maintainer decides whether to merge.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/lib/messaging/channels/googlechat/runtime/googlechat-outbound-auth.ts (1)

225-255: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the shared CommonJS/ESM source-rewrite loader infrastructure into one module.

isOpenClawGooglechatFile, errorMessage, fileNameFromModuleUrl, sourceToText, createComposableJsLoader, and the installXPatch shape are duplicated near-verbatim between these two files (and reportedly a third, slack-channel-guard.ts, per the in-file comments). Only patchSource/the anchor regexes actually differ per patch.

  • src/lib/messaging/channels/googlechat/runtime/googlechat-outbound-auth.ts#L225-L255: keep only patchGooglechatOutboundAuthSource here; delegate createComposableJsLoader, sourceToText, fileNameFromModuleUrl, errorMessage, and the file-matcher to a shared helper module (parameterized by channel name/path fragment).
  • src/lib/messaging/channels/googlechat/runtime/googlechat-trusted-proxy-fetch.ts#L245-L275: same — keep only patchTrustedProxyFetchSource and delegate the rest to the shared helper.

This keeps the two channel-specific files focused on their actual patch logic and avoids a third drifted copy the next time a channel needs this pattern.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/messaging/channels/googlechat/runtime/googlechat-outbound-auth.ts`
around lines 225 - 255, Extract the duplicated CommonJS/ESM rewrite
infrastructure into a shared helper module, parameterized by channel name/path
fragment and preserving the existing installXPatch shape. In
src/lib/messaging/channels/googlechat/runtime/googlechat-outbound-auth.ts lines
225-255, retain only patchGooglechatOutboundAuthSource and delegate
createComposableJsLoader, sourceToText, fileNameFromModuleUrl, errorMessage, and
isOpenClawGooglechatFile; apply the same change in
src/lib/messaging/channels/googlechat/runtime/googlechat-trusted-proxy-fetch.ts
lines 245-275, retaining only patchTrustedProxyFetchSource and delegating the
shared helpers.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/manage-sandboxes/enable-channels-during-onboarding.mdx`:
- Line 12: Remove the runtime AgentOnly import from the onboarding documentation
while preserving any build-time AgentOnly directive usage.

In `@src/lib/messaging/channels/googlechat/manifest.ts`:
- Around line 106-117: Update the explanatory comment above credentials in the
manifest to reference the actual messaging bridge provider implementation at
src/lib/onboard/messaging-bridge-provider.ts instead of the nonexistent
googlechat-bridge-provider.ts path; leave the surrounding authentication
description unchanged.

In `@src/lib/messaging/channels/googlechat/runtime/googlechat-outbound-auth.ts`:
- Around line 264-281: Gate both Module.registerHooks loaders in
src/lib/messaging/channels/googlechat/runtime/googlechat-outbound-auth.ts:264-281
and
src/lib/messaging/channels/googlechat/runtime/googlechat-trusted-proxy-fetch.ts:284-301
on a Node version known to support synchronous hooks, skipping them for Node
22.19.0 through 22.22.2, or raise the repository minimum to a fixed release.
Ensure affected versions never invoke nextLoad for unrelated module loads.

---

Nitpick comments:
In `@src/lib/messaging/channels/googlechat/runtime/googlechat-outbound-auth.ts`:
- Around line 225-255: Extract the duplicated CommonJS/ESM rewrite
infrastructure into a shared helper module, parameterized by channel name/path
fragment and preserving the existing installXPatch shape. In
src/lib/messaging/channels/googlechat/runtime/googlechat-outbound-auth.ts lines
225-255, retain only patchGooglechatOutboundAuthSource and delegate
createComposableJsLoader, sourceToText, fileNameFromModuleUrl, errorMessage, and
isOpenClawGooglechatFile; apply the same change in
src/lib/messaging/channels/googlechat/runtime/googlechat-trusted-proxy-fetch.ts
lines 245-275, retaining only patchTrustedProxyFetchSource and delegating the
shared helpers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 22d36853-0225-44c0-84fd-db82510b6b78

📥 Commits

Reviewing files that changed from the base of the PR and between d5fa194 and 0345f3b.

📒 Files selected for processing (56)
  • ci/reviewed-npm-lifecycle-allowlist.json
  • docs/index.yml
  • docs/manage-sandboxes/add-channels-after-onboarding.mdx
  • docs/manage-sandboxes/enable-channels-during-onboarding.mdx
  • docs/manage-sandboxes/manage-messaging-channels.mdx
  • docs/manage-sandboxes/messaging-channels.mdx
  • docs/manage-sandboxes/set-up-google-chat.mdx
  • src/lib/actions/sandbox/destroy.ts
  • src/lib/actions/sandbox/policy-channel-dependencies.ts
  • src/lib/actions/sandbox/policy-channel.ts
  • src/lib/messaging-channel-config.test.ts
  • src/lib/messaging/applier/build/messaging-build-applier.mts
  • src/lib/messaging/channels/built-ins.ts
  • src/lib/messaging/channels/googlechat/hooks/index.ts
  • src/lib/messaging/channels/googlechat/hooks/tunnel-audience-gate.test.ts
  • src/lib/messaging/channels/googlechat/hooks/tunnel-audience-gate.ts
  • src/lib/messaging/channels/googlechat/hooks/tunnel-runtime.test.ts
  • src/lib/messaging/channels/googlechat/hooks/tunnel-runtime.ts
  • src/lib/messaging/channels/googlechat/manifest.ts
  • src/lib/messaging/channels/googlechat/policy/openclaw.yaml
  • src/lib/messaging/channels/googlechat/provider-profile/openclaw.yaml
  • src/lib/messaging/channels/googlechat/rendered-config-parser.ts
  • src/lib/messaging/channels/googlechat/runtime/googlechat-outbound-auth.test.ts
  • src/lib/messaging/channels/googlechat/runtime/googlechat-outbound-auth.ts
  • src/lib/messaging/channels/googlechat/runtime/googlechat-trusted-proxy-fetch.test.ts
  • src/lib/messaging/channels/googlechat/runtime/googlechat-trusted-proxy-fetch.ts
  • src/lib/messaging/channels/googlechat/template-resolver.test.ts
  • src/lib/messaging/channels/googlechat/template-resolver.ts
  • src/lib/messaging/channels/manifests.test.ts
  • src/lib/messaging/channels/metadata.test.ts
  • src/lib/messaging/channels/rendered-config-parser.ts
  • src/lib/messaging/channels/template-resolver.ts
  • src/lib/messaging/diagnostics.test.ts
  • src/lib/messaging/hooks/builtins.ts
  • src/lib/messaging/hooks/hook-runner.test.ts
  • src/lib/messaging/utils.test.ts
  • src/lib/onboard/messaging-bridge-provider.test.ts
  • src/lib/onboard/messaging-bridge-provider.ts
  • src/lib/onboard/messaging-prep.test.ts
  • src/lib/onboard/messaging-prep.ts
  • src/lib/onboard/providers.ts
  • src/lib/sandbox/channels.test.ts
  • src/lib/state/openclaw-managed-extensions.test.ts
  • src/lib/tunnel/googlechat-webhook-lifecycle.test.ts
  • src/lib/tunnel/googlechat-webhook-lifecycle.ts
  • src/lib/tunnel/googlechat-webhook-proxy.test.ts
  • src/lib/tunnel/googlechat-webhook-proxy.ts
  • src/lib/tunnel/services.ts
  • test/channels-add-bridge-lifecycle.test.ts
  • test/channels-add-preset.test.ts
  • test/destroy-cleanup-sandbox-services.test.ts
  • test/e2e/live/channels-stop-start-helpers.ts
  • test/e2e/live/channels-stop-start-progress.ts
  • test/e2e/support/channels-stop-start-progress.test.ts
  • test/messaging-build-applier-integrity.test.ts
  • test/onboard-readiness.test.ts

Comment thread docs/manage-sandboxes/enable-channels-during-onboarding.mdx Outdated
Comment thread src/lib/messaging/channels/googlechat/manifest.ts
hunglp6d added 2 commits July 21, 2026 17:18
Signed-off-by: Hung Le <hple@nvidia.com>
@sandl99
sandl99 marked this pull request as draft July 21, 2026 13:42
@copy-pr-bot

copy-pr-bot Bot commented Jul 21, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@github-actions

Copy link
Copy Markdown
Contributor

@NVIDIA NVIDIA deleted a comment from coderabbitai Bot Jul 21, 2026
@wscurran wscurran added area: messaging Messaging channels, bridges, manifests, or channel lifecycle feature PR adds or expands user-visible functionality integration: openclaw OpenClaw integration behavior labels Jul 21, 2026
hunglp6d and others added 13 commits July 22, 2026 11:49
…plyPreset

Signed-off-by: Hung Le <hple@nvidia.com>
… import

Signed-off-by: Hung Le <hple@nvidia.com>
Signed-off-by: Hung Le <hple@nvidia.com>
- Group the webhook, appPrincipal, and service-account guidance into aligned
  left-rail blocks, color the webhook URL, and add blank-line spacing before
  configuration prompts.
- Cap the masked echo for a long pasted secret (the service-account JSON) with
  an "(and N more characters)" tail and support word-delete in the masked prompt.
- Add opt-in re-prompts (maxTokenAttempts) and a Google Chat-owned token-paste
  hook that rejects an unparseable service-account JSON at the prompt instead of
  aborting onboarding later at token minting.
- Make the tunnel/audience gate the single source of the webhook audience.
- Suppress the harmless "profile not found" probe output when registering the
  bridge provider profile, and surface only an unexpected probe error.
- Rename the e2e stop/start heartbeat local to avoid colliding with the merged
  progress fixture.

Signed-off-by: Hung Le <hple@nvidia.com>
…ract test

Signed-off-by: Hung Le <hple@nvidia.com>
@hunglp6d
hunglp6d marked this pull request as ready for review July 24, 2026 06:45
@hunglp6d hunglp6d self-assigned this Jul 24, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/onboard/messaging-bridge-provider.ts`:
- Around line 375-409: Update buildRefreshMaterial for the
google-service-account-jwt strategy so secretKeys always includes "private_key",
even when profile.secretMaterialKeys is non-empty and omits it; preserve any
other declared secret keys without duplication. Add coverage for a profile
omitting "private_key" and verify it remains secret material rather than argv
material.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 6b05bbe8-689c-4e47-b9ec-410c8ca379f7

📥 Commits

Reviewing files that changed from the base of the PR and between b4903f0 and e358640.

📒 Files selected for processing (27)
  • ci/reviewed-npm-lifecycle-allowlist.json
  • docs/index.yml
  • docs/manage-sandboxes/enable-channels-during-onboarding.mdx
  • src/lib/actions/sandbox/destroy.ts
  • src/lib/actions/sandbox/policy-channel-dependencies.ts
  • src/lib/actions/sandbox/policy-channel.ts
  • src/lib/credentials/store.ts
  • src/lib/messaging/applier/build/messaging-build-applier.mts
  • src/lib/messaging/channels/googlechat/hooks/index.ts
  • src/lib/messaging/channels/googlechat/hooks/service-account-token-paste.ts
  • src/lib/messaging/channels/googlechat/hooks/tunnel-audience-gate.test.ts
  • src/lib/messaging/channels/googlechat/hooks/tunnel-audience-gate.ts
  • src/lib/messaging/channels/googlechat/hooks/tunnel-runtime.ts
  • src/lib/messaging/channels/googlechat/manifest.ts
  • src/lib/messaging/channels/googlechat/runtime-contract.test.ts
  • src/lib/messaging/channels/googlechat/tunnel/lifecycle.test.ts
  • src/lib/messaging/channels/googlechat/tunnel/lifecycle.ts
  • src/lib/messaging/channels/googlechat/tunnel/proxy.test.ts
  • src/lib/messaging/channels/googlechat/tunnel/proxy.ts
  • src/lib/messaging/channels/metadata.test.ts
  • src/lib/messaging/hooks/common/config-prompt.ts
  • src/lib/messaging/hooks/common/token-paste.ts
  • src/lib/messaging/hooks/hook-runner.test.ts
  • src/lib/messaging/manifest/types.ts
  • src/lib/onboard/messaging-bridge-provider.test.ts
  • src/lib/onboard/messaging-bridge-provider.ts
  • test/channels-add-bridge-lifecycle.test.ts
💤 Files with no reviewable changes (1)
  • docs/manage-sandboxes/enable-channels-during-onboarding.mdx
🚧 Files skipped from review as they are similar to previous changes (11)
  • src/lib/messaging/hooks/hook-runner.test.ts
  • ci/reviewed-npm-lifecycle-allowlist.json
  • src/lib/messaging/applier/build/messaging-build-applier.mts
  • src/lib/actions/sandbox/policy-channel-dependencies.ts
  • docs/index.yml
  • src/lib/actions/sandbox/destroy.ts
  • src/lib/messaging/channels/googlechat/manifest.ts
  • src/lib/messaging/channels/metadata.test.ts
  • src/lib/messaging/channels/googlechat/hooks/tunnel-audience-gate.test.ts
  • test/channels-add-bridge-lifecycle.test.ts
  • src/lib/actions/sandbox/policy-channel.ts

Comment thread src/lib/onboard/messaging-bridge-provider.ts
…der-declares secrets

Signed-off-by: Hung Le <hple@nvidia.com>
@github-actions

Copy link
Copy Markdown
Contributor

E2E Target Results — ❌ Some tests failed

Run: 30082756521
Workflow ref: feat/messaging-channel-integration-googlechat
Requested targets: (default — all supported)
Requested test IDs: (selector rejected by workflow validation)
Summary: 0 passed, 1 failed, 0 cancelled, 0 skipped, 0 unknown

Test Result Total wall clock time
base-image-publication ❌ failure 5s

Failed tests: base-image-publication. Check the workflow run for all logs and artifacts.

Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
@apurvvkumaria

Copy link
Copy Markdown
Collaborator

Maintainer security follow-up is pushed at exact GitHub-Verified signed head 55cae1b06 with the contributor history preserved through a normal merge from current main.

Small follow-up commits:

  • fd9d00a57: reject malformed Google Chat service-account JSON and require non-empty string client_email and private_key fields, including the env/noninteractive provider path.
  • 16bee1639: disable request-body credential rewriting for Google Chat so the gateway-minted bearer can only be injected through the outbound Authorization header; add a regression contract.
  • b3ead7a78: signed merge of current main, no rewritten contributor commits.
  • 55cae1b06: document both security contracts.

Exact-head local validation:

  • focused CLI: 14 files / 112 tests passed
  • focused integration: 5 files / 90 tests passed
  • E2E support: 1 file / 2 tests passed
  • CLI typecheck and CLI build passed
  • docs build/routes passed (0 errors; 2 existing warnings)
  • changed-file hooks, source-shape/test-size gates, secret scan, and pre-push TypeScript checks passed
  • 0 unresolved review threads

The pinned @openclaw/googlechat@2026.7.1 archive/SRI and both runtime source-rewrite anchors were also checked against the actual published bundle. Awaiting fresh exact-head CI, required E2E, and human approval before merge.

Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
@apurvvkumaria

Copy link
Copy Markdown
Collaborator

Addressed advisor blocker PRA-1 in signed, GitHub-Verified commit f23369302.

  • Pre-supplied app-url audiences must now parse as HTTPS and have a pathname ending exactly in /googlechat.
  • Wrong paths, trailing slashes, and HTTP URLs fail before hook outputs can be persisted.
  • Pre-supplied project-number audiences remain unchanged.

Validation:

  • Google Chat CLI suite: 9 files, 56 tests passed
  • npm run typecheck:cli: passed
  • changed-file hooks, repository checks, source-shape budget, test-size budget, and secret scan: passed
  • documentation writer: no additional docs needed; the existing setup page already states HTTPS, /googlechat, and no trailing slash

@cv cv added v0.0.97 Release target and removed v0.0.96 Release target labels Jul 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: messaging Messaging channels, bridges, manifests, or channel lifecycle feature PR adds or expands user-visible functionality integration: openclaw OpenClaw integration behavior v0.0.97 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants