Add risk assessment system to CLI, MCP, and N8N

Expose the full risk assessment hierarchy (assessments, scopes, nodes,
processes, threats, scenarios) with CRUD operations and scenario
linking across all three interfaces.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2026-05-20 16:24:55 +02:00
parent 797e3da52f
commit 883031830f
86 changed files with 10720 additions and 11 deletions

View File

@@ -186,6 +186,11 @@ export class Probo implements INodeType {
value: 'risk',
description: 'Manage risks',
},
{
name: 'Risk Assessment',
value: 'riskAssessment',
description: 'Manage risk assessments',
},
{
name: 'Statement of Applicability',
value: 'statementOfApplicability',

View File

@@ -35,6 +35,7 @@ import * as organization from './organization';
import * as organizationContext from './organizationContext';
import * as processingActivity from './processingActivity';
import * as rightsRequest from './rightsRequest';
import * as riskAssessment from './riskAssessment';
import * as user from './user';
import * as risk from './risk';
import * as statementOfApplicability from './statementOfApplicability';
@@ -77,6 +78,7 @@ export const resources: Record<string, ResourceModule> = {
organizationContext: organizationContext as ResourceModule,
processingActivity: processingActivity as ResourceModule,
rightsRequest: rightsRequest as ResourceModule,
riskAssessment: riskAssessment as ResourceModule,
user: user as ResourceModule,
risk: risk as ResourceModule,
statementOfApplicability: statementOfApplicability as ResourceModule,

View File

@@ -0,0 +1,109 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Organization ID',
name: 'organizationId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['create'],
},
},
default: '',
description: 'The ID of the organization',
required: true,
},
{
displayName: 'Name',
name: 'name',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['create'],
},
},
default: '',
description: 'The name of the risk assessment',
required: true,
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['create'],
},
},
options: [
{
displayName: 'Description',
name: 'description',
type: 'string',
default: '',
description: 'The description of the risk assessment',
},
],
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const organizationId = this.getNodeParameter('organizationId', itemIndex) as string;
const name = this.getNodeParameter('name', itemIndex) as string;
const additionalFields = this.getNodeParameter('additionalFields', itemIndex, {}) as {
description?: string;
};
const query = `
mutation CreateRiskAssessment($input: CreateRiskAssessmentInput!) {
createRiskAssessment(input: $input) {
riskAssessmentEdge {
node {
id
name
description
createdAt
updatedAt
}
}
}
}
`;
const input: Record<string, unknown> = {
organizationId,
name,
};
if (additionalFields.description) input.description = additionalFields.description;
const responseData = await proboApiRequest.call(this, query, { input });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,114 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scope ID',
name: 'riskAssessmentScopeId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['createNode'],
},
},
default: '',
description: 'The ID of the scope',
required: true,
},
{
displayName: 'Node Type',
name: 'nodeType',
type: 'options',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['createNode'],
},
},
options: [
{
name: 'Entity',
value: 'ENTITY',
},
{
name: 'Boundary',
value: 'BOUNDARY',
},
{
name: 'Asset',
value: 'ASSET',
},
{
name: 'Data',
value: 'DATA',
},
],
default: 'ENTITY',
description: 'The type of the node',
required: true,
},
{
displayName: 'Name',
name: 'name',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['createNode'],
},
},
default: '',
description: 'The name of the node',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const riskAssessmentScopeId = this.getNodeParameter('riskAssessmentScopeId', itemIndex) as string;
const nodeType = this.getNodeParameter('nodeType', itemIndex) as string;
const name = this.getNodeParameter('name', itemIndex) as string;
const query = `
mutation CreateRiskAssessmentNode($input: CreateRiskAssessmentNodeInput!) {
createRiskAssessmentNode(input: $input) {
riskAssessmentNodeEdge {
node {
id
riskAssessmentScopeId
nodeType
name
createdAt
updatedAt
}
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, {
input: { riskAssessmentScopeId, nodeType, name },
});
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,112 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scope ID',
name: 'riskAssessmentScopeId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['createProcess'],
},
},
default: '',
description: 'The ID of the scope',
required: true,
},
{
displayName: 'Source Node ID',
name: 'sourceNodeId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['createProcess'],
},
},
default: '',
description: 'The ID of the source node',
required: true,
},
{
displayName: 'Target Node ID',
name: 'targetNodeId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['createProcess'],
},
},
default: '',
description: 'The ID of the target node',
required: true,
},
{
displayName: 'Name',
name: 'name',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['createProcess'],
},
},
default: '',
description: 'The name of the process',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const riskAssessmentScopeId = this.getNodeParameter('riskAssessmentScopeId', itemIndex) as string;
const sourceNodeId = this.getNodeParameter('sourceNodeId', itemIndex) as string;
const targetNodeId = this.getNodeParameter('targetNodeId', itemIndex) as string;
const name = this.getNodeParameter('name', itemIndex) as string;
const query = `
mutation CreateRiskAssessmentProcess($input: CreateRiskAssessmentProcessInput!) {
createRiskAssessmentProcess(input: $input) {
riskAssessmentProcessEdge {
node {
id
riskAssessmentScopeId
sourceNodeId
targetNodeId
name
createdAt
updatedAt
}
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, {
input: { riskAssessmentScopeId, sourceNodeId, targetNodeId, name },
});
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,110 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scope ID',
name: 'riskAssessmentScopeId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['createScenario'],
},
},
default: '',
description: 'The ID of the scope',
required: true,
},
{
displayName: 'Name',
name: 'name',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['createScenario'],
},
},
default: '',
description: 'The name of the scenario',
required: true,
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['createScenario'],
},
},
options: [
{
displayName: 'Description',
name: 'description',
type: 'string',
default: '',
description: 'The description of the scenario',
},
],
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const riskAssessmentScopeId = this.getNodeParameter('riskAssessmentScopeId', itemIndex) as string;
const name = this.getNodeParameter('name', itemIndex) as string;
const additionalFields = this.getNodeParameter('additionalFields', itemIndex, {}) as {
description?: string;
};
const query = `
mutation CreateRiskAssessmentScenario($input: CreateRiskAssessmentScenarioInput!) {
createRiskAssessmentScenario(input: $input) {
riskAssessmentScenarioEdge {
node {
id
riskAssessmentScopeId
name
description
createdAt
updatedAt
}
}
}
}
`;
const input: Record<string, unknown> = {
riskAssessmentScopeId,
name,
};
if (additionalFields.description) input.description = additionalFields.description;
const responseData = await proboApiRequest.call(this, query, { input });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,80 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Risk Assessment ID',
name: 'riskAssessmentId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['createScope'],
},
},
default: '',
description: 'The ID of the risk assessment',
required: true,
},
{
displayName: 'Name',
name: 'name',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['createScope'],
},
},
default: '',
description: 'The name of the scope',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const riskAssessmentId = this.getNodeParameter('riskAssessmentId', itemIndex) as string;
const name = this.getNodeParameter('name', itemIndex) as string;
const query = `
mutation CreateRiskAssessmentScope($input: CreateRiskAssessmentScopeInput!) {
createRiskAssessmentScope(input: $input) {
riskAssessmentScopeEdge {
node {
id
riskAssessmentId
name
createdAt
updatedAt
}
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, {
input: { riskAssessmentId, name },
});
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,112 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scope ID',
name: 'riskAssessmentScopeId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['createThreat'],
},
},
default: '',
description: 'The ID of the scope',
required: true,
},
{
displayName: 'Process ID',
name: 'processId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['createThreat'],
},
},
default: '',
description: 'The ID of the process',
required: true,
},
{
displayName: 'Name',
name: 'name',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['createThreat'],
},
},
default: '',
description: 'The name of the threat',
required: true,
},
{
displayName: 'Category',
name: 'category',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['createThreat'],
},
},
default: '',
description: 'The category of the threat',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const riskAssessmentScopeId = this.getNodeParameter('riskAssessmentScopeId', itemIndex) as string;
const processId = this.getNodeParameter('processId', itemIndex) as string;
const name = this.getNodeParameter('name', itemIndex) as string;
const category = this.getNodeParameter('category', itemIndex) as string;
const query = `
mutation CreateRiskAssessmentThreat($input: CreateRiskAssessmentThreatInput!) {
createRiskAssessmentThreat(input: $input) {
riskAssessmentThreatEdge {
node {
id
riskAssessmentScopeId
processId
name
category
createdAt
updatedAt
}
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, {
input: { riskAssessmentScopeId, processId, name, category },
});
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,55 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Risk Assessment ID',
name: 'riskAssessmentId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['delete'],
},
},
default: '',
description: 'The ID of the risk assessment to delete',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const riskAssessmentId = this.getNodeParameter('riskAssessmentId', itemIndex) as string;
const query = `
mutation DeleteRiskAssessment($input: DeleteRiskAssessmentInput!) {
deleteRiskAssessment(input: $input) {
deletedRiskAssessmentId
}
}
`;
const responseData = await proboApiRequest.call(this, query, { input: { riskAssessmentId } });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,57 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Node ID',
name: 'nodeId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['deleteNode'],
},
},
default: '',
description: 'The ID of the node to delete',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const nodeId = this.getNodeParameter('nodeId', itemIndex) as string;
const query = `
mutation DeleteRiskAssessmentNode($input: DeleteRiskAssessmentNodeInput!) {
deleteRiskAssessmentNode(input: $input) {
deletedRiskAssessmentNodeId
}
}
`;
const responseData = await proboApiRequest.call(this, query, {
input: { riskAssessmentNodeId: nodeId },
});
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,57 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Process ID',
name: 'processId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['deleteProcess'],
},
},
default: '',
description: 'The ID of the process to delete',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const processId = this.getNodeParameter('processId', itemIndex) as string;
const query = `
mutation DeleteRiskAssessmentProcess($input: DeleteRiskAssessmentProcessInput!) {
deleteRiskAssessmentProcess(input: $input) {
deletedRiskAssessmentProcessId
}
}
`;
const responseData = await proboApiRequest.call(this, query, {
input: { riskAssessmentProcessId: processId },
});
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,57 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scenario ID',
name: 'scenarioId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['deleteScenario'],
},
},
default: '',
description: 'The ID of the scenario to delete',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const scenarioId = this.getNodeParameter('scenarioId', itemIndex) as string;
const query = `
mutation DeleteRiskAssessmentScenario($input: DeleteRiskAssessmentScenarioInput!) {
deleteRiskAssessmentScenario(input: $input) {
deletedRiskAssessmentScenarioId
}
}
`;
const responseData = await proboApiRequest.call(this, query, {
input: { riskAssessmentScenarioId: scenarioId },
});
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,57 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scope ID',
name: 'scopeId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['deleteScope'],
},
},
default: '',
description: 'The ID of the scope to delete',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const scopeId = this.getNodeParameter('scopeId', itemIndex) as string;
const query = `
mutation DeleteRiskAssessmentScope($input: DeleteRiskAssessmentScopeInput!) {
deleteRiskAssessmentScope(input: $input) {
deletedRiskAssessmentScopeId
}
}
`;
const responseData = await proboApiRequest.call(this, query, {
input: { riskAssessmentScopeId: scopeId },
});
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,57 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Threat ID',
name: 'threatId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['deleteThreat'],
},
},
default: '',
description: 'The ID of the threat to delete',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const threatId = this.getNodeParameter('threatId', itemIndex) as string;
const query = `
mutation DeleteRiskAssessmentThreat($input: DeleteRiskAssessmentThreatInput!) {
deleteRiskAssessmentThreat(input: $input) {
deletedRiskAssessmentThreatId
}
}
`;
const responseData = await proboApiRequest.call(this, query, {
input: { riskAssessmentThreatId: threatId },
});
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,65 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Risk Assessment ID',
name: 'riskAssessmentId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['get'],
},
},
default: '',
description: 'The ID of the risk assessment',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const riskAssessmentId = this.getNodeParameter('riskAssessmentId', itemIndex) as string;
const query = `
query GetRiskAssessment($id: ID!) {
node(id: $id) {
... on RiskAssessment {
id
name
description
createdAt
updatedAt
}
}
}
`;
const variables = {
id: riskAssessmentId,
};
const responseData = await proboApiRequest.call(this, query, variables);
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,114 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData, IDataObject } from 'n8n-workflow';
import { proboApiRequestAllItems } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Organization ID',
name: 'organizationId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getAll'],
},
},
default: '',
description: 'The ID of the organization',
required: true,
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getAll'],
},
},
default: false,
description: 'Whether to return all results or only up to a given limit',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getAll'],
returnAll: [false],
},
},
typeOptions: {
minValue: 1,
},
default: 50,
description: 'Max number of results to return',
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const organizationId = this.getNodeParameter('organizationId', itemIndex) as string;
const returnAll = this.getNodeParameter('returnAll', itemIndex) as boolean;
const limit = this.getNodeParameter('limit', itemIndex, 50) as number;
const query = `
query GetRiskAssessments($organizationId: ID!, $first: Int, $after: CursorKey) {
node(id: $organizationId) {
... on Organization {
riskAssessments(first: $first, after: $after) {
edges {
node {
id
name
description
createdAt
updatedAt
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
}
`;
const riskAssessments = await proboApiRequestAllItems.call(
this,
query,
{ organizationId },
(response) => {
const data = response?.data as IDataObject | undefined;
const node = data?.node as IDataObject | undefined;
return node?.riskAssessments as IDataObject | undefined;
},
returnAll,
limit,
);
return {
json: { riskAssessments },
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,115 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData, IDataObject } from 'n8n-workflow';
import { proboApiRequestAllItems } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scope ID',
name: 'scopeId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getAllNodes'],
},
},
default: '',
description: 'The ID of the scope',
required: true,
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getAllNodes'],
},
},
default: false,
description: 'Whether to return all results or only up to a given limit',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getAllNodes'],
returnAll: [false],
},
},
typeOptions: {
minValue: 1,
},
default: 50,
description: 'Max number of results to return',
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const scopeId = this.getNodeParameter('scopeId', itemIndex) as string;
const returnAll = this.getNodeParameter('returnAll', itemIndex) as boolean;
const limit = this.getNodeParameter('limit', itemIndex, 50) as number;
const query = `
query GetNodes($scopeId: ID!, $first: Int, $after: CursorKey) {
node(id: $scopeId) {
... on RiskAssessmentScope {
nodes(first: $first, after: $after) {
edges {
node {
id
riskAssessmentScopeId
nodeType
name
createdAt
updatedAt
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
}
`;
const nodes = await proboApiRequestAllItems.call(
this,
query,
{ scopeId },
(response) => {
const data = response?.data as IDataObject | undefined;
const node = data?.node as IDataObject | undefined;
return node?.nodes as IDataObject | undefined;
},
returnAll,
limit,
);
return {
json: { nodes },
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,116 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData, IDataObject } from 'n8n-workflow';
import { proboApiRequestAllItems } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scope ID',
name: 'scopeId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getAllProcesses'],
},
},
default: '',
description: 'The ID of the scope',
required: true,
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getAllProcesses'],
},
},
default: false,
description: 'Whether to return all results or only up to a given limit',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getAllProcesses'],
returnAll: [false],
},
},
typeOptions: {
minValue: 1,
},
default: 50,
description: 'Max number of results to return',
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const scopeId = this.getNodeParameter('scopeId', itemIndex) as string;
const returnAll = this.getNodeParameter('returnAll', itemIndex) as boolean;
const limit = this.getNodeParameter('limit', itemIndex, 50) as number;
const query = `
query GetProcesses($scopeId: ID!, $first: Int, $after: CursorKey) {
node(id: $scopeId) {
... on RiskAssessmentScope {
processes(first: $first, after: $after) {
edges {
node {
id
riskAssessmentScopeId
sourceNodeId
targetNodeId
name
createdAt
updatedAt
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
}
`;
const processes = await proboApiRequestAllItems.call(
this,
query,
{ scopeId },
(response) => {
const data = response?.data as IDataObject | undefined;
const node = data?.node as IDataObject | undefined;
return node?.processes as IDataObject | undefined;
},
returnAll,
limit,
);
return {
json: { processes },
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,115 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData, IDataObject } from 'n8n-workflow';
import { proboApiRequestAllItems } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scope ID',
name: 'scopeId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getAllScenarios'],
},
},
default: '',
description: 'The ID of the scope',
required: true,
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getAllScenarios'],
},
},
default: false,
description: 'Whether to return all results or only up to a given limit',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getAllScenarios'],
returnAll: [false],
},
},
typeOptions: {
minValue: 1,
},
default: 50,
description: 'Max number of results to return',
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const scopeId = this.getNodeParameter('scopeId', itemIndex) as string;
const returnAll = this.getNodeParameter('returnAll', itemIndex) as boolean;
const limit = this.getNodeParameter('limit', itemIndex, 50) as number;
const query = `
query GetScenarios($scopeId: ID!, $first: Int, $after: CursorKey) {
node(id: $scopeId) {
... on RiskAssessmentScope {
scenarios(first: $first, after: $after) {
edges {
node {
id
riskAssessmentScopeId
name
description
createdAt
updatedAt
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
}
`;
const scenarios = await proboApiRequestAllItems.call(
this,
query,
{ scopeId },
(response) => {
const data = response?.data as IDataObject | undefined;
const node = data?.node as IDataObject | undefined;
return node?.scenarios as IDataObject | undefined;
},
returnAll,
limit,
);
return {
json: { scenarios },
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,114 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData, IDataObject } from 'n8n-workflow';
import { proboApiRequestAllItems } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Risk Assessment ID',
name: 'riskAssessmentId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getAllScopes'],
},
},
default: '',
description: 'The ID of the risk assessment',
required: true,
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getAllScopes'],
},
},
default: false,
description: 'Whether to return all results or only up to a given limit',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getAllScopes'],
returnAll: [false],
},
},
typeOptions: {
minValue: 1,
},
default: 50,
description: 'Max number of results to return',
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const riskAssessmentId = this.getNodeParameter('riskAssessmentId', itemIndex) as string;
const returnAll = this.getNodeParameter('returnAll', itemIndex) as boolean;
const limit = this.getNodeParameter('limit', itemIndex, 50) as number;
const query = `
query GetScopes($riskAssessmentId: ID!, $first: Int, $after: CursorKey) {
node(id: $riskAssessmentId) {
... on RiskAssessment {
scopes(first: $first, after: $after) {
edges {
node {
id
riskAssessmentId
name
createdAt
updatedAt
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
}
`;
const scopes = await proboApiRequestAllItems.call(
this,
query,
{ riskAssessmentId },
(response) => {
const data = response?.data as IDataObject | undefined;
const node = data?.node as IDataObject | undefined;
return node?.scopes as IDataObject | undefined;
},
returnAll,
limit,
);
return {
json: { scopes },
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,116 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData, IDataObject } from 'n8n-workflow';
import { proboApiRequestAllItems } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scope ID',
name: 'scopeId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getAllThreats'],
},
},
default: '',
description: 'The ID of the scope',
required: true,
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getAllThreats'],
},
},
default: false,
description: 'Whether to return all results or only up to a given limit',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getAllThreats'],
returnAll: [false],
},
},
typeOptions: {
minValue: 1,
},
default: 50,
description: 'Max number of results to return',
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const scopeId = this.getNodeParameter('scopeId', itemIndex) as string;
const returnAll = this.getNodeParameter('returnAll', itemIndex) as boolean;
const limit = this.getNodeParameter('limit', itemIndex, 50) as number;
const query = `
query GetThreats($scopeId: ID!, $first: Int, $after: CursorKey) {
node(id: $scopeId) {
... on RiskAssessmentScope {
threats(first: $first, after: $after) {
edges {
node {
id
riskAssessmentScopeId
processId
name
category
createdAt
updatedAt
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
}
`;
const threats = await proboApiRequestAllItems.call(
this,
query,
{ scopeId },
(response) => {
const data = response?.data as IDataObject | undefined;
const node = data?.node as IDataObject | undefined;
return node?.threats as IDataObject | undefined;
},
returnAll,
limit,
);
return {
json: { threats },
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,62 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Node ID',
name: 'nodeId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getNode'],
},
},
default: '',
description: 'The ID of the node',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const nodeId = this.getNodeParameter('nodeId', itemIndex) as string;
const query = `
query GetRiskAssessmentNode($id: ID!) {
node(id: $id) {
... on RiskAssessmentNode {
id
riskAssessmentScopeId
nodeType
name
createdAt
updatedAt
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, { id: nodeId });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,63 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Process ID',
name: 'processId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getProcess'],
},
},
default: '',
description: 'The ID of the process',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const processId = this.getNodeParameter('processId', itemIndex) as string;
const query = `
query GetRiskAssessmentProcess($id: ID!) {
node(id: $id) {
... on RiskAssessmentProcess {
id
riskAssessmentScopeId
sourceNodeId
targetNodeId
name
createdAt
updatedAt
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, { id: processId });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,62 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scenario ID',
name: 'scenarioId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getScenario'],
},
},
default: '',
description: 'The ID of the scenario',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const scenarioId = this.getNodeParameter('scenarioId', itemIndex) as string;
const query = `
query GetRiskAssessmentScenario($id: ID!) {
node(id: $id) {
... on RiskAssessmentScenario {
id
riskAssessmentScopeId
name
description
createdAt
updatedAt
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, { id: scenarioId });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,61 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scope ID',
name: 'scopeId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getScope'],
},
},
default: '',
description: 'The ID of the scope',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const scopeId = this.getNodeParameter('scopeId', itemIndex) as string;
const query = `
query GetRiskAssessmentScope($id: ID!) {
node(id: $id) {
... on RiskAssessmentScope {
id
riskAssessmentId
name
createdAt
updatedAt
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, { id: scopeId });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,59 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scope ID',
name: 'scopeId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getScopeMermaidChart'],
},
},
default: '',
description: 'The ID of the risk assessment scope',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const scopeId = this.getNodeParameter('scopeId', itemIndex) as string;
const query = `
query GetScopeMermaidChart($id: ID!) {
node(id: $id) {
... on RiskAssessmentScope {
id
name
mermaidChart
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, { id: scopeId });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,63 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Threat ID',
name: 'threatId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['getThreat'],
},
},
default: '',
description: 'The ID of the threat',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const threatId = this.getNodeParameter('threatId', itemIndex) as string;
const query = `
query GetRiskAssessmentThreat($id: ID!) {
node(id: $id) {
... on RiskAssessmentThreat {
id
riskAssessmentScopeId
processId
name
category
createdAt
updatedAt
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, { id: threatId });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,345 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties } from 'n8n-workflow';
import * as createOp from './create.operation';
import * as getOp from './get.operation';
import * as getAllOp from './getAll.operation';
import * as updateOp from './update.operation';
import * as deleteOp from './delete.operation';
import * as createScopeOp from './createScope.operation';
import * as getScopeOp from './getScope.operation';
import * as getAllScopesOp from './getAllScopes.operation';
import * as updateScopeOp from './updateScope.operation';
import * as deleteScopeOp from './deleteScope.operation';
import * as getScopeMermaidChartOp from './getScopeMermaidChart.operation';
import * as createNodeOp from './createNode.operation';
import * as getNodeOp from './getNode.operation';
import * as getAllNodesOp from './getAllNodes.operation';
import * as updateNodeOp from './updateNode.operation';
import * as deleteNodeOp from './deleteNode.operation';
import * as createProcessOp from './createProcess.operation';
import * as getProcessOp from './getProcess.operation';
import * as getAllProcessesOp from './getAllProcesses.operation';
import * as updateProcessOp from './updateProcess.operation';
import * as deleteProcessOp from './deleteProcess.operation';
import * as createThreatOp from './createThreat.operation';
import * as getThreatOp from './getThreat.operation';
import * as getAllThreatsOp from './getAllThreats.operation';
import * as updateThreatOp from './updateThreat.operation';
import * as deleteThreatOp from './deleteThreat.operation';
import * as createScenarioOp from './createScenario.operation';
import * as getScenarioOp from './getScenario.operation';
import * as getAllScenariosOp from './getAllScenarios.operation';
import * as updateScenarioOp from './updateScenario.operation';
import * as deleteScenarioOp from './deleteScenario.operation';
import * as linkScenarioThreatOp from './linkScenarioThreat.operation';
import * as unlinkScenarioThreatOp from './unlinkScenarioThreat.operation';
import * as linkScenarioRiskOp from './linkScenarioRisk.operation';
import * as unlinkScenarioRiskOp from './unlinkScenarioRisk.operation';
export const description: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['riskAssessment'],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a risk assessment',
action: 'Create a risk assessment',
},
{
name: 'Create Node',
value: 'createNode',
description: 'Create a node in a scope',
action: 'Create a node',
},
{
name: 'Create Process',
value: 'createProcess',
description: 'Create a process in a scope',
action: 'Create a process',
},
{
name: 'Create Scenario',
value: 'createScenario',
description: 'Create a scenario in a scope',
action: 'Create a scenario',
},
{
name: 'Create Scope',
value: 'createScope',
description: 'Create a scope in a risk assessment',
action: 'Create a scope',
},
{
name: 'Create Threat',
value: 'createThreat',
description: 'Create a threat in a scope',
action: 'Create a threat',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete a risk assessment',
action: 'Delete a risk assessment',
},
{
name: 'Delete Node',
value: 'deleteNode',
description: 'Delete a node',
action: 'Delete a node',
},
{
name: 'Delete Process',
value: 'deleteProcess',
description: 'Delete a process',
action: 'Delete a process',
},
{
name: 'Delete Scenario',
value: 'deleteScenario',
description: 'Delete a scenario',
action: 'Delete a scenario',
},
{
name: 'Delete Scope',
value: 'deleteScope',
description: 'Delete a scope',
action: 'Delete a scope',
},
{
name: 'Delete Threat',
value: 'deleteThreat',
description: 'Delete a threat',
action: 'Delete a threat',
},
{
name: 'Get',
value: 'get',
description: 'Get a risk assessment',
action: 'Get a risk assessment',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Get many risk assessments',
action: 'Get many risk assessments',
},
{
name: 'Get Many Nodes',
value: 'getAllNodes',
action: 'Get many nodes',
},
{
name: 'Get Many Processes',
value: 'getAllProcesses',
action: 'Get many processes',
},
{
name: 'Get Many Scenarios',
value: 'getAllScenarios',
action: 'Get many scenarios',
},
{
name: 'Get Many Scopes',
value: 'getAllScopes',
action: 'Get many scopes',
},
{
name: 'Get Many Threats',
value: 'getAllThreats',
action: 'Get many threats',
},
{
name: 'Get Node',
value: 'getNode',
description: 'Get a node',
action: 'Get a node',
},
{
name: 'Get Process',
value: 'getProcess',
description: 'Get a process',
action: 'Get a process',
},
{
name: 'Get Scenario',
value: 'getScenario',
description: 'Get a scenario',
action: 'Get a scenario',
},
{
name: 'Get Scope',
value: 'getScope',
description: 'Get a scope',
action: 'Get a scope',
},
{
name: 'Get Scope Mermaid Chart',
value: 'getScopeMermaidChart',
description: 'Get the Mermaid diagram for a scope',
action: 'Get a scope mermaid chart',
},
{
name: 'Get Threat',
value: 'getThreat',
description: 'Get a threat',
action: 'Get a threat',
},
{
name: 'Link Scenario Risk',
value: 'linkScenarioRisk',
description: 'Link a scenario to a risk',
action: 'Link a scenario to a risk',
},
{
name: 'Link Scenario Threat',
value: 'linkScenarioThreat',
description: 'Link a scenario to a threat',
action: 'Link a scenario to a threat',
},
{
name: 'Unlink Scenario Risk',
value: 'unlinkScenarioRisk',
description: 'Unlink a scenario from a risk',
action: 'Unlink a scenario from a risk',
},
{
name: 'Unlink Scenario Threat',
value: 'unlinkScenarioThreat',
description: 'Unlink a scenario from a threat',
action: 'Unlink a scenario from a threat',
},
{
name: 'Update',
value: 'update',
description: 'Update a risk assessment',
action: 'Update a risk assessment',
},
{
name: 'Update Node',
value: 'updateNode',
description: 'Update a node',
action: 'Update a node',
},
{
name: 'Update Process',
value: 'updateProcess',
description: 'Update a process',
action: 'Update a process',
},
{
name: 'Update Scenario',
value: 'updateScenario',
description: 'Update a scenario',
action: 'Update a scenario',
},
{
name: 'Update Scope',
value: 'updateScope',
description: 'Update a scope',
action: 'Update a scope',
},
{
name: 'Update Threat',
value: 'updateThreat',
description: 'Update a threat',
action: 'Update a threat',
},
],
default: 'create',
},
...createOp.description,
...getOp.description,
...getAllOp.description,
...updateOp.description,
...deleteOp.description,
...createScopeOp.description,
...getScopeOp.description,
...getAllScopesOp.description,
...updateScopeOp.description,
...deleteScopeOp.description,
...getScopeMermaidChartOp.description,
...createNodeOp.description,
...getNodeOp.description,
...getAllNodesOp.description,
...updateNodeOp.description,
...deleteNodeOp.description,
...createProcessOp.description,
...getProcessOp.description,
...getAllProcessesOp.description,
...updateProcessOp.description,
...deleteProcessOp.description,
...createThreatOp.description,
...getThreatOp.description,
...getAllThreatsOp.description,
...updateThreatOp.description,
...deleteThreatOp.description,
...createScenarioOp.description,
...getScenarioOp.description,
...getAllScenariosOp.description,
...updateScenarioOp.description,
...deleteScenarioOp.description,
...linkScenarioThreatOp.description,
...unlinkScenarioThreatOp.description,
...linkScenarioRiskOp.description,
...unlinkScenarioRiskOp.description,
];
export {
createOp as create,
getOp as get,
getAllOp as getAll,
updateOp as update,
deleteOp as delete,
createScopeOp as createScope,
getScopeOp as getScope,
getAllScopesOp as getAllScopes,
updateScopeOp as updateScope,
deleteScopeOp as deleteScope,
getScopeMermaidChartOp as getScopeMermaidChart,
createNodeOp as createNode,
getNodeOp as getNode,
getAllNodesOp as getAllNodes,
updateNodeOp as updateNode,
deleteNodeOp as deleteNode,
createProcessOp as createProcess,
getProcessOp as getProcess,
getAllProcessesOp as getAllProcesses,
updateProcessOp as updateProcess,
deleteProcessOp as deleteProcess,
createThreatOp as createThreat,
getThreatOp as getThreat,
getAllThreatsOp as getAllThreats,
updateThreatOp as updateThreat,
deleteThreatOp as deleteThreat,
createScenarioOp as createScenario,
getScenarioOp as getScenario,
getAllScenariosOp as getAllScenarios,
updateScenarioOp as updateScenario,
deleteScenarioOp as deleteScenario,
linkScenarioThreatOp as linkScenarioThreat,
unlinkScenarioThreatOp as unlinkScenarioThreat,
linkScenarioRiskOp as linkScenarioRisk,
unlinkScenarioRiskOp as unlinkScenarioRisk,
};

View File

@@ -0,0 +1,75 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scenario ID',
name: 'riskAssessmentScenarioId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['linkScenarioRisk'],
},
},
default: '',
description: 'The ID of the scenario',
required: true,
},
{
displayName: 'Risk ID',
name: 'riskId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['linkScenarioRisk'],
},
},
default: '',
description: 'The ID of the risk to link',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const riskAssessmentScenarioId = this.getNodeParameter('riskAssessmentScenarioId', itemIndex) as string;
const riskId = this.getNodeParameter('riskId', itemIndex) as string;
const query = `
mutation LinkRiskAssessmentScenarioRisk($input: LinkRiskAssessmentScenarioRiskInput!) {
linkRiskAssessmentScenarioRisk(input: $input) {
riskAssessmentScenario {
id
name
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, {
input: { riskAssessmentScenarioId, riskId },
});
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,75 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scenario ID',
name: 'riskAssessmentScenarioId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['linkScenarioThreat'],
},
},
default: '',
description: 'The ID of the scenario',
required: true,
},
{
displayName: 'Threat ID',
name: 'threatId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['linkScenarioThreat'],
},
},
default: '',
description: 'The ID of the threat to link',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const riskAssessmentScenarioId = this.getNodeParameter('riskAssessmentScenarioId', itemIndex) as string;
const threatId = this.getNodeParameter('threatId', itemIndex) as string;
const query = `
mutation LinkRiskAssessmentScenarioThreat($input: LinkRiskAssessmentScenarioThreatInput!) {
linkRiskAssessmentScenarioThreat(input: $input) {
riskAssessmentScenario {
id
name
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, {
input: { riskAssessmentScenarioId, threatId },
});
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,75 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scenario ID',
name: 'riskAssessmentScenarioId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['unlinkScenarioRisk'],
},
},
default: '',
description: 'The ID of the scenario',
required: true,
},
{
displayName: 'Risk ID',
name: 'riskId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['unlinkScenarioRisk'],
},
},
default: '',
description: 'The ID of the risk to unlink',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const riskAssessmentScenarioId = this.getNodeParameter('riskAssessmentScenarioId', itemIndex) as string;
const riskId = this.getNodeParameter('riskId', itemIndex) as string;
const query = `
mutation UnlinkRiskAssessmentScenarioRisk($input: UnlinkRiskAssessmentScenarioRiskInput!) {
unlinkRiskAssessmentScenarioRisk(input: $input) {
riskAssessmentScenario {
id
name
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, {
input: { riskAssessmentScenarioId, riskId },
});
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,75 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scenario ID',
name: 'riskAssessmentScenarioId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['unlinkScenarioThreat'],
},
},
default: '',
description: 'The ID of the scenario',
required: true,
},
{
displayName: 'Threat ID',
name: 'threatId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['unlinkScenarioThreat'],
},
},
default: '',
description: 'The ID of the threat to unlink',
required: true,
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const riskAssessmentScenarioId = this.getNodeParameter('riskAssessmentScenarioId', itemIndex) as string;
const threatId = this.getNodeParameter('threatId', itemIndex) as string;
const query = `
mutation UnlinkRiskAssessmentScenarioThreat($input: UnlinkRiskAssessmentScenarioThreatInput!) {
unlinkRiskAssessmentScenarioThreat(input: $input) {
riskAssessmentScenario {
id
name
}
}
}
`;
const responseData = await proboApiRequest.call(this, query, {
input: { riskAssessmentScenarioId, threatId },
});
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,102 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Risk Assessment ID',
name: 'riskAssessmentId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['update'],
},
},
default: '',
description: 'The ID of the risk assessment to update',
required: true,
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['update'],
},
},
options: [
{
displayName: 'Description',
name: 'description',
type: 'string',
default: '',
description: 'The description of the risk assessment',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
description: 'The name of the risk assessment',
},
],
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const riskAssessmentId = this.getNodeParameter('riskAssessmentId', itemIndex) as string;
const additionalFields = this.getNodeParameter('additionalFields', itemIndex, {}) as {
name?: string;
description?: string;
};
const query = `
mutation UpdateRiskAssessment($input: UpdateRiskAssessmentInput!) {
updateRiskAssessment(input: $input) {
riskAssessment {
id
name
description
createdAt
updatedAt
}
}
}
`;
const input: Record<string, unknown> = { id: riskAssessmentId };
if (additionalFields.name) input.name = additionalFields.name;
if (additionalFields.description !== undefined) input.description = additionalFields.description === '' ? null : additionalFields.description;
if (Object.keys(input).length === 1) {
throw new Error('At least one field must be provided to update');
}
const responseData = await proboApiRequest.call(this, query, { input });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,121 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Node ID',
name: 'nodeId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['updateNode'],
},
},
default: '',
description: 'The ID of the node to update',
required: true,
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['updateNode'],
},
},
options: [
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
description: 'The name of the node',
},
{
displayName: 'Node Type',
name: 'nodeType',
type: 'options',
options: [
{
name: 'Entity',
value: 'ENTITY',
},
{
name: 'Boundary',
value: 'BOUNDARY',
},
{
name: 'Asset',
value: 'ASSET',
},
{
name: 'Data',
value: 'DATA',
},
],
default: 'ENTITY',
description: 'The type of the node',
},
],
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const nodeId = this.getNodeParameter('nodeId', itemIndex) as string;
const additionalFields = this.getNodeParameter('additionalFields', itemIndex, {}) as {
name?: string;
nodeType?: string;
};
const query = `
mutation UpdateRiskAssessmentNode($input: UpdateRiskAssessmentNodeInput!) {
updateRiskAssessmentNode(input: $input) {
riskAssessmentNode {
id
riskAssessmentScopeId
nodeType
name
createdAt
updatedAt
}
}
}
`;
const input: Record<string, unknown> = { id: nodeId };
if (additionalFields.name) input.name = additionalFields.name;
if (additionalFields.nodeType) input.nodeType = additionalFields.nodeType;
if (Object.keys(input).length === 1) {
throw new Error('At least one field must be provided to update');
}
const responseData = await proboApiRequest.call(this, query, { input });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,113 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Process ID',
name: 'processId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['updateProcess'],
},
},
default: '',
description: 'The ID of the process to update',
required: true,
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['updateProcess'],
},
},
options: [
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
description: 'The name of the process',
},
{
displayName: 'Source Node ID',
name: 'sourceNodeId',
type: 'string',
default: '',
description: 'The ID of the source node',
},
{
displayName: 'Target Node ID',
name: 'targetNodeId',
type: 'string',
default: '',
description: 'The ID of the target node',
},
],
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const processId = this.getNodeParameter('processId', itemIndex) as string;
const additionalFields = this.getNodeParameter('additionalFields', itemIndex, {}) as {
name?: string;
sourceNodeId?: string;
targetNodeId?: string;
};
const query = `
mutation UpdateRiskAssessmentProcess($input: UpdateRiskAssessmentProcessInput!) {
updateRiskAssessmentProcess(input: $input) {
riskAssessmentProcess {
id
riskAssessmentScopeId
sourceNodeId
targetNodeId
name
createdAt
updatedAt
}
}
}
`;
const input: Record<string, unknown> = { id: processId };
if (additionalFields.name) input.name = additionalFields.name;
if (additionalFields.sourceNodeId) input.sourceNodeId = additionalFields.sourceNodeId;
if (additionalFields.targetNodeId) input.targetNodeId = additionalFields.targetNodeId;
if (Object.keys(input).length === 1) {
throw new Error('At least one field must be provided to update');
}
const responseData = await proboApiRequest.call(this, query, { input });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,103 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scenario ID',
name: 'scenarioId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['updateScenario'],
},
},
default: '',
description: 'The ID of the scenario to update',
required: true,
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['updateScenario'],
},
},
options: [
{
displayName: 'Description',
name: 'description',
type: 'string',
default: '',
description: 'The description of the scenario',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
description: 'The name of the scenario',
},
],
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const scenarioId = this.getNodeParameter('scenarioId', itemIndex) as string;
const additionalFields = this.getNodeParameter('additionalFields', itemIndex, {}) as {
name?: string;
description?: string;
};
const query = `
mutation UpdateRiskAssessmentScenario($input: UpdateRiskAssessmentScenarioInput!) {
updateRiskAssessmentScenario(input: $input) {
riskAssessmentScenario {
id
riskAssessmentScopeId
name
description
createdAt
updatedAt
}
}
}
`;
const input: Record<string, unknown> = { id: scenarioId };
if (additionalFields.name) input.name = additionalFields.name;
if (additionalFields.description !== undefined) input.description = additionalFields.description === '' ? null : additionalFields.description;
if (Object.keys(input).length === 1) {
throw new Error('At least one field must be provided to update');
}
const responseData = await proboApiRequest.call(this, query, { input });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,93 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Scope ID',
name: 'scopeId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['updateScope'],
},
},
default: '',
description: 'The ID of the scope to update',
required: true,
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['updateScope'],
},
},
options: [
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
description: 'The name of the scope',
},
],
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const scopeId = this.getNodeParameter('scopeId', itemIndex) as string;
const additionalFields = this.getNodeParameter('additionalFields', itemIndex, {}) as {
name?: string;
};
const query = `
mutation UpdateRiskAssessmentScope($input: UpdateRiskAssessmentScopeInput!) {
updateRiskAssessmentScope(input: $input) {
riskAssessmentScope {
id
riskAssessmentId
name
createdAt
updatedAt
}
}
}
`;
const input: Record<string, unknown> = { id: scopeId };
if (additionalFields.name) input.name = additionalFields.name;
if (Object.keys(input).length === 1) {
throw new Error('At least one field must be provided to update');
}
const responseData = await proboApiRequest.call(this, query, { input });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}

View File

@@ -0,0 +1,113 @@
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { proboApiRequest } from '../../GenericFunctions';
export const description: INodeProperties[] = [
{
displayName: 'Threat ID',
name: 'threatId',
type: 'string',
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['updateThreat'],
},
},
default: '',
description: 'The ID of the threat to update',
required: true,
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['riskAssessment'],
operation: ['updateThreat'],
},
},
options: [
{
displayName: 'Category',
name: 'category',
type: 'string',
default: '',
description: 'The category of the threat',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
description: 'The name of the threat',
},
{
displayName: 'Process ID',
name: 'processId',
type: 'string',
default: '',
description: 'The ID of the process',
},
],
},
];
export async function execute(
this: IExecuteFunctions,
itemIndex: number,
): Promise<INodeExecutionData> {
const threatId = this.getNodeParameter('threatId', itemIndex) as string;
const additionalFields = this.getNodeParameter('additionalFields', itemIndex, {}) as {
name?: string;
processId?: string;
category?: string;
};
const query = `
mutation UpdateRiskAssessmentThreat($input: UpdateRiskAssessmentThreatInput!) {
updateRiskAssessmentThreat(input: $input) {
riskAssessmentThreat {
id
riskAssessmentScopeId
processId
name
category
createdAt
updatedAt
}
}
}
`;
const input: Record<string, unknown> = { id: threatId };
if (additionalFields.name) input.name = additionalFields.name;
if (additionalFields.processId) input.processId = additionalFields.processId;
if (additionalFields.category) input.category = additionalFields.category;
if (Object.keys(input).length === 1) {
throw new Error('At least one field must be provided to update');
}
const responseData = await proboApiRequest.call(this, query, { input });
return {
json: responseData,
pairedItem: { item: itemIndex },
};
}