Skip to content

feat(konnect): move Konnect projects into a global Control Planes organization [INS-3148] - #10315

Open
yaoweiprc wants to merge 1 commit into
developfrom
feat/migrate-konnect
Open

feat(konnect): move Konnect projects into a global Control Planes organization [INS-3148]#10315
yaoweiprc wants to merge 1 commit into
developfrom
feat/migrate-konnect

Conversation

@yaoweiprc

Copy link
Copy Markdown
Contributor

Problem

The Konnect PAT is stored once per account (Electron safeStorage, key konnectPat), but the projects it syncs were created with parentId: organizationId — so they belonged to whichever organization happened to be active. The same PAT could therefore be synced independently under several organizations, producing duplicated Konnect data with no single source of truth.

Solution

Konnect projects now live in a hardcoded, local-only organization org_konnect_<accountId>, displayed as Control Planes in the organization dropdown (same pattern as the existing Scratchpad organization). The account id is baked into the id because the NeDB database is not partitioned per user.

The Projects/Konnect tab split in the navigation sidebar is removed — the sidebar now switches its header controls (Sync button, gear, sync progress, sync result panel, intro card) based on the active organization instead of a persisted tab.

Feature flag

konnectSync is a per-organization feature flag, but the Konnect organization is account-wide, so it is now the OR across every organization the user belongs to. It is fetched concurrently once per app start via a new AsyncTask.SyncKonnectFeature and cached in localStorage with a 6h TTL. A failed lookup never downgrades a cached true, so the flag survives being offline.

The organization is visible when the flag is on, or when the account already has Konnect data from a previous version — in which case it stays reachable but the Sync button is disabled.

Migration

On startup, existing Konnect projects are re-parented onto the Konnect organization:

  • One source organization → migrated silently in the background.
  • Several source organizations → a modal asks the user to pick one; the others are deleted along with their workspaces, requests, environments and cookie jars.
  • Projects belonging to another account on the same machine → left untouched.

The migration is idempotent by predicate (no "already migrated" flag), so dismissing the modal simply re-prompts on the next start.

API guards

Roughly half of the organization-scoped API calls were never guarded for Scratchpad — Scratchpad gets away with it because its entry point is hidden. Control Planes is reachable from the dropdown, so each one now short-circuits on a shared isLocalOrganizationId predicate: features, storage rules, team projects, collaborators, collaborator search, check-seats, invitations, reinvites, member roles, git project count, real-time presence and the SSE stream.

HeaderPlanIndicator is deliberately kept — per docs/header-plan-indicator-data-scope.md everything it displays is account-scoped and fetched with sessionId only, so hiding it would just make billing info vanish for no reason.

Notable details

  • buildKonnectOrganization copies is_owner from the user's real organizations rather than hardcoding true; usePlanData derives isOwner from the organization list, and hardcoding it would show an enterprise member the wrong "upgrade yourself" CTA.
  • Dragging a collection workspace between two Konnect projects is now rejected. Konnect projects are local, so the existing canDrop logic (which only blocks cloud projects) allowed it — the workspace would keep a konnectServiceId under the wrong parent and the next sync would delete or duplicate it.
  • The Konnect sync trigger moved out of the sidebar into a small registry module, so KonnectSettingsModal no longer takes a ref prop and works regardless of what renders it.
  • The migration buffers the parentId rewrites but not the deletions: database.bufferChanges() is not re-entrant and db.remove() buffers and flushes internally, which defeats an outer buffer. This is documented in the plan; the pre-existing instance of the same pattern in the disconnect flow is left alone.

Drive-by fix

syncProjects issued fetchTeamProjects before checking whether the organization was local, so the Scratchpad guard never actually prevented the request. The guard now runs first.

Test plan

  • npm run type-check — clean
  • npm run lint — 0 errors
  • npm test — 2169 passing; the 6 failures are pre-existing on develop (verified via git stash)
  • New migrate-konnect-organization.test.ts — 10 cases covering auto / conflict / orphan-ignored / idempotency / cascade delete / timestamp carry-over
  • Smoke tests updated to enter Control Planes through the organization dropdown

Manual verification still to do (24 checks listed in the plan doc), most importantly: the DevTools Network audit inside Control Planes, the two-organization conflict flow, and confirming account B cannot see account A's data.

Docs

docs/konnect-control-planes-organization-plan.md records the design, the audit findings (unguarded API surface, non-re-entrant buffering, the two classes of ${accountId}:spaces readers), the decisions taken, and the list of scratchpad special-cases deliberately not extended — notably the organization dropdown itself, which must stay visible or the user would be trapped inside Control Planes.

Copilot AI review requested due to automatic review settings July 30, 2026 10:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes Konnect projects account-global by moving them under a dedicated local-only “Control Planes” organization (org_konnect_<accountId>), and removes the sidebar’s Projects/Konnect tab split in favor of organization-driven UI/behavior.

Changes:

  • Add a local-only Konnect organization model and widen “local organization” API guards to cover both Scratchpad and Control Planes.
  • Aggregate the konnectSync feature flag across all user organizations with caching + TTL, and surface Control Planes based on the aggregated flag or existing Konnect data.
  • Add an idempotent migration that re-parents Konnect projects to the Control Planes org (with a conflict-resolution modal) plus updated unit + smoke tests.

Reviewed changes

Copilot reviewed 40 out of 40 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/insomnia/src/ui/utils/router.ts Adds startup async task to sync the aggregated Konnect feature flag and restores last visited Control Planes org id.
packages/insomnia/src/ui/organization-utils.ts Implements aggregated konnectSync caching (TTL) and guards syncProjects against local-only orgs.
packages/insomnia/src/ui/hooks/use-organization-features.tsx Prevents org-scoped permission/feature loads for any local-only organization.
packages/insomnia/src/ui/hooks/konnect-sync-trigger.ts Adds a small registry to trigger Konnect sync without prop-drilling callbacks.
packages/insomnia/src/ui/context/app/insomnia-event-stream-context.tsx Guards real-time collaborator presence and SSE subscription for local-only orgs.
packages/insomnia/src/ui/components/sidebar/project-navigation-sidebar/use-sidebar-drag-and-drop.tsx Blocks dragging collection workspaces across Konnect projects to avoid orphaned Konnect keys.
packages/insomnia/src/ui/components/sidebar/project-navigation-sidebar/use-project-navigation-sidebar-navigation.ts Removes tab-driven navigation logic; navigation is now organization-driven.
packages/insomnia/src/ui/components/sidebar/project-navigation-sidebar/project-navigation-sidebar.tsx Removes Projects/Konnect tabs and switches sidebar controls based on whether org is Control Planes.
packages/insomnia/src/ui/components/settings/import-export.tsx Avoids feature/workspace fetches for local-only orgs.
packages/insomnia/src/ui/components/project/organization-select.tsx Renders Kong logo for Control Planes in the org dropdown and selected value.
packages/insomnia/src/ui/components/modals/request-settings-modal.tsx Avoids fetching org workspaces for local-only orgs.
packages/insomnia/src/ui/components/modals/konnect-settings-modal.tsx Uses the new sync-trigger registry instead of a ref passed from the sidebar.
packages/insomnia/src/ui/components/modals/konnect-org-migration-modal.tsx Adds conflict-resolution modal for choosing which org’s Konnect data to keep.
packages/insomnia/src/ui/components/header-invite-button.tsx Skips org-permissions request for local-only orgs.
packages/insomnia/src/ui/components/dropdowns/git-project-sync-dropdown.tsx Avoids storage-rule loads for local-only orgs.
packages/insomnia/src/routes/untracked-projects.tsx Treats Control Planes org id as “tracked” to avoid false untracked banners.
packages/insomnia/src/routes/organization.tsx Injects Control Planes into the org list, hides collaboration UI for local orgs, and mounts the migration modal.
packages/insomnia/src/routes/organization.sync-organizations-and-projects.tsx Chains org sync → aggregated Konnect feature sync, and triggers Konnect migration after project migration.
packages/insomnia/src/routes/organization.$organizationId.project.new.tsx Guards org-scoped reporting and disallows non-local storage types in local-only orgs.
packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.spec.tsx Updates storage-rule fetch guard to local-only org predicate.
packages/insomnia/src/routes/organization.$organizationId.project.$projectId.update.tsx Disallows non-local storage types in local-only orgs.
packages/insomnia/src/routes/organization.$organizationId.project.$projectId.tsx Removes sidebar-tab state and switches outlet context to isKonnectOrganization.
packages/insomnia/src/routes/organization.$organizationId.project.$projectId._index.tsx Uses isKonnectOrganization to gate first-request creation UI and guards storage rules fetch.
packages/insomnia/src/routes/organization.$organizationId.project._index.tsx Guards storage-rule loads for local-only orgs.
packages/insomnia/src/routes/organization.$organizationId.permissions.tsx Short-circuits feature/billing loads for local-only orgs and merges konnectSync into cache.
packages/insomnia/src/routes/organization.$organizationId.members.$userId.roles.tsx Guards member-role mutation for local-only orgs.
packages/insomnia/src/routes/organization.$organizationId.collaborators.tsx Returns empty collaborator results for local-only orgs.
packages/insomnia/src/routes/organization.$organizationId.collaborators.invites.$invitationId.tsx Guards invitation-role mutation for local-only orgs.
packages/insomnia/src/routes/organization.$organizationId.collaborators.invites.$invitationId.reinvite.tsx Guards reinvite action for local-only orgs.
packages/insomnia/src/routes/organization.$organizationId.collaborators-search.tsx Returns empty collaborator search results for local-only orgs.
packages/insomnia/src/routes/organization.$organizationId.collaborators-check-seats.tsx Guards seat-check calls for local-only orgs.
packages/insomnia/src/routes/organization._index.tsx Ensures aggregated Konnect feature sync + migration run in the login redirect path.
packages/insomnia/src/routes/git-credentials.$id.related-projects.tsx Treats Control Planes org id as “owned” to avoid cross-account leakage in related projects.
packages/insomnia/src/konnect/migrate-konnect-organization.ts Adds detection and execution of Konnect project migration into Control Planes.
packages/insomnia/src/konnect/tests/migrate-konnect-organization.test.ts Adds unit tests covering auto/conflict/orphan-ignore/idempotency and cascading delete expectations.
packages/insomnia/src/common/organization-storage-rules.ts Uses local-only organization predicate to force local-only storage rules.
packages/insomnia-smoke-test/tests/smoke/konnect.test.ts Updates smoke tests to enter Konnect via org dropdown and validate hiding when flag disabled.
packages/insomnia-smoke-test/playwright/pages/components/navigation-sidebar.ts Updates test page object from “tabs” to organization selection helpers.
packages/insomnia-data/src/models/organization.ts Adds Konnect org constants/helpers and the unified isLocalOrganizationId predicate.
docs/konnect-control-planes-organization-plan.md Adds design/plan doc describing the approach, risks, and verification checklist.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +102 to +105
const organizations = JSON.parse(localStorage.getItem(`${accountId}:spaces`) || '[]') as Organization[];
if (organizations.length === 0) {
return;
}
Comment on lines +73 to +74
const parsed = JSON.parse(raw) as KonnectSyncEnabledCache;
return typeof parsed?.enabled === 'boolean' ? parsed : null;
};
syncKonnectProjectsAndNotifyRef.current = syncKonnectProjectsAndNotify;

registerKonnectSyncTrigger(syncKonnectProjectsAndNotify);
Comment on lines +33 to +36
<ModalOverlay
isOpen
className="fixed top-0 left-0 z-10 flex h-(--visual-viewport-height) w-full items-center justify-center bg-black/30"
>
@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown

✅ Circular References Report

Generated at: 2026-08-06T10:15:54.582Z
Status: ✅ NO CHANGE

Summary

Metric Base (develop) PR Change
Total Circular References 9 9 0 (0.00%)
Click to view all circular references in PR (9)
insomnia-inso/src/db/models/types.ts -> insomnia-inso/src/db/types.ts
insomnia/src/main/prompt-bridge.ts -> insomnia/src/main/window-utils.ts -> insomnia/src/main/plugin-window.ts
insomnia/src/main/window-utils.ts -> insomnia/src/main/plugin-window.ts
insomnia/src/network/network.ts -> insomnia-scripting-environment/src/objects/index.ts -> insomnia-scripting-environment/src/objects/collection.ts -> insomnia-scripting-environment/src/objects/response.ts
insomnia/src/network/network.ts -> insomnia/src/common/render.ts
insomnia/src/ui/components/settings/import-export.tsx -> insomnia/src/ui/components/modals/export-requests-modal.tsx
insomnia/src/ui/components/tabs/tab-list.tsx -> insomnia/src/ui/components/tabs/tab.tsx
insomnia/src/ui/components/templating/tag-editor-arg-sub-form.tsx -> insomnia/src/ui/components/templating/external-vault/external-vault-form.tsx
insomnia/src/ui/components/viewers/response-viewer.tsx -> insomnia/src/ui/components/viewers/response-multipart-viewer.tsx
Click to view all circular references in base branch (9)
insomnia-inso/src/db/models/types.ts -> insomnia-inso/src/db/types.ts
insomnia/src/main/prompt-bridge.ts -> insomnia/src/main/window-utils.ts -> insomnia/src/main/plugin-window.ts
insomnia/src/main/window-utils.ts -> insomnia/src/main/plugin-window.ts
insomnia/src/network/network.ts -> insomnia-scripting-environment/src/objects/index.ts -> insomnia-scripting-environment/src/objects/collection.ts -> insomnia-scripting-environment/src/objects/response.ts
insomnia/src/network/network.ts -> insomnia/src/common/render.ts
insomnia/src/ui/components/settings/import-export.tsx -> insomnia/src/ui/components/modals/export-requests-modal.tsx
insomnia/src/ui/components/tabs/tab-list.tsx -> insomnia/src/ui/components/tabs/tab.tsx
insomnia/src/ui/components/templating/tag-editor-arg-sub-form.tsx -> insomnia/src/ui/components/templating/external-vault/external-vault-form.tsx
insomnia/src/ui/components/viewers/response-viewer.tsx -> insomnia/src/ui/components/viewers/response-multipart-viewer.tsx

Analysis

No Change: This PR does not introduce or remove any circular references.


This report was generated automatically by comparing against the develop branch.

@yaoweiprc yaoweiprc changed the title feat(konnect): move Konnect projects into a global Control Planes organization feat(konnect): move Konnect projects into a global Control Planes organization [INS-3148] Jul 30, 2026
…anization

Konnect projects move from `parentId: <real org>` to one account-wide,
local-only organization `org_konnect_<accountId>` ("Control Planes"), and the
Projects/Konnect tab split is removed from the project navigation sidebar.

- Add the fake organization helpers and the `isLocalOrganizationId` predicate
  every "skip all remote APIs" branch now uses.
- Aggregate the per-organization `konnectSync` flag into one account-wide,
  TTL-cached value and inject the fake organization from the layout loader.
- Guard the organization-scoped remote calls that were never guarded for
  Scratchpad: collaborators, invites, member roles, check-seats, presence, the
  SSE stream, and the team-project/git-project-count mutations.
- One-time migration in `entry.client.tsx` before hydration, with a modal for
  the ambiguous case where several organizations hold Konnect data.
- Hide project creation inside Control Planes, including the `NoProjectView`
  create form.

Design notes, audit findings and verification steps live in
docs/konnect-control-planes-organization-plan.md.

INS-3148
@yaoweiprc
yaoweiprc force-pushed the feat/migrate-konnect branch from 88c84ee to b623f1f Compare August 6, 2026 10:09
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.

2 participants