bpmnlint-plugin-camunda-compat 2.57.0 → 2.58.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -13,6 +13,7 @@ const camundaCloud10Rules = withConfig({
13
13
  'message-reference': 'error',
14
14
  'io-mapping': 'error',
15
15
  'no-binding-type': 'error',
16
+ 'no-business-id': 'error',
16
17
  'no-candidate-users': 'error',
17
18
  'no-cancel-execution-listener': 'error',
18
19
  'no-execution-listener-headers': 'error',
@@ -124,6 +125,7 @@ const camundaCloud89Rules = withConfig({
124
125
 
125
126
  const camundaCloud810Rules = withConfig({
126
127
  ...omit(camundaCloud89Rules, [
128
+ 'no-business-id',
127
129
  'no-execution-listener-headers',
128
130
  'no-before-all-execution-listener',
129
131
  'no-cancel-execution-listener',
@@ -200,6 +202,7 @@ const rules = {
200
202
  'io-mapping': './rules/camunda-cloud/io-mapping',
201
203
  'message-reference': './rules/camunda-cloud/message-reference',
202
204
  'no-binding-type': './rules/camunda-cloud/no-binding-type',
205
+ 'no-business-id': './rules/camunda-cloud/no-business-id',
203
206
  'no-before-all-execution-listener': './rules/camunda-cloud/no-before-all-execution-listener',
204
207
  'no-candidate-users': './rules/camunda-cloud/no-candidate-users',
205
208
  'no-cancel-execution-listener': './rules/camunda-cloud/no-cancel-execution-listener',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bpmnlint-plugin-camunda-compat",
3
- "version": "2.57.0",
3
+ "version": "2.58.1",
4
4
  "description": "A bpmnlint plug-in for Camunda compatibility",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -34,7 +34,7 @@
34
34
  "modeler-moddle": "^0.2.0",
35
35
  "sinon": "^21.0.1",
36
36
  "sinon-chai": "^4.0.1",
37
- "zeebe-bpmn-moddle": "^1.15.0"
37
+ "zeebe-bpmn-moddle": "^1.17.0"
38
38
  },
39
39
  "dependencies": {
40
40
  "@bpmn-io/feel-analyzer": "^0.3.0",
@@ -12,7 +12,13 @@ const { reportErrors } = require('../utils/reporter');
12
12
 
13
13
  const { skipInNonExecutableProcess } = require('../utils/rule');
14
14
 
15
- module.exports = skipInNonExecutableProcess(function() {
15
+ const { greaterOrEqual } = require('../utils/version');
16
+
17
+ const BUSINESS_ID_ALLOWED_VERSION = '8.10';
18
+
19
+ const MAX_BUSINESS_ID_LENGTH = 256;
20
+
21
+ module.exports = skipInNonExecutableProcess(function({ version }) {
16
22
  function check(node, reporter) {
17
23
  if (!is(node, 'bpmn:CallActivity')) {
18
24
  return;
@@ -31,6 +37,9 @@ module.exports = skipInNonExecutableProcess(function() {
31
37
  errors = hasProperties(calledElement, {
32
38
  processId: {
33
39
  required: true
40
+ },
41
+ businessId: {
42
+ allowed: (value) => isValidBusinessId(value, version)
34
43
  }
35
44
  }, node);
36
45
 
@@ -42,4 +51,22 @@ module.exports = skipInNonExecutableProcess(function() {
42
51
  return annotateRule('called-element', {
43
52
  check
44
53
  });
45
- });
54
+ });
55
+
56
+
57
+ // helpers //////////
58
+
59
+ // Business ID is not supported before BUSINESS_ID_ALLOWED_VERSION; the
60
+ // `no-business-id` rule flags its presence in that range, so it is treated
61
+ // as valid here to avoid reporting the same value twice.
62
+ function isValidBusinessId(value, version) {
63
+ if (!value || value.startsWith('=')) {
64
+ return true;
65
+ }
66
+
67
+ if (!greaterOrEqual(version, BUSINESS_ID_ALLOWED_VERSION)) {
68
+ return true;
69
+ }
70
+
71
+ return value.length < MAX_BUSINESS_ID_LENGTH;
72
+ }
@@ -0,0 +1,38 @@
1
+ const { is } = require('bpmnlint-utils');
2
+
3
+ const { hasProperties, findExtensionElement } = require('../utils/element');
4
+
5
+ const { reportErrors } = require('../utils/reporter');
6
+
7
+ const { skipInNonExecutableProcess } = require('../utils/rule');
8
+
9
+ const ALLOWED_VERSION = '8.10';
10
+
11
+ module.exports = skipInNonExecutableProcess(function() {
12
+ function check(node, reporter) {
13
+ if (!is(node, 'bpmn:CallActivity')) {
14
+ return;
15
+ }
16
+
17
+ const calledElement = findExtensionElement(node, 'zeebe:CalledElement');
18
+
19
+ if (!calledElement) {
20
+ return;
21
+ }
22
+
23
+ const errors = hasProperties(calledElement, {
24
+ businessId: {
25
+ allowed: false,
26
+ allowedVersion: ALLOWED_VERSION
27
+ }
28
+ }, node);
29
+
30
+ if (errors && errors.length) {
31
+ reportErrors(node, reporter, errors);
32
+ }
33
+ }
34
+
35
+ return {
36
+ check
37
+ };
38
+ });
@@ -530,6 +530,13 @@ module.exports.findAncestorAdHocSubProcess = findAncestorAdHocSubProcess;
530
530
  // both roles on the same element.
531
531
  const TOOL_CONTAINER_PROPERTY = 'io.camunda.agenticai.toolContainer';
532
532
 
533
+ // The AI Agent job-worker template applied to an ad-hoc sub-process. Its id is
534
+ // stable across template versions (versioning is tracked separately via
535
+ // zeebe:modelerTemplateVersion), so matching it recognizes every version. Older
536
+ // versions of this template predate the TOOL_CONTAINER_PROPERTY marker, so
537
+ // their AHSPs are agentic but carry no marker; the template id identifies them.
538
+ const LEGACY_AI_AGENT_TEMPLATE = 'io.camunda.connectors.agenticai.aiagent.jobworker.v1';
539
+
533
540
  function hasToolContainerRoleProperty(node) {
534
541
  const properties = findExtensionElement(node, 'zeebe:Properties');
535
542
 
@@ -556,11 +563,19 @@ module.exports.hasToolContainerRoleProperty = hasToolContainerRoleProperty;
556
563
  // Deliberately does not fall back to a bare `zeebe:AdHoc` extension: that
557
564
  // extension is also carried by plain ad-hoc sub-processes using output
558
565
  // collection, so it can't reliably distinguish agentic from non-agentic ones.
566
+ //
567
+ // Older AI Agent job-worker templates predate the property marker; they are
568
+ // still agentic and are recognized by their (version-agnostic) element template
569
+ // id (see LEGACY_AI_AGENT_TEMPLATE).
559
570
  function isAgenticAdHocSubProcess(ahsp, version) {
560
571
  if (hasToolContainerRoleProperty(ahsp)) {
561
572
  return true;
562
573
  }
563
574
 
575
+ if (ahsp.get('modelerTemplate') === LEGACY_AI_AGENT_TEMPLATE) {
576
+ return true;
577
+ }
578
+
564
579
  return !!version
565
580
  && greaterOrEqual(version, '8.10')
566
581
  && !!findExtensionElement(ahsp, 'zeebe:AgentDefinition');