You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
msgvault ships with an embedded, centrally-verified Google OAuth client. First-time setup no longer requires creating a Google Cloud project.
BYO ([oauth] client_secrets) and named-app routing (--oauth-app NAME) remain as advanced fallbacks for Workspace orgs that block third-party apps, custom-quota needs, or fallback during the verification window.
Service-account paths (Workspace domain-wide delegation) are unchanged.
Why
Forcing every user to create a Google Cloud project, enable the Gmail API, and configure an OAuth consent screen before they could sync any mail was the biggest onboarding wall — #89 documented users walking away at this step. Eliminating it makes msgvault usable by people who want to archive Gmail without learning Google's developer console.
Note on embedding OAuth credentials
The "client secret" for a desktop OAuth app isn't actually secret once the binary ships — anyone with the binary can extract it. Google says so directly in their OAuth 2.0 docs under "Installed applications": "The process results in a client ID and, in some cases, a client secret, which you embed in the source code of your application. (In this context, the client secret is obviously not treated as a secret.)"
This PR uses the same hybrid pattern the GitHub CLI uses, where gh bakes its production oauthClientSecret directly into source under the comment // This value is safe to be embedded in version control. Source defaults live in internal/oauth/embedded.go; release builds override them via -X ldflags sourced from GitHub Actions Secrets.
How to use
msgvault init-db
msgvault add-account you@gmail.com # opens browser; no other setup
msgvault sync-full you@gmail.com
msgvault tui
See README's "Advanced: bring your own OAuth client" for the BYO path. Full design in docs/superpowers/specs/2026-05-20-centralized-oauth-design.md.
Pre-merge checklist
Merge-blocking:
Resolve internal/oauth/embedded.goTBD-* placeholder defaults: either bake in production credentials at source, or change to empty strings so source builds without ldflags fall back to BYO
Create production Google Cloud project, configure OAuth consent screen (app name, privacy policy URL, logo, support email), and create a Desktop OAuth 2.0 client
Add MSGVAULT_OAUTH_CLIENT_ID and MSGVAULT_OAUTH_CLIENT_SECRET to wesm/msgvault GitHub Actions Secrets (release builds now fail-fast if either is empty)
Cut one release tag and smoke-test the artifact end-to-end on a fresh MSGVAULT_HOME: add-account → consent → sync-full --limit 5
Operational follow-ups (out of band, not merge-blocking but track separately):
Submit the production OAuth client for Google verification (restricted scopes: gmail.readonly, gmail.modify, mail.google.com/)
Plan a CASA Tier 2 assessment — required by Google for restricted scopes; the 100-grant lifetime cap on unverified restricted-scope clients applies from the first grant
Medium: the PR has one blocking correctness issue around placeholder embedded OAuth credentials.
Medium
internal/oauth/embedded.go:20 - The embedded OAuth defaults are non-empty "TBD-..." placeholders, so HasEmbeddedCredentials() treats them as valid. Source builds or local make build runs without injected env vars will fall through to embedded OAuth and attempt authentication with an invalid client, despite the quick start saying no OAuth setup is required.
Fix: Replace the placeholders with real dev OAuth credentials before merging, or make HasEmbeddedCredentials() reject placeholder values and return an actionable BYO/configuration error.
High severity issue found: module path mismatch will break the new resolver/build metadata.
High
cmd/msgvault/cmd/oauth_resolve.go:6
The new resolver imports go.kenn.io/msgvault/internal/..., but this repository’s module path is github.com/wesm/msgvault. The same mismatch is also reported in the new tests and Makefile ldflags, so the added code and local build metadata are not consistently targeting this module’s packages. Fix: Replace go.kenn.io/msgvault with github.com/wesm/msgvault in the new Go imports and Makefile -X paths.
High-level verdict: changes need revision due to a module path mismatch that will break builds.
High
cmd/msgvault/cmd/oauth_resolve.go:6 - The new resolver imports go.kenn.io/msgvault/internal/..., but this repository’s module path is github.com/wesm/msgvault. The same mismatch is also reported in the new tests and Makefile ldflags, so the added code and local build metadata are not consistently targeting this module’s packages.
Fix: Replace go.kenn.io/msgvault with github.com/wesm/msgvault in the new Go imports and Makefile -X paths.
OAuth/version ldflags -X package paths are inconsistent between the release workflow and Makefile (github.com/wesm/msgvault/... vs go.kenn.io/msgvault/...). If the path does not match the actual built package path, release or local binaries may silently miss injected version metadata and embedded OAuth credentials.
Fix: Align all ldflags -X entries in both files to the actual module/package path used by the built package.
Medium
cmd/msgvault/cmd/addaccount.go:200
add-account still skips TokenMatchesClient for the default OAuth binding because needsClientCheck is false when resolvedApp == "". A user with an existing BYO token who removes [oauth] client_secrets may be told the account is already authorized, leaving a token minted for the old client in place; later refresh can fail under the embedded client.
Fix: Require the client identity check when resolving through the embedded client, or whenever the active manager’s client ID may differ from the stored token.
The new OAuth resolver code, tests, and linker flags reference go.kenn.io/msgvault/..., but this repository’s module path is github.com/wesm/msgvault. This can cause compilation failures and prevents MSGVAULT_OAUTH_CLIENT_ID / MSGVAULT_OAUTH_CLIENT_SECRET from overriding embedded credentials during make build or make build-release.
Fix: Update all new module references to match go.mod:
refine-pr note: the latest roborev PR comment appears stale/incorrect. Current go.mod declares module go.kenn.io/msgvault, and the resolver imports plus Makefile ldflags now use go.kenn.io/msgvault/.... CI confirms this head builds/tests successfully, including nix-build, and the GitHub roborev status for 41ef2ee is passing. roborev wait reports no local job for HEAD to close.
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
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.
Closes #89.
Closes #259.
What changed
[oauth] client_secrets) and named-app routing (--oauth-app NAME) remain as advanced fallbacks for Workspace orgs that block third-party apps, custom-quota needs, or fallback during the verification window.Why
Forcing every user to create a Google Cloud project, enable the Gmail API, and configure an OAuth consent screen before they could sync any mail was the biggest onboarding wall — #89 documented users walking away at this step. Eliminating it makes msgvault usable by people who want to archive Gmail without learning Google's developer console.
Note on embedding OAuth credentials
The "client secret" for a desktop OAuth app isn't actually secret once the binary ships — anyone with the binary can extract it. Google says so directly in their OAuth 2.0 docs under "Installed applications": "The process results in a client ID and, in some cases, a client secret, which you embed in the source code of your application. (In this context, the client secret is obviously not treated as a secret.)"
This PR uses the same hybrid pattern the GitHub CLI uses, where
ghbakes its productionoauthClientSecretdirectly into source under the comment// This value is safe to be embedded in version control. Source defaults live ininternal/oauth/embedded.go; release builds override them via-Xldflags sourced from GitHub Actions Secrets.How to use
msgvault init-db msgvault add-account you@gmail.com # opens browser; no other setup msgvault sync-full you@gmail.com msgvault tuiSee README's "Advanced: bring your own OAuth client" for the BYO path. Full design in
docs/superpowers/specs/2026-05-20-centralized-oauth-design.md.Pre-merge checklist
Merge-blocking:
internal/oauth/embedded.goTBD-*placeholder defaults: either bake in production credentials at source, or change to empty strings so source builds without ldflags fall back to BYOMSGVAULT_OAUTH_CLIENT_IDandMSGVAULT_OAUTH_CLIENT_SECRETtowesm/msgvaultGitHub Actions Secrets (release builds now fail-fast if either is empty)MSGVAULT_HOME:add-account→ consent →sync-full --limit 5Operational follow-ups (out of band, not merge-blocking but track separately):
gmail.readonly,gmail.modify,mail.google.com/)