## Problem
When editing a project environment in Table View with no key/value entries, the trailing blank row could freeze the UI after renaming the environment in the header and immediately clicking the blank `Input Name` field.
The blank row was simultaneously managed by React Aria's `ListBox autoFocus="last"`, an imperative `ListBoxItem.onFocus` handoff, and `OneLineEditor` autofocus/retry logic. In the single-item boundary case these focus owners could race with `FocusScope` restoration and async environment revalidation.
## Fix
- Keep the trailing blank row inside the existing React Aria `ListBox` so row semantics, styling, keyboard navigation, drag-and-drop, and state behavior remain unchanged.
- Remove `ListBox autoFocus="last"` and the blank-row `ListBoxItem` focus handoff.
- Give the blank row's `OneLineEditor` one-shot autofocus on initial editor mount. This works for both empty and non-empty lists and is cleared after the initial autofocus.
- Track editor refs by distinct name/value editor ids.
- Restore focus once to the editor that was active when a blank row was converted into a persisted pair, after the persisted data update has mounted the new editor.
This prevents repeated focus stealing while preserving focus through the blank-row-to-persisted-row transition.
## Summary
- Splits the single "Manage Environments" popover into two independent dropdowns — project-level and collection-level — each with a scope tooltip and an inheritance-order hint (folder overrides collection, which overrides project).
- Replaces the hidden "+" menu in the collection environment editor and the project-level full-page environment editor with explicit, always-visible "Add Sub Environment" / "Add Private Sub Environment" buttons.
- Adds an "Add Project Environment" action to the project dropdown (does not auto-select the new environment).
- Adds a keyboard shortcut for the project dropdown (Cmd/Ctrl+Alt+E), alongside the existing collection-environment shortcut (Cmd/Ctrl+Shift+E).
- Fixes smoke tests broken by removing the old single-picker trigger, and adds new coverage for the split dropdowns and create flows.
[INS-2791](https://konghq.atlassian.net/browse/INS-2791)
## Summary
- Switching a request's project environment (activeGlobalEnvironment) left the request pane's template values stale, since its remount `key` only tracked the workspace environment (activeEnvironment).
- Added the project environment id/modified timestamp to the URL bar's remount key so it also refreshes on project environment switch.
## Background
- In the latest vite up gradation, the log is `VITE v7.3.1 ready in 1145 ms` instead of `VITE ready in`
- Playwright SIGKILLs the process by default, which leaves a stale .vite-port file
## Changes
- Update the wait pattern
- Use gracefulShutdown
- Always try to cleanup when receive any exit event
actions/checkout steps across CI workflows leaves GITHUB_TOKEN persisted in git config after checkout. None of these steps perform a git push using that persisted credential, disable credential persistence on the actions.
## Background
- Cloud Sync workspace uses local workspace id as its id, which may duplicate with the workspace id in the local db. (Clone a github repo -> convert to cloud sync -> clone it again)
## Changes
- Use team project id + project id as the unique id
* fix(main): compare full origin, not string prefix, for renderer nav guard (INS-3622)
Use isTrustedAppOrigin (parsed origin comparison) instead of
url.startsWith(appUrl) for will-navigate and will-redirect on the main
window.
* fix(main): restrict trusted-origin check to http/https schemes (INS-3622)
blob:/data: URLs report an origin derived from embedded text, not
actual creation context, so they could spoof isTrustedAppOrigin.
[INS-3637](https://konghq.atlassian.net/browse/INS-3637)
## Summary
- SSE ("Event Stream") sends re-fetched the raw, unrendered request from the database instead of using the already-rendered/de-duplicated/interpolated request the renderer had computed, so headers/authentication/body reaching curl could diverge from what the user configured.
- `openCurlConnection` now takes one fully-rendered request object (`{ workspaceId, renderedRequest, initialPayload? }`) instead of piecemeal fields, drops the redundant DB read, and computes the auth header in-process via `getAuthHeader` instead of a separate IPC round trip.
- Fixed `createConfiguredCurlInstance`'s manual-proxy branch, which resolved protocol/hostname from the raw stored URL instead of the request's actual URL.
- Added `curl.test.ts` and `libcurl-promise.test.ts`; patched shared test infra (`setup-vitest.ts`, `src/__mocks__/electron.ts`) so named imports from `electron` resolve under the mock and `electron.app.on(...)` doesn't throw.
## Test plan
- [x] `npx tsc --noEmit` clean on changed files
- [x] `npx eslint` clean on changed files
- [x] `npx vitest run` — full suite: 162 files / 2244 passed, 15 pre-existing skips
- [x] Manually verify an SSE request (e.g. POST with `Accept: text/event-stream` to a streaming API) sends the expected single Accept header and correct body/auth
[INS-3637]: https://konghq.atlassian.net/browse/INS-3637?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
* fix(cloud-sync): surface stale/reverted staged changes instead of silently committing them
status() diffed the working tree against HEAD only, so a key whose content
returned to HEAD while still staged (or was staged-then-deleted before ever
being committed) was invisible to both the staged and unstaged views —
takeSnapshot() would then commit the stale staged content unnoticed
(INS-3520).
- status() now diffs against the index (HEAD with the stage overlaid via a
new applyStageToState helper, also reused by takeSnapshot()) so these
cases surface as actionable unstaged entries, with explicit branches for
every stage/entry combination instead of a single blobId comparison that
was tautological for deletions.
- stage() drops an entry instead of storing it when the incoming content is
a no-op relative to HEAD, keeping the sparse stage map from accumulating
entries that would otherwise still show as staged and produce empty
commits.
- Removed the unused key field from status()'s return (and the Status
type), which was computed but never read anywhere.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Fix type check
* rm doc
---------
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* chore: support dynamic port
* fix: handle missing .vite-port and prevent stale file race
- window-utils.ts: wrap .vite-port read in try/catch with fallback to
default port 3334, preventing crash when file is missing
- esbuild.entrypoints.ts: delete .vite-port at start of dev build so
wait-on doesn't pick up a stale port from a previous run
* fix: derive smoke-test webServer port from per-worktree .vite-port
Hardcoded url: 'http://localhost:3334' made playwright's webServer
reuse-detection cross-worktree: if another worktree's dev server was
already answering on 3334, this worktree's tests silently reused it
instead of starting their own. Read the worktree's own .vite-port file
(written by vite.config.ts) instead, falling back to plain stdout-regex
readiness when no port file exists yet.
PR #10097 dropped h-fit from the Modal className as an unrelated
side effect of a class rewrite, leaving the modal stretched to the
overlay's full height with empty space below the content.
* fix(test): ensure scoped selection for storage type and improve click reliability in project creation
* fix(test): expand shard matrix for smoke tests and repeat each test for git-local-repos
* fix(test): adjust shard matrix for smoke tests to match total shards
* fix(test): update shard matrix for smoke tests to include additional runs
* fix(test): update smoke test sharding to improve parallel execution and reliability
* fix(test): update smoke test configuration for improved execution and reporting
* fix(test): update smoke test configuration to use sharding for improved execution
* fix(test): refactor git repository relocation tests to use dedicated method for moving repositories
Opening an existing local folder as a git project could leave an empty
[user] name/email in the repo's .git/config, which blocks git's fallback
to the machine's global identity and breaks `git commit` outside Insomnia.
- Pass repoPath into GitVCS.init() for openGitRepoAction so the "native"
credentials provider can actually read user.name/user.email via
`git config` in that directory instead of always resolving empty.
- setAuthor() now skips writing config when no author name/email can be
resolved, instead of writing empty user.name/user.email keys.
* fix(ui): re-render url bar templates on project environment switch
The request URL bar's remount key only tracked the workspace
environment (activeEnvironment), so switching the project
environment (activeGlobalEnvironment) left stale nunjucks tag
values in the URL bar. The URL preview was unaffected since it
re-renders on any loader revalidation and refetches the render
context fresh from the DB.
* fix(ui): re-render mcp url bar templates on project environment switch
Same issue as the request URL bar: the remount key only tracked
the workspace environment, so switching the project environment
left stale nunjucks tag values.