feat(m365): add customer Graph Read consent#2511
Merged
Merged
Conversation
Deploying breeze with
|
| Latest commit: |
6d051a1
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://ddb0e2b4.breeze-9te.pages.dev |
| Branch Preview URL: | https://feat-m365-customer-graph-rea.breeze-9te.pages.dev |
Collaborator
Author
|
Final CI follow-up on head
Run: https://github.com/LanternOps/breeze/actions/runs/29379256113 |
ToddHebebrand
marked this pull request as ready for review
July 16, 2026 04:08
ToddHebebrand
force-pushed
the
agent/m365-control-plane-foundation
branch
2 times, most recently
from
July 16, 2026 04:21
11c9433 to
416d8d6
Compare
ToddHebebrand
force-pushed
the
feat/m365-customer-graph-read-consent
branch
from
July 16, 2026 04:36
52abb4d to
422b646
Compare
ToddHebebrand
force-pushed
the
feat/m365-customer-graph-read-consent
branch
from
July 16, 2026 04:53
422b646 to
5ec279a
Compare
ToddHebebrand
added a commit
that referenced
this pull request
Jul 16, 2026
) **Problem:** the `typecheck` job (`tsc --noEmit` over the full `apps/api` project + `astro check`) OOMs — `FATAL ERROR: ... JavaScript heap out of memory` — on the type-heaviest feature branches (e.g. #2548 extensions, #2511 m365). Reproduced deterministically on re-run. Main passes today but is at the edge as the Drizzle type graph grows. **Fix:** set `NODE_OPTIONS=--max-old-space-size=8192` at the `typecheck` job level (covers both `tsc` and `astro check`). No type errors were involved — this is purely heap headroom. ubuntu-latest runners have ~16 GB, so 8 GB old-space is safe. Unblocks the release: the OOM'ing feature PRs pass Type Check once rebased onto this. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Todd Hebebrand <todd@lanternops.io> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
added 19 commits
July 15, 2026 23:11
added 23 commits
July 15, 2026 23:12
ToddHebebrand
force-pushed
the
feat/m365-customer-graph-read-consent
branch
from
July 16, 2026 05:12
5ec279a to
6d051a1
Compare
ToddHebebrand
added a commit
that referenced
this pull request
Jul 16, 2026
Technical-docs sweep for the **v0.96.0** release (range `v0.95.1..main`). Companion to the tagged release; no code changes, docs + docs-review mapping only. ## Pages updated - **TD SYNNEX AI tool** — `features/mcp-server.mdx`, `features/ai.mdx`, `features/distributor-integrations.mdx`: new `lookup_distributor_product` (Tier 2 / `ai:write`; live EC Express price+availability; reseller cost redacted for org-scoped callers, error+no outbound call when no partner in context) (#2559) - **M365 customer Graph-read host config** — `deploy/environment.mdx` new "Customer Microsoft 365 Graph-read consent (optional)" section: 9 env vars, **all required only when `M365_CUSTOMER_GRAPH_READ_ONBOARDING_ENABLED=true`** (dark by default); `deploy/production.mdx` optional `m365-graph-read-executor` sidecar note; `features/identity-integrations.mdx` pointer (#2495, #2511) - **Quotes** — `features/quotes.mdx`: cloning, change-customer-on-draft, per-table subtotals, customer bill-to "Prepared for" block, optional send message, click-to-zoom, Pax8-order-on-acceptance cross-link (#2535, #2584, #2549) - **Backups** — `backup/overview.mdx` (per-device "Run backup now", timezone-correct next-run, `breeze-backup` helper now bundled by shell-script installs), `backup/restoring.mdx` (System image badge, mode+mtime + system-image restore), `backup/verification.mdx` (integrity = size+SHA-256 vs manifest, real corruption detection) (#2558, #2564, #2581) - **Enrollment keys** — `agents/enrollment-keys.mdx`: required Site selector on create form (#2557) ## Mapping / tracker - `scripts/docs-review/mapping.json`: repoint pax8 → `distributor-integrations.mdx`; add `pax8Orders`, `pax8Order*`, `quoteToPax8Order`, `aiToolsCatalog`, `m365ControlPlane/**`, `runtimeConfig.ts`→environment, `m365CustomerGraphRead`/`m365ConsentCallback`, `apps/m365-graph-read-executor/**`, quote pdf/email services, `agent/scripts/install/**` - `scripts/docs-review/last-reviewed.json`: bumped to `20276393e` (2026-07-16) ## Verification notes - The M365 consent **callback URL derives from `PUBLIC_URL`** in the API; the `..._CALLBACK_URL` env var is consumed by the **executor app**, not the API — documented accordingly (not as dead config). - The `m365-graph-read-executor` sidecar is **published (GHCR) but not wired into the tracked compose files** — documented as such, not as a turnkey service. - `apps/docs` `astro build` passes. Intentionally **skipped** (no admin/integrator doc surface): versioned extension contract #2548 (developer-only SDK), Windows helper RDS lifecycle #2520 (internal agent fix), backup execution/result-recording internals #2554/#2556. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Todd Hebebrand <todd@lanternops.io> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ToddHebebrand
added a commit
that referenced
this pull request
Jul 18, 2026
…ion (#2615) ## Summary First consumer value from the M365 control plane (#2495/#2511): a closed, typed catalog of 12 Microsoft Graph **read** actions on the `customer-graph-read` connection, exposed as six `m365_query_*` AI tools (in-app chat + Breeze MCP). Risk-tier T1 only — no mutations, no approval layer, no manifest bump (all actions fit the already-consented manifest v2), and **zero DB migrations**. - **Shared contracts** (`packages/shared/src/m365/readActions.ts`): 12-action Zod discriminated union with bounded params, per-action field-projection allowlists, and typed failure codes. - **Executor** (`m365-graph-read-executor`): one new bounded op `POST /v1/read-action` (same Ed25519 body-hash-bound internal auth), fixed Graph URL templates, status-aware error mapping (license-403 vs permission-403, 404, 429 w/ bounded Retry-After), truncate-don't-throw pagination, projection so no non-allowlisted field ever leaves the executor. Credentials still never cross the boundary. - **API** (`m365ControlPlane/readActionService.ts`): authz ladder — site-restriction gate (`allowedSiteIds`), org resolution, `M365_GRAPH_READ_TOOLS_ENABLED` + org allowlist (boot-validated), connection state (`active`/`degraded` only), fail-closed Redis budget (30/min, 2,000/day per connection), executor call, audit (fixed 4-key metadata, never Graph payloads) + `breeze_m365_graph_read_actions_total{action,outcome}`. - **AI tools**: six tools registered across all gate surfaces (aiTools hub, guardrails, input schemas, system prompt, chat-SDK `TOOL_TIERS`/MCP server) with cap-accurate descriptions. - **Docs**: deploy env vars + read-action acceptance section (R1–R5) in the real-tenant runbook. Ships **dark**: `M365_GRAPH_READ_TOOLS_ENABLED=false` by default; deploy-order safe in both directions (old executor 404 → `executor_unavailable`). Spec: `docs/superpowers/specs/2026-07-18-m365-typed-graph-read-tools-design.md` · Plan: `docs/superpowers/plans/2026-07-18-m365-typed-graph-read-tools.md` ## Review Subagent-driven build: per-task spec+quality reviews on every task, plus a final whole-branch review (verdict: ready to merge). Notable catches fixed along the way: Zod v4 `z.record` arity, site-gate signal corrected to `allowedSiteIds` (`canAccessSite` is always defined for org scope), chat-SDK tool registration drift, boot validation of the tools allowlist. ## Verification - Shared 1,259/1,259 · executor 240/240 · API 14,927 passed (0 failed) — full suites - `tsc --noEmit` clean (API + executor + shared), eslint clean, `git diff --check` clean - Real-tenant read-action acceptance checklist added to the runbook (to run at rollout, tenant-side) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Todd Hebebrand <todd@lanternops.io> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Breeze-owned, customer-tenant Microsoft 365 Graph Read consent and lifecycle management on top of the M365 control-plane foundation.
Why
This keeps Breeze as the approval and orchestration control plane while isolating customer-tenant Graph credentials and execution. It avoids making Delegant a second general authentication control plane and provides a safe foundation for future approval-tiered M365 tools.
Security and correctness
The final two-pass security review and independent whole-branch review are clean. Follow-up tests and fixes cover:
Validation
The local full API regression run completed with 13,436 passes, 31 failures, and 71 skips; the failures were unrelated timeout/load failures in existing OAuth/MCP/metrics/encryption/partner-route suites. The complete M365-focused API suite and API lint/typecheck/build gates are green.
Live Microsoft consent and disposable-tenant permission mutation were not run because dedicated tenant/executor/Azure credentials were not present. The runbook scopes those checks to a disposable tenant.
Dependency
This is a stacked draft PR based on #2495 (
agent/m365-control-plane-foundation). Review and merge #2495 first; GitHub will then reduce this PR to the Graph Read phase.Delegant removal is intentionally out of scope until Breeze-owned consumers are migrated.