Repository navigation
feat: Gmail provider (Google OAuth, Gmail loader, Sources Google mode) (GATE EDIT FOR OWNER REVIEW) - #61
Merged
Conversation
…ction (gate allowance: OWNER-APPROVED)
First slice of PR-2 in docs/plans/2026-09-27-google-provider-and-shared-registration.md.
Graph crate only; the Sources screen Google mode follows in the next commit.
- live/google/mod.rs: google_endpoints(config) (accounts.google.com authorize,
oauth2.googleapis.com token, loopback-IP redirect, installed-app client secret in the
request body alongside PKCE, access_type=online, prompt=select_account,
include_granted_scopes=true); scopes openid/email/profile + gmail.readonly or tasks;
with_google_session over the per-provider session slot; check_connection via userinfo +
the Gmail profile endpoint (content discarded).
- live.rs: run_with_session_for(provider, ..) generalises the cached-session path; the
Microsoft wrapper is unchanged; a Google 401 clears only the Google slot. Refresh tokens
are still removed before the OAuth library parses the response.
- live/google/gmail.rs: userinfo identity (account "google:{sub}", lowercased address),
INBOX and SENT listings (q=newer_than:30d, 100 ids, <=10 pages, partial on cap), hydration
through the shared add_hydrated path with cache hits skipping the fetch, MailItem with
provider Google, conversation = threadId, Gmail web link, internalDate cutoff,
MessageTooLarge parity. Every fetch is origin-confined; tests use loopback servers.
- live/google/mime.rs: part walk (attachments skipped, html preferred), base64url via
encoding::base64url_decode (new), utf-8 / iso-8859-1 / windows-1252 / lossy charsets,
RFC 2047 B and Q words, address-list parsing matching the Microsoft item() formatting.
- live/provider.rs: the Google arms call the real functions.
- tools/check-public-repo.ps1 (OWNER-APPROVED gate edit): the "personal Unix
home-directory path" rule's negative lookahead also excludes `me/` and `@me/`, so the
Gmail and Tasks API paths (users/me/..., users/@me/...) pass while real home paths are
still blocked. New tools/test-public-repo.ps1 proves all three cases against the real
checker in throwaway repositories.
Verified: cargo fmt --check; clippy -D warnings (graph live-connection, desktop
native-ui,ui-screenshot); graph 182 passed; desktop 438 passed, 0 failed, 3 ignored;
tools/test-public-repo.ps1 passed; public-repo gate on staged files; the other checkers
match the main baseline; Cargo.lock unchanged.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YCesN8ZHnhqa6n3rWFThas
…vider Second slice of PR-2 in docs/plans/2026-09-27-google-provider-and-shared-registration.md. - Sources card 1 is "Connect your mailbox" with a "Mail provider" Segmented (Microsoft 365 / Google). The Microsoft branch is today's content unchanged. The Google branch mirrors the Microsoft shipped/BYO pattern: with a shipped Google client, helper text about the unverified-app notice and the test-user list plus an optional "Use my own Google Cloud client" disclosure; without one, the client-ID and client-secret fields (Show secret checkbox, "Open Google Cloud console" link). One "Sign in & check inbox" button and per-provider status lines. The scope-summary cells name "Inbox / Sent" and "Microsoft only" for Groups in Google mode. - AppModel: active_mail_provider() from settings.mail_providers (single element in this PR; PR-4 widens it); switching persists the choice and clears every session. effective_google_registration() (BYO fields > shipped > none), account_config(provider) builds the ConnectionConfig or GoogleConfig, Service::Mailbox(MailProvider) routes worker failures to the right status, connection_report_status(provider, report). - Loading, retry and sign-in hints go through AccountConfig for the active provider. - Reminders stay Microsoft-only until PR-3: in Google mode the reminder control is disabled with "Reminders for Google accounts arrive in a later release." Verified: cargo fmt --check; clippy -D warnings (desktop native-ui,ui-screenshot, graph live-connection); desktop 444 passed, 0 failed, 3 ignored; Cargo.lock unchanged; public-repo gate on staged files. Review fixes folded in: sign-in enablement is based on registration presence (validation errors still surface on click, as before); the Google-mode reminder notice no longer masks decision-store errors; the inbox pill follows the active provider; switching providers resets the review state; shared helpers for status routing, edit clearing and sign-in labels; dispatch_reminder_sync guarded to Microsoft until PR-3. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YCesN8ZHnhqa6n3rWFThas
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.
What
PR-2 of
docs/plans/2026-09-27-google-provider-and-shared-registration.md: a Gmail account can be connected and reviewed, one provider at a time. Google Tasks reminders are PR-3; both providers together are PR-4.Owner-approved gate edit:
tools/check-public-repo.ps1's "personal Unix home-directory path" rule now also excludesme/and@me/in its negative lookahead so the Gmail and Tasks API paths (users/me/…,users/@me/…) pass while real home paths are still blocked. Newtools/test-public-repo.ps1proves the three cases against the real checker.Graph crate (commit 1)
OAuthEndpoints/authorize_withpath:accounts.google.comauthorize,oauth2.googleapis.comtoken, loopback-IP redirect, the installed-app client secret in the request body alongside PKCE,access_type=online,prompt=select_account,include_granted_scopes=true. Google'suserinfo.email/userinfo.profilescope URLs are normalised back toemail/profileso the cached session matches (caught in review). Refresh tokens are still removed before the OAuth library parses the response.run_with_session_for); a Google 401 clears only the Google slot and re-authorizes once, like Microsoft.google:{sub}), INBOX and SENT listings (q=newer_than:30d, 100 ids, ≤10 pages,partialon cap), hydration through the shared path with cache hits skipping the fetch,conversation = threadId, Gmail web link,internalDatecutoff,MessageTooLargeparity, header bounds matching the Microsoft item. Every fetch is origin-confined; tests use loopback servers.check_connectionfor Google via userinfo + Gmail profile, content discarded.Desktop (commit 2)
See the commit message: "Mail provider"
Segmentedon the Sources card, Google client fields with the same shipped/BYO disclosure pattern as Microsoft, per-provider status lines,AccountConfigrouting for load/retry,Service::Mailbox(MailProvider), Google reminders disabled with a fixed status until PR-3.Verification
cargo fmt --all -- --check; clippy-D warningsonopenloops-graph(live-connection) andopenloops-desktop(native-ui,ui-screenshot): cleancargo test -p openloops-graph --features live-connection: 182 passedcargo test -p openloops-desktop --features native-ui -- --test-threads=1: 444 passed, 0 failed, 3 ignoredtools/test-public-repo.ps1passed;tools/check-public-repo.ps1 -Mode Stagedpassed on each committools/check-*.ps1checkers match themainbaseline (the four pre-existing failures are unchanged)Cargo.lockunchangedNot yet exercised live
No Google sign-in has been performed against a real Google Cloud client; the loopback tests pin the request shapes. The owner's smoke test (plan §Verification) needs the Google Cloud project and Desktop OAuth client from plan phase G0, with the owner's address on the test-user list.
🤖 Generated with Claude Code
https://claude.ai/code/session_01YCesN8ZHnhqa6n3rWFThas