Commit Graph
2 Commits
Author SHA1 Message Date
TonioandClaude Opus 5 38752c4e5e fix(ui): clear account-scoped query caches on sign-out (#11380)
Sign-out invalidated two query keys - the auth session and health - and left
everything else in the cache. `invalidateQueries` also keeps serving the old
data while it refetches, so it was insufficient even for the two it did touch.
The company list was never touched at all, which is how one account's
companies could still be in hand when the next account signed in.

The self-hosted path now resets every account-scoped entry. Scoping is an
allowlist of instance-scoped roots rather than a list of things to clear, so a
query key added later is account-scoped unless someone deliberately says
otherwise - forgetting this file fails closed.

`health` is the only exemption. It carries deployment mode, bootstrap state
and Cloud metadata, nothing account-scoped, and `useCloudInstance` observes it
with `enabled: false` and leaves the fetch to CloudAccessGate. Dropping the
entry would strand every such observer on `null` until the gate happened to
refetch, flipping Cloud instances into their self-hosted rendering mid
sign-out. It is refreshed in place instead.

`resetQueries` rather than `removeQueries`: removal empties the cache without
notifying the observers already subscribed, so a mounted `useQuery` keeps
returning its last result until an unrelated re-render rebuilds it.
CompanyProvider sits above the router and stays mounted across the whole
sign-out and sign-in cycle, so that is the common case here rather than a
corner one. Reset notifies them, so the old data leaves the cache and
everything reading it.

The cloud path is untouched: it is a top-level navigation, and the document
reload builds a new QueryClient with nothing left to clear.

This is the root cause behind the onboarding draft-ownership gate added in
#11382. That gate stays, and its comment now says why: this fix covers the
sign-out button, not the question. An account can change without it - a
session lapsing server-side, a second account signing in on a warm tab, a
caller supplying the company context from somewhere else - so the gate stays
independent rather than deferring to this.

ui typecheck clean; full ui suite 4014 pass, with only the timezone-dependent
IssueProperties failure already present on master.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 07:55:14 -07:00
DottaandPaperclip f258b34bbd fix(ui): unify cloud-managed sign-out (#10994)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Paperclip can run as a self-hosted app or as a Cloud-managed tenant.
> - These modes need different sign-out sequences because Cloud owns
three sessions.
> - Several visible controls implemented sign-out separately and could
choose different paths.
> - This pull request adds one Cloud-aware sign-out action and moves
every visible control to it.
> - The benefit is one safe sign-out path in Cloud and unchanged local
sign-out in self-hosted deployments.

## Linked Issues or Issue Description

Refs #2073. That older PR adds a separate company-settings sign-out
surface. This change centralizes the existing account, company, and
instance-settings surfaces and preserves the self-hosted behavior
described there.

**What happened?**

Visible sign-out controls used separate implementations. A Cloud-managed
control could call the app-local sign-out endpoint and open the local
auth page. That path did not enter the Cloud-owned logout sequence for
the tenant, Cloud, and identity sessions.

**Expected behavior**

Every visible sign-out control must use one action. Cloud-managed
instances must navigate the top-level window to the same-origin
`/cloud/logout` route without a local sign-out call first. Authenticated
self-hosted instances must keep the local sign-out API and cache
invalidation behavior.

**Steps to reproduce**

1. Open a Cloud-managed tenant.
2. Use the account menu, company menu, or instance-settings sign-out
control.
3. Observe that independently implemented controls can enter different
sign-out paths.

**Paperclip version or commit**

The problem reproduces at `656ecfa585b31938e2685ffab3db22e794474803`.

**Deployment mode**

Cloud-managed tenant built from source. The regression tests also cover
authenticated self-hosted mode.

## What Changed

- Added `useSignOut` as the shared Cloud-aware sign-out action.
- Navigated Cloud-managed sessions to `/cloud/logout` exactly once
without calling local auth first.
- Preserved local API sign-out and cache invalidation for authenticated
self-hosted sessions.
- Migrated the account menu, company menu, and instance general settings
to the shared action.
- Added focused tests for mode selection, menu closure, pending state,
failure state, and settings behavior.

## Verification

- `pnpm exec vitest run ui/src/hooks/useSignOut.test.tsx
ui/src/components/SidebarAccountMenu.test.tsx
ui/src/components/SidebarCompanyMenu.test.tsx
ui/src/pages/InstanceGeneralSettings.test.tsx` — 26 tests passed.
- `pnpm --filter @paperclipai/ui typecheck` — passed.
- `pnpm check:token-gates` — passed.
- `git diff --check origin/master..HEAD` — passed.

## Risks

- Low risk. The change centralizes existing behavior and adds no schema,
API, telemetry, or style-token changes.
- Cloud mode depends on the existing health decision. Tests pin both
mode branches.
- The change does not alter Fetch Metadata, CSRF, cookie, prefetch, or
return-URL protections owned by the Cloud logout route.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- OpenAI Codex, GPT-5. The runtime does not expose a more specific model
ID or context-window size. The agent used high-reasoning mode, shell
tools, and API tools.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-06 12:13:14 -05:00