| Dimension | Shared | Only in A | Only in B | Overlap |
|---|---|---|---|---|
| Sections | 0 | 10 | 26 | 0% |
| Commands | 0 | 1 | 23 | 0% |
| Section tags | 3 | 0 | 9 | 25% |
What each file covers
Sections
0 shared · 10 only in A · 26 only in B- − Seed n8n instance
- − Quick start
- − Environment variables
- − What it creates
- − Two non-obvious architectural rules
- − Tunable knobs
- − Verifying a run
- − Re-running and cleanup
- − Adding new behaviour
- − Known limitations
- + AGENTS.md
- + Project Overview
- + General Guidelines
- + Agent Skills and Claude Code Plugin
- + Essential Commands
- + Fresh checkout / agent setup
- + Building
- + Testing
- + Code Quality
- + Architecture Overview
- + Package Structure
- + Technology Stack
- + Key Architectural Patterns
- + Key Development Patterns
- + Workflow Traversal Utilities
- + TypeScript Best Practices
- + Error Handling
- + Persistence layer & the TypeORM boundary
- + Frontend Development
- + Testing Guidelines
- + Common Development Tasks
- + Design Principles
- + Security Must Not Degrade the Building Experience
- + Security Fix Hygiene
- + Customer Confidentiality
- + Github Guidelines
Commands
0 shared · 1 only in A · 23 only in B- − node scripts/instance-seeding/seedInstance.mjs
- + pnpm agent:setup
- + pnpm agent:setup install
- + pnpm agent:setup --json
- + pnpm build > build.log 2>&1
- + pnpm --filter @n8n/telemetry catalog
- + pnpm build
- + pnpm reset
- + pnpm reset --full
- + pnpm test
- + pnpm test:affected
- + pnpm test <test-file>
- + pnpm lint
- + pnpm typecheck
- + node-dev
- + pnpm dev:ai
- + eslint-disable
- + vitest
- + pnpm --filter=n8n-playwright test:local
- + pnpm dev
- + pnpm --filter n8n-containers services --services postgres,redis,mailpit,proxy
- + node-1234-improve-request-handling
- + node-1234-fix-ddos-vulnerability
- + gh pr create --draft
Section tags
3 shared · 0 only in A · 9 only in B- + build
- + test
- + lint-format
- + architecture
- + types
- + testing-strategy
- + git-pr
- + security
- + agent-behaviour
- setup
- code-style
- do-not
Line diff
n8n-io/n8n · scripts/instance-seeding/AGENTS.md
@@ −1 @@
1# Seed n8n instance
2
3`seedInstance.mjs` fills a local n8n instance with a realistic-looking spread of
4projects, workflows, credentials, and data tables via the **public API**. The
5resulting dependency graph is designed to render like a real org's automation
6estate: dense intra-team clusters, sparse cross-team bridges through shared
7utility projects, a few legacy "trenchcoat" projects sitting off to the side,
8and one central data table that everything reaches through a proxy workflow.
9
10Useful for demos, perf testing, visual QA of the workflow dependency graph, and
11poking at the workflow-index module with non-trivial input.
12
13## Quick start
14
15```sh
16N8N_API_KEY="<a public-api JWT for an owner/admin>" \
17 node scripts/instance-seeding/seedInstance.mjs
18```
19
20Targets `http://localhost:5678` by default. The script is **destructive by
21default**: it deletes its own prior output (anything tagged `[seed]`) and any
22team projects whose names match the current taxonomy plus orphans from older
23runs. Personal-project entities that don't match the seed prefix are left
24alone, as are the n8n-default `My project` team projects.
25
26### Environment variables
27
28| Var | Default | Purpose |
29| --- | --- | --- |
30| `N8N_API_KEY` | (required) | Public-API JWT. Must have owner or admin scopes. |
31| `N8N_BASE_URL` | `http://localhost:5678` | n8n instance to seed. |
32| `CLEAR` | `false` | Set to `true` to wipe data instead. |
33| `PERSONAL_WORKFLOWS` | `50` | Amount of workflows to create in the personal project. |
34
35Runtime is ~30–45 s for a default run (~500 workflows, ~30 projects).
36
37## What it creates
38
39**Projects** (30 team projects + your existing personal):
40
41- **2 utility projects** — `Shared Platform` (technical plumbing: Audit
42 Logger, Slack Alerts Dispatcher, Sentry Error Forwarder, …) and
43 `Org Utilities` (business helpers: Tenant Resolver, Vault Reader, Feature
44 Flag Resolver, …). These are the hub workflows the rest of the org calls
45 into.
46- **25 community projects** organised into 5 themed communities of 5 projects
47 each: Revenue, Customer, Engineering, Operations, Knowledge.
48- **3 trenchcoat projects** — Legacy Migrations, Skunkworks, Founder's
49 Workflows. Smaller, internally split into 2-3 disjoint sub-systems (e.g.
50 `[HR System]`, `[Old Billing]`, `[Acme Acquisition]`), and almost entirely
51 detached from the rest of the org. They model accreted legacy state.
52
53**Credentials** (~110):
54- Two per project max (random recipes: Notion, Slack, Postgres, GitHub, …).
55- Plus **5 global credentials** living in the utility projects (Production
56 Slack Webhook, Datadog API, GitHub platform bot, OpenAI production,
57 Vault read-only).
58
59**Data tables** (~15–20):
60- One per ~55% of projects, with 5–20 sample rows.
61- Plus one **central data table** `seed_customers` in `Org Utilities` that
62 the entire org reaches through a single proxy workflow.
63
64**Workflows** (~500), built in four phases:
65- **Phase 0** — Utility lynchpin workflows in `Shared Platform` and
66 `Org Utilities`, plus the Customers Proxy.
67- **Phase 1** — Leaf workflows in every project, no sub-calls.
68- **Phase 2** — Parent workflows with sub-workflow refs. Community projects
69 pick own/sibling/lynchpin; trenchcoats pick within their internal group.
70- **Phase 3** — Data-table consumer workflows (one per project DT).
71- **Phase 4** — Cross-project data-table proxies for ~6 non-utility DTs.
72
73## Two non-obvious architectural rules
74
751. **`DataTable` nodes can only point at tables in their own project.** Cross-
76 project access goes through a proxy workflow. The `customersProxy` in
77 `Org Utilities` is the only workflow with a direct `DataTable` node on
78 the central table; everyone else calls the proxy via `ExecuteWorkflow`.
79 Phase 4 generalises this pattern to ~6 other data tables.
80
812. **Per-project external-ref budgets.** Each community project is capped at
82 2–5 distinct external workflow refs and 5–10 external credential refs,
83 tracked across all phases. About a third of community projects opt out of
84 utility refs entirely (some of those go fully self-contained — no
85 external refs of any kind). Trenchcoats and utility projects are exempt.
86
87## Tunable knobs
88
89All knobs live at the top of `seedInstance.mjs`. The ones that change the
90shape of the graph the most:
91
92| Constant | Effect |
93| --- | --- |
94| `COMMUNITIES` | Project taxonomy. Add/remove communities or projects. |
95| `TRENCHCOAT_PROJECTS` + `TRENCHCOAT_GROUPS` | Legacy projects and their internal subsystems. |
96| `UTILITY_WORKFLOW_THEMES` | Lynchpin workflow names per utility project. |
97| `LYNCHPIN_CRED_RECIPES` | The 5 global credentials. |
98| `UTILITY_REF_PROB` (0.6) | Per-workflow probability of including a utility ref. |
99| `CENTRAL_DT_REF_PROB` (0.08) | Per-workflow probability of calling the Customers Proxy (indirect central-DT use). |
100| `ORG_UTIL_DIRECT_DT_PROB` (0.5) | Per-workflow probability that an Org Utilities phase-0 workflow gets a direct DataTable node on the central table. |
101| `EXT_WF_REF_BUDGET` / `EXT_CRED_REF_BUDGET` | Per-project distinct-ref caps. |
102| `NON_UTILITY_USING_TARGET` (9) | How many community projects opt out of utility refs. |
103| `SELF_CONTAINED_PROJECT_PROB` | Subset of the opt-out projects that go fully siloed. |
104| `sampleWorkflowCount()` | Power-law-ish size buckets per project kind. |
105
106`SUBWF_PROB_OWN`/`_SIBLING`/`_LYNCHPIN` (in `pickCommunitySubWf`) govern how
107parent workflows route sub-calls.
108
109## Verifying a run
110
111The dependency-graph endpoint is the canonical view of what the seed
112produced. It includes both the community structure and the central-DT proxy
113pattern:
114
115```sh
116curl -s "$N8N_BASE_URL/api/v1/workflows/dependency-graph?format=dot" \
117 -H "X-N8N-API-KEY: $N8N_API_KEY" | sfdp -Tsvg -Goverlap=prism > graph.svg
118```
119
120`sfdp`/`fdp` (Graphviz force-directed layouts) reveal the cluster topology
121better than the default hierarchical `dot` layout.
122
123Counts via API:
124
125```sh
126for path in workflows projects credentials data-tables; do
127 echo -n "$path: "
128 curl -s "$N8N_BASE_URL/api/v1/$path?limit=1" \
129 -H "X-N8N-API-KEY: $N8N_API_KEY" | jq -r '.data | length'
130done
131```
132
133Key numbers a default run should land near:
134- ~500 workflows, 30 team projects, ~110 credentials, ~15 data tables
135- ~45% of workflows reference a utility workflow
136- ~5–10% of workflows reach the central data table (2–4 direct refs from
137 workflows inside Org Utilities — Customers Proxy plus a few service
138 workflows like Region Router or Feature Flag Resolver — and the rest via
139 `ExecuteWorkflow` into the proxy)
140- 20 of 29 non-utility projects use utility workflows
141- 0 direct cross-project DataTable references (architectural invariant)
142
143## Re-running and cleanup
144
145The clear step is greedy: any workflow / credential / data-table with the
146`[seed]` (or `seed_` for data tables) prefix is deleted, plus any team
147project owning a `[seed]`-prefixed entity, plus any orphan team project from
148an earlier run that doesn't match the current `PROJECT_NAMES` list and is
149empty and not named `My project`.
150
151To remove all seeded data without reseeding:
152
153```sh
154N8N_API_KEY=… CLEAR=only node bin/seedInstance/seedInstance.mjs
155```
156
157
158## Adding new behaviour
159
160Adding a new shape of workflow usually means three places:
161
1621. A constant or recipe at the top of the file (theme name, cred type, …).
1632. A change inside `workflowNodes()` if it needs a new node type.
1643. A phase change (or new phase) inside `main()` that calls `createWf()`.
165
166`applyOrgUtilityRefs()` is the central hook for "every workflow should
167sometimes touch X". Phase 4 (`/* cross-project data-table proxies */`) is
168the template for "select a few entities, give each its own consumer
169fan-out".
170
171## Known limitations
172
173- Trenchcoat phase-3 (data-table consumer) workflows don't carry an internal
174 group label, so they show up as ungrouped within their trenchcoat project.
175 Minor visual artifact only.
176- The `[seed] X: [group] Y N` naming convention is what powers the
177 group-aware visualisation. Renaming a workflow externally severs the
178 link the analyser uses to group it.
179- No protection against running against a non-local instance. **Don't point
180 it at a shared/production n8n** — the clear step will delete everything
181 prefixed `[seed]` regardless of who created it.
182
n8n-io/n8n · AGENTS.md
@@ +1 @@
1# AGENTS.md
2
3This file provides guidance on how to work with the n8n repository.
4
5## Project Overview
6
7n8n is a workflow automation platform written in TypeScript, using a monorepo
8structure managed by pnpm workspaces. It consists of a Node.js backend, Vue.js
9frontend, and extensible node-based workflow engine.
10
11## General Guidelines
12
13- Always use pnpm
14- **Secrets on the command line:** if a developer opted into anonymous dev
15 metrics (`scripts/dev-metrics`), pnpm command arguments are recorded. Arguments
16 of secret-carrying words (`config`, `login`, `publish`, `token`) — whether a
17 subcommand or baked into a flag — are dropped, and the home dir is stripped from
18 paths, but other args are sent as-is — so never put secrets in a command. Pass
19 sensitive values via environment variables, which are never captured.
20- When adding comments, keep them concise and to the point - explain the "why"
21 in a line or two; don't be overly verbose. Comments should be scoped and
22 relevant to the surrounding code, not just to the current task
23- We use Linear as a ticket tracking system
24- We use Posthog for feature flags
25- To find registered telemetry events (names, descriptions, properties), run
26 `pnpm --filter @n8n/telemetry catalog` (`--json` for structured output). The
27 registry is being adopted incrementally, so search call sites if the catalog
28 has no match. The `n8n:telemetry` skill covers adding or changing events
29- When starting to work on a new ticket – create a new branch from fresh
30 master with the name specified in Linear ticket
31- When creating a new branch for a ticket in Linear - use the branch name
32 suggested by Linear, **unless it is a security fix** (see Security Fix
33 Hygiene below)
34- Use mermaid diagrams in MD files when you need to visualise something
35- **Developing v3 features:** land normal feature work on `master` behind an
36 opt-in flag; introduce breaking changes only on the `3.x` branch. See
37 [.github/DEVELOPING_V3.md](.github/DEVELOPING_V3.md).
38
39## Agent Skills and Claude Code Plugin
40
41n8n shared skills live in `.agents/skills/`. Claude Code consumes them through
42symlinks in `.claude/plugins/n8n/skills/`; OpenCode reads `.agents/skills/`
43directly. Harness-specific overrides remain real directories in the harness
44path, such as `.opencode/skills/setup-mcps/`. See
45[skills README](.agents/skills/AGENTS.md) for editing and sync guidance.
46
47n8n-specific Claude Code commands and agents live in `.claude/plugins/n8n/` and
48are namespaced under `n8n:`. Use `n8n:` prefix when invoking them (e.g.
49`/n8n:create-pr`, `/n8n:plan`, `n8n:developer` agent). See
50[plugin README](.claude/plugins/n8n/README.md) for structure and details.
51
52## Essential Commands
53
54### Fresh checkout / agent setup
55
56For a fresh checkout (cat-bot, a new hire, any agent verifying the repo
57builds), prefer `pnpm agent:setup` over running install + build + tests by
58hand. It chains them in one process, caps per-process memory and turbo
59concurrency so a 6GB box doesn't OOM, streams all output to
60`.agent-setup/<step>.log` (gitignored), and surfaces only a one-line summary
61per step plus the tail of the failing log. A machine-readable
62`.agent-setup/summary.json` is always written so a backgrounded run is
63readable in a single shot — no polling, no scrolling logs.
64
65```bash
66pnpm agent:setup # install → build → test (full suite)
67pnpm agent:setup install # one step at a time
68pnpm agent:setup --json # JSON summary on stdout (for scripts/agents)
69```
70
71### Building
72Use `pnpm build` to build all packages. ALWAYS redirect the output of the
73build command to a file:
74
75```bash
76pnpm build > build.log 2>&1
77```
78
79You can inspect the last few lines of the build log file to check for errors:
80```bash
81tail -n 20 build.log
82```
83
84If build outputs or the turbo cache are stale (e.g. after switching branches
85or worktrees) but dependencies haven't changed, use `pnpm reset` (lightweight
86by default) for a fast recovery: it cleans build outputs and force-rebuilds
87(keeping `node_modules` and untracked files). If that doesn't fix your issue,
88use `pnpm reset --full`, which also wipes untracked files and reinstalls
89dependencies.
90
91### Testing
92- `pnpm test` - Run all tests
93- `pnpm test:affected` - Runs tests based on what has changed since the last
94 commit
95
96Running a particular test file requires going to the directory of that test
97and running: `pnpm test <test-file>`.
98
99When changing directories, use `pushd` to navigate into the directory and
100`popd` to return to the previous directory. When in doubt, use `pwd` to check
101your current directory.
102
103### Code Quality
104- `pnpm lint` - Lint code
105- `pnpm typecheck` - Run type checks
106
107Always run lint and typecheck before committing code to ensure quality.
108Execute these commands from within the specific package directory you're
109working on (e.g., `cd packages/cli && pnpm lint`). Run the full repository
110check only when preparing the final PR. When your changes affect type
111definitions, interfaces in `@n8n/api-types`, or cross-package dependencies,
112build the system before running lint and typecheck.
113
114## Architecture Overview
115
116**Monorepo Structure:** pnpm workspaces with Turbo build orchestration
117
118### Package Structure
119
120The monorepo is organized into these key packages:
121
122- **`packages/@n8n/api-types`**: Shared TypeScript interfaces between frontend and backend
123- **`packages/workflow`**: Core workflow interfaces and types
124- **`packages/core`**: Workflow execution engine
125- **`packages/cli`**: Express server, REST API, and CLI commands
126- **`packages/frontend/editor-ui`**: Vue 3 frontend application
127- **`packages/frontend/@n8n/i18n`**: Internationalization for UI text
128- **`packages/nodes-base`**: Built-in nodes for integrations
129- **`packages/@n8n/nodes-langchain`**: AI/LangChain nodes
130- **`packages/@n8n/instance-ai`**: "AI Assistant" in the UI, "Instance AI" in code — AI assistant backend. See its `CLAUDE.md` for architecture docs.
131- **`@n8n/design-system`**: Vue component library for UI consistency
132- **`@n8n/config`**: Centralized configuration management
133
134## Technology Stack
135
136- **Frontend:** Vue 3 + TypeScript + Vite + Pinia + Storybook UI Library
137- **Backend:** Node.js + TypeScript + Express + TypeORM
138- **Testing:** Vitest (unit) + Playwright (E2E)
139- **Database:** TypeORM with SQLite/PostgreSQL support
140- **Code Quality:** Biome (for formatting) + ESLint + lefthook git hooks
141
142### Key Architectural Patterns
143
1441. **Dependency Injection**: Uses `@n8n/di` for IoC container
1452. **Controller-Service-Repository**: Backend follows MVC-like pattern
1463. **Event-Driven**: Internal event bus for decoupled communication
1474. **Context-Based Execution**: Different contexts for different node types
1485. **State Management**: Frontend uses Pinia stores
1496. **Design System**: Reusable components and design tokens are centralized in
150 `@n8n/design-system`, where all pure Vue components should be placed to
151 ensure consistency and reusability
152
153## Key Development Patterns
154
155- Each package has isolated build configuration and can be developed independently
156- Hot reload works across the full stack during development
157- Node development uses dedicated `node-dev` CLI tool
158- Workflow tests are JSON-based for integration testing
159- AI features have dedicated development workflow (`pnpm dev:ai`)
160
161### Workflow Traversal Utilities
162
163The `n8n-workflow` package exports graph traversal utilities from
164`packages/workflow/src/common/`. Use these instead of custom traversal logic.
165
166**Key concept:** `workflow.connections` is indexed by **source node**.
167To find parent nodes, use `mapConnectionsByDestination()` to invert it first.
168
169```typescript
170import { getParentNodes, getChildNodes, mapConnectionsByDestination } from 'n8n-workflow';
171
172// Finding parent nodes (predecessors) - requires inverted connections
173const connectionsByDestination = mapConnectionsByDestination(workflow.connections);
174const parents = getParentNodes(connectionsByDestination, 'NodeName', 'main', 1);
175
176// Finding child nodes (successors) - uses connections directly
177const children = getChildNodes(workflow.connections, 'NodeName', 'main', 1);
178```
179
180### TypeScript Best Practices
181- **NEVER use `any` type** - use proper types or `unknown`
182- **Avoid type casting with `as`** - use type guards or type predicates instead (except in test code where `as` is acceptable)
183- **Define shared interfaces in `@n8n/api-types`** package for FE/BE communication
184- **Lazy-load heavy modules** — if a module is only used in a specific code
185 path (not every request), use `await import()` at point of use instead of
186 top-level `import`. Applies especially to native modules and large parsers.
187
188### Error Handling
189- Don't use the deprecated `ApplicationError` class anywhere — it's a
190 compatibility shim kept only so community nodes keep resolving. Use one of
191 these instead, picking by cause:
192 - `UserError` — the user caused it (invalid input, unauthorized action,
193 business-rule violation).
194 - `OperationalError` — a transient, expected issue (network request failing,
195 DB query timing out) that should be handled gracefully.
196 - `UnexpectedError` — a bug in the code (logic mistake, unhandled case,
197 failed assertion) that developers need to fix.
198- Import from appropriate error classes in each package
199
200### Persistence layer & the TypeORM boundary
201
202TypeORM (`@n8n/typeorm`) must stay in the **persistence layer** — the `@n8n/db`
203package or a backend module's own `database/` folder (entity/repository files).
204Business logic — services, controllers, handlers, commands, factories — must not
205import from `@n8n/typeorm` (including `@n8n/typeorm/...` subpaths). In
206`packages/cli` this is enforced by the `misplaced-n8n-typeorm-import` lint rule;
207a new import (or an inline `eslint-disable` of the rule) fails CI.
208
209- **Pattern:** when a query needs operators (`In`, `IsNull`, `LessThan`,
210 `FindOptionsWhere`, …), put it behind a **use-case-named repository method**
211 that takes plain parameters and returns domain-shaped values — not a generic
212 `find(options)` passthrough.
213- **Transactions:** transaction orchestration belongs in the persistence layer.
214 Don't reach for `.manager` / `.manager.transaction(...)` or
215 `createQueryBuilder(...)` in business logic. Use the sanctioned primitive in
216 `@n8n/db`: inject the abstract `TransactionRunner` and wrap the unit of work in
217 `txRunner.run(ctx, async (ctx) => …)`. The callback receives an
218 `OperationContext` carrying the active transaction; thread that `ctx` into the
219 repository methods you call. `run` **requires** a context — pass an empty `{}`
220 at the operation entry point, and reuse the one you were handed everywhere
221 below it (a context that already carries a transaction is joined, not nested).
222 Repositories extend `BaseRepository` and resolve the right `EntityManager` with
223 `this.managerFor(ctx)`; the `Transaction` handle is opaque and never exposes a
224 driver type to business logic. See `oauth-token.service.ts` +
225 `oauth-*-token.repository.ts` for a worked example.
226- **Anti-patterns reviewers reject** — they hide the dependency instead of
227 removing it:
228 - String-matching TypeORM errors, e.g. `error.name === 'QueryFailedError'`.
229 - Relabeling the import from `@n8n/typeorm` to `@n8n/db` to silence the rule
230 (`@n8n/db` re-exports several operators/types, but this relabels the
231 dependency rather than removing it).
232 - Pushing `.manager` / `createQueryBuilder` into business logic to avoid an
233 operator import — trades a visible leak for an invisible one.
234
235### Frontend Development
236- Refer to `packages/frontend/AGENTS.md`
237- **All UI text must use i18n** - add translations to `@n8n/i18n` package
238- **Use CSS variables directly** - never hardcode spacing as px values
239- **data-testid must be a single value** (no spaces or multiple values)
240- Always use `design-system-rules` skill in reviews
241
242### Testing Guidelines
243- **Always work from within the package directory** when running tests
244- **Mock all external dependencies** in unit tests
245- **Prefer reusing hoisted shared `mock<T>(...)` fixtures** when a typed mock is immutable and used across tests. This rule exists to avoid massive test slowdowns from repeatedly creating nested proxy mocks while preserving the type contract. Avoid replacing these with `as unknown as T` helpers for entities like `User`.
246- **Confirm test cases with user** before writing unit tests
247- **Typecheck is critical before committing** - always run `pnpm typecheck`
248- **When modifying pinia stores**, check for unused computed properties
249- **For Vitest packages that use `@n8n/di` decorators**, use `createVitestConfigWithDecorators` from `@n8n/vitest-config/node-decorators`. It enables SWC `decoratorMetadata` (esbuild doesn't emit it) and externalizes workspace packages that register services (`@n8n/di`, `@n8n/config`, `@n8n/constants`, `n8n-workflow`) so a single DI `Container` instance is shared across the runtime. Loading them through Vitest's pipeline alongside their CJS dist produces two `Container`s and `Container.get(...)` returns `undefined`.
250
251What we use for testing and writing tests:
252- For testing nodes and other backend components, we use Vitest for unit tests. Examples can be found in `packages/nodes-base/nodes/**/*test*`.
253- We use `nock` for server mocking
254- For frontend we use `vitest`
255- For E2E tests we use Playwright. Run with `pnpm --filter=n8n-playwright test:local`.
256 See `packages/testing/playwright/README.md` for details.
257- **To iterate on a feature without docker rebuilds**, boot service containers
258 and run `pnpm dev` locally — `pnpm --filter n8n-containers services --services postgres,redis,mailpit,proxy`
259 then `pnpm dev`. See [Develop against running containers](packages/testing/playwright/README.md#develop-against-running-containers-avoid-docker-rebuilds).
260- **For Playwright test maintenance/cleanup**, see `packages/testing/playwright/AGENTS.md` (includes janitor tool for static analysis, dead code removal, architecture enforcement, and TCR workflows).
261
262### Common Development Tasks
263
264When implementing features:
2651. Define API types in `packages/@n8n/api-types`
2662. Implement backend logic in `packages/cli` module, follow
267 `scripts/backend-module/backend-module-guide.md`
2683. Add API endpoints via controllers
2694. Update frontend in `packages/frontend/editor-ui` with i18n support
2705. Write tests with proper mocks
2716. Run `pnpm typecheck` to verify types
272
273## Design Principles
274
275### Security Must Not Degrade the Building Experience
276
277Security improvements, whether driven by enterprise requirements or internal
278standards, must NEVER add friction to the common-case building experience. When
279designing security-related features (defaults, behaviors, flows, error
280handling), apply these checks:
281
282- **No friction for the common case:** A community builder's workflow should
283 remain intuitive. Security should be invisible when it can be.
284- **Migration and upgrade paths:** Existing users must have a clear,
285 non-disruptive path forward when defaults or behaviors change.
286- **Security layers on top, not in competition:** Great UX and strong security
287 are not trade-offs. They're both required. If a design forces a choice
288 between them, the design needs more work.
289
290### Security Fix Hygiene
291
292**This is a public repository.** When working on security fixes, never expose
293the attack vector or vulnerability type in any public-facing artifact. Attackers
294monitor open-source repos for signals like branch names, commit messages, PR
295titles, test descriptions, and Linear URLs.
296
297**Rules for security fixes:**
298
299- **Branch names:** Do NOT use the Linear-suggested branch name if it reveals
300 the vulnerability. Rename to describe the fix neutrally
301 (e.g. `node-1234-improve-request-handling`, not
302 `node-1234-fix-ddos-vulnerability`).
303- **Commit messages:** Describe what the code now does, not the threat it
304 prevents (e.g. `fix: add payload size validation`, not
305 `fix: prevent denial of service`).
306- **Test descriptions:** Use neutral, functional language
307 (e.g. `'should sanitize query parameters'`, not
308 `'should prevent SQL injection'`).
309- **Code comments:** Do not describe the attack scenario in comments.
310- **Linear references:** Never include the URL slug
311 (e.g. `.../N8N-1234/fix-ssrf-vulnerability`).
312
313### Customer Confidentiality
314
315**This is a public repository.** Never mention customer names in any
316public-facing artifact — not all customers have agreed to be named publicly,
317and naming them can reveal security-relevant details about their setup.
318
319This applies to PR titles and descriptions, branch names, commit messages,
320code, code comments, test names and test data, and fixtures. When implementing
321a customer request, describe the use case neutrally (e.g. "a customer with a
322large multi-main setup", not the company name) and use generic placeholder
323names (e.g. `Acme Corp`) in tests and examples.
324
325## Github Guidelines
326- When creating a PR, use the conventions in
327 `.github/pull_request_template.md` and
328 `.github/pull_request_title_conventions.md`.
329- Use `gh pr create --draft` to create draft PRs.
330- If there is a corresponding Linear ticket, reference it in the PR
331 description using `https://linear.app/n8n/issue/[TICKET-ID]`. Do not
332 create a Linear ticket on your own — ask first.
333- always link to the github issue if mentioned in the linear ticket.
334
@@ −1 +1 @@
1−# Seed n8n instance
1+# AGENTS.md
22
3−`seedInstance.mjs` fills a local n8n instance with a realistic-looking spread of
4−projects, workflows, credentials, and data tables via the **public API**. The
5−resulting dependency graph is designed to render like a real org's automation
6−estate: dense intra-team clusters, sparse cross-team bridges through shared
7−utility projects, a few legacy "trenchcoat" projects sitting off to the side,
8−and one central data table that everything reaches through a proxy workflow.
3+This file provides guidance on how to work with the n8n repository.
94
10−Useful for demos, perf testing, visual QA of the workflow dependency graph, and
11−poking at the workflow-index module with non-trivial input.
5+## Project Overview
126
13−## Quick start
7+n8n is a workflow automation platform written in TypeScript, using a monorepo
8+structure managed by pnpm workspaces. It consists of a Node.js backend, Vue.js
9+frontend, and extensible node-based workflow engine.
1410
15−```sh
16−N8N_API_KEY="<a public-api JWT for an owner/admin>" \
17− node scripts/instance-seeding/seedInstance.mjs
11+## General Guidelines
12+
13+- Always use pnpm
14+- **Secrets on the command line:** if a developer opted into anonymous dev
15+ metrics (`scripts/dev-metrics`), pnpm command arguments are recorded. Arguments
16+ of secret-carrying words (`config`, `login`, `publish`, `token`) — whether a
17+ subcommand or baked into a flag — are dropped, and the home dir is stripped from
18+ paths, but other args are sent as-is — so never put secrets in a command. Pass
19+ sensitive values via environment variables, which are never captured.
20+- When adding comments, keep them concise and to the point - explain the "why"
21+ in a line or two; don't be overly verbose. Comments should be scoped and
22+ relevant to the surrounding code, not just to the current task
23+- We use Linear as a ticket tracking system
24+- We use Posthog for feature flags
25+- To find registered telemetry events (names, descriptions, properties), run
26+ `pnpm --filter @n8n/telemetry catalog` (`--json` for structured output). The
27+ registry is being adopted incrementally, so search call sites if the catalog
28+ has no match. The `n8n:telemetry` skill covers adding or changing events
29+- When starting to work on a new ticket – create a new branch from fresh
30+ master with the name specified in Linear ticket
31+- When creating a new branch for a ticket in Linear - use the branch name
32+ suggested by Linear, **unless it is a security fix** (see Security Fix
33+ Hygiene below)
34+- Use mermaid diagrams in MD files when you need to visualise something
35+- **Developing v3 features:** land normal feature work on `master` behind an
36+ opt-in flag; introduce breaking changes only on the `3.x` branch. See
37+ [.github/DEVELOPING_V3.md](.github/DEVELOPING_V3.md).
38+
39+## Agent Skills and Claude Code Plugin
40+
41+n8n shared skills live in `.agents/skills/`. Claude Code consumes them through
42+symlinks in `.claude/plugins/n8n/skills/`; OpenCode reads `.agents/skills/`
43+directly. Harness-specific overrides remain real directories in the harness
44+path, such as `.opencode/skills/setup-mcps/`. See
45+[skills README](.agents/skills/AGENTS.md) for editing and sync guidance.
46+
47+n8n-specific Claude Code commands and agents live in `.claude/plugins/n8n/` and
48+are namespaced under `n8n:`. Use `n8n:` prefix when invoking them (e.g.
49+`/n8n:create-pr`, `/n8n:plan`, `n8n:developer` agent). See
50+[plugin README](.claude/plugins/n8n/README.md) for structure and details.
51+
52+## Essential Commands
53+
54+### Fresh checkout / agent setup
55+
56+For a fresh checkout (cat-bot, a new hire, any agent verifying the repo
57+builds), prefer `pnpm agent:setup` over running install + build + tests by
58+hand. It chains them in one process, caps per-process memory and turbo
59+concurrency so a 6GB box doesn't OOM, streams all output to
60+`.agent-setup/<step>.log` (gitignored), and surfaces only a one-line summary
61+per step plus the tail of the failing log. A machine-readable
62+`.agent-setup/summary.json` is always written so a backgrounded run is
63+readable in a single shot — no polling, no scrolling logs.
64+
65+```bash
66+pnpm agent:setup # install → build → test (full suite)
67+pnpm agent:setup install # one step at a time
68+pnpm agent:setup --json # JSON summary on stdout (for scripts/agents)
1869 ```
1970
20−Targets `http://localhost:5678` by default. The script is **destructive by
21−default**: it deletes its own prior output (anything tagged `[seed]`) and any
22−team projects whose names match the current taxonomy plus orphans from older
23−runs. Personal-project entities that don't match the seed prefix are left
24−alone, as are the n8n-default `My project` team projects.
71+### Building
72+Use `pnpm build` to build all packages. ALWAYS redirect the output of the
73+build command to a file:
2574
26−### Environment variables
75+```bash
76+pnpm build > build.log 2>&1
77+```
2778
28−| Var | Default | Purpose |
29−| --- | --- | --- |
30−| `N8N_API_KEY` | (required) | Public-API JWT. Must have owner or admin scopes. |
31−| `N8N_BASE_URL` | `http://localhost:5678` | n8n instance to seed. |
32−| `CLEAR` | `false` | Set to `true` to wipe data instead. |
33−| `PERSONAL_WORKFLOWS` | `50` | Amount of workflows to create in the personal project. |
79+You can inspect the last few lines of the build log file to check for errors:
80+```bash
81+tail -n 20 build.log
82+```
3483
35−Runtime is ~30–45 s for a default run (~500 workflows, ~30 projects).
84+If build outputs or the turbo cache are stale (e.g. after switching branches
85+or worktrees) but dependencies haven't changed, use `pnpm reset` (lightweight
86+by default) for a fast recovery: it cleans build outputs and force-rebuilds
87+(keeping `node_modules` and untracked files). If that doesn't fix your issue,
88+use `pnpm reset --full`, which also wipes untracked files and reinstalls
89+dependencies.
3690
37−## What it creates
91+### Testing
92+- `pnpm test` - Run all tests
93+- `pnpm test:affected` - Runs tests based on what has changed since the last
94+ commit
3895
39−**Projects** (30 team projects + your existing personal):
96+Running a particular test file requires going to the directory of that test
97+and running: `pnpm test <test-file>`.
4098
41−- **2 utility projects** — `Shared Platform` (technical plumbing: Audit
42− Logger, Slack Alerts Dispatcher, Sentry Error Forwarder, …) and
43− `Org Utilities` (business helpers: Tenant Resolver, Vault Reader, Feature
44− Flag Resolver, …). These are the hub workflows the rest of the org calls
45− into.
46−- **25 community projects** organised into 5 themed communities of 5 projects
47− each: Revenue, Customer, Engineering, Operations, Knowledge.
48−- **3 trenchcoat projects** — Legacy Migrations, Skunkworks, Founder's
49− Workflows. Smaller, internally split into 2-3 disjoint sub-systems (e.g.
50− `[HR System]`, `[Old Billing]`, `[Acme Acquisition]`), and almost entirely
51− detached from the rest of the org. They model accreted legacy state.
99+When changing directories, use `pushd` to navigate into the directory and
100+`popd` to return to the previous directory. When in doubt, use `pwd` to check
101+your current directory.
52102
53−**Credentials** (~110):
54−- Two per project max (random recipes: Notion, Slack, Postgres, GitHub, …).
55−- Plus **5 global credentials** living in the utility projects (Production
56− Slack Webhook, Datadog API, GitHub platform bot, OpenAI production,
57− Vault read-only).
103+### Code Quality
104+- `pnpm lint` - Lint code
105+- `pnpm typecheck` - Run type checks
58106
59−**Data tables** (~15–20):
60−- One per ~55% of projects, with 5–20 sample rows.
61−- Plus one **central data table** `seed_customers` in `Org Utilities` that
62− the entire org reaches through a single proxy workflow.
107+Always run lint and typecheck before committing code to ensure quality.
108+Execute these commands from within the specific package directory you're
109+working on (e.g., `cd packages/cli && pnpm lint`). Run the full repository
110+check only when preparing the final PR. When your changes affect type
111+definitions, interfaces in `@n8n/api-types`, or cross-package dependencies,
112+build the system before running lint and typecheck.
63113
64−**Workflows** (~500), built in four phases:
65−- **Phase 0** — Utility lynchpin workflows in `Shared Platform` and
66− `Org Utilities`, plus the Customers Proxy.
67−- **Phase 1** — Leaf workflows in every project, no sub-calls.
68−- **Phase 2** — Parent workflows with sub-workflow refs. Community projects
69− pick own/sibling/lynchpin; trenchcoats pick within their internal group.
70−- **Phase 3** — Data-table consumer workflows (one per project DT).
71−- **Phase 4** — Cross-project data-table proxies for ~6 non-utility DTs.
114+## Architecture Overview
72115
73−## Two non-obvious architectural rules
116+**Monorepo Structure:** pnpm workspaces with Turbo build orchestration
74117
75−1. **`DataTable` nodes can only point at tables in their own project.** Cross-
76− project access goes through a proxy workflow. The `customersProxy` in
77− `Org Utilities` is the only workflow with a direct `DataTable` node on
78− the central table; everyone else calls the proxy via `ExecuteWorkflow`.
79− Phase 4 generalises this pattern to ~6 other data tables.
118+### Package Structure
80119
81−2. **Per-project external-ref budgets.** Each community project is capped at
82− 2–5 distinct external workflow refs and 5–10 external credential refs,
83− tracked across all phases. About a third of community projects opt out of
84− utility refs entirely (some of those go fully self-contained — no
85− external refs of any kind). Trenchcoats and utility projects are exempt.
120+The monorepo is organized into these key packages:
86121
87−## Tunable knobs
122+- **`packages/@n8n/api-types`**: Shared TypeScript interfaces between frontend and backend
123+- **`packages/workflow`**: Core workflow interfaces and types
124+- **`packages/core`**: Workflow execution engine
125+- **`packages/cli`**: Express server, REST API, and CLI commands
126+- **`packages/frontend/editor-ui`**: Vue 3 frontend application
127+- **`packages/frontend/@n8n/i18n`**: Internationalization for UI text
128+- **`packages/nodes-base`**: Built-in nodes for integrations
129+- **`packages/@n8n/nodes-langchain`**: AI/LangChain nodes
130+- **`packages/@n8n/instance-ai`**: "AI Assistant" in the UI, "Instance AI" in code — AI assistant backend. See its `CLAUDE.md` for architecture docs.
131+- **`@n8n/design-system`**: Vue component library for UI consistency
132+- **`@n8n/config`**: Centralized configuration management
88133
89−All knobs live at the top of `seedInstance.mjs`. The ones that change the
90−shape of the graph the most:
134+## Technology Stack
91135
92−| Constant | Effect |
93−| --- | --- |
94−| `COMMUNITIES` | Project taxonomy. Add/remove communities or projects. |
95−| `TRENCHCOAT_PROJECTS` + `TRENCHCOAT_GROUPS` | Legacy projects and their internal subsystems. |
96−| `UTILITY_WORKFLOW_THEMES` | Lynchpin workflow names per utility project. |
97−| `LYNCHPIN_CRED_RECIPES` | The 5 global credentials. |
98−| `UTILITY_REF_PROB` (0.6) | Per-workflow probability of including a utility ref. |
99−| `CENTRAL_DT_REF_PROB` (0.08) | Per-workflow probability of calling the Customers Proxy (indirect central-DT use). |
100−| `ORG_UTIL_DIRECT_DT_PROB` (0.5) | Per-workflow probability that an Org Utilities phase-0 workflow gets a direct DataTable node on the central table. |
101−| `EXT_WF_REF_BUDGET` / `EXT_CRED_REF_BUDGET` | Per-project distinct-ref caps. |
102−| `NON_UTILITY_USING_TARGET` (9) | How many community projects opt out of utility refs. |
103−| `SELF_CONTAINED_PROJECT_PROB` | Subset of the opt-out projects that go fully siloed. |
104−| `sampleWorkflowCount()` | Power-law-ish size buckets per project kind. |
136+- **Frontend:** Vue 3 + TypeScript + Vite + Pinia + Storybook UI Library
137+- **Backend:** Node.js + TypeScript + Express + TypeORM
138+- **Testing:** Vitest (unit) + Playwright (E2E)
139+- **Database:** TypeORM with SQLite/PostgreSQL support
140+- **Code Quality:** Biome (for formatting) + ESLint + lefthook git hooks
105141
106−`SUBWF_PROB_OWN`/`_SIBLING`/`_LYNCHPIN` (in `pickCommunitySubWf`) govern how
107−parent workflows route sub-calls.
142+### Key Architectural Patterns
108143
109−## Verifying a run
144+1. **Dependency Injection**: Uses `@n8n/di` for IoC container
145+2. **Controller-Service-Repository**: Backend follows MVC-like pattern
146+3. **Event-Driven**: Internal event bus for decoupled communication
147+4. **Context-Based Execution**: Different contexts for different node types
148+5. **State Management**: Frontend uses Pinia stores
149+6. **Design System**: Reusable components and design tokens are centralized in
150+ `@n8n/design-system`, where all pure Vue components should be placed to
151+ ensure consistency and reusability
110152
111−The dependency-graph endpoint is the canonical view of what the seed
112−produced. It includes both the community structure and the central-DT proxy
113−pattern:
153+## Key Development Patterns
114154
115−```sh
116−curl -s "$N8N_BASE_URL/api/v1/workflows/dependency-graph?format=dot" \
117− -H "X-N8N-API-KEY: $N8N_API_KEY" | sfdp -Tsvg -Goverlap=prism > graph.svg
118−```
155+- Each package has isolated build configuration and can be developed independently
156+- Hot reload works across the full stack during development
157+- Node development uses dedicated `node-dev` CLI tool
158+- Workflow tests are JSON-based for integration testing
159+- AI features have dedicated development workflow (`pnpm dev:ai`)
119160
120−`sfdp`/`fdp` (Graphviz force-directed layouts) reveal the cluster topology
121−better than the default hierarchical `dot` layout.
161+### Workflow Traversal Utilities
122162
123−Counts via API:
163+The `n8n-workflow` package exports graph traversal utilities from
164+`packages/workflow/src/common/`. Use these instead of custom traversal logic.
124165
125−```sh
126−for path in workflows projects credentials data-tables; do
127− echo -n "$path: "
128− curl -s "$N8N_BASE_URL/api/v1/$path?limit=1" \
129− -H "X-N8N-API-KEY: $N8N_API_KEY" | jq -r '.data | length'
130−done
166+**Key concept:** `workflow.connections` is indexed by **source node**.
167+To find parent nodes, use `mapConnectionsByDestination()` to invert it first.
168+
169+```typescript
170+import { getParentNodes, getChildNodes, mapConnectionsByDestination } from 'n8n-workflow';
171+
172+// Finding parent nodes (predecessors) - requires inverted connections
173+const connectionsByDestination = mapConnectionsByDestination(workflow.connections);
174+const parents = getParentNodes(connectionsByDestination, 'NodeName', 'main', 1);
175+
176+// Finding child nodes (successors) - uses connections directly
177+const children = getChildNodes(workflow.connections, 'NodeName', 'main', 1);
131178 ```
132179
133−Key numbers a default run should land near:
134−- ~500 workflows, 30 team projects, ~110 credentials, ~15 data tables
135−- ~45% of workflows reference a utility workflow
136−- ~5–10% of workflows reach the central data table (2–4 direct refs from
137− workflows inside Org Utilities — Customers Proxy plus a few service
138− workflows like Region Router or Feature Flag Resolver — and the rest via
139− `ExecuteWorkflow` into the proxy)
140−- 20 of 29 non-utility projects use utility workflows
141−- 0 direct cross-project DataTable references (architectural invariant)
180+### TypeScript Best Practices
181+- **NEVER use `any` type** - use proper types or `unknown`
182+- **Avoid type casting with `as`** - use type guards or type predicates instead (except in test code where `as` is acceptable)
183+- **Define shared interfaces in `@n8n/api-types`** package for FE/BE communication
184+- **Lazy-load heavy modules** — if a module is only used in a specific code
185+ path (not every request), use `await import()` at point of use instead of
186+ top-level `import`. Applies especially to native modules and large parsers.
142187
143−## Re-running and cleanup
188+### Error Handling
189+- Don't use the deprecated `ApplicationError` class anywhere — it's a
190+ compatibility shim kept only so community nodes keep resolving. Use one of
191+ these instead, picking by cause:
192+ - `UserError` — the user caused it (invalid input, unauthorized action,
193+ business-rule violation).
194+ - `OperationalError` — a transient, expected issue (network request failing,
195+ DB query timing out) that should be handled gracefully.
196+ - `UnexpectedError` — a bug in the code (logic mistake, unhandled case,
197+ failed assertion) that developers need to fix.
198+- Import from appropriate error classes in each package
144199
145−The clear step is greedy: any workflow / credential / data-table with the
146−`[seed]` (or `seed_` for data tables) prefix is deleted, plus any team
147−project owning a `[seed]`-prefixed entity, plus any orphan team project from
148−an earlier run that doesn't match the current `PROJECT_NAMES` list and is
149−empty and not named `My project`.
200+### Persistence layer & the TypeORM boundary
150201
151−To remove all seeded data without reseeding:
202+TypeORM (`@n8n/typeorm`) must stay in the **persistence layer** — the `@n8n/db`
203+package or a backend module's own `database/` folder (entity/repository files).
204+Business logic — services, controllers, handlers, commands, factories — must not
205+import from `@n8n/typeorm` (including `@n8n/typeorm/...` subpaths). In
206+`packages/cli` this is enforced by the `misplaced-n8n-typeorm-import` lint rule;
207+a new import (or an inline `eslint-disable` of the rule) fails CI.
152208
153−```sh
154−N8N_API_KEY=… CLEAR=only node bin/seedInstance/seedInstance.mjs
155−```
209+- **Pattern:** when a query needs operators (`In`, `IsNull`, `LessThan`,
210+ `FindOptionsWhere`, …), put it behind a **use-case-named repository method**
211+ that takes plain parameters and returns domain-shaped values — not a generic
212+ `find(options)` passthrough.
213+- **Transactions:** transaction orchestration belongs in the persistence layer.
214+ Don't reach for `.manager` / `.manager.transaction(...)` or
215+ `createQueryBuilder(...)` in business logic. Use the sanctioned primitive in
216+ `@n8n/db`: inject the abstract `TransactionRunner` and wrap the unit of work in
217+ `txRunner.run(ctx, async (ctx) => …)`. The callback receives an
218+ `OperationContext` carrying the active transaction; thread that `ctx` into the
219+ repository methods you call. `run` **requires** a context — pass an empty `{}`
220+ at the operation entry point, and reuse the one you were handed everywhere
221+ below it (a context that already carries a transaction is joined, not nested).
222+ Repositories extend `BaseRepository` and resolve the right `EntityManager` with
223+ `this.managerFor(ctx)`; the `Transaction` handle is opaque and never exposes a
224+ driver type to business logic. See `oauth-token.service.ts` +
225+ `oauth-*-token.repository.ts` for a worked example.
226+- **Anti-patterns reviewers reject** — they hide the dependency instead of
227+ removing it:
228+ - String-matching TypeORM errors, e.g. `error.name === 'QueryFailedError'`.
229+ - Relabeling the import from `@n8n/typeorm` to `@n8n/db` to silence the rule
230+ (`@n8n/db` re-exports several operators/types, but this relabels the
231+ dependency rather than removing it).
232+ - Pushing `.manager` / `createQueryBuilder` into business logic to avoid an
233+ operator import — trades a visible leak for an invisible one.
156234
235+### Frontend Development
236+- Refer to `packages/frontend/AGENTS.md`
237+- **All UI text must use i18n** - add translations to `@n8n/i18n` package
238+- **Use CSS variables directly** - never hardcode spacing as px values
239+- **data-testid must be a single value** (no spaces or multiple values)
240+- Always use `design-system-rules` skill in reviews
157241
158−## Adding new behaviour
242+### Testing Guidelines
243+- **Always work from within the package directory** when running tests
244+- **Mock all external dependencies** in unit tests
245+- **Prefer reusing hoisted shared `mock<T>(...)` fixtures** when a typed mock is immutable and used across tests. This rule exists to avoid massive test slowdowns from repeatedly creating nested proxy mocks while preserving the type contract. Avoid replacing these with `as unknown as T` helpers for entities like `User`.
246+- **Confirm test cases with user** before writing unit tests
247+- **Typecheck is critical before committing** - always run `pnpm typecheck`
248+- **When modifying pinia stores**, check for unused computed properties
249+- **For Vitest packages that use `@n8n/di` decorators**, use `createVitestConfigWithDecorators` from `@n8n/vitest-config/node-decorators`. It enables SWC `decoratorMetadata` (esbuild doesn't emit it) and externalizes workspace packages that register services (`@n8n/di`, `@n8n/config`, `@n8n/constants`, `n8n-workflow`) so a single DI `Container` instance is shared across the runtime. Loading them through Vitest's pipeline alongside their CJS dist produces two `Container`s and `Container.get(...)` returns `undefined`.
159250
160−Adding a new shape of workflow usually means three places:
251+What we use for testing and writing tests:
252+- For testing nodes and other backend components, we use Vitest for unit tests. Examples can be found in `packages/nodes-base/nodes/**/*test*`.
253+- We use `nock` for server mocking
254+- For frontend we use `vitest`
255+- For E2E tests we use Playwright. Run with `pnpm --filter=n8n-playwright test:local`.
256+ See `packages/testing/playwright/README.md` for details.
257+- **To iterate on a feature without docker rebuilds**, boot service containers
258+ and run `pnpm dev` locally — `pnpm --filter n8n-containers services --services postgres,redis,mailpit,proxy`
259+ then `pnpm dev`. See [Develop against running containers](packages/testing/playwright/README.md#develop-against-running-containers-avoid-docker-rebuilds).
260+- **For Playwright test maintenance/cleanup**, see `packages/testing/playwright/AGENTS.md` (includes janitor tool for static analysis, dead code removal, architecture enforcement, and TCR workflows).
161261
162−1. A constant or recipe at the top of the file (theme name, cred type, …).
163−2. A change inside `workflowNodes()` if it needs a new node type.
164−3. A phase change (or new phase) inside `main()` that calls `createWf()`.
262+### Common Development Tasks
165263
166−`applyOrgUtilityRefs()` is the central hook for "every workflow should
167−sometimes touch X". Phase 4 (`/* cross-project data-table proxies */`) is
168−the template for "select a few entities, give each its own consumer
169−fan-out".
264+When implementing features:
265+1. Define API types in `packages/@n8n/api-types`
266+2. Implement backend logic in `packages/cli` module, follow
267+ `scripts/backend-module/backend-module-guide.md`
268+3. Add API endpoints via controllers
269+4. Update frontend in `packages/frontend/editor-ui` with i18n support
270+5. Write tests with proper mocks
271+6. Run `pnpm typecheck` to verify types
170272
171−## Known limitations
273+## Design Principles
172274
173−- Trenchcoat phase-3 (data-table consumer) workflows don't carry an internal
174− group label, so they show up as ungrouped within their trenchcoat project.
175− Minor visual artifact only.
176−- The `[seed] X: [group] Y N` naming convention is what powers the
177− group-aware visualisation. Renaming a workflow externally severs the
178− link the analyser uses to group it.
179−- No protection against running against a non-local instance. **Don't point
180− it at a shared/production n8n** — the clear step will delete everything
181− prefixed `[seed]` regardless of who created it.
275+### Security Must Not Degrade the Building Experience
276+
277+Security improvements, whether driven by enterprise requirements or internal
278+standards, must NEVER add friction to the common-case building experience. When
279+designing security-related features (defaults, behaviors, flows, error
280+handling), apply these checks:
281+
282+- **No friction for the common case:** A community builder's workflow should
283+ remain intuitive. Security should be invisible when it can be.
284+- **Migration and upgrade paths:** Existing users must have a clear,
285+ non-disruptive path forward when defaults or behaviors change.
286+- **Security layers on top, not in competition:** Great UX and strong security
287+ are not trade-offs. They're both required. If a design forces a choice
288+ between them, the design needs more work.
289+
290+### Security Fix Hygiene
291+
292+**This is a public repository.** When working on security fixes, never expose
293+the attack vector or vulnerability type in any public-facing artifact. Attackers
294+monitor open-source repos for signals like branch names, commit messages, PR
295+titles, test descriptions, and Linear URLs.
296+
297+**Rules for security fixes:**
298+
299+- **Branch names:** Do NOT use the Linear-suggested branch name if it reveals
300+ the vulnerability. Rename to describe the fix neutrally
301+ (e.g. `node-1234-improve-request-handling`, not
302+ `node-1234-fix-ddos-vulnerability`).
303+- **Commit messages:** Describe what the code now does, not the threat it
304+ prevents (e.g. `fix: add payload size validation`, not
305+ `fix: prevent denial of service`).
306+- **Test descriptions:** Use neutral, functional language
307+ (e.g. `'should sanitize query parameters'`, not
308+ `'should prevent SQL injection'`).
309+- **Code comments:** Do not describe the attack scenario in comments.
310+- **Linear references:** Never include the URL slug
311+ (e.g. `.../N8N-1234/fix-ssrf-vulnerability`).
312+
313+### Customer Confidentiality
314+
315+**This is a public repository.** Never mention customer names in any
316+public-facing artifact — not all customers have agreed to be named publicly,
317+and naming them can reveal security-relevant details about their setup.
318+
319+This applies to PR titles and descriptions, branch names, commit messages,
320+code, code comments, test names and test data, and fixtures. When implementing
321+a customer request, describe the use case neutrally (e.g. "a customer with a
322+large multi-main setup", not the company name) and use generic placeholder
323+names (e.g. `Acme Corp`) in tests and examples.
324+
325+## Github Guidelines
326+- When creating a PR, use the conventions in
327+ `.github/pull_request_template.md` and
328+ `.github/pull_request_title_conventions.md`.
329+- Use `gh pr create --draft` to create draft PRs.
330+- If there is a corresponding Linear ticket, reference it in the PR
331+ description using `https://linear.app/n8n/issue/[TICKET-ID]`. Do not
332+ create a Linear ticket on your own — ask first.
333+- always link to the github issue if mentioned in the linear ticket.
182334
