Skip to content

feat(msgraph-mail-wake): Microsoft Graph mailbox change-notification wake provider#111658

Closed
a-alphayed wants to merge 2 commits into
openclaw:mainfrom
a-alphayed:graph-mailbox-ingress
Closed

feat(msgraph-mail-wake): Microsoft Graph mailbox change-notification wake provider#111658
a-alphayed wants to merge 2 commits into
openclaw:mainfrom
a-alphayed:graph-mailbox-ingress

Conversation

@a-alphayed

Copy link
Copy Markdown

What

Adds msgraph-mail-wake, a bundled channel plugin that watches Microsoft 365 / Outlook mailboxes via Microsoft Graph change notifications and wakes an OpenClaw agent session when matching mail arrives. It mirrors the Gmail Pub/Sub wake pattern but needs no bridge process — Graph posts native HTTPS webhooks straight to the Gateway route. Disabled by default; a no-op until at least one mailbox is configured. Docs: docs/plugins/msgraph-mail-wake.md.

Two commits: the plugin itself, and a fix commit for four bugs surfaced by testing against a live Microsoft Graph tenant.

Bugs found via live-tenant testing

Exercising the subscription lifecycle against a live Microsoft 365 tenant surfaced four issues the original documented-contracts-only implementation missed:

  • Expiration ceiling. Graph's real maximum for mail subscriptions is 10070 minutes, not the 10080 (7 days) the docs imply — Graph rejects 10080 with ExtensionError: Subscription expiration can only be 10070 minutes in the future. MAX is now 10070, default 10000 (clock-skew margin), plus an adaptive one-shot retry that clamps to a tenant-reported ceiling and applies the learned ceiling to renewals, not just create.
  • Duplicate subscriptions. The gateway can call the plugin's register() more than once per startup; two subscription-manager start()s could race an empty store and each create a subscription. Registrations are now serialized.
  • Opaque errors. Create failures logged only error=Error. A structured GraphRequestError now surfaces a sanitized op/status/code (the Graph error code gated behind a safe enum-like pattern) — never raw messages, bodies, or request paths.
  • Orphaned subscriptions. With provider state keyed by mailbox, a duplicate create could orphan a subscription in Graph. On start, the plugin now deletes subscriptions on its own notificationUrl that it no longer tracks (best-effort, only-ours).

Validation

  • Live Microsoft 365 tenant: client-credentials auth, subscription create, and Graph's callback validation handshake verified through a public HTTPS endpoint — the four fixes above came directly from this.
  • Not yet observed: end-to-end new-mail notification delivery on the freshly-created test tenant within the test window (Graph change-notification delivery on brand-new tenants can lag substantially). That path rests on the documented API contracts and the unit suite.
  • 139 tests pass; typecheck and lint clean.

Known non-blocking tradeoffs

  • The adaptive-clamp floor (60 min) could, on a tenant whose ceiling is below the renew interval, let a subscription lapse between renew ticks (recreated on the next tick). Hypothetical for mail (real ceiling ~10070).
  • listSubscriptions reads a single page (no @odata.nextLink follow); orphan cleanup is best-effort, re-runs every start, and Graph expires orphans regardless.

alphayed added 2 commits July 18, 2026 13:08
…uplicate subscriptions, surface Graph errors safely, self-heal orphans

Found by live Microsoft Graph tenant validation:
- expiration: real mail ceiling is 10070 min, not 10080 (7d). MAX->10070,
  default 10000 (clock-skew margin); adaptive one-shot retry clamps to a
  tenant-reported ceiling and applies the learned ceiling to renew too.
- duplicate subscriptions: serialize plugin (re)registrations so concurrent
  startups can't each create a subscription.
- diagnostics: sanitized GraphRequestError (op/status + pattern-gated code)
  replaces the opaque "error=Error".
- orphans: on start, delete Graph subscriptions on our notificationUrl that
  we no longer track (best-effort, ours-only).
@a-alphayed
a-alphayed requested a review from a team as a code owner July 20, 2026 04:50
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation scripts Repository scripts size: XL labels Jul 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Dependency Guard

This PR changes dependency-related files. Maintainers should confirm these changes are intentional.

Changed files:

  • extensions/msgraph-mail-wake/package.json
  • pnpm-lock.yaml

Maintainer follow-up:

  • Review whether the dependency changes are intentional.
  • Inspect resolved package deltas when lockfile, shrinkwrap, or workspace dependency policy changes are present.
  • Treat package-lock.json and npm-shrinkwrap.json diffs as security-review surfaces.
  • Run pnpm deps:changes:report -- --base-ref origin/main --markdown /tmp/dependency-changes.md --json /tmp/dependency-changes.json locally for detailed release-style evidence.

@github-actions github-actions Bot added the dependencies-changed PR changes dependency-related files label Jul 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Dependency graph changes are blocked

OpenClaw does not accept dependency graph changes through PRs unless a repository admin or security explicitly authorizes the current head SHA. Dependency updates are generated internally by maintainers so external PRs cannot change the resolved graph.

Detected dependency graph changes:

  • pnpm-lock.yaml changed.
  • extensions/msgraph-mail-wake/package.json changed dependencies, devDependencies, name, version.

Auto-scrub was not attempted because this PR changes package manifest dependency graph fields:

  • extensions/msgraph-mail-wake/package.json changed dependencies, devDependencies, name, version.

Dependency graph changes must be reviewed by security or handled by maintainers internally. Please remove lockfile changes manually if they are not needed.

To remove lockfile changes, restore them from the target branch:

git fetch origin
git checkout 'origin/main' -- 'pnpm-lock.yaml'
git commit -m 'chore: remove dependency lockfile change'
git push

If this PR intentionally needs a dependency graph change, ask a repository admin or member of @openclaw/openclaw-secops to comment:

/allow-dependencies-change

The action will approve the current head SHA (447ea1577317e9873a3c4de581910a04f25b5b3d) when it reruns. A later push requires a fresh approval.

@openclaw-barnacle openclaw-barnacle Bot added the triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. label Jul 20, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. merge-risk: 🚨 automation 🚨 May affect CI, automerge, proof capture, label sync, or maintainer automation. labels Jul 20, 2026
@clawsweeper

clawsweeper Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Thanks for the idea. I checked the current extension path, and this is a better fit for ClawHub.com than OpenClaw core.

Close this bundled-core feature PR: the requested Microsoft Graph mailbox wake integration is optional provider-specific functionality that already fits the public plugin SDK seams used by the branch, while current repository direction reserves bundled core distribution for functionality that needs a core capability or explicit sponsorship.

ClawHub handoff
If you want to carry this forward, package it as a self-serve ClawHub item rather than a core patch:

  • Scope: choose the smallest skill, plugin, provider, channel, bundle, or MCP integration that matches the requested capability.
  • Checklist: include package metadata/manifest, entrypoint, required permissions, secrets/config notes, install/update docs, example usage, and a smoke test or proof command.
  • Boundary: ClawSweeper will not open a ClawHub issue or PR, create a tracking issue, or publish the package automatically; the contributor should create that ClawHub work separately.

So I’m closing this as a scope-fit item for the plugin/community path. Please upload or publish it through ClawHub.com so it can live as an installable ClawHub package instead of a bundled OpenClaw core change.

Review details

Best possible solution:

Publish this as an external ClawHub plugin: verify manifest metadata and entrypoint, declared webhook permissions, Graph secret/config handling, install/update documentation, example configuration, and a redacted end-to-end mail-delivery-to-session-wake smoke proof; ClawSweeper should not open a ClawHub issue or PR, create tracking work, or publish it for the contributor.

Do we have a high-confidence way to reproduce the issue?

Not applicable as a bug reproduction: this PR proposes a new optional integration. Its own report documents live subscription creation and callback validation but not an observed mail-notification-to-wake delivery.

Is this the best way to solve the issue?

No. The implementation is technically shaped as a standalone plugin and relies on existing public plugin SDK contracts, so external ClawHub distribution is the narrower maintainable solution unless an owner identifies a missing core API or explicitly sponsors bundling.

Security review:

Security review needs attention: The PR introduces a public webhook/credential surface and a dependency-graph change that require explicit security or repository-admin review before any core merge.

  • [medium] Authorize the new dependency graph — extensions/msgraph-mail-wake/package.json:11
    The package introduces a runtime dependency and lockfile importer change; repository automation explicitly blocks external dependency-graph updates without approval for the current head.
    Confidence: 0.99
  • [medium] Avoid expanding core webhook credential surface — extensions/msgraph-mail-wake/index.ts:1
    Bundling a Graph callback endpoint that schedules agent work and resolves Graph credentials makes a service-specific security boundary part of the core distribution rather than an independently installable plugin.
    Confidence: 0.9

AGENTS.md: unclear because the file could not be read completely.

What I checked:

  • Plugin-boundary fit: The proposed implementation is already isolated under a plugin package and consumes documented plugin SDK barrels for HTTP ingress, state, secret resolution, SSRF-guarded fetches, and session scheduling; the diff does not demonstrate a missing core extension API. (extensions/msgraph-mail-wake/runtime-api.ts:1, 447ea1577317)
  • Repository product direction: Current VISION.md guidance says core should remain lean and supports external community development through plugins and ClawHub; this service-specific mailbox integration is optional and disabled until configured. (VISION.md:286, 1508a586744d)
  • Bundled distribution and dependency expansion: The branch marks the integration as an included private package and adds @azure/identity to its runtime dependencies; the PR discussion’s dependency guard explicitly requires repository-admin or security authorization for the dependency graph change. (extensions/msgraph-mail-wake/package.json:1, 447ea1577317)
  • End-to-end evidence remains incomplete: The PR body reports live subscription creation and callback validation, but expressly says actual new-mail notification delivery was not observed; that leaves the central wake path without posted after-fix evidence. (extensions/msgraph-mail-wake/src/handler.ts:1, 447ea1577317)

Likely related people:

  • steipete: Likely routing owner for the core-versus-plugin distribution decision reflected in current repository vision; source-history inspection was unavailable in the read-only command sandbox. (role: likely product-direction owner; confidence: low; files: VISION.md)

Codex review notes: model internal, reasoning high; reviewed against 1508a586744d.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies-changed PR changes dependency-related files docs Improvements or additions to documentation merge-risk: 🚨 automation 🚨 May affect CI, automerge, proof capture, label sync, or maintainer automation. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. scripts Repository scripts size: XL status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants