chore(eslint-config): Apply module boundary tags to all packages (spike, no-changelog)

Stamps boundaries: { type, scope } into all 71 workspace package.json files per
the assessment table, extends the rule's type set (runtime/nodes/sdk/tooling) to
cover the whole repo, and adds a validation harness that checks the real workspace
dependency graph against the matrices.

Harness output: 19 type + 21 scope violations, clustering on known smells
(n8n-workflow is types+runtime in one; design-system/workflow-sdk want 'shared'
scope; core->platform layering inversion). See scripts/spike-apply-boundaries.mjs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Charlie Kolb 2026-07-10 13:40:58 +02:00
parent 8740da1128
commit c4d08ecb69
No known key found for this signature in database
73 changed files with 287 additions and 3 deletions

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "sdk", "scope": "ai" },
"name": "@n8n/agents",
"version": "0.15.0",
"description": "AI agent SDK for n8n's code-first execution engine",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "sdk", "scope": "nodes" },
"name": "@n8n/ai-node-sdk",
"version": "0.20.0",
"description": "SDK for building AI nodes in n8n",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "nodes" },
"name": "@n8n/ai-utilities",
"version": "0.23.0",
"description": "Utilities for building AI nodes in n8n",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "feature", "scope": "ai" },
"name": "@n8n/ai-workflow-builder",
"version": "1.30.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "data-access", "scope": "shared" },
"name": "@n8n/api-types",
"version": "1.30.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "platform" },
"name": "@n8n/backend-common",
"version": "1.30.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "data-access", "scope": "platform" },
"name": "@n8n/backend-network",
"version": "1.4.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "tooling" },
"name": "@n8n/backend-test-utils",
"version": "1.30.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "tooling" },
"name": "@n8n/n8n-benchmark",
"version": "2.15.0",
"description": "Cli for running benchmark tests for n8n",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "feature", "scope": "ai" },
"name": "@n8n/chat-hub",
"version": "1.23.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "app", "scope": "platform" },
"name": "@n8n/cli",
"version": "0.10.0",
"description": "[beta] Client CLI for n8n — manage workflows, executions, and credentials from the terminal",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "platform" },
"name": "@n8n/client-oauth2",
"version": "1.12.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "editor" },
"name": "@n8n/codemirror-lang-html",
"version": "1.6.0",
"description": "HTML + n8n expression language support for CodeMirror 6",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "editor" },
"name": "@n8n/codemirror-lang-sql",
"version": "1.11.0",
"description": "SQL + n8n expression language support for CodeMirror 6",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "editor" },
"name": "@n8n/codemirror-lang",
"version": "0.10.0",
"description": "Language support package for CodeMirror 6 in n8n",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "app", "scope": "ai" },
"name": "@n8n/computer-use",
"version": "0.14.0",
"description": "Local AI gateway for n8n AI Assistant — filesystem, shell, screenshots, mouse/keyboard, and browser automation",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "shared" },
"name": "@n8n/config",
"version": "2.28.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "shared" },
"name": "@n8n/constants",
"version": "0.30.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "persistence" },
"name": "@n8n/crdt",
"version": "0.8.0",
"description": "CRDT abstraction layer for n8n collaborative editing",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "nodes" },
"name": "@n8n/create-node",
"version": "0.38.0",
"description": "Official CLI to create new community nodes for n8n",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "data-access", "scope": "persistence" },
"name": "@n8n/db",
"version": "1.30.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "shared" },
"name": "@n8n/decorators",
"version": "1.30.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "shared" },
"name": "@n8n/di",
"version": "0.14.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "runtime", "scope": "workflow-engine" },
"name": "@n8n/engine",
"version": "0.10.0",
"description": "n8n workflow execution engine (v2)",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "shared" },
"name": "@n8n/errors",
"version": "0.11.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "tooling" },
"private": true,
"name": "@n8n/eslint-config",
"type": "module",

View File

@ -0,0 +1,185 @@
#!/usr/bin/env node
/**
* SPIKE: stamp `boundaries: { type, scope }` into every workspace package.json,
* then validate the real workspace dependency graph against the module-boundary
* matrices. Run from the repo root: `node packages/@n8n/eslint-config/scripts/spike-apply-boundaries.mjs`
*
* Not production code — this is the throwaway harness that answers "what breaks
* if we adopt the tags in the table". The real tag source would be a generator
* wired into the eslint config; here we embed the mapping so it stays reviewable.
*
* NOTE: uses key `boundaries`, NOT `n8n` — the `n8n` key is already taken by
* node/credential registration in nodes-base et al.
*/
import { readFileSync, writeFileSync, readdirSync, existsSync } from 'node:fs';
import { join } from 'node:path';
// name -> [type, scope]. Mirrors the assessment table (extended type set).
const TAGS = {
// shared
'@n8n/utils': ['util', 'shared'],
'@n8n/constants': ['util', 'shared'],
'@n8n/errors': ['util', 'shared'],
'@n8n/di': ['util', 'shared'],
'@n8n/decorators': ['util', 'shared'],
'@n8n/config': ['util', 'shared'],
'@n8n/permissions': ['util', 'shared'],
'@n8n/i18n': ['util', 'shared'],
'@n8n/json-schema-to-zod': ['util', 'shared'],
'@n8n/api-types': ['data-access', 'shared'],
// workflow-engine
'n8n-workflow': ['runtime', 'workflow-engine'],
'n8n-core': ['runtime', 'workflow-engine'],
'@n8n/engine': ['runtime', 'workflow-engine'],
'@n8n/expression-runtime': ['runtime', 'workflow-engine'],
'@n8n/scheduler': ['util', 'workflow-engine'],
'@n8n/tournament': ['util', 'workflow-engine'],
'@n8n/task-runner': ['app', 'workflow-engine'],
'@n8n/workflow-sdk': ['sdk', 'workflow-engine'],
// nodes
'n8n-nodes-base': ['nodes', 'nodes'],
'@n8n/n8n-nodes-langchain': ['nodes', 'nodes'],
'@n8n/ai-node-sdk': ['sdk', 'nodes'],
'@n8n/ai-utilities': ['util', 'nodes'],
'@n8n/extension-sdk': ['sdk', 'nodes'],
'@n8n/create-node': ['tooling', 'nodes'],
'@n8n/node-cli': ['tooling', 'nodes'],
'n8n-node-dev': ['tooling', 'nodes'],
'@n8n/scan-community-package': ['tooling', 'nodes'],
'@n8n/eslint-plugin-community-nodes': ['tooling', 'nodes'],
// ai
'@n8n/instance-ai': ['feature', 'ai'],
'@n8n/ai-workflow-builder': ['feature', 'ai'],
'@n8n/agents': ['sdk', 'ai'],
'@n8n/computer-use': ['app', 'ai'],
'@n8n/mcp-apps': ['feature', 'ai'],
'@n8n/mcp-browser': ['util', 'ai'],
'@n8n/mcp-browser-extension': ['app', 'ai'],
'@n8n/chat-hub': ['feature', 'ai'],
'@n8n/chat': ['feature', 'ai'],
// editor (frontend)
'n8n-editor-ui': ['app', 'editor'],
'@n8n/design-system': ['ui', 'editor'],
'@n8n/stores': ['data-access', 'editor'],
'@n8n/rest-api-client': ['data-access', 'editor'],
'@n8n/composables': ['util', 'editor'],
'@n8n/codemirror-lang': ['util', 'editor'],
'@n8n/codemirror-lang-html': ['util', 'editor'],
'@n8n/codemirror-lang-sql': ['util', 'editor'],
// persistence
'@n8n/db': ['data-access', 'persistence'],
'@n8n/typeorm': ['util', 'persistence'],
'@n8n/crdt': ['util', 'persistence'],
// platform (backend server)
n8n: ['app', 'platform'],
'@n8n/cli': ['app', 'platform'],
'@n8n/backend-common': ['util', 'platform'],
'@n8n/backend-network': ['data-access', 'platform'],
'@n8n/local-gateway': ['app', 'platform'],
'@n8n/syslog-client': ['util', 'platform'],
'@n8n/imap': ['util', 'platform'],
'@n8n/client-oauth2': ['util', 'platform'],
// insights
'@n8n/n8n-extension-insights': ['feature', 'insights'],
// tooling
'@n8n/eslint-config': ['tooling', 'tooling'],
'@n8n/typescript-config': ['tooling', 'tooling'],
'@n8n/vitest-config': ['tooling', 'tooling'],
'@n8n/stylelint-config': ['tooling', 'tooling'],
'@n8n/storybook': ['tooling', 'tooling'],
'@n8n/code-health': ['tooling', 'tooling'],
'@n8n/test-impact': ['tooling', 'tooling'],
'@n8n/playwright-janitor': ['tooling', 'tooling'],
'n8n-playwright': ['tooling', 'tooling'],
'n8n-containers': ['tooling', 'tooling'],
'@n8n/performance': ['tooling', 'tooling'],
'@n8n/n8n-benchmark': ['tooling', 'tooling'],
'@n8n/backend-test-utils': ['tooling', 'tooling'],
'@n8n/rules-engine': ['tooling', 'tooling'],
};
const ALL = [
'app', 'feature', 'runtime', 'nodes', 'sdk', 'data-access', 'domain-ui', 'ui', 'util', 'tooling',
];
const ALLOWED_TYPES = {
app: ALL,
tooling: ALL,
feature: ['data-access', 'domain-ui', 'ui', 'util', 'sdk'],
runtime: ['runtime', 'data-access', 'util'],
nodes: ['nodes', 'runtime', 'data-access', 'sdk', 'util'],
sdk: ['sdk', 'runtime', 'data-access', 'util'],
'data-access': ['data-access', 'util'],
'domain-ui': ['domain-ui', 'ui', 'util'],
ui: ['ui', 'util'],
util: ['util'],
};
const SCOPE_EXEMPT_TYPES = new Set(['app', 'tooling']);
const SHARED_SCOPES = new Set(['shared', 'tooling']);
// --- discover package.json files ---
const roots = [
'packages',
'packages/@n8n',
'packages/frontend',
'packages/frontend/@n8n',
'packages/extensions',
'packages/testing',
];
const pkgFiles = [];
for (const root of roots) {
if (!existsSync(root)) continue;
for (const entry of readdirSync(root, { withFileTypes: true })) {
if (!entry.isDirectory()) continue;
const pj = join(root, entry.name, 'package.json');
if (existsSync(pj)) pkgFiles.push(pj);
}
}
// --- stamp tags (textual insert to keep diffs to one line) ---
const byName = {};
let stamped = 0;
const untagged = [];
for (const pj of pkgFiles) {
const raw = readFileSync(pj, 'utf8');
const pkg = JSON.parse(raw);
byName[pkg.name] = { pj, pkg };
const tag = TAGS[pkg.name];
if (!tag) { untagged.push(pkg.name); continue; }
const [type, scope] = tag;
if (raw.includes('"boundaries"')) { stamped++; continue; }
const insert = ` "boundaries": { "type": "${type}", "scope": "${scope}" },\n`;
writeFileSync(pj, raw.replace(/^{\n/, `{\n${insert}`));
stamped++;
}
// --- validate the runtime dependency graph ---
const names = new Set(Object.keys(byName));
const typeViol = [];
const scopeViol = [];
for (const [name, { pkg }] of Object.entries(byName)) {
const tag = TAGS[name];
if (!tag) continue;
const [fromType, fromScope] = tag;
for (const dep of Object.keys(pkg.dependencies ?? {})) {
if (!names.has(dep) || dep === name) continue;
const toTag = TAGS[dep];
if (!toTag) continue;
const [toType, toScope] = toTag;
if (!ALLOWED_TYPES[fromType].includes(toType)) {
typeViol.push(`${name} (${fromType}) -> ${dep} (${toType})`);
continue;
}
const scopeOk =
SCOPE_EXEMPT_TYPES.has(fromType) ||
fromScope === toScope ||
SHARED_SCOPES.has(toScope);
if (!scopeOk) scopeViol.push(`${name} [${fromScope}] -> ${dep} [${toScope}]`);
}
}
console.log(`\n=== stamped ${stamped}/${pkgFiles.length} package.json files ===`);
if (untagged.length) console.log(`untagged (no mapping): ${untagged.join(', ')}`);
console.log(`\n=== TYPE violations (${typeViol.length}) ===`);
typeViol.sort().forEach((v) => console.log(' ' + v));
console.log(`\n=== SCOPE violations (${scopeViol.length}) — need explicit opt-in ===`);
scopeViol.sort().forEach((v) => console.log(' ' + v));

View File

@ -19,7 +19,17 @@ import { ESLintUtils } from '@typescript-eslint/utils';
* `n8n.tags` field at config-build time (one fs scan, cached). Add when adopted.
*/
export type BoundaryType = 'app' | 'feature' | 'data-access' | 'domain-ui' | 'ui' | 'util';
export type BoundaryType =
| 'app'
| 'feature'
| 'runtime'
| 'nodes'
| 'sdk'
| 'data-access'
| 'domain-ui'
| 'ui'
| 'util'
| 'tooling';
export interface PackageTag {
name: string;
@ -40,9 +50,26 @@ export interface Options {
// Konstantin's hierarchy: apps glue everything, features slice vertically and
// must not import each other, data-access stays UI-free, utils are universal.
const ALL_TYPES: BoundaryType[] = [
'app',
'feature',
'runtime',
'nodes',
'sdk',
'data-access',
'domain-ui',
'ui',
'util',
'tooling',
];
const DEFAULT_ALLOWED_TYPES: Record<BoundaryType, BoundaryType[]> = {
app: ['app', 'feature', 'data-access', 'domain-ui', 'ui', 'util'],
feature: ['data-access', 'domain-ui', 'ui', 'util'],
app: ALL_TYPES, // apps glue everything together
tooling: ALL_TYPES, // dev/CI only, not in any runtime bundle
feature: ['data-access', 'domain-ui', 'ui', 'util', 'sdk'],
runtime: ['runtime', 'data-access', 'util'],
nodes: ['nodes', 'runtime', 'data-access', 'sdk', 'util'],
sdk: ['sdk', 'runtime', 'data-access', 'util'],
'data-access': ['data-access', 'util'],
'domain-ui': ['domain-ui', 'ui', 'util'],
ui: ['ui', 'util'],
@ -112,6 +139,7 @@ export const EnforceModuleBoundariesRule = ESLintUtils.RuleCreator.withoutDocs({
const scopeAllowed =
fromPkg.type === 'app' || // apps glue every scope together
fromPkg.type === 'tooling' || // dev/CI crosses every domain
fromPkg.scope === toPkg.scope ||
sharedScopes.includes(toPkg.scope) ||
(allowedScopeDependencies[fromPkg.scope] ?? []).includes(toPkg.scope);

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "nodes" },
"name": "@n8n/eslint-plugin-community-nodes",
"type": "module",
"version": "0.24.0",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "runtime", "scope": "workflow-engine" },
"name": "@n8n/expression-runtime",
"version": "0.21.0",
"description": "Secure, isolated expression evaluation runtime for n8n",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "sdk", "scope": "nodes" },
"name": "@n8n/extension-sdk",
"version": "0.14.0",
"type": "module",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "platform" },
"name": "@n8n/imap",
"version": "0.23.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "feature", "scope": "ai" },
"name": "@n8n/instance-ai",
"version": "1.15.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "shared" },
"name": "@n8n/json-schema-to-zod",
"version": "1.13.0",
"description": "Converts JSON schema objects into Zod schemas",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "app", "scope": "platform" },
"name": "@n8n/local-gateway",
"version": "0.1.0",
"description": "n8n Local Gateway",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "feature", "scope": "ai" },
"name": "@n8n/mcp-apps",
"version": "0.7.0",
"description": "MCP Apps UI resources and server helpers for n8n",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "app", "scope": "ai" },
"name": "@n8n/mcp-browser-extension",
"version": "0.0.4",
"private": true,

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "ai" },
"name": "@n8n/mcp-browser",
"version": "0.13.0",
"description": "Browser automation MCP tools built on Playwright, WebDriver BiDi, and safaridriver",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "nodes" },
"name": "@n8n/node-cli",
"version": "0.39.0",
"description": "Official CLI for developing community nodes for n8n",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "nodes", "scope": "nodes" },
"name": "@n8n/n8n-nodes-langchain",
"version": "2.30.0",
"description": "",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "shared" },
"name": "@n8n/permissions",
"version": "0.67.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "nodes" },
"name": "@n8n/scan-community-package",
"version": "0.26.0",
"description": "Static code analyser for n8n community packages",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "workflow-engine" },
"name": "@n8n/scheduler",
"version": "0.2.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "tooling" },
"private": true,
"name": "@n8n/stylelint-config",
"type": "module",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "platform" },
"name": "@n8n/syslog-client",
"version": "1.7.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "app", "scope": "workflow-engine" },
"name": "@n8n/task-runner",
"version": "2.30.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "workflow-engine" },
"name": "@n8n/tournament",
"version": "1.6.0",
"description": "Output compatible rewrite of riot tmpl",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "persistence" },
"name": "@n8n/typeorm",
"version": "0.4.0",
"description": "Data-Mapper ORM for TypeScript, ES7, ES6, ES5. Supports PostgreSQL and SQLite databases.",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "tooling" },
"name": "@n8n/typescript-config",
"version": "1.8.0",
"type": "module",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "shared" },
"name": "@n8n/utils",
"type": "module",
"version": "1.38.0",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "tooling" },
"name": "@n8n/vitest-config",
"version": "1.17.0",
"type": "module",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "sdk", "scope": "workflow-engine" },
"name": "@n8n/workflow-sdk",
"version": "0.23.0",
"description": "TypeScript SDK for programmatically creating n8n workflows",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "app", "scope": "platform" },
"name": "n8n",
"version": "2.30.0",
"description": "n8n Workflow Automation Tool",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "runtime", "scope": "workflow-engine" },
"name": "n8n-core",
"version": "2.30.0",
"description": "Core functionality of n8n",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "feature", "scope": "insights" },
"name": "@n8n/n8n-extension-insights",
"version": "0.17.0",
"type": "module",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "feature", "scope": "ai" },
"name": "@n8n/chat",
"version": "1.29.0",
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "editor" },
"name": "@n8n/composables",
"type": "module",
"version": "1.20.0",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "ui", "scope": "editor" },
"type": "module",
"name": "@n8n/design-system",
"version": "2.29.0",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "util", "scope": "shared" },
"name": "@n8n/i18n",
"type": "module",
"version": "2.30.0",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "data-access", "scope": "editor" },
"name": "@n8n/rest-api-client",
"type": "module",
"version": "2.30.0",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "data-access", "scope": "editor" },
"name": "@n8n/stores",
"type": "module",
"version": "2.30.0",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "tooling" },
"name": "@n8n/storybook",
"private": true,
"version": "0.0.0",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "app", "scope": "editor" },
"name": "n8n-editor-ui",
"version": "2.30.0",
"description": "Workflow Editor UI for n8n",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "nodes" },
"name": "n8n-node-dev",
"version": "2.9.0",
"description": "CLI to simplify n8n credentials/node development",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "nodes", "scope": "nodes" },
"name": "n8n-nodes-base",
"version": "2.30.0",
"description": "Base nodes of n8n",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "tooling" },
"name": "@n8n/code-health",
"private": true,
"version": "0.1.0",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "tooling" },
"name": "n8n-containers",
"private": true,
"version": "1.0.0",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "tooling" },
"name": "@n8n/playwright-janitor",
"private": true,
"version": "0.1.0",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "tooling" },
"name": "@n8n/performance",
"version": "1.0.0",
"private": true,

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "tooling" },
"name": "n8n-playwright",
"private": true,
"scripts": {

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "tooling" },
"name": "@n8n/rules-engine",
"private": true,
"version": "0.1.0",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "tooling", "scope": "tooling" },
"name": "@n8n/test-impact",
"private": true,
"version": "0.1.0",

View File

@ -1,4 +1,5 @@
{
"boundaries": { "type": "runtime", "scope": "workflow-engine" },
"name": "n8n-workflow",
"version": "2.30.0",
"description": "Workflow base code of n8n",