Skip to content

feat(messaging): add Google Chat channel - #7317

Merged
prekshivyas merged 73 commits into
mainfrom
feat/messaging-channel-integration-googlechat
Aug 1, 2026
Merged

feat(messaging): add Google Chat channel#7317
prekshivyas merged 73 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.

Documentation

https://docs.google.com/document/d/1x5NAXOvxNSPGEsDwDZrButB1Q92Vbc_Q20eAcu7ofxE/edit?tab=t.0

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; exact current-main delta review PASS at 8897acb3fbbffcfba59eb8ad27238e566d6292ad, feature diff fingerprint 2badf49554a0bc79fbd104eb88d1f4dfba26ba6f9c52a0b848c0d191653e1e8b. The sync changes no Google Chat feature behavior.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Documentation Writer Review

  • Documentation writer subagent reviewed the completed changes
  • Result: docs-updated
  • Evidence: Reviewed the complete Google Chat implementation and six documentation paths at current head. The docs accurately cover experimental/OpenClaw-only scope, interactive enrollment, restricted public ingress, service-account handling, access controls, policy, verification, rotation, lifecycle, removal, and destruction. All 33 changed deterministic test files pass 385/385, CLI/plugin builds and typechecks pass, npm run checks:repository passes, and npm run docs passes with 0 errors and two existing warnings.
  • Agent: Codex Desktop

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 for OpenClaw sandboxes.
    • Added interactive setup with service-account credentials, public HTTPS webhooks, audience controls, and user allowlists.
    • Added lifecycle controls for the dedicated webhook endpoint.
  • Bug Fixes
    • Improved cleanup reliability when webhook shutdown fails, preserving channel state for retry.
    • Improved fail-closed behavior for incomplete or invalid configuration.
  • Documentation
    • Added Google Chat setup and onboarding guidance.
  • Security
    • Added credential validation, masked secret entry, protected token handling, and restricted webhook routing.

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

This PR adds experimental Google Chat messaging support for OpenClaw sandboxes. It adds channel configuration, webhook enrollment, bridge-provider token minting, runtime patches, lifecycle handling, documentation, CI updates, and E2E coverage.

Changes

Google Chat Channel Integration

Layer / File(s) Summary
Channel contracts and registry wiring
src/lib/messaging/channels/googlechat/*, src/lib/messaging/channels/built-ins.ts, src/lib/messaging/hooks/builtins.ts, src/lib/messaging/applier/build/*
Defines the Google Chat manifest, policy, provider profile, configuration resolvers, hooks, package trust, and built-in registry integration.
Secret masking and token enrollment
src/lib/credentials/store.ts, src/lib/messaging/hooks/common/*, src/lib/messaging/manifest/types.ts
Adds capped secret masking, token validation and retry controls, and service-account JSON enrollment validation.
Webhook tunnel and audience enrollment
src/lib/messaging/channels/googlechat/hooks/*, src/lib/messaging/channels/googlechat/tunnel/*, src/lib/tunnel/services.ts
Implements interactive and capability-gated enrollment, a sandbox-scoped tunnel, and a route-restricted /googlechat proxy.
Gateway bridge-provider provisioning
src/lib/onboard/messaging-bridge-provider.ts, src/lib/onboard/messaging-prep.ts, src/lib/onboard/providers.ts
Discovers provider profiles, creates pending token definitions, imports profiles, and configures gateway-side refresh material through environment injection.
Runtime auth and trusted-proxy patches
src/lib/messaging/channels/googlechat/runtime/*
Rewrites bundled Google Chat authentication and fetch behavior at load time, with idempotency, drift detection, and composition tests.
Channel and sandbox lifecycle wiring
src/lib/actions/sandbox/*, src/lib/onboard.ts, src/lib/onboard/messaging-channel-setup.ts
Connects tunnel and bridge dependencies to channel add/remove, onboarding, sandbox destruction, provider cleanup, and fail-closed teardown.
Documentation, CI, and live E2E coverage
docs/manage-sandboxes/*, docs/index.yml, ci/*, test/e2e/live/*, test/e2e/support/*
Documents Google Chat setup and lifecycle behavior, updates CI policy, and adds live stop/start composition and progress coverage.

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

Sequence Diagram(s)

sequenceDiagram
  participant Onboarding
  participant AudienceGateHook
  participant TunnelRuntime
  participant Cloudflared
  participant WebhookProxy
  Onboarding->>AudienceGateHook: enroll googlechat
  AudienceGateHook->>TunnelRuntime: start sandbox-scoped tunnel
  TunnelRuntime->>Cloudflared: start public endpoint
  TunnelRuntime->>WebhookProxy: start /googlechat proxy
  WebhookProxy-->>TunnelRuntime: report readiness
  TunnelRuntime-->>AudienceGateHook: return audience URL
  AudienceGateHook-->>Onboarding: persist googlechat audience
Loading
sequenceDiagram
  participant MessagingPrep
  participant BridgeProvider
  participant OpenShell
  participant Gateway
  MessagingPrep->>BridgeProvider: collect bridge token definitions
  BridgeProvider-->>MessagingPrep: return pending token definitions
  BridgeProvider->>OpenShell: import provider profile
  BridgeProvider->>OpenShell: configure refresh material through env
  OpenShell->>Gateway: mint Google Chat access token
Loading

Possibly related PRs

Suggested labels: area: onboarding, area: security, area: e2e

Suggested reviewers: cjagwani, cv

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.85% 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
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main change: adding Google Chat as a messaging channel.
✨ 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 a5ac963 in the feat/messaging-chann... branch remains at 96%, unchanged from commit b5aaa27 in the main branch.

TypeScript / code-coverage/cli

The overall coverage in commit a5ac963 in the feat/messaging-chann... branch remains at 81%, unchanged from commit b5aaa27 in the main branch.

Show a code coverage summary of the most impacted files.
File main b5aaa27 feat/messaging-chann... a5ac963 +/-
src/lib/credentials/store.ts 61% 55% -6%
src/lib/onboard/docker-cdi.ts 70% 80% +10%
src/lib/messagi...-proxy-fetch.ts 0% 71% +71%
src/lib/messagi...nnel-runtime.ts 0% 71% +71%
src/lib/messagi...utbound-auth.ts 0% 75% +75%
src/lib/messagi...tunnel/proxy.ts 0% 88% +88%
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 August 01, 2026 12:01 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 — No blocking findings reported

Advisor assessment: No blocking advisor findings reported
Next action: Review the warnings below.
Findings: 0 blockers · 1 warning · 0 suggestions

Model lanes

  • GPT-5.6 Terra (primary): Completed · medium confidence · 0 blockers · 1 warning · 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; severity counts match.
3 additional E2E selections from the second opinion

Advisory only. The primary lane did not select these E2E jobs or targets.

  • openclaw-slack-pairing: The completed second-opinion lane identified E2E coverage that the primary lane omitted.
  • openclaw-discord-pairing: The completed second-opinion lane identified E2E coverage that the primary lane omitted.
  • rebuild-openclaw: The completed second-opinion lane identified E2E coverage that the primary lane omitted.

Second-opinion E2E selections are advisory. They do not change the primary assessment or E2E / PR Gate.

E2E guidance

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

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

4 optional E2E recommendations
  • ubuntu-repo-cloud-openclaw
  • tunnel-lifecycle
  • messaging-providers
  • openshell-credential-generation-window
1 warning · 0 suggestions

Warnings

Warnings do not block.

PRA-1 Warning — Cover orphaned Google Chat endpoint removal

  • Location: src/lib/actions/sandbox/policy-channel.ts:1659
  • Category: tests
  • Problem: Google Chat removal stops its dedicated endpoint even when registry, policy, session, and messaging-plan residue is absent, but checked-in tests cover only teardown failure after a configured channel. The orphan-recovery path can regress without a test.
  • Impact: An interrupted enrollment can leave a public endpoint running. A later refactor could skip its teardown when no durable channel record exists, leaving the endpoint orphaned.
  • Recommendation: Add a remove-channel regression test with no Google Chat registry, policy, session, or plan residue. Assert tunnel teardown runs and the command completes through the existing generic cleanup path without creating or persisting channel state.
  • Verification: Inspect test/channels-add-bridge-lifecycle.test.ts and add a case adjacent to the existing teardown-failure test.
  • Test coverage: Call removeSandboxChannel for googlechat with no channel residue. Assert stopGooglechatWebhookTunnel is called, no policy or registry write creates channel state, and generic provider cleanup follows its current behavior.
  • Evidence: src/lib/actions/sandbox/policy-channel.ts:1652-1676 invokes stopGooglechatWebhookTunnel before checking downstream channel state and says it applies when registry residue is absent. test/channels-add-bridge-lifecycle.test.ts covers configured-channel teardown and teardown failure, but contains no no-residue orphan-recovery case. src/lib/actions/sandbox/policy-channel.ts:1678-1701 clears tokens and calls applyChannelRemoveToGatewayAndRegistry after successful Google Chat tunnel teardown. src/lib/actions/sandbox/policy-channel.ts:1652-1676 establishes that the tunnel teardown also runs without registry residue.

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 commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator Author

Status update

CI is green on 36584b6, including E2E / PR Gate — the channels-stop-start (openclaw) path that was failing on the Google Chat import now passes end-to-end. B1/B2 fixed by @apurvvkumaria (27c209593, 682f6c41a); the CodeRabbit env-leak fixed in 6acc24866 (tracked vi.stubEnv).

The one red check — PR review advisor (Nemotron 3 Ultra) — is a non-deterministic flake, not a finding: the failing lane alternates run-to-run (Terra on fa63aa2, Nemotron on 36584b6), only the post-analysis Verify advisor analysis outcome step fails, and the advisor's own verdict is 0 blockers · 0 warnings · 0 suggestions. Advisory / non-blocking; a re-run clears it.

@cjagwani — the exact-head deterministic gates are green on 36584b6 (E2E / PR Gate passed; the only red is the advisor-lane flake above). Per your note the E2E evidence is green, so this head should be ready for re-review after the hold.
@cv — per @cjagwani's note the stale CHANGES_REQUESTED needs the original reviewer to clear it; the Google Chat wiring was reworked substantially since July 26 and CI + E2E are now green.
@laitingsheng — thanks for the thorough review; every one is addressed on this head. Thanks @apurvvkumaria for the guardrail and composition fixes.

@prekshivyas
prekshivyas enabled auto-merge (squash) August 1, 2026 10:16
@prekshivyas
prekshivyas merged commit 77ebb5b into main Aug 1, 2026
45 checks passed
@prekshivyas
prekshivyas deleted the feat/messaging-channel-integration-googlechat branch August 1, 2026 12:28
senthilr-nv added a commit that referenced this pull request Aug 4, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Adds the canonical dated `v0.0.101` changelog entry that was missing
when the release tag was cut. This post-release recovery records the
shipped behavior on current `main` without changing or replacing the
existing tag.

## Changes

- Add `docs/changelog/2026-08-03.mdx` with the exact `## v0.0.101`
heading, release summary, detailed behavior changes, support boundaries,
and links to durable documentation.
- [#7317](#7317) ->
`docs/changelog/2026-08-03.mdx`: Records experimental OpenClaw Google
Chat support and its restricted credential and webhook boundary.
- [#7715](#7715) ->
`docs/changelog/2026-08-03.mdx`: Records strict onboarding recovery
state and authoritative resume identity.
- [#7749](#7749) ->
`docs/changelog/2026-08-03.mdx`: Records the provider-neutral policy
seam and unchanged runtime support boundary.
- [#7817](#7817) ->
`docs/changelog/2026-08-03.mdx`: Records preserved Hermes home-channel
assignments across rebuilds.
- [#7820](#7820) ->
`docs/changelog/2026-08-03.mdx`: Records the SSH-session status field
correction.
- [#7847](#7847) ->
`docs/changelog/2026-08-03.mdx`: Records fail-closed credential
filtering for migration and rebuild backups.
- [#7870](#7870) ->
`docs/changelog/2026-08-03.mdx`: Records sandbox-qualified in-sandbox
host command hints.
- [#7875](#7875) ->
`docs/changelog/2026-08-03.mdx`: Records Microsoft Teams stop and start
E2E coverage.
- [#7885](#7885) ->
`docs/changelog/2026-08-03.mdx`: Records Hermes managed gateway
detection in status.
- [#7889](#7889) ->
`docs/changelog/2026-08-03.mdx`: Records policy-authenticated HTTPS Pin
Runtime route revocation.
- [#7891](#7891) ->
`docs/changelog/2026-08-03.mdx`: Records default fallback for negative
timeout and polling overrides.
- [#7993](#7993) ->
`docs/changelog/2026-08-03.mdx`: Records correct sibling detection
during uninstall.
- [#7995](#7995) ->
`docs/changelog/2026-08-03.mdx`: Records absent configuration-hash
handling before shields lock.
- [#8001](#8001) ->
`docs/changelog/2026-08-03.mdx`: Records the dormant atomic managed
workload replacement foundation.
- [#8029](#8029) ->
`docs/changelog/2026-08-03.mdx`: Records repository terminology review
in PR Review Advisor.
- [#8031](#8031) ->
`docs/changelog/2026-08-03.mdx`: Records provider-neutral managed
snapshot authority.
- [#8032](#8032) ->
`docs/changelog/2026-08-03.mdx`: Records immutable managed clone handoff
contracts.
- [#8034](#8034) ->
`docs/changelog/2026-08-03.mdx`: Records the dormant provider-owned
clone transaction surface.
- [#8035](#8035) ->
`docs/changelog/2026-08-03.mdx`: Records the dormant Hermes managed
clone broker boundary.
- [#8036](#8036) ->
`docs/changelog/2026-08-03.mdx`: Records the dormant transactional
managed bootstrap boundary.
- [#8037](#8037) ->
`docs/changelog/2026-08-03.mdx`: Records dormant Docker bootstrap
primitives and the unchanged provider support boundary.
- [#8070](#8070) ->
`docs/changelog/2026-08-03.mdx`: Records consolidated sandbox
resource-limit E2E coverage.
- [#8071](#8071) ->
`docs/changelog/2026-08-03.mdx`: Records escaped and bounded CLI
validation diagnostics.
- [#8081](#8081) ->
`docs/changelog/2026-08-03.mdx`: Records bounded linear snapshot Base64
validation.
- [#8085](#8085) ->
`docs/changelog/2026-08-03.mdx`: Records commit-bound workflow approval
for eligible same-repository maintainers.
- [#8088](#8088) ->
`docs/changelog/2026-08-03.mdx`: Records Hermes managed-policy E2E
selection.
- [#8090](#8090) ->
`docs/changelog/2026-08-03.mdx`: Records pinned CI search-tool
provisioning.
- [#8106](#8106) ->
`docs/changelog/2026-08-03.mdx`: Records fallback from failed managed
OpenShell gateway startup.
- [#8107](#8107) ->
`docs/changelog/2026-08-03.mdx`: Records Hermes adapter lifecycle E2E
selection.
- [#8128](#8128) ->
`docs/changelog/2026-08-03.mdx`: Records the dormant transactional
Docker bootstrap adapter and rollback authority.
- [#8140](#8140) ->
`docs/changelog/2026-08-03.mdx`: Records Slack conflict scope across
independent OpenShell gateways.
- [#8147](#8147) ->
`docs/changelog/2026-08-03.mdx`: Records completion of durable v0.0.100
documentation audit follow-ups.

## Type of Change

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

## Quality Gates

- [ ] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [x] Tests not applicable — justification: This documentation-only
recovery does not change executable behavior.
- [x] 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 — reviewer/approval link/justification:
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Documentation Writer Review

- [x] Documentation writer subagent reviewed the completed changes
- Result: `docs-updated`
- Evidence: Independently reviewed `docs/changelog/2026-08-03.mdx` at
commit `0bebe1f568e3dc85cf410aac1dfb8f8830070b85`. Its blob is
`82887920f9720eafd75db6b2271c35f7477edb9b`. The entry follows the
writing guide, controlled terminology, changelog structure, MDX SPDX
format, literal CLI-name rule, and root-absolute route requirements. It
accurately records the `v0.0.100...v0.0.101` release range, Announcement
#8162, accepted scope boundaries, and shipped security behavior. There
are no code samples. Focused changelog tests and the documentation build
pass for this commit.
- Agent: Codex Desktop independent documentation writer
<!-- docs-review-head-sha: 0bebe1f -->
<!-- docs-review-agents-blob-sha:
3dd7c24 -->

## Security Review

- Result: `PASS`
- Reviewed commit: `0bebe1f568e3dc85cf410aac1dfb8f8830070b85`
- Base commit: `643a4ab8b5f583d8555192a37927268b26022c51`
- Findings: None.
- Secrets and credentials: `PASS`. No credential values or secret files
are present.
- Input validation and data sanitization: `PASS`. No executable input
path changes.
- Authentication and authorization: `PASS`. No identity or permission
logic changes.
- Dependencies and third-party libraries: `PASS`. No dependency changes.
- Error handling and logging: `PASS`. No runtime path changes;
diagnostic-security claims are precise.
- Cryptography and data protection: `PASS`. No implementation changes.
- Configuration and security controls: `PASS`. No configuration,
container, port, or HTTP changes.
- Security testing: `PASS`. No coverage is removed; the entry records
shipped test and security behavior.
- System security: `PASS`. No runtime control changes; dormant and
non-activation boundaries are explicit.
- Agent: Codex Desktop independent security reviewer

## Verification

- [ ] PR description includes a `Signed-off-by:` line and every commit
appears as `Verified` in GitHub — verification is pending after commit
`0bebe1f568e3dc85cf410aac1dfb8f8830070b85` is pushed.
- [ ] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run validate:pr` passed after refreshing `origin/main` when hooks
were skipped or unavailable — commit hooks passed; pre-push is pending.
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — tests are not applicable to this
documentation-only recovery.
- [x] Applicable broad gate passed — not applicable to this
documentation-only recovery.
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, credentials, or private keys are added by
this diff.
- [ ] `npm run docs` builds without warnings (doc changes only) — GitHub
documentation checks are pending.
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only) — independent documentation review passed.
- [x] New doc pages include SPDX header and frontmatter (new pages only)
— the native changelog entry uses the required parser-safe MDX SPDX
comment and intentionally has no frontmatter.

GitHub CI is authoritative.
Focused changelog tests and `npm run docs` passed after the merge
refresh.

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


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Added experimental Google Chat support.
  * Improved runtime and session status visibility.
  * Added onboarding recovery and persistence safeguards.
  * Added snapshot validation and dormant managed-workload support.

* **Bug Fixes**
* Improved backup sanitization, route handling, and gateway reliability.

* **Documentation**
  * Added the v0.0.101 changelog and related updates.

* **Tests**
  * Expanded end-to-end coverage and strengthened trusted CI validation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Co-authored-by: Carlos Villela <cvillela@nvidia.com>
Co-authored-by: Senthil Ravichandran <senthilr@nvidia.com>
cv pushed a commit that referenced this pull request Aug 20, 2026
…EST pull (#9393)

<!-- markdownlint-disable MD041 -->
## Summary
Google Chat was the only messaging channel restricted to OpenClaw. This
change enables it for Hermes without placing the service-account key
inside the sandbox: Hermes pulls Chat events from the configured Pub/Sub
subscription over the REST API and replies through the OpenShell L7
proxy with a gateway-minted bearer, so the sandbox only ever holds a
credential placeholder. Before, `channels add googlechat` was refused on
a Hermes sandbox; after, the channel enrolls, receives DMs, and replies.

## Related Issue
Completes the Hermes half of #5492 for Google Chat. That issue models
support per agent and states a channel needs to work for each runtime
whose upstream actually supports it; Hermes `v2026.7.20` ships
`plugins/platforms/google_chat/adapter.py`, so Hermes is inside its
accepted scope. #7317 delivered the OpenClaw half and the issue was
closed with that half done. It is reopened, and its channel table now
records this PR against the Google Chat row. Not a closing reference,
since the issue tracks the whole channel catalogue. Release target: next
patch release.

## Changes
- Add `channels/googlechat/policy/hermes.yaml`: Pub/Sub REST pull for
inbound and Chat REST for the reply, restricted to the two Pub/Sub
operations the adapter issues (`:pull`, `:acknowledge`) and to the Chat
`spaces` tree for writes.
- Add `channels/googlechat/provider-profile/hermes.yaml`: one
gateway-minted token covering `chat.bot` and `pubsub`, with the
service-account private key designated as gateway-side secret material.
- Extend `channels/googlechat/manifest.ts`: allow Hermes, add the
Hermes-only project and subscription inputs, render the Hermes env and
platform fragment, and declare the `google-*` packages the managed image
needs.
- Move `google_chat` from the managed-image neutral list to the Hermes
supported list, and let the bridge-provider collector select a profile
by agent.
- Add `channels/googlechat/runtime/hermes-adapter.py`: a channel-owned
runtime asset that subclasses the bundled Google Chat adapter for a
Pub/Sub REST pull loop, placeholder credentials, and an aiohttp reply
transport, and attaches it through `platform_registry.get()` plus
`dataclasses.replace()`.
- Correct the DM allowlist prompt, which told every operator to use
`users/NNN` ids and claimed emails are ignored. That holds for OpenClaw
and is inverted for Hermes, and the prompt did not say that filling the
allowlist switches the DM policy from pairing to allowlist, so a
wrong-form entry drops the sender with no reply and no pairing code.

**Why the module load is conditional.** Hermes loads only `__init__.py`
as the plugin entry, so the gate in `agents/hermes/plugin/__init__.py`
loads the sibling channel asset by path when the rendered
`GOOGLE_CHAT_SUBSCRIPTION_NAME` is present. Nothing else reads the
module, and the registry entry is replaced through
`platform_registry.get()` and `dataclasses.replace()` rather than a
global `register` wrapper. A failed load logs and returns without
aborting plugin registration. The gate itself has no automated test, for
the reason recorded under Quality Gates.

## Type of Change
- [x] 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
- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [ ] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification:
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

**Coverage gap.** The override itself is covered:
`channels/googlechat/runtime/hermes-adapter.test.ts` drives the real
pull loop under `python3`, and `channels/googlechat/policy.test.ts` pins
the egress preset. What has no automated coverage is the load gate in
`agents/hermes/plugin/__init__.py`, because this repository runs no CI
lane for Python tests under `agents/hermes/plugin/`, so a unit test
placed there would gate nothing. The risk it would guard against is a
runtime property, that the gate stops firing and Hermes silently keeps
the stock gRPC and service-account adapter, which the REST-only policy
then blocks. The nearest real coverage is the `hermes-e2e` lane. Live
validation is recorded under Verification.

## DGX Station Hardware Evidence
- [ ] Tested on DGX Station
- Tested commit:
- Station profile/scenario:
- Result:
- Supporting evidence:

## Verification
- [x] PR description includes a `Signed-off-by:` line and every commit
appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run validate:pr` passed after refreshing `origin/main` when hooks
were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — command/result or justification: `npx
vitest run src/lib/messaging/channels --project cli --coverage=false`
passes 410 tests across 36 files; `npx vitest run
src/lib/messaging/applier/setup-applier.test.ts --project cli
--coverage=false` passes 24 tests. Both were run after merging
`origin/main` into the branch.
`src/lib/messaging/channels/googlechat/tunnel/lifecycle.test.ts` needs
the compiled plugin, so run `npm --prefix nemoclaw run build` first.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result:
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only)
- [ ] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

**Live validation.** On a managed Hermes sandbox built from this branch,
the plugin replaces the bundled `google_chat` entry, `connect()` reports
the keyless REST pull transport, a Chat DM reaches the agent, and the
bot replies in the space. The conditional load was exercised against the
baked module inside that sandbox in both directions: with the channel
configured the module loads and the entry is replaced; without it the
module is not loaded and the bundled entry stands.

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

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
  - Added Google Chat support for Hermes alongside OpenClaw.
- Added configuration for Google Cloud projects, Pub/Sub subscriptions,
service accounts, and message allowlists.
- Added secure message receiving and acknowledgement through Google Chat
and Pub/Sub.
- Added agent-specific setup and provider configuration for Google Chat
integrations.

- **Bug Fixes**
- Improved resilience during temporary connection and acknowledgement
failures, including message retries.
- Added preflight checks to block setup when required messaging
credentials are missing.

- **Tests**
- Added coverage for setup, permissions, delivery, retries, and
configuration resolution.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: San Dang <sdang@nvidia.com>
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants