Repository navigation
fix: report unlinked pinned accounts instead of organization denial - #86
Merged
Merged
Conversation
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.
Change
ConnectionAccountUnlinked(HTTP 409), notOrganizationForbidden, when a connection targets accounts but none remain among the caller's usable app links. Covers plain andmany()requirements, HTTP tool discovery/calls, MCP search/describe/calls and their shared account-resolution consumers.Error shape
HTTP 409:
{ "_tag": "ConnectionAccountUnlinked", "app": "app_...", "accounts": ["acc_..."], "message": "This connection runs as account acc_..., which is no longer linked to this app for you. Relink it, or edit the connection to run as another of your accounts.", "recovery": { "action": "Relink the account, or edit the connection to run as another account.", "instructions": "..." } }MCP preserves the stable code and status in its error projection/diagnostics, with recovery and
retryable: false. Several pinned IDs use the plural message.Review fixes
d7c3f106f: replaced the nonexistent operator/admin reset recovery with owner-only relinking or editing the connection to run as another owned account. Instructions explicitly say organization admins cannot edit another member's connection, explain both recovery entry points, warn that relinking a single-account app replaces the current link, and retain the prohibition on changing roles or bypassing account access. Updated HTTP and MCP expectations, including the full HTTP recovery instructions.3266d8292: show Needs account — saving replaces before replacing a single-account link. Extended both pinned-account browser scenarios to inspect the warning and save: a plain requirement replaces the other link, whilemany()retains it. Error responses still do not disclose account labels.relinkingkeeps the save bar visible. Discard does not repair or dismiss the missing-link condition; leaving the editor makes no changes.requireConnectionAccountsinapps/hosted/server/src/implementation/app-accounts.tsuses.someacross requirements. For apps needing several providers, one provider's still-linked pinned account suppresses the new error even when another provider's pinned account is unlinked; those cases fall back to the old errors. Per-provider missing-link diagnosis is not fixed here.GrantForbiddentargetexplanation path inapps/hosted/server/src/implementation/mcp.ts(explained, formerly lines 119–145). This PR does not remove or establish reachability of that path.3dc3d7c6dis an unrelated preparatory skill-digest refresh required forbun run check, not part of the pinned-account fix.Review-fix verification
bun run format,bun run check, andbun run e2e:prepare: passed (check reports existing Effect warnings).bun run e2e:self-host --test-name 'Pinned (many|plain)-account connections|pinned account is replaced during an execution': 3 passed, covering both touched specs (connection-account-unlinked.spec.tsandmcp-connections.spec.ts)..local/e2e/2026-11-10T01-31-55.884Z-self-host-bc4144; regression evidence:.local/e2e/2026-11-10T01-30-57.657Z-self-host-255997.Original implementation verification
bun run formatandbun run check: pass.bun run e2e:prepare: pass.many()and plain-account cases: member unlinks own pinned account; zero links and another linked account; HTTP list/index/get/call; MCP call/search/describe; no labels disclosed; browser needs-account status and save-to-relink recovery; unrestricted calls still work; genuine app-access denial remainsOrganizationForbidden.GrantForbidden.403 OrganizationForbiddenversus expected 409. Restored the fix and reran successfully.Evidence (worktree-relative):
.local/e2e/2026-11-10T01-12-34.419Z-self-host-181685.local/e2e/2026-11-10T01-17-20.773Z-self-host-80042a.local/e2e/2026-11-10T01-15-22.143Z-self-host-f8d709.local/e2e/2026-11-10T01-16-20.375Z-self-host-986121The unrelated preparatory commit
3dc3d7c6drefreshes the staleapp-authoring/SKILL.mddigest left by baseline commit3a60a9928; the unchanged generator produced it, allowingbun run checkto pass.