Files
insomnia/AGENTS.md
Jack Kavanagh 7cd8854f24 feat: lift network.ts fs/path behind window.main.timeline IPC bridge (#9945)
* updated plan

* feat: lift network.ts fs/path use behind window.main.timeline IPC bridge

Removes `node:fs` and `node:path` from the renderer-reachable
`src/network/network.ts`. Three timeline-path constructions and two
`appendFile` calls are replaced with narrow `window.main.timeline.getPath`
(sync IPC) and `window.main.timeline.appendToFile` (async IPC) helpers
that live in main, where Node builtins belong.

Path validation in `appendToTimeline` mirrors `writeResponseBodyToFile`:
only paths inside the `responses/` directory ending in `.timeline` are
accepted, preventing a compromised renderer from writing arbitrary files.

Updates `config/renderer-node-import-baseline.json` to remove the two
`src/network/network.ts` entries — the baseline shrinks as intended.

Part of the nodeIntegration: false migration (PR B).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: address Aikido path-traversal feedback and mock window.main in network tests

- `getTimelinePath`: use `path.resolve` + `path.relative` check instead of
  `path.join` to prevent path-traversal attacks (Aikido medium severity finding)
- `network.test.ts`: add `vi.stubGlobal('window', ...)` mock for
  `window.main.timeline` so tests don't throw "window is not defined" now
  that `defaultSendActionRuntime` calls `window.main.timeline.appendToFile`

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: suppress echoServer stdout in playwright config

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: update insomnia-inso logger for consola v3 compatibility

FancyReporter and BasicReporter were removed in consola v3; LogLevel became
a type-only export and the runtime enum is now LogLevels. Replace with
createConsola + a local BasicReporter shim, and import LogLevels in cli.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: address timeline IPC review concerns

- Convert timeline.getPath from sendSync to invoke (async) to avoid
  blocking the renderer thread; path construction has no I/O
- Extract getResponsesDir() shared helper so both getTimelinePath and
  appendToTimeline read the same source of truth, eliminating env-drift
  between the two calls
- Guard mkdir with a Set so the responses directory is only created once
  per process rather than on every appendFile call

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: upgrade consola to v3 and fix type/import issues in insomnia-inso

- Bump consola from ^2.15.3 to ^3.4.2 to match logger.ts which already used v3 API (createConsola)
- Fix logType → LogType (renamed in v3)
- Remove fancy option (removed in v3 ConsolaOptions)
- Use ConsolaInstance instead of Consola in result-report.ts so .log() resolves correctly
- Fix import sort in cli.ts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: restore Node.js-safe fallbacks in network.ts for inso CLI

The timeline IPC bridge introduced window.main.timeline calls without
guarding against the inso CLI context where window is not defined.
The electron shim (aliased in the inso bundle) provides app.getPath
as a fallback, matching the pre-bridge behaviour.

- getTimelinePath: check typeof window before using IPC; fall back to
  the electron shim path (os.tmpdir()/insomnia-send-request/responses)
- defaultSendActionRuntime.appendTimeline: fall back to fs.promises.appendFile
- tryToExecutePreRequestScript catch block: skip IPC appendToFile in
  Node.js context

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: sort node: imports before third-party and replace if/else with ternary in network.ts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: replace static fs/path imports with inline require() to pass renderer baseline check

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: replace process.type branching in network.ts with build-time adapter modules

Eliminates all runtime process.type and typeof window checks by introducing
network-adapter.renderer.ts and network-adapter.node.ts. Vite and Vitest resolve
the import to the renderer adapter; inso esbuild resolves to the node adapter.
No branching code remains in network.ts itself.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: restore object alias format in vite.config.ts to fix rollup build

Array-form alias with find:'~' was not matching prefix imports like
~/common/insomnia-fetch in the react-router production build. Object
form behaves correctly in Vite 7.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: resolve merge conflicts in logger.ts and cli.ts, restore AGENTS.md indented tree

- logger.ts: keep LogType (consola v3 casing), drop duplicate conflict markers
- cli.ts: remove stashed duplicate LogLevels import from conflict block
- AGENTS.md: restore indented hierarchy in Repository Structure and Data Model sections

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* remove cx

* fix: add path traversal guard to getTimelinePath in node adapter

Mirrors the same defence-in-depth check already present in the IPC handler.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix tests which use network from main

* flake

* refactor: replace bundler aliases with process.type runtime detection in network-adapter

Instead of three separate bundler aliases (Vite, esbuild main, esbuild inso),
network-adapter.ts now selects the correct adapter at runtime using
process.type === 'renderer'.

- Vite prod: process.type is already inlined as 'renderer' via define, so
  Rollup tree-shakes the node branch
- esbuild main: define process.type='browser' so esbuild tree-shakes renderer branch
- esbuild inso: define process.type=undefined so esbuild tree-shakes renderer branch
- Vitest (insomnia): existing renderer alias kept for test environment
- Vitest (inso): add renderer alias to match pre-existing test behaviour and
  avoid loading native node-libcurl module in tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: restore vite alias for network-adapter to fix server bundle build

The react-router build produces both client and server bundles. Without
the alias, the server bundle encountered a runtime require() for
'./network-adapter.renderer' that couldn't resolve (Vite inlines
process.type='renderer' via define for the server build too, so Rollup
tree-shakes to the renderer branch, but the module gets externalized in
the server bundle rather than inlined, leaving a broken runtime require).

Restoring the alias ensures both builds inline network-adapter.renderer
directly, which is safe because the module only defines functions —
window.main is never called at module init time.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feedback

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 09:44:48 +00:00

5.2 KiB

AGENTS.md

Tech Stack

  • UI: React with React Router (loaders/actions pattern)
  • Components: React Aria Components
  • Desktop Shell: Electron (main + renderer processes)
  • Styling: TailwindCSS
  • Language: TypeScript
  • Database: NeDB (@seald-io/nedb) — embedded NoSQL
  • Build/Dev: Vite, npm workspaces monorepo

See package.json for current versions and .nvmrc for the Node version.

Strict Rules

  • No unsolicited formatting. Rely on ESLint/Prettier. Do not reformat existing code.
  • Strict scoping. Only modify code directly related to the prompt. Do not refactor adjacent code unless asked.

Command Output

Prefer quiet command variants to minimise output volume:

  • git log --oneline -20 not git log
  • git diff --stat not git diff
  • npm test --silent not npm test
  • tsc --noEmit 2>&1 | head -50 for type-check failures
  • Use the Read tool with limit rather than cat on large files
  • Use Grep with head_limit rather than unrestricted searches

Validation Commands

Run from repo root before considering work complete:

npm run lint          # ESLint all workspaces
npm run type-check    # TypeScript check all workspaces
npm test              # Tests all workspaces (or: npm test -w packages/insomnia)

Worktree Setup

  • New git worktrees may not have node_modules yet. Before installing or validating, switch to the repo's required runtime from the worktree root:
fnm use "$(cat .nvmrc)"
node -v
npm -v
  • This repo expects the .nvmrc Node version and npm 11+. If fnm is unavailable, manually use an equivalent Node/npm version before running any npm commands.
  • After switching versions in a fresh worktree, install dependencies from repo root with npm ci.
  • Do not use npm ci --ignore-scripts for normal worktree setup. It leaves Electron partially installed, which later breaks builds, renderer import checks, and other validation commands.

Repository Structure

packages/ insomnia/ ← Main Electron app src/ common/ ← Shared utils, settings types models/ ← Data model definitions insomnia-data/ ← Model defaults, init(), NeDB db implementation, business logic routes/ ← React Router files (clientLoader/clientAction) ui/ ← React components, hooks, insomnia-fetch.ts main/ ← Electron IPC handlers, preload.ts account/ ← Auth, session, encryption sync/ ← Git/VCS sync network/ ← Request execution engine templating/ ← Nunjucks rendering (Web Worker) insomnia-api/ ← Cloud API client insomnia-inso/ ← CLI tool insomnia-testing/ ← Test framework

Data Model Hierarchy

Organization → Project (local | remote/cloud | git-backed) → Workspace (scope: 'collection' | 'design') → Base Environment (auto-created: use models.environment.getOrCreateForParentId(workspaceId)) → Sub-Environments → Cookie Jar (auto-created) → Request Group (folders) → Request (HTTP, GraphQL, gRPC, WebSocket, Socket.IO) → Request (can be direct child of workspace) Note: A Workspace with scope: 'collection' IS the collection.

Key Patterns

  • Route-Based Actions: Mutations use React Router's clientAction (src/routes/).
    • CRITICAL: clientAction blocks navigation. For long-running UI operations, use plain async functions instead.
  • Database Buffering: Always buffer bulk writes (database.bufferChangesIndefinitely(), then flushChanges()). Unbuffered writes fire UI revalidation per operation, causing severe lag.
  • State Management: Use Router loaders/actions and NeDB for persistent state. Use React useState/context for ephemeral UI state (No Redux/Zustand).
  • Electron IPC: For main↔renderer communication, define handlers in src/main/ipc/, expose in src/main/preload.ts, and update window.main in src/global.d.ts.
  • Templates: Nunjucks runs in a Web Worker (src/templating/). Use {{ _.variable_name }}.
  • Models: Follow CRUD via models.<type> (e.g., create(), update()).
  • HTTP Calls: Use insomniaFetch() for Insomnia backend APIs. Use plain fetch() for external/third-party APIs.
  • Styling: Tailwind utility classes only. Use clsx/tailwind-merge for conditionals. Use React Aria for interactive HTML elements.
  • Testing: Use Vitest (unit) and Playwright (E2E). Co-locate unit tests as filename.test.ts. Use vi.mock(). Prefer testing logic via loaders over mounting components.
  • E2E tests live in packages/insomnia-smoke-test/. Full docs: packages/insomnia-smoke-test/README.md.
  • Run E2E from repo root: npm run test:smoke:dev (filter: npm run test:smoke:dev -- <title-substring>).
  • New test imports: import { test } from '../../playwright/test' and import { expect } from '@playwright/test'.

Sensitive Data

  • Vault system (AES-GCM): For environment secrets (EnvironmentKvPairDataType.SECRET).
  • Electron safeStorage: Platform-native encryption (window.main.secretStorage).