Repository navigation
Make onboarding honest, Gmail disconnect real, and the app readable at large text - #75
Merged
Merged
Conversation
M1: onboarding's local step said conversations stay on this computer. They live in CopilotKit Intelligence (its cloud unless self-hosted), every message goes to the model, and runtime telemetry is on by default. The step now says each of those, and how to turn telemetry off. M3: Disconnect on Gmail and Google Calendar now works. DELETE /servers/:id/connection takes user-oauth apps down a new store.disconnectHeld: it asks the vendor to revoke the refresh token at the catalogue's revokeUrl (RFC 7009), then revokes the vault row and deletes the connection in one transaction, and audits it. If the vendor can't be reached, nothing changes. If the vendor refuses, access still ends here and the page says to finish at Google. M4: CopilotKit's inspector and its popover are off unless VITE_COPILOTKIT_INSPECTOR=true. M6: page body line heights are ratios. The page title wraps between words and gets its own row at large text. The Tasks header wraps. The + and the icon buttons stay a fixed size, with a spacer that clears the +. Also: Escape on New channel closes only the innermost thing and asks before dropping typed fields. User-visible "OpenBot" becomes the product name. The roster step loses the approval demo and the brief demo shows today's date. Model and network failures are plain sentences that survive a reload while still current. The Chat pill says "Still working on it" after 20 quiet seconds. The checklist reads an idle Bot computer as Ready, and the official API base URLs are no longer "custom".
Collaborator
Author
Security reviewI reviewed the whole diff, with most attention on the disconnect change (M3). No findings that block this PR. Details below. Disconnect (
|
jerelvelarde
added a commit
that referenced
this pull request
Oct 26, 2026
#75 made Disconnect real for user-held accounts: it asks Google to revoke the refresh token, then revokes the stored credential and removes the connection. The Gmail and Calendar and Google Drive pages still said it was not built and sent people to Google's settings instead.
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.
The problem
The release review ran the app end to end at phone width with a real model and found these, all reproduced on current main (71dc24c):
leading-[27px]fixed while the text grew), the page title broke mid-word into a column, the Tasks search button was pushed off-screen, and the + covered the first row.https://api.anthropic.coma custom endpoint.The approach
M1. Accurate copy. The step is now "Where your data lives": Bots and settings stay in this install's database; conversations and memory are in CopilotKit Intelligence, in CopilotKit's cloud unless you host it yourself; what you ask goes to your AI model; and a footnote says CopilotKit receives usage events and
DO_NOT_TRACK=1turns them off. Each sentence is checked against code (.env.example,docs/telemetry.md,server/src/telemetry.ts, the schema). Files and connected accounts are left out on purpose, because a file's content also reaches the thread and the model, and a brokered app's account is held by the broker. The step only shows for a single-user install, so naming the variable is fine.M3. A real disconnect.
DELETE /api/plugins/servers/:id/connectionnow handlesuser-oauthapps (Gmail and Calendar, Drive, Notion). Before, it answered "That app doesn't connect this way." A newstore.disconnectHelddoes this:revokeUrl(RFC 7009). That address was already declared "where a disconnect is sent" but never used.mcp.account_disconnected(reasonself, plus the vendor's answer as one word).If the vendor can't be reached (timeout, 5xx, 429), the transaction rolls back and nothing changes; pressing again retries. If the vendor answers no, access still ends here, and the page tells the person to remove the app at Google too. The page's menu item is now a working "Disconnect", with a status line afterwards. The copy uses the product name from app config.
M4.
enableInspector={false}onCopilotKitProvider(react-core 1.77's documented prop).VITE_COPILOTKIT_INSPECTOR=trueturns it back on for developers.M6.
em.Minors.
/botchat uses the same mapping. The sentence is kept insessionStoragewith the id of the last message, so a reload shows it again only while nothing newer has arrived.idle. The row reads Ready, "each Bot's computer starts the first time it's needed", and names no variables. When the service doesn't answer, the row names the address and token. The official OpenAI and Anthropic base URLs (with or without/v1) no longer count as custom endpoints.What is not covered
openbot/docs/plugins/google-workspace.mdandgoogle-drive.mdstill say Disconnect is "Not built yet". The docs belong to another agent's lane, so I left them alone.retireConnectionsFor) still revokes only our vault copy and doesn't ask the vendor. That is a separate change.app/serve.ts's production log line. Fixing those means passing the product name through server modules, which belongs in its own change.Verification
bun test app/tests: 2421 pass, 0 fail (265 files). Addscopilot-inspector,held-account-disconnect,patient-stepandrun-error-memory, plus new cases inchannel-sheet,chat-run-lifecycle,onboarding-route,run-lifecycleandplugin-mutation-refresh.bun test server(full suite against a throwaway Postgres 17 on :55473): 6334 pass, 14 fail of 6367. 13 of the 14 also fail on pristineorigin/mainon this machine:app-access-routes.integration(5, Team Bot timeouts),test-network-guard(5),learning-mastra(1) andlearning-langgraph(2), which need the real network or providers. The 14th isassertion-shape's whole-tree scan going past bun's 5s timeout under full-suite load, and it passes on its own (10/10). Three guards this change did trip are fixed in the commit.sole-definitionandassertion-shapenow pass: the disconnect audit writes a literal boolean, and an un-awaitedrejectsthe allow-list was carrying is now awaited and its entry removed.plugin-user-credential.integration22/22 (7 new store cases and 2 route cases for disconnect, including an unreachable vendor, a refusal, already-revoked, other people's rows and the audit row),oauth-revoke5/5,google-workspace-fake18/18 (a real revoke against the fake Google),plugin-routes86/86,openduet-setup45/45,model-availability-check16/16.bun run typecheck: clean.bun run typecheck:tests: clean against the baseline. I typed the test vault stub fully, which fixes one baselined error, and removed that line from the baseline.biome lint --error-on-warnings: clean.biome format: clean./private/tmp/claude-501/-Users-jerel-cpk-OpenDuet/8d570fdc-9cf4-4d73-a2c3-5a0db6c25efb/scratchpad/shots/:before-tasks-200pct.jpg→after-tasks-200pct.jpg,after-tasks-100pct.jpgbefore-page-200pct.jpg→after-page-200pct.jpg,after-page-100pct.jpgbefore-onboarding-roster.jpg→after-onboarding-roster.jpgafter-onboarding-local-step.jpgbefore-gmail-disconnect-menu.jpg→after-gmail-disconnected.jpgafter-channel-sheet-escape.jpginspector-with-opt-in-as-before.jpg(the overlay as everybody saw it) →inspector-off-by-default-after.jpg