Skip to content

feat(otterware): one environment-owned Otter Account, Google per device - #98

Open
Laurin-Notemann wants to merge 1 commit into
mainfrom
feat/shared-otter-account
Open

Laurin-Notemann wants to merge 1 commit into
mainfrom
feat/shared-otter-account

Conversation

@Laurin-Notemann

Copy link
Copy Markdown
Contributor

Problem

Otterware had competing account paths:

  • Home used the environment's own login.
  • Mail, Calendar and Drive used a separately attached session. It lasted at most 30 days and only renewed while a settings page was open, so users had to press "Use on this environment".
  • The Drive CLI had its own Drive login.
  • Calendar showed developer OAuth controls.
  • Device-flow (headless) grants could not get a suite session at all, because Accounts required an authorization code.
  • Mail UI preferences never synced, because undefined failed to encode.

Fix

  • One environment-owned account. The environment's own login (the one Code's relay link uses) drives the Otter Account for Code, Home, Mail, Calendar and Drive, and renews on the server. Removed: attach/detach, "Use on this environment" and the UI timer.
  • Signing an environment in. Any client can start account.session.signIn (Accounts device flow) and open the approval page. account.session.signOut revokes the environment's grant at Accounts. The relay link is untouched.
  • Google per device (Laurin's decision).
    • One consent covers Mail, Calendar and contacts (PROVIDER_SCOPES). The tokens live in the environment's secret store (DeviceGoogle), never in Otter Cloud.
    • "Remove from this device" only forgets locally and never revokes at Google, because Google revokes per project. Calendar's remove path no longer revokes either.
    • Headless servers get no provider grants, since VM Mail/Calendar is deferred.
    • Mail shows "Needs Google on this device", plus "Needs its password on this device" for IMAP.
  • Calendar developer controls removed. The client ID/secret fields, local PKCE button and callback paste are gone.
  • Sessions list. New Accounts endpoints GET /code/grants and POST /code/grants/revoke back Settings › Account › Sessions, now shown in every profile including Code. Device-flow grants get a stable grant ID, so they can hold suite sessions.
  • Drive CLI. otterdrive auth login uses the Accounts device flow (otter-code-cli) and calls Cloud /api/v1 with an otterware:drive capability. logout revokes the grant. Credentials are sent only to the API origin, and identity_conflict gets a clear message.
  • Mail. RPC handlers that return nothing now answer null, which fixes the preferences:setUi sync.

Not changed: Cloud provider_connection code and rows, and the relay.

Release gates (not addressed here)

  1. Device Google client. T3CODE_GOOGLE_CLIENT_ID/_SECRET (a Desktop-app client) is not injected by any build yet. Until it is, "Connect Google on this device" reports that it isn't configured. The client and project must be chosen and verified before release.
  2. Outlook. Existing Cloud-held Google and Microsoft grants are no longer read on desktop environments. Outlook through the account stops on new desktop clients until a device-local Microsoft flow exists; Laurin has accepted this.
  3. Browser runtime. The browser still consumes Cloud grants, and new connects there are disabled. Moving it to the standalone Mail web approach (browser-sealed token plus relay refresh) is a follow-up, and it gates any Cloud Google cleanup.
  4. Separate deployments. The Accounts endpoints and grant-ID hook (otter-accounts Worker) and the Drive CLI's dependency on Cloud /api/v1 are separate deployments. Don't publish the CLI before Cloud and Accounts are deployed.

Validation

  • Typecheck: module-kit, otter-cloud-client, calendar-engine, calendar-node, mail-engine, mail-node, drive-engine, composition, server, web, otterdrive, cloud.
  • Focused tests:
    • module-kit account session (new)
    • Calendar account session, AccountGoogleAuth, preference sync, GoogleAuthLive (remove without revoke)
    • Drive service
    • composition contracts
    • otterdrive
    • Accounts worker (43)
  • Changed files formatted and linted; upstream seams check passes.
  • Not run live: no real sign-in, Google consent or deploy.

Claude Opus 5.5 · Claude Code (T3 Code)

🤖 Generated with Claude Code

- The environment's own login (the one Code's relay link uses) now drives the Otter
  Account for Code, Home, Mail, Calendar and Drive. It renews on the server. The
  attach/detach RPCs, "Use on this environment" and the settings-page renewal timer
  are gone.
- Clients sign an environment in through Accounts' device flow
  (account.session.signIn/signOut). Signing out revokes the environment's grant.
- Google is connected per device. One consent (Mail, Calendar, contacts) is stored in
  the environment's secret store (DeviceGoogle), never in Otter Cloud. Disconnect
  forgets it locally and never revokes at Google, which revokes per project.
  Headless servers get no provider grants (VM Mail/Calendar deferred).
- Calendar's developer OAuth controls are removed, and its remove path no longer
  revokes the Google grant.
- Accounts: device-flow grants get a stable grant ID, so they can hold a suite
  session. New /code/grants list and revoke endpoints back the Sessions list in
  Account settings, now shown in every profile including Code.
- Drive CLI signs in through Accounts' device flow (otter-code-cli) and calls Otter
  Cloud /api/v1 with an otterware:drive capability. Logout revokes the grant.
  Credentials go only to the API origin.
- Mail: undefined RPC results encode as null, which fixes the preferences:setUi sync.
  New "Needs Google on this device" and "Needs its password on this device" statuses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Laurin-Notemann
Laurin-Notemann enabled auto-merge (squash) October 16, 2026 18:49

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant