n8n-nodes-trusera 0.2.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.
Files changed (55) hide show
  1. package/README.md +76 -0
  2. package/dist/credentials/TruseraApi.credentials.d.ts +9 -0
  3. package/dist/credentials/TruseraApi.credentials.d.ts.map +1 -0
  4. package/dist/credentials/TruseraApi.credentials.js +39 -0
  5. package/dist/credentials/TruseraApi.credentials.js.map +1 -0
  6. package/dist/index.d.ts +7 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +23 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/lib/config.d.ts +30 -0
  11. package/dist/lib/config.d.ts.map +1 -0
  12. package/dist/lib/config.js +254 -0
  13. package/dist/lib/config.js.map +1 -0
  14. package/dist/lib/dashboardHtml.d.ts +13 -0
  15. package/dist/lib/dashboardHtml.d.ts.map +1 -0
  16. package/dist/lib/dashboardHtml.js +605 -0
  17. package/dist/lib/dashboardHtml.js.map +1 -0
  18. package/dist/lib/models.d.ts +93 -0
  19. package/dist/lib/models.d.ts.map +1 -0
  20. package/dist/lib/models.js +101 -0
  21. package/dist/lib/models.js.map +1 -0
  22. package/dist/lib/policyEngine.d.ts +22 -0
  23. package/dist/lib/policyEngine.d.ts.map +1 -0
  24. package/dist/lib/policyEngine.js +52 -0
  25. package/dist/lib/policyEngine.js.map +1 -0
  26. package/dist/lib/riskScorer.d.ts +13 -0
  27. package/dist/lib/riskScorer.d.ts.map +1 -0
  28. package/dist/lib/riskScorer.js +72 -0
  29. package/dist/lib/riskScorer.js.map +1 -0
  30. package/dist/lib/scanner.d.ts +33 -0
  31. package/dist/lib/scanner.d.ts.map +1 -0
  32. package/dist/lib/scanner.js +590 -0
  33. package/dist/lib/scanner.js.map +1 -0
  34. package/dist/nodes/TruseraDashboard/TruseraDashboard.node.d.ts +6 -0
  35. package/dist/nodes/TruseraDashboard/TruseraDashboard.node.d.ts.map +1 -0
  36. package/dist/nodes/TruseraDashboard/TruseraDashboard.node.js +66 -0
  37. package/dist/nodes/TruseraDashboard/TruseraDashboard.node.js.map +1 -0
  38. package/dist/nodes/TruseraDashboard/trusera.png +0 -0
  39. package/dist/nodes/TruseraDashboard/trusera.svg +4 -0
  40. package/dist/nodes/TruseraPolicy/TruseraPolicy.node.d.ts +6 -0
  41. package/dist/nodes/TruseraPolicy/TruseraPolicy.node.d.ts.map +1 -0
  42. package/dist/nodes/TruseraPolicy/TruseraPolicy.node.js +114 -0
  43. package/dist/nodes/TruseraPolicy/TruseraPolicy.node.js.map +1 -0
  44. package/dist/nodes/TruseraPolicy/trusera.svg +4 -0
  45. package/dist/nodes/TruseraReport/TruseraReport.node.d.ts +6 -0
  46. package/dist/nodes/TruseraReport/TruseraReport.node.d.ts.map +1 -0
  47. package/dist/nodes/TruseraReport/TruseraReport.node.js +201 -0
  48. package/dist/nodes/TruseraReport/TruseraReport.node.js.map +1 -0
  49. package/dist/nodes/TruseraReport/trusera.svg +4 -0
  50. package/dist/nodes/TruseraScan/TruseraScan.node.d.ts +6 -0
  51. package/dist/nodes/TruseraScan/TruseraScan.node.d.ts.map +1 -0
  52. package/dist/nodes/TruseraScan/TruseraScan.node.js +140 -0
  53. package/dist/nodes/TruseraScan/TruseraScan.node.js.map +1 -0
  54. package/dist/nodes/TruseraScan/trusera.svg +4 -0
  55. package/package.json +62 -0
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TruseraDashboard = void 0;
4
+ const scanner_1 = require("../../lib/scanner");
5
+ const dashboardHtml_1 = require("../../lib/dashboardHtml");
6
+ class TruseraDashboard {
7
+ constructor() {
8
+ this.description = {
9
+ displayName: 'Trusera Dashboard',
10
+ name: 'truseraDashboard',
11
+ icon: 'file:trusera.png',
12
+ group: ['output'],
13
+ version: 1,
14
+ subtitle: 'AI Security Dashboard',
15
+ description: 'Fetch all n8n workflows, scan them for AI security risks, and return an interactive HTML dashboard',
16
+ defaults: {
17
+ name: 'Trusera Dashboard',
18
+ },
19
+ inputs: ['main'],
20
+ outputs: ['main'],
21
+ credentials: [
22
+ {
23
+ name: 'truseraApi',
24
+ required: true,
25
+ },
26
+ ],
27
+ properties: [
28
+ {
29
+ displayName: 'Dashboard Password',
30
+ name: 'password',
31
+ type: 'string',
32
+ typeOptions: { password: true },
33
+ default: '',
34
+ description: 'Optional. If set, the dashboard is AES-256-GCM encrypted and visitors must enter this password to view it.',
35
+ },
36
+ ],
37
+ };
38
+ }
39
+ async execute() {
40
+ const creds = await this.getCredentials('truseraApi');
41
+ const baseUrl = creds.baseUrl.replace(/\/$/, '');
42
+ const password = this.getNodeParameter('password', 0, '');
43
+ // Fetch all workflows via n8n REST API (paginated)
44
+ const allWorkflows = [];
45
+ let cursor = null;
46
+ do {
47
+ const url = `${baseUrl}/api/v1/workflows?limit=100` +
48
+ (cursor ? `&cursor=${cursor}` : '');
49
+ const resp = await this.helpers.httpRequestWithAuthentication.call(this, 'truseraApi', { method: 'GET', url, json: true });
50
+ const data = resp;
51
+ allWorkflows.push(...data.data);
52
+ cursor = data.nextCursor ?? null;
53
+ } while (cursor);
54
+ // Scan all workflows
55
+ const workflows = allWorkflows.map((wf) => ({
56
+ data: wf,
57
+ filePath: wf.name || wf.id || 'unknown',
58
+ }));
59
+ const scanResult = (0, scanner_1.scanWorkflows)(workflows);
60
+ // Generate HTML dashboard
61
+ const html = (0, dashboardHtml_1.generateDashboardHtml)(scanResult, password || undefined);
62
+ return [[{ json: { html } }]];
63
+ }
64
+ }
65
+ exports.TruseraDashboard = TruseraDashboard;
66
+ //# sourceMappingURL=TruseraDashboard.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TruseraDashboard.node.js","sourceRoot":"","sources":["../../../nodes/TruseraDashboard/TruseraDashboard.node.ts"],"names":[],"mappings":";;;AAOA,+CAAkD;AAClD,2DAAgE;AAEhE,MAAa,gBAAgB;IAA7B;QACE,gBAAW,GAAyB;YAClC,WAAW,EAAE,mBAAmB;YAChC,IAAI,EAAE,kBAAkB;YACxB,IAAI,EAAE,kBAAkB;YACxB,KAAK,EAAE,CAAC,QAAQ,CAAC;YACjB,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,uBAAuB;YACjC,WAAW,EACT,oGAAoG;YACtG,QAAQ,EAAE;gBACR,IAAI,EAAE,mBAAmB;aAC1B;YACD,MAAM,EAAE,CAAC,MAAM,CAAC;YAChB,OAAO,EAAE,CAAC,MAAM,CAAC;YACjB,WAAW,EAAE;gBACX;oBACE,IAAI,EAAE,YAAY;oBAClB,QAAQ,EAAE,IAAI;iBACf;aACF;YACD,UAAU,EAAE;gBACV;oBACE,WAAW,EAAE,oBAAoB;oBACjC,IAAI,EAAE,UAAU;oBAChB,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;oBAC/B,OAAO,EAAE,EAAE;oBACX,WAAW,EACT,4GAA4G;iBAC/G;aACF;SACF,CAAC;IAoCJ,CAAC;IAlCC,KAAK,CAAC,OAAO;QACX,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;QACtD,MAAM,OAAO,GAAI,KAAK,CAAC,OAAkB,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,CAAW,CAAC;QAEpE,mDAAmD;QACnD,MAAM,YAAY,GAAmC,EAAE,CAAC;QACxD,IAAI,MAAM,GAAkB,IAAI,CAAC;QACjC,GAAG,CAAC;YACF,MAAM,GAAG,GACP,GAAG,OAAO,6BAA6B;gBACvC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACtC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,6BAA6B,CAAC,IAAI,CAChE,IAAI,EACJ,YAAY,EACZ,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CACnC,CAAC;YACF,MAAM,IAAI,GAAG,IAAqE,CAAC;YACnF,YAAY,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;YAChC,MAAM,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC;QACnC,CAAC,QAAQ,MAAM,EAAE;QAEjB,qBAAqB;QACrB,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YAC1C,IAAI,EAAE,EAAE;YACR,QAAQ,EAAG,EAAE,CAAC,IAAe,IAAK,EAAE,CAAC,EAAa,IAAI,SAAS;SAChE,CAAC,CAAC,CAAC;QACJ,MAAM,UAAU,GAAG,IAAA,uBAAa,EAAC,SAAS,CAAC,CAAC;QAE5C,0BAA0B;QAC1B,MAAM,IAAI,GAAG,IAAA,qCAAqB,EAAC,UAAU,EAAE,QAAQ,IAAI,SAAS,CAAC,CAAC;QAEtE,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IAChC,CAAC;CACF;AApED,4CAoEC"}
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
2
+ <path d="M32 4L56 18V46L32 60L8 46V18L32 4Z" fill="#0F172A" stroke="#3B82F6" stroke-width="2"/>
3
+ <text x="32" y="40" text-anchor="middle" font-family="Arial, sans-serif" font-size="28" font-weight="bold" fill="#3B82F6">T</text>
4
+ </svg>
@@ -0,0 +1,6 @@
1
+ import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class TruseraPolicy implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
6
+ //# sourceMappingURL=TruseraPolicy.node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TruseraPolicy.node.d.ts","sourceRoot":"","sources":["../../../nodes/TruseraPolicy/TruseraPolicy.node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,oBAAoB,EACrB,MAAM,cAAc,CAAC;AAKtB,qBAAa,aAAc,YAAW,SAAS;IAC7C,WAAW,EAAE,oBAAoB,CA8D/B;IAEI,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;CAoDxE"}
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TruseraPolicy = void 0;
4
+ const policyEngine_1 = require("../../lib/policyEngine");
5
+ class TruseraPolicy {
6
+ constructor() {
7
+ this.description = {
8
+ displayName: 'Trusera Policy',
9
+ name: 'truseraPolicy',
10
+ icon: 'file:trusera.svg',
11
+ group: ['transform'],
12
+ version: 1,
13
+ subtitle: 'Enforce AI security policy',
14
+ description: 'Evaluate AI-BOM scan results against a security policy',
15
+ defaults: {
16
+ name: 'Trusera Policy',
17
+ },
18
+ inputs: ['main'],
19
+ outputs: ['main'],
20
+ properties: [
21
+ {
22
+ displayName: 'Scan Result Field',
23
+ name: 'scanResultField',
24
+ type: 'string',
25
+ default: '',
26
+ description: 'Field containing the scan result. If empty, the entire input JSON is used.',
27
+ },
28
+ {
29
+ displayName: 'Max Critical',
30
+ name: 'maxCritical',
31
+ type: 'number',
32
+ default: 0,
33
+ description: 'Maximum number of critical-severity components allowed',
34
+ },
35
+ {
36
+ displayName: 'Max High',
37
+ name: 'maxHigh',
38
+ type: 'number',
39
+ default: -1,
40
+ description: 'Maximum number of high-severity components allowed (-1 = unlimited)',
41
+ },
42
+ {
43
+ displayName: 'Max Risk Score',
44
+ name: 'maxRiskScore',
45
+ type: 'number',
46
+ default: -1,
47
+ description: 'Maximum risk score allowed for any component (-1 = unlimited)',
48
+ },
49
+ {
50
+ displayName: 'Block Providers',
51
+ name: 'blockProviders',
52
+ type: 'string',
53
+ default: '',
54
+ description: 'Comma-separated list of AI providers to block (e.g. "OpenAI,Anthropic")',
55
+ },
56
+ {
57
+ displayName: 'Block Flags',
58
+ name: 'blockFlags',
59
+ type: 'string',
60
+ default: '',
61
+ description: 'Comma-separated list of risk flags to block (e.g. "hardcoded_api_key,no_auth")',
62
+ },
63
+ ],
64
+ };
65
+ }
66
+ async execute() {
67
+ const items = this.getInputData();
68
+ const returnData = [];
69
+ for (let i = 0; i < items.length; i++) {
70
+ const scanResultField = this.getNodeParameter('scanResultField', i, '');
71
+ const maxCritical = this.getNodeParameter('maxCritical', i, 0);
72
+ const maxHigh = this.getNodeParameter('maxHigh', i, -1);
73
+ const maxRiskScore = this.getNodeParameter('maxRiskScore', i, -1);
74
+ const blockProvidersStr = this.getNodeParameter('blockProviders', i, '');
75
+ const blockFlagsStr = this.getNodeParameter('blockFlags', i, '');
76
+ const scanResult = scanResultField
77
+ ? items[i].json[scanResultField]
78
+ : items[i].json;
79
+ if (!scanResult || !Array.isArray(scanResult.components)) {
80
+ returnData.push({
81
+ json: {
82
+ passed: false,
83
+ violations: ['Invalid scan result: missing components array'],
84
+ },
85
+ });
86
+ continue;
87
+ }
88
+ const policy = {
89
+ maxCritical,
90
+ blockProviders: blockProvidersStr
91
+ ? blockProvidersStr.split(',').map((s) => s.trim())
92
+ : [],
93
+ blockFlags: blockFlagsStr
94
+ ? blockFlagsStr.split(',').map((s) => s.trim())
95
+ : [],
96
+ };
97
+ if (maxHigh >= 0)
98
+ policy.maxHigh = maxHigh;
99
+ if (maxRiskScore >= 0)
100
+ policy.maxRiskScore = maxRiskScore;
101
+ const result = (0, policyEngine_1.evaluatePolicy)(scanResult, policy);
102
+ returnData.push({
103
+ json: {
104
+ ...result,
105
+ policyApplied: policy,
106
+ totalComponents: scanResult.components.length,
107
+ },
108
+ });
109
+ }
110
+ return [returnData];
111
+ }
112
+ }
113
+ exports.TruseraPolicy = TruseraPolicy;
114
+ //# sourceMappingURL=TruseraPolicy.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TruseraPolicy.node.js","sourceRoot":"","sources":["../../../nodes/TruseraPolicy/TruseraPolicy.node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
2
+ <path d="M32 4L56 18V46L32 60L8 46V18L32 4Z" fill="#0F172A" stroke="#3B82F6" stroke-width="2"/>
3
+ <text x="32" y="40" text-anchor="middle" font-family="Arial, sans-serif" font-size="28" font-weight="bold" fill="#3B82F6">T</text>
4
+ </svg>
@@ -0,0 +1,6 @@
1
+ import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class TruseraReport implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
6
+ //# sourceMappingURL=TruseraReport.node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TruseraReport.node.d.ts","sourceRoot":"","sources":["../../../nodes/TruseraReport/TruseraReport.node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,oBAAoB,EACrB,MAAM,cAAc,CAAC;AAMtB,qBAAa,aAAc,YAAW,SAAS;IAC7C,WAAW,EAAE,oBAAoB,CAmD/B;IAEI,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;CAqCxE"}
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TruseraReport = void 0;
4
+ const models_1 = require("../../lib/models");
5
+ const riskScorer_1 = require("../../lib/riskScorer");
6
+ class TruseraReport {
7
+ constructor() {
8
+ this.description = {
9
+ displayName: 'Trusera Report',
10
+ name: 'truseraReport',
11
+ icon: 'file:trusera.svg',
12
+ group: ['transform'],
13
+ version: 1,
14
+ subtitle: '={{$parameter["format"]}}',
15
+ description: 'Generate a human-readable AI security report from scan results',
16
+ defaults: {
17
+ name: 'Trusera Report',
18
+ },
19
+ inputs: ['main'],
20
+ outputs: ['main'],
21
+ properties: [
22
+ {
23
+ displayName: 'Scan Result Field',
24
+ name: 'scanResultField',
25
+ type: 'string',
26
+ default: '',
27
+ description: 'Field containing the scan result. If empty, the entire input JSON is used.',
28
+ },
29
+ {
30
+ displayName: 'Format',
31
+ name: 'format',
32
+ type: 'options',
33
+ noDataExpression: true,
34
+ options: [
35
+ {
36
+ name: 'Markdown',
37
+ value: 'markdown',
38
+ description: 'Generate a Markdown report',
39
+ action: 'Generate Markdown report',
40
+ },
41
+ {
42
+ name: 'JSON Summary',
43
+ value: 'jsonSummary',
44
+ description: 'Generate a compact JSON summary',
45
+ action: 'Generate JSON summary',
46
+ },
47
+ ],
48
+ default: 'markdown',
49
+ },
50
+ {
51
+ displayName: 'Include Low Severity',
52
+ name: 'includeLow',
53
+ type: 'boolean',
54
+ default: false,
55
+ description: 'Whether to include low-severity findings in the report',
56
+ },
57
+ ],
58
+ };
59
+ }
60
+ async execute() {
61
+ const items = this.getInputData();
62
+ const returnData = [];
63
+ for (let i = 0; i < items.length; i++) {
64
+ const scanResultField = this.getNodeParameter('scanResultField', i, '');
65
+ const format = this.getNodeParameter('format', i);
66
+ const includeLow = this.getNodeParameter('includeLow', i, false);
67
+ const scanResult = scanResultField
68
+ ? items[i].json[scanResultField]
69
+ : items[i].json;
70
+ if (!scanResult || !Array.isArray(scanResult.components)) {
71
+ returnData.push({
72
+ json: { error: 'Invalid scan result: missing components array' },
73
+ });
74
+ continue;
75
+ }
76
+ const filtered = includeLow
77
+ ? scanResult.components
78
+ : scanResult.components.filter((c) => c.risk.severity !== models_1.Severity.Low);
79
+ if (format === 'markdown') {
80
+ returnData.push({
81
+ json: { report: generateMarkdown(scanResult, filtered) },
82
+ });
83
+ }
84
+ else {
85
+ returnData.push({
86
+ json: generateJsonSummary(scanResult, filtered),
87
+ });
88
+ }
89
+ }
90
+ return [returnData];
91
+ }
92
+ }
93
+ exports.TruseraReport = TruseraReport;
94
+ function severityEmoji(severity) {
95
+ switch (severity) {
96
+ case 'critical': return '[CRITICAL]';
97
+ case 'high': return '[HIGH]';
98
+ case 'medium': return '[MEDIUM]';
99
+ case 'low': return '[LOW]';
100
+ default: return '';
101
+ }
102
+ }
103
+ function generateMarkdown(result, components) {
104
+ const lines = [];
105
+ lines.push('# Trusera AI-BOM Security Report');
106
+ lines.push('');
107
+ lines.push(`**Scan Date:** ${result.scanTimestamp}`);
108
+ lines.push(`**Target:** ${result.targetPath}`);
109
+ lines.push(`**AI-BOM Version:** ${result.aiBomVersion}`);
110
+ lines.push('');
111
+ // Summary
112
+ const summary = result.summary;
113
+ lines.push('## Summary');
114
+ lines.push('');
115
+ lines.push(`| Metric | Value |`);
116
+ lines.push(`| --- | --- |`);
117
+ lines.push(`| Total Components | ${summary.totalComponents} |`);
118
+ lines.push(`| Files Scanned | ${summary.totalFilesScanned} |`);
119
+ lines.push(`| Highest Risk Score | ${summary.highestRiskScore} |`);
120
+ lines.push(`| Scan Duration | ${summary.scanDurationSeconds.toFixed(2)}s |`);
121
+ lines.push('');
122
+ // Severity breakdown
123
+ if (Object.keys(summary.bySeverity).length > 0) {
124
+ lines.push('### By Severity');
125
+ lines.push('');
126
+ for (const [sev, count] of Object.entries(summary.bySeverity)) {
127
+ lines.push(`- ${severityEmoji(sev)} **${sev}**: ${count}`);
128
+ }
129
+ lines.push('');
130
+ }
131
+ // Provider breakdown
132
+ if (Object.keys(summary.byProvider).length > 0) {
133
+ lines.push('### By Provider');
134
+ lines.push('');
135
+ for (const [provider, count] of Object.entries(summary.byProvider)) {
136
+ lines.push(`- **${provider}**: ${count}`);
137
+ }
138
+ lines.push('');
139
+ }
140
+ // Findings
141
+ if (components.length > 0) {
142
+ lines.push('## Findings');
143
+ lines.push('');
144
+ const sorted = [...components].sort((a, b) => b.risk.score - a.risk.score);
145
+ for (const comp of sorted) {
146
+ lines.push(`### ${severityEmoji(comp.risk.severity)} ${comp.name} (Score: ${comp.risk.score})`);
147
+ lines.push('');
148
+ lines.push(`- **Type:** ${comp.type}`);
149
+ lines.push(`- **Provider:** ${comp.provider}`);
150
+ if (comp.modelName)
151
+ lines.push(`- **Model:** ${comp.modelName}`);
152
+ lines.push(`- **Location:** ${comp.location.filePath}`);
153
+ if (comp.location.contextSnippet) {
154
+ lines.push(`- **Context:** ${comp.location.contextSnippet}`);
155
+ }
156
+ if (comp.flags.length > 0) {
157
+ lines.push('- **Flags:**');
158
+ for (const flag of comp.flags) {
159
+ const desc = riskScorer_1.FLAG_DESCRIPTIONS[flag] || flag.replace(/_/g, ' ');
160
+ lines.push(` - \`${flag}\`: ${desc}`);
161
+ }
162
+ }
163
+ if (comp.risk.factors.length > 0) {
164
+ lines.push('- **Risk Factors:**');
165
+ for (const factor of comp.risk.factors) {
166
+ lines.push(` - ${factor}`);
167
+ }
168
+ }
169
+ lines.push('');
170
+ }
171
+ }
172
+ else {
173
+ lines.push('## Findings');
174
+ lines.push('');
175
+ lines.push('No findings above the selected severity threshold.');
176
+ lines.push('');
177
+ }
178
+ lines.push('---');
179
+ lines.push('*Generated by [Trusera AI-BOM](https://trusera.dev)*');
180
+ return lines.join('\n');
181
+ }
182
+ function generateJsonSummary(result, components) {
183
+ return {
184
+ scanTimestamp: result.scanTimestamp,
185
+ targetPath: result.targetPath,
186
+ aiBomVersion: result.aiBomVersion,
187
+ summary: result.summary,
188
+ findingsCount: components.length,
189
+ findings: components.map((c) => ({
190
+ name: c.name,
191
+ type: c.type,
192
+ provider: c.provider,
193
+ modelName: c.modelName,
194
+ severity: c.risk.severity,
195
+ score: c.risk.score,
196
+ flags: c.flags,
197
+ factors: c.risk.factors,
198
+ })),
199
+ };
200
+ }
201
+ //# sourceMappingURL=TruseraReport.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TruseraReport.node.js","sourceRoot":"","sources":["../../../nodes/TruseraReport/TruseraReport.node.ts"],"names":[],"mappings":";;;AASA,6CAA4C;AAC5C,qDAAyD;AAEzD,MAAa,aAAa;IAA1B;QACE,gBAAW,GAAyB;YAClC,WAAW,EAAE,gBAAgB;YAC7B,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,kBAAkB;YACxB,KAAK,EAAE,CAAC,WAAW,CAAC;YACpB,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,2BAA2B;YACrC,WAAW,EAAE,gEAAgE;YAC7E,QAAQ,EAAE;gBACR,IAAI,EAAE,gBAAgB;aACvB;YACD,MAAM,EAAE,CAAC,MAAM,CAAC;YAChB,OAAO,EAAE,CAAC,MAAM,CAAC;YACjB,UAAU,EAAE;gBACV;oBACE,WAAW,EAAE,mBAAmB;oBAChC,IAAI,EAAE,iBAAiB;oBACvB,IAAI,EAAE,QAAQ;oBACd,OAAO,EAAE,EAAE;oBACX,WAAW,EACT,4EAA4E;iBAC/E;gBACD;oBACE,WAAW,EAAE,QAAQ;oBACrB,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,SAAS;oBACf,gBAAgB,EAAE,IAAI;oBACtB,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,UAAU;4BAChB,KAAK,EAAE,UAAU;4BACjB,WAAW,EAAE,4BAA4B;4BACzC,MAAM,EAAE,0BAA0B;yBACnC;wBACD;4BACE,IAAI,EAAE,cAAc;4BACpB,KAAK,EAAE,aAAa;4BACpB,WAAW,EAAE,iCAAiC;4BAC9C,MAAM,EAAE,uBAAuB;yBAChC;qBACF;oBACD,OAAO,EAAE,UAAU;iBACpB;gBACD;oBACE,WAAW,EAAE,sBAAsB;oBACnC,IAAI,EAAE,YAAY;oBAClB,IAAI,EAAE,SAAS;oBACf,OAAO,EAAE,KAAK;oBACd,WAAW,EAAE,wDAAwD;iBACtE;aACF;SACF,CAAC;IAuCJ,CAAC;IArCC,KAAK,CAAC,OAAO;QACX,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QAClC,MAAM,UAAU,GAAyB,EAAE,CAAC;QAE5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,eAAe,GAAG,IAAI,CAAC,gBAAgB,CAAC,iBAAiB,EAAE,CAAC,EAAE,EAAE,CAAW,CAAC;YAClF,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,CAAW,CAAC;YAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,CAAC,YAAY,EAAE,CAAC,EAAE,KAAK,CAAY,CAAC;YAE5E,MAAM,UAAU,GAAe,eAAe;gBAC5C,CAAC,CAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAA2B;gBAC3D,CAAC,CAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAA8B,CAAC;YAE7C,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBACzD,UAAU,CAAC,IAAI,CAAC;oBACd,IAAI,EAAE,EAAE,KAAK,EAAE,+CAA+C,EAAE;iBACjE,CAAC,CAAC;gBACH,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,UAAU;gBACzB,CAAC,CAAC,UAAU,CAAC,UAAU;gBACvB,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,KAAK,iBAAQ,CAAC,GAAG,CAAC,CAAC;YAE1E,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;gBAC1B,UAAU,CAAC,IAAI,CAAC;oBACd,IAAI,EAAE,EAAE,MAAM,EAAE,gBAAgB,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE;iBACzD,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,UAAU,CAAC,IAAI,CAAC;oBACd,IAAI,EAAE,mBAAmB,CAAC,UAAU,EAAE,QAAQ,CAA2B;iBAC1E,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,CAAC,UAAU,CAAC,CAAC;IACtB,CAAC;CACF;AA3FD,sCA2FC;AAED,SAAS,aAAa,CAAC,QAAgB;IACrC,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,UAAU,CAAC,CAAC,OAAO,YAAY,CAAC;QACrC,KAAK,MAAM,CAAC,CAAC,OAAO,QAAQ,CAAC;QAC7B,KAAK,QAAQ,CAAC,CAAC,OAAO,UAAU,CAAC;QACjC,KAAK,KAAK,CAAC,CAAC,OAAO,OAAO,CAAC;QAC3B,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC;IACrB,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAkB,EAAE,UAAyB;IACrE,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;IAC/C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,kBAAkB,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC;IACrD,KAAK,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;IAC/C,KAAK,CAAC,IAAI,CAAC,uBAAuB,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;IACzD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,UAAU;IACV,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;IAC/B,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACzB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACjC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC5B,KAAK,CAAC,IAAI,CAAC,wBAAwB,OAAO,CAAC,eAAe,IAAI,CAAC,CAAC;IAChE,KAAK,CAAC,IAAI,CAAC,qBAAqB,OAAO,CAAC,iBAAiB,IAAI,CAAC,CAAC;IAC/D,KAAK,CAAC,IAAI,CAAC,0BAA0B,OAAO,CAAC,gBAAgB,IAAI,CAAC,CAAC;IACnE,KAAK,CAAC,IAAI,CAAC,qBAAqB,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC7E,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,qBAAqB;IACrB,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/C,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9D,KAAK,CAAC,IAAI,CAAC,KAAK,aAAa,CAAC,GAAG,CAAC,MAAM,GAAG,OAAO,KAAK,EAAE,CAAC,CAAC;QAC7D,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,qBAAqB;IACrB,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/C,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YACnE,KAAK,CAAC,IAAI,CAAC,OAAO,QAAQ,OAAO,KAAK,EAAE,CAAC,CAAC;QAC5C,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,WAAW;IACX,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,MAAM,MAAM,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE3E,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;YAC1B,KAAK,CAAC,IAAI,CACR,OAAO,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,IAAI,YAAY,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CACpF,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,mBAAmB,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC/C,IAAI,IAAI,CAAC,SAAS;gBAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;YACjE,KAAK,CAAC,IAAI,CAAC,mBAAmB,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;YACxD,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC;gBACjC,KAAK,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC;YAC/D,CAAC;YAED,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBAC3B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;oBAC9B,MAAM,IAAI,GAAG,8BAAiB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;oBAChE,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,OAAO,IAAI,EAAE,CAAC,CAAC;gBACzC,CAAC;YACH,CAAC;YAED,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;gBAClC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;oBACvC,KAAK,CAAC,IAAI,CAAC,OAAO,MAAM,EAAE,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC;YAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;QACjE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,KAAK,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;IAEnE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,mBAAmB,CAC1B,MAAkB,EAClB,UAAyB;IAEzB,OAAO;QACL,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,aAAa,EAAE,UAAU,CAAC,MAAM;QAChC,QAAQ,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC/B,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ;YACzB,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK;YACnB,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO;SACxB,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
2
+ <path d="M32 4L56 18V46L32 60L8 46V18L32 4Z" fill="#0F172A" stroke="#3B82F6" stroke-width="2"/>
3
+ <text x="32" y="40" text-anchor="middle" font-family="Arial, sans-serif" font-size="28" font-weight="bold" fill="#3B82F6">T</text>
4
+ </svg>
@@ -0,0 +1,6 @@
1
+ import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class TruseraScan implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
6
+ //# sourceMappingURL=TruseraScan.node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TruseraScan.node.d.ts","sourceRoot":"","sources":["../../../nodes/TruseraScan/TruseraScan.node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,oBAAoB,EACrB,MAAM,cAAc,CAAC;AAItB,qBAAa,WAAY,YAAW,SAAS;IAC3C,WAAW,EAAE,oBAAoB,CA4E/B;IAEI,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;CA4DxE"}
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TruseraScan = void 0;
4
+ const scanner_1 = require("../../lib/scanner");
5
+ class TruseraScan {
6
+ constructor() {
7
+ this.description = {
8
+ displayName: 'Trusera Scan',
9
+ name: 'truseraScan',
10
+ icon: 'file:trusera.svg',
11
+ group: ['transform'],
12
+ version: 1,
13
+ subtitle: '={{$parameter["operation"]}}',
14
+ description: 'Scan n8n workflows for AI security risks using Trusera AI-BOM',
15
+ defaults: {
16
+ name: 'Trusera Scan',
17
+ },
18
+ inputs: ['main'],
19
+ outputs: ['main'],
20
+ credentials: [
21
+ {
22
+ name: 'truseraApi',
23
+ required: false,
24
+ },
25
+ ],
26
+ properties: [
27
+ {
28
+ displayName: 'Operation',
29
+ name: 'operation',
30
+ type: 'options',
31
+ noDataExpression: true,
32
+ options: [
33
+ {
34
+ name: 'Scan Workflow JSON',
35
+ value: 'scanJson',
36
+ description: 'Scan a workflow JSON object from input',
37
+ action: 'Scan a workflow JSON object',
38
+ },
39
+ {
40
+ name: 'Scan Multiple Workflows',
41
+ value: 'scanMultiple',
42
+ description: 'Scan multiple workflow JSON objects from input array',
43
+ action: 'Scan multiple workflow JSON objects',
44
+ },
45
+ ],
46
+ default: 'scanJson',
47
+ },
48
+ {
49
+ displayName: 'Workflow JSON Field',
50
+ name: 'jsonField',
51
+ type: 'string',
52
+ default: 'json',
53
+ required: true,
54
+ description: 'Name of the input field containing the n8n workflow JSON',
55
+ displayOptions: {
56
+ show: {
57
+ operation: ['scanJson'],
58
+ },
59
+ },
60
+ },
61
+ {
62
+ displayName: 'Workflows Array Field',
63
+ name: 'arrayField',
64
+ type: 'string',
65
+ default: 'workflows',
66
+ required: true,
67
+ description: 'Name of the input field containing an array of workflow JSON objects',
68
+ displayOptions: {
69
+ show: {
70
+ operation: ['scanMultiple'],
71
+ },
72
+ },
73
+ },
74
+ {
75
+ displayName: 'File Path',
76
+ name: 'filePath',
77
+ type: 'string',
78
+ default: 'workflow.json',
79
+ required: false,
80
+ description: 'Virtual file path used in scan results for identification',
81
+ },
82
+ ],
83
+ };
84
+ }
85
+ async execute() {
86
+ const items = this.getInputData();
87
+ const returnData = [];
88
+ for (let i = 0; i < items.length; i++) {
89
+ const operation = this.getNodeParameter('operation', i);
90
+ const filePath = this.getNodeParameter('filePath', i, 'workflow.json');
91
+ if (operation === 'scanJson') {
92
+ const jsonField = this.getNodeParameter('jsonField', i);
93
+ const workflowData = items[i].json[jsonField] ?? items[i].json;
94
+ if (!(0, scanner_1.isValidWorkflow)(workflowData)) {
95
+ returnData.push({
96
+ json: {
97
+ error: 'Invalid n8n workflow JSON: missing nodes or connections',
98
+ components: [],
99
+ summary: null,
100
+ },
101
+ });
102
+ continue;
103
+ }
104
+ const components = (0, scanner_1.scanWorkflow)(workflowData, filePath);
105
+ returnData.push({
106
+ json: {
107
+ components,
108
+ totalComponents: components.length,
109
+ filePath,
110
+ },
111
+ });
112
+ }
113
+ else if (operation === 'scanMultiple') {
114
+ const arrayField = this.getNodeParameter('arrayField', i);
115
+ const workflowsArray = items[i].json[arrayField];
116
+ if (!Array.isArray(workflowsArray)) {
117
+ returnData.push({
118
+ json: {
119
+ error: `Field "${arrayField}" is not an array`,
120
+ components: [],
121
+ summary: null,
122
+ },
123
+ });
124
+ continue;
125
+ }
126
+ const workflows = workflowsArray.map((data, idx) => ({
127
+ data,
128
+ filePath: `${filePath.replace('.json', '')}_${idx}.json`,
129
+ }));
130
+ const result = (0, scanner_1.scanWorkflows)(workflows);
131
+ returnData.push({
132
+ json: result,
133
+ });
134
+ }
135
+ }
136
+ return [returnData];
137
+ }
138
+ }
139
+ exports.TruseraScan = TruseraScan;
140
+ //# sourceMappingURL=TruseraScan.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TruseraScan.node.js","sourceRoot":"","sources":["../../../nodes/TruseraScan/TruseraScan.node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
2
+ <path d="M32 4L56 18V46L32 60L8 46V18L32 4Z" fill="#0F172A" stroke="#3B82F6" stroke-width="2"/>
3
+ <text x="32" y="40" text-anchor="middle" font-family="Arial, sans-serif" font-size="28" font-weight="bold" fill="#3B82F6">T</text>
4
+ </svg>