n8nac 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/dist/commands/base.d.ts +39 -0
- package/dist/commands/base.d.ts.map +1 -1
- package/dist/commands/base.js +84 -36
- package/dist/commands/base.js.map +1 -1
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +2 -2
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +28 -6
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/test.d.ts.map +1 -1
- package/dist/commands/test.js +2 -2
- package/dist/commands/test.js.map +1 -1
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/services/folder-path-resolver.d.ts +51 -0
- package/dist/core/services/folder-path-resolver.d.ts.map +1 -0
- package/dist/core/services/folder-path-resolver.js +123 -0
- package/dist/core/services/folder-path-resolver.js.map +1 -0
- package/dist/core/services/n8n-api-client.d.ts +53 -1
- package/dist/core/services/n8n-api-client.d.ts.map +1 -1
- package/dist/core/services/n8n-api-client.js +184 -2
- package/dist/core/services/n8n-api-client.js.map +1 -1
- package/dist/core/services/resolution-manager.d.ts.map +1 -1
- package/dist/core/services/resolution-manager.js +4 -4
- package/dist/core/services/resolution-manager.js.map +1 -1
- package/dist/core/services/state-manager.d.ts +1 -1
- package/dist/core/services/state-manager.d.ts.map +1 -1
- package/dist/core/services/sync-engine.d.ts +48 -1
- package/dist/core/services/sync-engine.d.ts.map +1 -1
- package/dist/core/services/sync-engine.js +200 -6
- package/dist/core/services/sync-engine.js.map +1 -1
- package/dist/core/services/sync-manager.d.ts.map +1 -1
- package/dist/core/services/sync-manager.js +10 -8
- package/dist/core/services/sync-manager.js.map +1 -1
- package/dist/core/services/tls-certificates.d.ts +105 -0
- package/dist/core/services/tls-certificates.d.ts.map +1 -0
- package/dist/core/services/tls-certificates.js +329 -0
- package/dist/core/services/tls-certificates.js.map +1 -0
- package/dist/core/services/workflow-path-utils.d.ts +56 -0
- package/dist/core/services/workflow-path-utils.d.ts.map +1 -0
- package/dist/core/services/workflow-path-utils.js +102 -0
- package/dist/core/services/workflow-path-utils.js.map +1 -0
- package/dist/core/services/workflow-state-tracker.d.ts +56 -0
- package/dist/core/services/workflow-state-tracker.d.ts.map +1 -1
- package/dist/core/services/workflow-state-tracker.js +225 -32
- package/dist/core/services/workflow-state-tracker.js.map +1 -1
- package/dist/core/services/workflow-transformer-adapter.d.ts +7 -1
- package/dist/core/services/workflow-transformer-adapter.d.ts.map +1 -1
- package/dist/core/services/workflow-transformer-adapter.js +8 -2
- package/dist/core/services/workflow-transformer-adapter.js.map +1 -1
- package/dist/core/types.d.ts +84 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/index.js +46 -10
- package/dist/index.js.map +1 -1
- package/dist/services/config-service.d.ts +33 -6
- package/dist/services/config-service.d.ts.map +1 -1
- package/dist/services/config-service.js +54 -3
- package/dist/services/config-service.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import * as tls from 'tls';
|
|
5
|
+
/**
|
|
6
|
+
* Additional trust anchors for outbound HTTPS.
|
|
7
|
+
*
|
|
8
|
+
* Node honours `NODE_EXTRA_CA_CERTS` and `--use-system-ca` when it builds the default
|
|
9
|
+
* TLS trust store, but only when the process is a stock Node build that is started with
|
|
10
|
+
* those settings. The VS Code extension host is neither: it is an Electron process
|
|
11
|
+
* (BoringSSL, no `NODE_EXTRA_CA_CERTS` support) that users cannot pass Node flags to.
|
|
12
|
+
* The same gap exists for anything reaching n8n through the global `fetch`
|
|
13
|
+
* (`@n8n-as-code/n8n-manager-core` health probes, project listing, credential REST calls),
|
|
14
|
+
* because `fetch` ignores `https.Agent` options entirely.
|
|
15
|
+
*
|
|
16
|
+
* So we read the certificates ourselves and append them to every secure context the
|
|
17
|
+
* process creates, which covers axios, `fetch`, `ws` and `http-proxy` in one place.
|
|
18
|
+
*/
|
|
19
|
+
const PEM_CERTIFICATE_PATTERN = /-----BEGIN CERTIFICATE-----[\s\S]*?-----END CERTIFICATE-----/g;
|
|
20
|
+
/** Read in addition to Node's own `NODE_EXTRA_CA_CERTS`; accepts several paths. */
|
|
21
|
+
export const N8NAC_EXTRA_CA_CERTS_ENV = 'N8NAC_EXTRA_CA_CERTS';
|
|
22
|
+
const patchedHosts = new WeakMap();
|
|
23
|
+
let defaultSecureContextHost;
|
|
24
|
+
/**
|
|
25
|
+
* The mutable `tls` module object.
|
|
26
|
+
*
|
|
27
|
+
* `import * as tls` yields a frozen module namespace, so the patch has to go through the
|
|
28
|
+
* CommonJS export object that `https`, `ws` and undici's `fetch` all read from.
|
|
29
|
+
*/
|
|
30
|
+
function getDefaultSecureContextHost() {
|
|
31
|
+
defaultSecureContextHost ??= createRequire(import.meta.url)('tls');
|
|
32
|
+
return defaultSecureContextHost;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Split a path list. Accepts the platform delimiter, commas and newlines so a single
|
|
36
|
+
* setting works whether it was copied from a shell variable or typed by hand.
|
|
37
|
+
*/
|
|
38
|
+
export function splitCertificatePathList(value) {
|
|
39
|
+
return value
|
|
40
|
+
.split(new RegExp(`[${escapeForCharacterClass(path.delimiter)},\\r\\n]`))
|
|
41
|
+
.map((entry) => entry.trim().replace(/^["']|["']$/g, ''))
|
|
42
|
+
.filter((entry) => entry.length > 0);
|
|
43
|
+
}
|
|
44
|
+
function escapeForCharacterClass(value) {
|
|
45
|
+
return value.replace(/[\\\]^-]/g, '\\$&');
|
|
46
|
+
}
|
|
47
|
+
/** Extract every PEM certificate block from a bundle, ignoring keys and comments. */
|
|
48
|
+
export function extractPemCertificates(contents) {
|
|
49
|
+
return contents.match(PEM_CERTIFICATE_PATTERN) ?? [];
|
|
50
|
+
}
|
|
51
|
+
function readCertificateFile(filePath, resolution, label) {
|
|
52
|
+
let contents;
|
|
53
|
+
try {
|
|
54
|
+
contents = fs.readFileSync(filePath, 'utf8');
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
resolution.errors.push(`${label}: cannot read "${filePath}" (${error?.code || error?.message || error})`);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const certificates = extractPemCertificates(contents);
|
|
61
|
+
if (!certificates.length) {
|
|
62
|
+
resolution.errors.push(`${label}: "${filePath}" does not contain any PEM certificate`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
resolution.hasConfiguredAnchors = true;
|
|
66
|
+
addCertificates(resolution, certificates, `${label}: ${filePath}`);
|
|
67
|
+
}
|
|
68
|
+
function addCertificates(resolution, certificates, source) {
|
|
69
|
+
let added = 0;
|
|
70
|
+
for (const certificate of certificates) {
|
|
71
|
+
const normalized = certificate.trim();
|
|
72
|
+
if (!normalized || resolution.certificates.includes(normalized))
|
|
73
|
+
continue;
|
|
74
|
+
resolution.certificates.push(normalized);
|
|
75
|
+
added++;
|
|
76
|
+
}
|
|
77
|
+
if (added > 0) {
|
|
78
|
+
resolution.sources.push(`${source} (${added})`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function readSystemCertificates(resolution) {
|
|
82
|
+
// Node 22.15+/24 only. Older hosts (and Electron) simply do not expose it, which is the
|
|
83
|
+
// expected state rather than a misconfiguration, so it is not reported as an error.
|
|
84
|
+
const getCACertificates = tls.getCACertificates;
|
|
85
|
+
if (typeof getCACertificates !== 'function') {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
addCertificates(resolution, getCACertificates('system'), 'system trust store');
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
resolution.errors.push(`system trust store: ${error?.message || error}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Collect the extra trust anchors from settings, `N8NAC_EXTRA_CA_CERTS`,
|
|
97
|
+
* `NODE_EXTRA_CA_CERTS` and — on request — the OS trust store.
|
|
98
|
+
*/
|
|
99
|
+
export function resolveExtraCaCertificates(options = {}) {
|
|
100
|
+
const env = options.env ?? process.env;
|
|
101
|
+
const baseDir = options.baseDir ?? process.cwd();
|
|
102
|
+
const resolution = {
|
|
103
|
+
certificates: [],
|
|
104
|
+
sources: [],
|
|
105
|
+
errors: [],
|
|
106
|
+
hasConfiguredAnchors: false,
|
|
107
|
+
};
|
|
108
|
+
const resolvePath = (candidate) => (path.isAbsolute(candidate) ? candidate : path.resolve(baseDir, candidate));
|
|
109
|
+
for (const candidate of options.caFiles ?? []) {
|
|
110
|
+
for (const filePath of splitCertificatePathList(candidate)) {
|
|
111
|
+
readCertificateFile(resolvePath(filePath), resolution, 'setting');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
for (const filePath of splitCertificatePathList(env[N8NAC_EXTRA_CA_CERTS_ENV] ?? '')) {
|
|
115
|
+
readCertificateFile(resolvePath(filePath), resolution, N8NAC_EXTRA_CA_CERTS_ENV);
|
|
116
|
+
}
|
|
117
|
+
for (const filePath of splitCertificatePathList(env.NODE_EXTRA_CA_CERTS ?? '')) {
|
|
118
|
+
readCertificateFile(resolvePath(filePath), resolution, 'NODE_EXTRA_CA_CERTS');
|
|
119
|
+
}
|
|
120
|
+
if (options.useSystemCertificateAuthorities) {
|
|
121
|
+
readSystemCertificates(resolution);
|
|
122
|
+
}
|
|
123
|
+
return resolution;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Append the resolved certificates to every secure context created from now on.
|
|
127
|
+
*
|
|
128
|
+
* Idempotent: calling it again replaces the certificate set instead of stacking another
|
|
129
|
+
* wrapper, so it is safe to re-run whenever the configuration changes.
|
|
130
|
+
*/
|
|
131
|
+
export function installExtraCaCertificates(options = {}, host = getDefaultSecureContextHost()) {
|
|
132
|
+
const resolution = resolveExtraCaCertificates(options);
|
|
133
|
+
const existing = patchedHosts.get(host);
|
|
134
|
+
if (existing) {
|
|
135
|
+
existing.certificates = resolution.certificates;
|
|
136
|
+
return { ...resolution, installed: resolution.certificates.length > 0 };
|
|
137
|
+
}
|
|
138
|
+
if (!resolution.certificates.length) {
|
|
139
|
+
// Nothing to trust yet — leave the runtime untouched rather than wrapping it for nothing.
|
|
140
|
+
return { ...resolution, installed: false };
|
|
141
|
+
}
|
|
142
|
+
const state = {
|
|
143
|
+
original: host.createSecureContext,
|
|
144
|
+
certificates: resolution.certificates,
|
|
145
|
+
};
|
|
146
|
+
patchedHosts.set(host, state);
|
|
147
|
+
host.createSecureContext = (contextOptions) => {
|
|
148
|
+
const context = state.original.call(host, contextOptions);
|
|
149
|
+
const nativeContext = context.context;
|
|
150
|
+
if (typeof nativeContext?.addCACert !== 'function') {
|
|
151
|
+
return context;
|
|
152
|
+
}
|
|
153
|
+
for (const certificate of state.certificates) {
|
|
154
|
+
try {
|
|
155
|
+
nativeContext.addCACert(certificate);
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
// A malformed or duplicate anchor must not break the whole handshake.
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return context;
|
|
162
|
+
};
|
|
163
|
+
return { ...resolution, installed: true };
|
|
164
|
+
}
|
|
165
|
+
/** Certificates currently appended by the installer, for diagnostics and tests. */
|
|
166
|
+
export function getInstalledExtraCaCertificates(host = getDefaultSecureContextHost()) {
|
|
167
|
+
return [...(patchedHosts.get(host)?.certificates ?? [])];
|
|
168
|
+
}
|
|
169
|
+
/** Restore the untouched `createSecureContext`. Intended for tests. */
|
|
170
|
+
export function uninstallExtraCaCertificates(host = getDefaultSecureContextHost()) {
|
|
171
|
+
const state = patchedHosts.get(host);
|
|
172
|
+
if (!state)
|
|
173
|
+
return;
|
|
174
|
+
host.createSecureContext = state.original;
|
|
175
|
+
patchedHosts.delete(host);
|
|
176
|
+
}
|
|
177
|
+
/** Set to 1/true/yes to skip certificate verification outright. Last resort, see below. */
|
|
178
|
+
export const N8NAC_INSECURE_TLS_ENV = 'N8NAC_INSECURE_TLS';
|
|
179
|
+
const PRIVATE_HOSTNAME_SUFFIXES = ['.localhost', '.local', '.internal', '.home.arpa'];
|
|
180
|
+
/** Pull the host out of a URL by hand, for the inputs `URL` refuses (an IPv6 zone id). */
|
|
181
|
+
function stripUrlDecorations(value) {
|
|
182
|
+
const bare = value
|
|
183
|
+
.replace(/^[a-z][a-z0-9+.-]*:\/\//i, '')
|
|
184
|
+
.replace(/^[^@/]*@/, '')
|
|
185
|
+
.replace(/[/?#].*$/, '');
|
|
186
|
+
const bracketed = /^\[([^\]]*)\]/.exec(bare);
|
|
187
|
+
if (bracketed)
|
|
188
|
+
return bracketed[1];
|
|
189
|
+
// A bare IPv6 literal holds several colons; a `host:port` pair holds exactly one.
|
|
190
|
+
return bare.split(':').length === 2 ? bare.replace(/:\d*$/, '') : bare;
|
|
191
|
+
}
|
|
192
|
+
/** Strip the scheme, port, brackets, IPv6 zone id and trailing dot from a configured host. */
|
|
193
|
+
function normalizeHostname(hostOrUrl) {
|
|
194
|
+
const value = hostOrUrl.trim();
|
|
195
|
+
if (!value)
|
|
196
|
+
return '';
|
|
197
|
+
let hostname;
|
|
198
|
+
try {
|
|
199
|
+
hostname = new URL(value.includes('://') ? value : `https://${value}`).hostname;
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
hostname = stripUrlDecorations(value);
|
|
203
|
+
}
|
|
204
|
+
return hostname
|
|
205
|
+
.toLowerCase()
|
|
206
|
+
.replace(/^\[|\]$/g, '')
|
|
207
|
+
.replace(/%.*$/, '')
|
|
208
|
+
.replace(/\.$/, '');
|
|
209
|
+
}
|
|
210
|
+
function isPrivateIpv4(hostname) {
|
|
211
|
+
const octets = hostname.split('.').map(Number);
|
|
212
|
+
if (octets.length !== 4 || octets.some((octet) => !Number.isInteger(octet) || octet < 0 || octet > 255)) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
const [first, second] = octets;
|
|
216
|
+
if (first === 0)
|
|
217
|
+
return true; // "this host on this network"
|
|
218
|
+
if (first === 10)
|
|
219
|
+
return true; // RFC 1918
|
|
220
|
+
if (first === 127)
|
|
221
|
+
return true; // loopback
|
|
222
|
+
if (first === 169 && second === 254)
|
|
223
|
+
return true; // link-local
|
|
224
|
+
if (first === 172 && second >= 16 && second <= 31)
|
|
225
|
+
return true; // RFC 1918
|
|
226
|
+
if (first === 192 && second === 168)
|
|
227
|
+
return true; // RFC 1918
|
|
228
|
+
if (first === 100 && second >= 64 && second <= 127)
|
|
229
|
+
return true; // CGNAT, incl. Tailscale
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
function isPrivateIpv6(hostname) {
|
|
233
|
+
if (hostname === '::1' || hostname === '::')
|
|
234
|
+
return true;
|
|
235
|
+
const mapped = /^::ffff:(\d{1,3}(?:\.\d{1,3}){3})$/.exec(hostname);
|
|
236
|
+
if (mapped)
|
|
237
|
+
return isPrivateIpv4(mapped[1]);
|
|
238
|
+
// `URL` rewrites an IPv4-mapped address to its hex form (`::ffff:c0a8:10a`), so the
|
|
239
|
+
// embedded IPv4 address has to be read back out of the last two groups.
|
|
240
|
+
const mappedHex = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(hostname);
|
|
241
|
+
if (mappedHex) {
|
|
242
|
+
const high = parseInt(mappedHex[1], 16);
|
|
243
|
+
const low = parseInt(mappedHex[2], 16);
|
|
244
|
+
return isPrivateIpv4([high >> 8, high & 0xff, low >> 8, low & 0xff].join('.'));
|
|
245
|
+
}
|
|
246
|
+
if (/^f[cd][0-9a-f]{2}:/.test(hostname))
|
|
247
|
+
return true; // fc00::/7 unique local
|
|
248
|
+
if (/^fe[89ab][0-9a-f]:/.test(hostname))
|
|
249
|
+
return true; // fe80::/10 link-local
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* `true` when the host can only be reached from this machine or a private network.
|
|
254
|
+
*
|
|
255
|
+
* These are precisely the destinations a public CA will not issue a certificate for, so they
|
|
256
|
+
* are the ones where a self-signed certificate is the normal setup rather than an attack.
|
|
257
|
+
* Anything else — a real domain name — is treated as public, which is the safe default: an
|
|
258
|
+
* unrecognised host fails closed into verification.
|
|
259
|
+
*/
|
|
260
|
+
export function isPrivateNetworkHost(hostOrUrl) {
|
|
261
|
+
const hostname = normalizeHostname(hostOrUrl);
|
|
262
|
+
if (!hostname)
|
|
263
|
+
return false;
|
|
264
|
+
if (hostname === 'localhost')
|
|
265
|
+
return true;
|
|
266
|
+
if (PRIVATE_HOSTNAME_SUFFIXES.some((suffix) => hostname.endsWith(suffix)))
|
|
267
|
+
return true;
|
|
268
|
+
if (/^\d{1,3}(\.\d{1,3}){3}$/.test(hostname))
|
|
269
|
+
return isPrivateIpv4(hostname);
|
|
270
|
+
if (hostname.includes(':'))
|
|
271
|
+
return isPrivateIpv6(hostname);
|
|
272
|
+
// A single-label name ("n8n-box") is an intranet name: it has no public DNS entry and no
|
|
273
|
+
// public CA will certify it.
|
|
274
|
+
return !hostname.includes('.');
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Whether the server certificate has to verify for this destination.
|
|
278
|
+
*
|
|
279
|
+
* Verification is the default. It is relaxed only where the historical zero-configuration
|
|
280
|
+
* behaviour is actually needed — a private or loopback address, which cannot hold a publicly
|
|
281
|
+
* trusted certificate — and only while the user has not configured any anchor of their own.
|
|
282
|
+
* Configuring an anchor still means "verify everywhere", so a private host does not become a
|
|
283
|
+
* hole for someone who did set the certificates up.
|
|
284
|
+
*
|
|
285
|
+
* The remaining case, a self-signed certificate on a public host name, has to opt out through
|
|
286
|
+
* {@link N8NAC_INSECURE_TLS_ENV}, because it is indistinguishable from an interception.
|
|
287
|
+
*/
|
|
288
|
+
export function shouldVerifyServerCertificate(policy) {
|
|
289
|
+
const env = policy.env ?? process.env;
|
|
290
|
+
if (/^(1|true|yes)$/i.test((env[N8NAC_INSECURE_TLS_ENV] ?? '').trim()))
|
|
291
|
+
return false;
|
|
292
|
+
if (policy.hasConfiguredAnchors)
|
|
293
|
+
return true;
|
|
294
|
+
return !isPrivateNetworkHost(policy.host);
|
|
295
|
+
}
|
|
296
|
+
/** `true` when the error is a TLS trust failure rather than a transport or HTTP error. */
|
|
297
|
+
export function isCertificateTrustError(error) {
|
|
298
|
+
const code = typeof error?.code === 'string' ? error.code : '';
|
|
299
|
+
if (code.startsWith('UNABLE_TO_') || code.startsWith('SELF_SIGNED') || code.startsWith('DEPTH_ZERO_')) {
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
if (code === 'CERT_HAS_EXPIRED' || code === 'ERR_TLS_CERT_ALTNAME_INVALID' || code === 'CERT_SIGNATURE_FAILURE') {
|
|
303
|
+
return true;
|
|
304
|
+
}
|
|
305
|
+
if (error?.cause && error.cause !== error && isCertificateTrustError(error.cause)) {
|
|
306
|
+
return true;
|
|
307
|
+
}
|
|
308
|
+
const message = String(error?.message ?? error ?? '');
|
|
309
|
+
return /unable to (get|verify)|self[- ]signed certificate|certificate has expired|CERT_/i.test(message);
|
|
310
|
+
}
|
|
311
|
+
/** Guidance appended to connection errors caused by an untrusted certificate. */
|
|
312
|
+
export const CERTIFICATE_TRUST_HINT = 'The certificate is not trusted by this process. Point "n8n.tls.certificateAuthorities" '
|
|
313
|
+
+ '(or the NODE_EXTRA_CA_CERTS environment variable) at the PEM bundle holding your root CA, then retry. '
|
|
314
|
+
+ 'The VS Code extension host cannot read Node\'s --use-system-ca flag, so the setting is the reliable path there.';
|
|
315
|
+
/**
|
|
316
|
+
* The same guidance for someone running `n8nac` in a terminal.
|
|
317
|
+
*
|
|
318
|
+
* Deliberately not {@link CERTIFICATE_TRUST_HINT}: that one points at the
|
|
319
|
+
* `n8n.tls.certificateAuthorities` VS Code setting and explains extension-host behaviour, and
|
|
320
|
+
* neither exists on the command line — following it would send a CLI user to a setting they
|
|
321
|
+
* have no way to set. The environment variables are the CLI's actual levers, and
|
|
322
|
+
* `N8NAC_EXTRA_CA_CERTS` is named first because it accepts several paths while Node's own
|
|
323
|
+
* variable takes exactly one.
|
|
324
|
+
*/
|
|
325
|
+
export const CERTIFICATE_TRUST_HINT_CLI = 'The certificate presented by the n8n instance is not trusted by this process. Point '
|
|
326
|
+
+ `${N8NAC_EXTRA_CA_CERTS_ENV} (accepts several paths) or NODE_EXTRA_CA_CERTS at the PEM bundle `
|
|
327
|
+
+ 'holding your root CA, then retry. If the instance is genuinely only reachable over a '
|
|
328
|
+
+ `self-signed certificate and you accept the risk, set ${N8NAC_INSECURE_TLS_ENV}=1 to skip verification.`;
|
|
329
|
+
//# sourceMappingURL=tls-certificates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tls-certificates.js","sourceRoot":"","sources":["../../../src/core/services/tls-certificates.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rewrites a path to POSIX separators.
|
|
3
|
+
*
|
|
4
|
+
* Workflow paths are stored POSIX-style in `.n8n-state.json` so a repository
|
|
5
|
+
* checked out on Windows and on Linux produces the same state file.
|
|
6
|
+
*/
|
|
7
|
+
export declare function toPosixRelativePath(value: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Normalises a workflow path relative to the workflows directory and rejects
|
|
10
|
+
* anything that could escape it.
|
|
11
|
+
*
|
|
12
|
+
* @param value Path as written by a user, a state file, or the CLI.
|
|
13
|
+
* @returns The normalised POSIX-relative path.
|
|
14
|
+
* @throws If the path is empty, absolute, climbs above the root, or contains a
|
|
15
|
+
* control character — all of which would let a crafted state file or filename
|
|
16
|
+
* write outside the sync scope.
|
|
17
|
+
*/
|
|
18
|
+
export declare function normalizeWorkflowRelativePath(value: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Resolves a workflow-relative path against the workflows directory.
|
|
21
|
+
*
|
|
22
|
+
* Validates before joining, so this is the only sanctioned way to turn a stored
|
|
23
|
+
* filename into an absolute path.
|
|
24
|
+
*
|
|
25
|
+
* @param root Absolute path of the workflows directory.
|
|
26
|
+
* @param relativePath Workflow-relative path (nested paths allowed).
|
|
27
|
+
*/
|
|
28
|
+
export declare function workflowRelativePathToAbsolute(root: string, relativePath: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* Inverse of {@link workflowRelativePathToAbsolute}: expresses an absolute path
|
|
31
|
+
* as a validated workflow-relative one.
|
|
32
|
+
*
|
|
33
|
+
* @throws If the file lies outside `root`.
|
|
34
|
+
*/
|
|
35
|
+
export declare function relativePathFromAbsolute(root: string, absolutePath: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* Creates the parent directory of `filePath` if it is missing.
|
|
38
|
+
*
|
|
39
|
+
* Needed since workflows can live in nested folders: the first pull or push of
|
|
40
|
+
* `Reports/Weekly/summary.workflow.ts` has to create `Reports/Weekly` first.
|
|
41
|
+
*/
|
|
42
|
+
export declare function ensureParentDirectory(filePath: string): void;
|
|
43
|
+
/**
|
|
44
|
+
* Lists every `*.workflow.ts` file under `root`, recursively.
|
|
45
|
+
*
|
|
46
|
+
* Dot-prefixed entries are skipped, so `.n8n-state.json` and `.git` never show
|
|
47
|
+
* up. Results are workflow-relative, normalised, and sorted for deterministic
|
|
48
|
+
* ordering across platforms.
|
|
49
|
+
*
|
|
50
|
+
* Synchronous by design — it runs inside the tracker's synchronous scan path.
|
|
51
|
+
* Fine for the hundreds of workflows a project realistically holds.
|
|
52
|
+
*
|
|
53
|
+
* @returns Sorted workflow-relative paths; empty when `root` does not exist.
|
|
54
|
+
*/
|
|
55
|
+
export declare function listWorkflowFilesRecursive(root: string): string[];
|
|
56
|
+
//# sourceMappingURL=workflow-path-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-path-utils.d.ts","sourceRoot":"","sources":["../../../src/core/services/workflow-path-utils.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAanE;AAED;;;;;;;;GAQG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAGzF;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAGnF;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAE5D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAmBjE"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
/**
|
|
4
|
+
* Rewrites a path to POSIX separators.
|
|
5
|
+
*
|
|
6
|
+
* Workflow paths are stored POSIX-style in `.n8n-state.json` so a repository
|
|
7
|
+
* checked out on Windows and on Linux produces the same state file.
|
|
8
|
+
*/
|
|
9
|
+
export function toPosixRelativePath(value) {
|
|
10
|
+
return value.split(path.sep).join('/').replace(/\\/g, '/');
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Normalises a workflow path relative to the workflows directory and rejects
|
|
14
|
+
* anything that could escape it.
|
|
15
|
+
*
|
|
16
|
+
* @param value Path as written by a user, a state file, or the CLI.
|
|
17
|
+
* @returns The normalised POSIX-relative path.
|
|
18
|
+
* @throws If the path is empty, absolute, climbs above the root, or contains a
|
|
19
|
+
* control character — all of which would let a crafted state file or filename
|
|
20
|
+
* write outside the sync scope.
|
|
21
|
+
*/
|
|
22
|
+
export function normalizeWorkflowRelativePath(value) {
|
|
23
|
+
const normalized = path.posix.normalize(toPosixRelativePath(value).trim());
|
|
24
|
+
if (!normalized || normalized === '.') {
|
|
25
|
+
throw new Error('Workflow path must not be empty');
|
|
26
|
+
}
|
|
27
|
+
if (normalized.startsWith('../') || normalized === '..' || path.posix.isAbsolute(normalized)) {
|
|
28
|
+
throw new Error(`Workflow path escapes the sync scope: ${value}`);
|
|
29
|
+
}
|
|
30
|
+
const parts = normalized.split('/');
|
|
31
|
+
if (parts.some((part) => !part || part === '.' || part === '..' || /[\u0000-\u001f\u007f]/.test(part))) {
|
|
32
|
+
throw new Error(`Workflow path contains an unsafe segment: ${value}`);
|
|
33
|
+
}
|
|
34
|
+
return normalized;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Resolves a workflow-relative path against the workflows directory.
|
|
38
|
+
*
|
|
39
|
+
* Validates before joining, so this is the only sanctioned way to turn a stored
|
|
40
|
+
* filename into an absolute path.
|
|
41
|
+
*
|
|
42
|
+
* @param root Absolute path of the workflows directory.
|
|
43
|
+
* @param relativePath Workflow-relative path (nested paths allowed).
|
|
44
|
+
*/
|
|
45
|
+
export function workflowRelativePathToAbsolute(root, relativePath) {
|
|
46
|
+
const safeRelativePath = normalizeWorkflowRelativePath(relativePath);
|
|
47
|
+
return path.join(root, ...safeRelativePath.split('/'));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Inverse of {@link workflowRelativePathToAbsolute}: expresses an absolute path
|
|
51
|
+
* as a validated workflow-relative one.
|
|
52
|
+
*
|
|
53
|
+
* @throws If the file lies outside `root`.
|
|
54
|
+
*/
|
|
55
|
+
export function relativePathFromAbsolute(root, absolutePath) {
|
|
56
|
+
const relative = path.relative(root, absolutePath);
|
|
57
|
+
return normalizeWorkflowRelativePath(toPosixRelativePath(relative));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Creates the parent directory of `filePath` if it is missing.
|
|
61
|
+
*
|
|
62
|
+
* Needed since workflows can live in nested folders: the first pull or push of
|
|
63
|
+
* `Reports/Weekly/summary.workflow.ts` has to create `Reports/Weekly` first.
|
|
64
|
+
*/
|
|
65
|
+
export function ensureParentDirectory(filePath) {
|
|
66
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Lists every `*.workflow.ts` file under `root`, recursively.
|
|
70
|
+
*
|
|
71
|
+
* Dot-prefixed entries are skipped, so `.n8n-state.json` and `.git` never show
|
|
72
|
+
* up. Results are workflow-relative, normalised, and sorted for deterministic
|
|
73
|
+
* ordering across platforms.
|
|
74
|
+
*
|
|
75
|
+
* Synchronous by design — it runs inside the tracker's synchronous scan path.
|
|
76
|
+
* Fine for the hundreds of workflows a project realistically holds.
|
|
77
|
+
*
|
|
78
|
+
* @returns Sorted workflow-relative paths; empty when `root` does not exist.
|
|
79
|
+
*/
|
|
80
|
+
export function listWorkflowFilesRecursive(root) {
|
|
81
|
+
const results = [];
|
|
82
|
+
const visit = (dir, relativeDir = '') => {
|
|
83
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
84
|
+
for (const entry of entries) {
|
|
85
|
+
if (entry.name.startsWith('.'))
|
|
86
|
+
continue;
|
|
87
|
+
const childRelative = relativeDir ? `${relativeDir}/${entry.name}` : entry.name;
|
|
88
|
+
const childAbsolute = path.join(dir, entry.name);
|
|
89
|
+
if (entry.isDirectory()) {
|
|
90
|
+
visit(childAbsolute, childRelative);
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (entry.isFile() && entry.name.endsWith('.workflow.ts')) {
|
|
94
|
+
results.push(normalizeWorkflowRelativePath(childRelative));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
if (fs.existsSync(root))
|
|
99
|
+
visit(root);
|
|
100
|
+
return results.sort();
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=workflow-path-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-path-utils.js","sourceRoot":"","sources":["../../../src/core/services/workflow-path-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,6 +20,8 @@ export declare class WorkflowStateTracker extends EventEmitter {
|
|
|
20
20
|
private ignoredTags;
|
|
21
21
|
private projectId;
|
|
22
22
|
private stateFilePath;
|
|
23
|
+
private folderSync;
|
|
24
|
+
private warnedFolderMetadataUnavailable;
|
|
23
25
|
private isConnected;
|
|
24
26
|
/** True during the first refreshRemoteState() call — suppresses status broadcasts */
|
|
25
27
|
private isInitialRemoteLoad;
|
|
@@ -36,11 +38,14 @@ export declare class WorkflowStateTracker extends EventEmitter {
|
|
|
36
38
|
private remoteActive;
|
|
37
39
|
/** Remote archived flag per workflow (populated by refreshRemoteState / updateSingleRemoteState). */
|
|
38
40
|
private remoteArchived;
|
|
41
|
+
private remoteParentFolderIds;
|
|
42
|
+
private remoteFolderPaths;
|
|
39
43
|
constructor(client: N8nApiClient, options: {
|
|
40
44
|
directory: string;
|
|
41
45
|
syncInactive: boolean;
|
|
42
46
|
ignoredTags: string[];
|
|
43
47
|
projectId: string;
|
|
48
|
+
folderSync?: boolean;
|
|
44
49
|
});
|
|
45
50
|
getDirectory(): string;
|
|
46
51
|
getFilenameForId(id: string): string | undefined;
|
|
@@ -89,6 +94,22 @@ export declare class WorkflowStateTracker extends EventEmitter {
|
|
|
89
94
|
calculateStatus(filename: string, workflowId?: string): WorkflowSyncStatus;
|
|
90
95
|
private shouldIgnore;
|
|
91
96
|
private safeName;
|
|
97
|
+
/**
|
|
98
|
+
* Builds the resolver that turns a remote workflow's folder into local path
|
|
99
|
+
* segments — when n8n tells us what that folder is.
|
|
100
|
+
*
|
|
101
|
+
* As of n8n 2.32 it does not: `parentFolderId` is declared `writeOnly` in the
|
|
102
|
+
* public API spec, the read handlers never load the `parentFolder` relation,
|
|
103
|
+
* and no endpoint maps workflows to folders. This holds on every edition,
|
|
104
|
+
* Enterprise included, so pull lays workflows out flat and this returns null.
|
|
105
|
+
*
|
|
106
|
+
* The detection is deliberately based on the payload rather than a version
|
|
107
|
+
* check: the day a workflow read carries folder fields, nested pulls start
|
|
108
|
+
* working with no change here.
|
|
109
|
+
*/
|
|
110
|
+
private createFolderResolver;
|
|
111
|
+
private warnFolderMetadataUnavailable;
|
|
112
|
+
private buildRelativeFilename;
|
|
92
113
|
/**
|
|
93
114
|
* Find local file that contains a specific workflow ID
|
|
94
115
|
* Used when we have an ID but no filename mapping yet (e.g., after file rename)
|
|
@@ -115,6 +136,41 @@ export declare class WorkflowStateTracker extends EventEmitter {
|
|
|
115
136
|
includeArchived?: boolean;
|
|
116
137
|
onlyArchived?: boolean;
|
|
117
138
|
}): Promise<IWorkflowStatus[]>;
|
|
139
|
+
/**
|
|
140
|
+
* Cheap drift computation for the lightweight `list` path.
|
|
141
|
+
*
|
|
142
|
+
* Single source of truth (SSOT) for the "did either side change since last sync?"
|
|
143
|
+
* question when a remote hash is not yet cached (i.e. before `n8nac fetch <id>`
|
|
144
|
+
* runs the expensive per-workflow hash roundtrip).
|
|
145
|
+
*
|
|
146
|
+
* Returns `undefined` when there is no reference state for the workflow
|
|
147
|
+
* (never pulled / first sync), so consumers can distinguish "no drift known"
|
|
148
|
+
* from "drift checked and nothing changed". Within the returned object each
|
|
149
|
+
* axis is likewise `undefined` when its input is missing, so an absent axis
|
|
150
|
+
* reads as "unknown" and never as "unchanged".
|
|
151
|
+
*
|
|
152
|
+
* Cost: O(1) Map lookups, one string compare and one timestamp parse. No AST,
|
|
153
|
+
* no I/O, no extra API calls.
|
|
154
|
+
* The data sources are already populated by the existing lightweight refresh:
|
|
155
|
+
* - `localHashes[filename]` - populated by `refreshLocalState`
|
|
156
|
+
* - `state.workflows[id]` - read from `.n8n-state.json`
|
|
157
|
+
* - `remoteTimestamp` - returned by `/api/v1/workflows` (now cached by
|
|
158
|
+
* `refreshRemoteState` into `remoteTimestamps`)
|
|
159
|
+
*/
|
|
160
|
+
private computeDrift;
|
|
161
|
+
/**
|
|
162
|
+
* True when the remote `updatedAt` is strictly newer than the recorded `lastSyncedAt`.
|
|
163
|
+
*
|
|
164
|
+
* `lastSyncedAt` is normally a verbatim copy of the remote `updatedAt` (see
|
|
165
|
+
* `updateWorkflowState`), so both sides usually share the same representation and
|
|
166
|
+
* equality means "in sync". They can still diverge in format — the fallback in
|
|
167
|
+
* `updateWorkflowState` writes a client-side `new Date().toISOString()` when the API
|
|
168
|
+
* response carried no `updatedAt`, and n8n instances differ in how they serialise
|
|
169
|
+
* timestamps. A lexical compare across two formats misreports silently (`' '` < `'T'`
|
|
170
|
+
* makes a space-separated timestamp always look older), so compare parsed instants,
|
|
171
|
+
* consistent with the existing remote-change guard in `sync-engine.ts`.
|
|
172
|
+
*/
|
|
173
|
+
private isNewerThan;
|
|
118
174
|
/**
|
|
119
175
|
* Get list of local workflow filenames (just checks file system, no parsing)
|
|
120
176
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-state-tracker.d.ts","sourceRoot":"","sources":["../../../src/core/services/workflow-state-tracker.ts"],"names":[],"mappings":"AAEA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"workflow-state-tracker.d.ts","sourceRoot":"","sources":["../../../src/core/services/workflow-state-tracker.ts"],"names":[],"mappings":"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"}
|