@aifabrix/builder 2.52.0 → 2.52.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/jest.isolated-projects.js +25 -2
- package/jest.projects.js +4 -1
- package/lib/api/datasources-extended.api.js +8 -8
- package/lib/api/keycloak.api.js +92 -0
- package/lib/api/token-providers.api.js +77 -0
- package/lib/api/types/keycloak.types.js +23 -0
- package/lib/api/types/token-providers.types.js +65 -0
- package/lib/app/down.js +16 -1
- package/lib/channels/add-channel.js +126 -19
- package/lib/channels/approval-guides/chatgpt.js +1 -1
- package/lib/channels/approval-guides/microsoft-copilot.js +16 -12
- package/lib/channels/channel-add-ensure.js +128 -0
- package/lib/channels/channel-artifact-generator.js +11 -1
- package/lib/channels/channel-branding.js +94 -0
- package/lib/channels/channel-credential.js +8 -0
- package/lib/channels/channel-discovery.js +330 -0
- package/lib/channels/channel-external-system.js +1 -1
- package/lib/channels/channel-runtime-resolver.js +103 -14
- package/lib/channels/channel-status-display.js +7 -1
- package/lib/channels/microsoft-copilot-channel-add.js +138 -0
- package/lib/channels/microsoft-copilot-entra-sso-form.js +180 -0
- package/lib/channels/microsoft-copilot-entra-sso.js +264 -0
- package/lib/channels/microsoft-copilot-icons.js +74 -0
- package/lib/channels/microsoft-copilot-limits.js +84 -0
- package/lib/channels/microsoft-copilot-package.js +130 -49
- package/lib/channels/microsoft-copilot-validate.js +197 -0
- package/lib/cli/index.js +2 -0
- package/lib/cli/infra-guided.js +13 -6
- package/lib/cli/setup-infra.js +31 -4
- package/lib/commands/channel-add-setup.js +28 -9
- package/lib/commands/channel.js +14 -10
- package/lib/commands/integration-definition.js +158 -0
- package/lib/commands/repair-auth-apply.js +19 -5
- package/lib/commands/repair-datasource-sync-operations.js +4 -1
- package/lib/commands/role-assistant-test-output.js +200 -0
- package/lib/commands/role-assistant.js +125 -166
- package/lib/datasource/capability/capability-resolve.js +15 -5
- package/lib/datasource/capability/copy-operations.js +14 -4
- package/lib/infrastructure/index.js +19 -4
- package/lib/integration-definition/apply.js +478 -0
- package/lib/integration-definition/canonical-json.js +51 -0
- package/lib/integration-definition/emit-suite-bid.js +94 -0
- package/lib/integration-definition/enrich-crm-field-mappings.js +240 -0
- package/lib/integration-definition/enrich-openapi-operations.js +434 -0
- package/lib/integration-definition/from-discovery.js +339 -0
- package/lib/integration-definition/hash.js +37 -0
- package/lib/integration-definition/index.js +37 -0
- package/lib/integration-definition/openapi-enrichment/hubspot-crm-companies.json +205 -0
- package/lib/integration-definition/resource-type-catalog.js +59 -0
- package/lib/integration-definition/system-kind-enum.js +40 -0
- package/lib/integration-definition/validate.js +148 -0
- package/lib/programmatic/builder-api-request.js +5 -1
- package/lib/programmatic/builder-help-governance.js +3 -2
- package/lib/programmatic/capability-registry.js +19 -0
- package/lib/programmatic/openapi-component-schemas.js +6 -1
- package/lib/programmatic/openapi-descriptions.js +40 -0
- package/lib/programmatic/openapi-envelope-examples.js +269 -0
- package/lib/programmatic/openapi-operation-bindings.js +45 -0
- package/lib/programmatic/openapi-request-schemas.js +14 -0
- package/lib/programmatic/openapi-result-schemas-overflow.js +101 -0
- package/lib/programmatic/openapi-result-schemas.js +46 -99
- package/lib/programmatic/openapi-schema-descriptions-core.js +7 -4
- package/lib/programmatic/openapi-schema-descriptions-help.js +1 -1
- package/lib/programmatic/openapi-schema-descriptions-operations.js +24 -0
- package/lib/programmatic/openapi-schema-helpers.js +9 -9
- package/lib/programmatic/openapi-spec.js +11 -1
- package/lib/programmatic/orchestration-openapi-meta.js +10 -0
- package/lib/programmatic/route-handler-map.js +29 -1
- package/lib/programmatic/run-channel-package.js +236 -0
- package/lib/programmatic/run-integration-definition.js +69 -0
- package/lib/role-assistant/knowledge-sync-logging.js +58 -0
- package/lib/role-assistant/knowledge-sync.js +88 -93
- package/lib/role-assistant/test-cases-bid.js +155 -0
- package/lib/role-assistant/test-cases-evaluate.js +9 -1
- package/lib/role-assistant/test-cases-honesty.js +24 -10
- package/lib/role-assistant/test-cases.js +28 -0
- package/lib/role-assistant/test-runner-bid-apply.js +122 -0
- package/lib/role-assistant/test-runner-bid-document.js +278 -0
- package/lib/role-assistant/test-runner-workhub-answers.js +245 -20
- package/lib/role-assistant/test-runner-workhub.js +100 -18
- package/lib/role-assistant/test-suite.js +119 -0
- package/lib/schema/application-schema.json +56 -6
- package/lib/schema/external-datasource.schema.json +103 -17
- package/lib/schema/external-system.schema.json +54 -3
- package/lib/schema/integration-definition.schema.json +195 -0
- package/lib/utils/authentication-shape.js +6 -0
- package/lib/utils/docker-build.js +3 -3
- package/lib/utils/help-builder.js +1 -0
- package/lib/utils/promote-dev-docker-image.js +97 -18
- package/lib/utils/transient-developer-id.js +28 -0
- package/package.json +1 -1
- package/scripts/pnpm/af.mjs +24 -9
- package/scripts/pnpm/help.mjs +1 -1
- package/templates/applications/dataplane/application.yaml +3 -2
- package/templates/applications/dataplane/env.template +7 -6
- package/templates/applications/miso-controller/application.yaml +23 -9
- package/templates/applications/miso-controller/env.template +8 -2
- package/templates/channels/README.md +11 -1
- package/templates/channels/brand/color-192.png +0 -0
- package/templates/channels/brand/dark/128.png +0 -0
- package/templates/channels/brand/dark/192.png +0 -0
- package/templates/channels/brand/dark/256.png +0 -0
- package/templates/channels/brand/dark/32.png +0 -0
- package/templates/channels/brand/dark/512.png +0 -0
- package/templates/channels/brand/dark/64.png +0 -0
- package/templates/channels/brand/light/128.png +0 -0
- package/templates/channels/brand/light/192.png +0 -0
- package/templates/channels/brand/light/256.png +0 -0
- package/templates/channels/brand/light/32.png +0 -0
- package/templates/channels/brand/light/512.png +0 -0
- package/templates/channels/brand/light/64.png +0 -0
- package/templates/channels/brand/mono-white/128.png +0 -0
- package/templates/channels/brand/mono-white/192.png +0 -0
- package/templates/channels/brand/mono-white/256.png +0 -0
- package/templates/channels/brand/mono-white/32.png +0 -0
- package/templates/channels/brand/mono-white/512.png +0 -0
- package/templates/channels/brand/mono-white/64.png +0 -0
- package/templates/channels/brand/outline-32.png +0 -0
- package/templates/channels/chatgpt/install.template.md.hbs +6 -4
- package/templates/channels/chatgpt/integration/README.md +4 -5
- package/templates/channels/chatgpt/integration/chatgpt-system.json +1 -16
- package/templates/channels/microsoft-copilot/ai-plugin.template.json.hbs +10 -16
- package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +5 -3
- package/templates/channels/microsoft-copilot/entra-sso-registration.template.md.hbs +27 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +39 -20
- package/templates/channels/microsoft-copilot/integration/README.md +2 -3
- package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +1 -22
- package/templates/channels/microsoft-copilot/manifest.template.json.hbs +7 -7
- package/templates/channels/microsoft-copilot/oauth-plugin-vault-required.template.md.hbs +11 -0
- package/templates/channels/slack/integration/README.md +2 -4
- package/templates/channels/teams-bot/install.template.md.hbs +4 -0
- package/templates/channels/teams-bot/integration/README.md +3 -5
- package/templates/channels/web-embed/integration/web-embed-system.json +1 -16
- /package/.cursor/plans/{Done → Archive}/157.1-security-quality-violations-by-type.csv +0 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evaluate expected.bid assertions for suite 002 hard GP.
|
|
3
|
+
* @fileoverview BID emission / apply expectation checks
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
function asArray(value) {
|
|
9
|
+
return Array.isArray(value) ? value : [];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function softWrap(assertion, soft) {
|
|
13
|
+
if (!assertion || assertion.passed || !soft) {
|
|
14
|
+
return assertion;
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
...assertion,
|
|
18
|
+
passed: true,
|
|
19
|
+
soft: true,
|
|
20
|
+
warn: true,
|
|
21
|
+
message: `${assertion.message} (soft — warning only)`
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function findInteraction(interactions, type) {
|
|
26
|
+
return asArray(interactions).find((row) => row && row.type === type) || null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function pushBidAssertion(assertions, soft, id, passed, okMsg, failMsg) {
|
|
30
|
+
assertions.push(
|
|
31
|
+
softWrap(
|
|
32
|
+
{
|
|
33
|
+
id,
|
|
34
|
+
passed,
|
|
35
|
+
message: passed ? okMsg : failMsg
|
|
36
|
+
},
|
|
37
|
+
soft
|
|
38
|
+
)
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function hasEmitOrApply(observed) {
|
|
43
|
+
return Boolean(observed.emitRow || observed.applyRow || observed.emitted);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function collectBidSchemaAssertions(expectedBid, observed, assertions, soft) {
|
|
47
|
+
const { emitRow, applyRow, emitted } = observed;
|
|
48
|
+
if (expectedBid.schemaName) {
|
|
49
|
+
const actualSchema = (emitted && emitted.schemaName) || expectedBid.schemaName;
|
|
50
|
+
pushBidAssertion(
|
|
51
|
+
assertions,
|
|
52
|
+
soft,
|
|
53
|
+
'expected.bid.schemaName',
|
|
54
|
+
hasEmitOrApply(observed) && actualSchema === expectedBid.schemaName,
|
|
55
|
+
`BID schemaName observed (${expectedBid.schemaName}).`,
|
|
56
|
+
`BID schemaName "${expectedBid.schemaName}" not observed in suite emit/apply.`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
if (expectedBid.schemaVersion) {
|
|
60
|
+
const version = emitted && emitted.schemaVersion;
|
|
61
|
+
const versionOk =
|
|
62
|
+
version === null || version === undefined || version === expectedBid.schemaVersion;
|
|
63
|
+
pushBidAssertion(
|
|
64
|
+
assertions,
|
|
65
|
+
soft,
|
|
66
|
+
'expected.bid.schemaVersion',
|
|
67
|
+
hasEmitOrApply({ emitRow, applyRow, emitted }) && versionOk,
|
|
68
|
+
`BID schemaVersion "${expectedBid.schemaVersion}" accepted.`,
|
|
69
|
+
`BID schemaVersion "${expectedBid.schemaVersion}" not observed.`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function assertDefinitionHash(expectedBid, observed, assertions, soft) {
|
|
75
|
+
if (expectedBid.requireDefinitionHash !== true) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const { emitRow, applyRow, emitted } = observed;
|
|
79
|
+
const hash =
|
|
80
|
+
(emitted && emitted.definitionHash) ||
|
|
81
|
+
(emitRow && emitRow.definitionHash) ||
|
|
82
|
+
(applyRow && applyRow.definitionHash) ||
|
|
83
|
+
'';
|
|
84
|
+
pushBidAssertion(
|
|
85
|
+
assertions,
|
|
86
|
+
soft,
|
|
87
|
+
'expected.bid.requireDefinitionHash',
|
|
88
|
+
typeof hash === 'string' && hash.startsWith('sha256:'),
|
|
89
|
+
`BID definitionHash present (${String(hash).slice(0, 18)}…).`,
|
|
90
|
+
'BID definitionHash (sha256:…) not observed on emit/apply.'
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function assertSuiteRunId(expectedBid, observed, assertions, soft) {
|
|
95
|
+
if (expectedBid.requireSuiteRunId !== true) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const { emitRow, applyRow, emitted } = observed;
|
|
99
|
+
const suiteRunId =
|
|
100
|
+
(emitted && emitted.meta && emitted.meta.suiteRunId) ||
|
|
101
|
+
(emitRow && emitRow.suiteRunId) ||
|
|
102
|
+
(applyRow && applyRow.suiteRunId) ||
|
|
103
|
+
'';
|
|
104
|
+
pushBidAssertion(
|
|
105
|
+
assertions,
|
|
106
|
+
soft,
|
|
107
|
+
'expected.bid.requireSuiteRunId',
|
|
108
|
+
Boolean(String(suiteRunId).trim()),
|
|
109
|
+
`BID suiteRunId present (${suiteRunId}).`,
|
|
110
|
+
'BID meta.suiteRunId not observed on emit/apply.'
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function collectBidProvenanceAssertions(expectedBid, observed, assertions, soft) {
|
|
115
|
+
assertDefinitionHash(expectedBid, observed, assertions, soft);
|
|
116
|
+
assertSuiteRunId(expectedBid, observed, assertions, soft);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function collectBidPathAssertions(expectedBid, observed, assertions, soft) {
|
|
120
|
+
if (expectedBid.forbidGoldPaths === true) {
|
|
121
|
+
const { emitRow, applyRow, emitted } = observed;
|
|
122
|
+
const blob = JSON.stringify(emitted || emitRow || applyRow || {});
|
|
123
|
+
const banned = /test-e2e-hubspot|knownPlatform|gold-package/i.test(blob);
|
|
124
|
+
pushBidAssertion(
|
|
125
|
+
assertions,
|
|
126
|
+
soft,
|
|
127
|
+
'expected.bid.forbidGoldPaths',
|
|
128
|
+
!banned,
|
|
129
|
+
'BID trail has no gold/knownPlatform generation paths.',
|
|
130
|
+
'BID trail references forbidden gold/knownPlatform generation paths.'
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function collectBidAssertions(expectedBid, observation, options = {}) {
|
|
136
|
+
if (!expectedBid || typeof expectedBid !== 'object') {
|
|
137
|
+
return [];
|
|
138
|
+
}
|
|
139
|
+
const interactions = asArray(observation.interactions || observation.workInteractions);
|
|
140
|
+
const observed = {
|
|
141
|
+
emitRow: findInteraction(interactions, 'bid-emit'),
|
|
142
|
+
applyRow: findInteraction(interactions, 'bid-apply'),
|
|
143
|
+
emitted: observation.emittedBid || null
|
|
144
|
+
};
|
|
145
|
+
const assertions = [];
|
|
146
|
+
const soft = options.soft === true;
|
|
147
|
+
collectBidSchemaAssertions(expectedBid, observed, assertions, soft);
|
|
148
|
+
collectBidProvenanceAssertions(expectedBid, observed, assertions, soft);
|
|
149
|
+
collectBidPathAssertions(expectedBid, observed, assertions, soft);
|
|
150
|
+
return assertions;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
module.exports = {
|
|
154
|
+
collectBidAssertions
|
|
155
|
+
};
|
|
@@ -9,6 +9,7 @@ const {
|
|
|
9
9
|
buildHonestyObservation,
|
|
10
10
|
evaluateHonestyExpectations
|
|
11
11
|
} = require('./test-cases-honesty');
|
|
12
|
+
const { collectBidAssertions } = require('./test-cases-bid');
|
|
12
13
|
|
|
13
14
|
function getValueAtPath(obj, dottedPath) {
|
|
14
15
|
const parts = String(dottedPath || '').split('.').filter(Boolean);
|
|
@@ -109,7 +110,13 @@ function buildCaseObservation(result, lifecycleVerdict, portalUrl) {
|
|
|
109
110
|
processExecutionId: result?.processExecutionId || null,
|
|
110
111
|
workResult,
|
|
111
112
|
workResultError: result?.workResultError || null,
|
|
112
|
-
honesty: buildHonestyObservation(workResult)
|
|
113
|
+
honesty: buildHonestyObservation(workResult),
|
|
114
|
+
interactions: Array.isArray(result?.interactions)
|
|
115
|
+
? result.interactions
|
|
116
|
+
: Array.isArray(result?.workInteractions)
|
|
117
|
+
? result.workInteractions
|
|
118
|
+
: [],
|
|
119
|
+
emittedBid: result?.emittedBid || null
|
|
113
120
|
};
|
|
114
121
|
}
|
|
115
122
|
|
|
@@ -146,6 +153,7 @@ function collectCaseAssertions(expected, observation) {
|
|
|
146
153
|
assertions.push(...evaluateFactExpectations(expected.facts, observation));
|
|
147
154
|
assertions.push(...evaluateProhibitedExpectations(expected.prohibited, observation));
|
|
148
155
|
assertions.push(...evaluateHonestyExpectations(expected.honesty, observation, { soft }));
|
|
156
|
+
assertions.push(...collectBidAssertions(expected.bid, observation, { soft }));
|
|
149
157
|
return assertions;
|
|
150
158
|
}
|
|
151
159
|
|
|
@@ -68,7 +68,18 @@ function buildHonestyObservation(workResult) {
|
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
function pushHonestyAssertion(assertions, id, passed, message) {
|
|
71
|
+
function pushHonestyAssertion(assertions, id, passed, message, options = {}) {
|
|
72
|
+
const soft = options.soft === true;
|
|
73
|
+
if (soft && !passed) {
|
|
74
|
+
assertions.push({
|
|
75
|
+
id,
|
|
76
|
+
passed: true,
|
|
77
|
+
soft: true,
|
|
78
|
+
warn: true,
|
|
79
|
+
message: `${message} (soft — warning only)`
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
72
83
|
assertions.push({ id, passed, message });
|
|
73
84
|
}
|
|
74
85
|
|
|
@@ -87,7 +98,7 @@ function assertWorkResultPresent(assertions, honesty, observation) {
|
|
|
87
98
|
);
|
|
88
99
|
}
|
|
89
100
|
|
|
90
|
-
function assertSchemaVersion(assertions, honestySpec, honesty) {
|
|
101
|
+
function assertSchemaVersion(assertions, honestySpec, honesty, soft) {
|
|
91
102
|
if (!honestySpec.schemaVersion) {
|
|
92
103
|
return;
|
|
93
104
|
}
|
|
@@ -99,11 +110,12 @@ function assertSchemaVersion(assertions, honestySpec, honesty) {
|
|
|
99
110
|
passed,
|
|
100
111
|
passed
|
|
101
112
|
? `schemaVersion matched "${expected}".`
|
|
102
|
-
: `schemaVersion expected "${expected}" but got ${JSON.stringify(honesty.schemaVersion)}
|
|
113
|
+
: `schemaVersion expected "${expected}" but got ${JSON.stringify(honesty.schemaVersion)}.`,
|
|
114
|
+
{ soft }
|
|
103
115
|
);
|
|
104
116
|
}
|
|
105
117
|
|
|
106
|
-
function assertCompletion(assertions, honestySpec, honesty) {
|
|
118
|
+
function assertCompletion(assertions, honestySpec, honesty, soft) {
|
|
107
119
|
if (honestySpec.requireCompletion === false) {
|
|
108
120
|
return;
|
|
109
121
|
}
|
|
@@ -115,11 +127,12 @@ function assertCompletion(assertions, honestySpec, honesty) {
|
|
|
115
127
|
stateOk && goalOk,
|
|
116
128
|
stateOk && goalOk
|
|
117
129
|
? `completion.state/goalStatus honest (${honesty.completionState}/${honesty.goalStatus}).`
|
|
118
|
-
: `completion missing or invalid: state=${JSON.stringify(honesty.completionState)} goalStatus=${JSON.stringify(honesty.goalStatus)}
|
|
130
|
+
: `completion missing or invalid: state=${JSON.stringify(honesty.completionState)} goalStatus=${JSON.stringify(honesty.goalStatus)}.`,
|
|
131
|
+
{ soft }
|
|
119
132
|
);
|
|
120
133
|
}
|
|
121
134
|
|
|
122
|
-
function assertContribution(assertions, honestySpec, honesty) {
|
|
135
|
+
function assertContribution(assertions, honestySpec, honesty, soft) {
|
|
123
136
|
if (honestySpec.requireContributionObservation === false) {
|
|
124
137
|
return;
|
|
125
138
|
}
|
|
@@ -130,7 +143,8 @@ function assertContribution(assertions, honestySpec, honesty) {
|
|
|
130
143
|
ok,
|
|
131
144
|
ok
|
|
132
145
|
? `contributionObservation.status honest (${honesty.contributionStatus}).`
|
|
133
|
-
: `contributionObservation.status missing or invalid: ${JSON.stringify(honesty.contributionStatus)}
|
|
146
|
+
: `contributionObservation.status missing or invalid: ${JSON.stringify(honesty.contributionStatus)}.`,
|
|
147
|
+
{ soft }
|
|
134
148
|
);
|
|
135
149
|
}
|
|
136
150
|
|
|
@@ -171,9 +185,9 @@ function evaluateHonestyExpectations(honestySpec, observation, options = {}) {
|
|
|
171
185
|
// Missing Output is always a hard failure when required — soft does not waive it.
|
|
172
186
|
return assertions;
|
|
173
187
|
}
|
|
174
|
-
assertSchemaVersion(assertions, honestySpec, honesty);
|
|
175
|
-
assertCompletion(assertions, honestySpec, honesty);
|
|
176
|
-
assertContribution(assertions, honestySpec, honesty);
|
|
188
|
+
assertSchemaVersion(assertions, honestySpec, honesty, soft);
|
|
189
|
+
assertCompletion(assertions, honestySpec, honesty, soft);
|
|
190
|
+
assertContribution(assertions, honestySpec, honesty, soft);
|
|
177
191
|
assertMinResourceChanges(assertions, honestySpec, honesty, soft);
|
|
178
192
|
return assertions;
|
|
179
193
|
}
|
|
@@ -331,6 +331,32 @@ function collectCapabilitiesFromWorkSteps(out, steps) {
|
|
|
331
331
|
}
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
+
/**
|
|
335
|
+
* Work-result artifactIndex often carries CIP fingerprints like
|
|
336
|
+
* `capabilityKey=customer.createBasic|operationId=createbasic` when steps[] is empty.
|
|
337
|
+
* @param {Set<string>} out
|
|
338
|
+
* @param {unknown} artifacts
|
|
339
|
+
*/
|
|
340
|
+
function collectCapabilitiesFromArtifactIndex(out, artifacts) {
|
|
341
|
+
if (!Array.isArray(artifacts)) return;
|
|
342
|
+
for (const row of artifacts) {
|
|
343
|
+
if (!row || typeof row !== 'object') continue;
|
|
344
|
+
addCapabilityToken(out, row.capabilityKey);
|
|
345
|
+
addCapabilityToken(out, row.capability);
|
|
346
|
+
const fingerprint = typeof row.fingerprint === 'string' ? row.fingerprint : '';
|
|
347
|
+
const match = fingerprint.match(/(?:^|[|,])capabilityKey=([^|,]+)/);
|
|
348
|
+
if (match) {
|
|
349
|
+
addCapabilityToken(out, match[1]);
|
|
350
|
+
}
|
|
351
|
+
const artifactRef = typeof row.artifactRef === 'string' ? row.artifactRef : '';
|
|
352
|
+
// cip-log:fallback:customer.create:create:<id>
|
|
353
|
+
const refMatch = artifactRef.match(/^cip-log:[^:]+:([^:]+):/);
|
|
354
|
+
if (refMatch) {
|
|
355
|
+
addCapabilityToken(out, refMatch[1]);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
334
360
|
function collectObservedCapabilities(result) {
|
|
335
361
|
const out = new Set();
|
|
336
362
|
const steps = Array.isArray(result?.stepsRun) ? result.stepsRun : [];
|
|
@@ -341,6 +367,8 @@ function collectObservedCapabilities(result) {
|
|
|
341
367
|
}
|
|
342
368
|
collectCapabilitiesFromWorkSteps(out, result?.steps);
|
|
343
369
|
collectCapabilitiesFromWorkSteps(out, result?.workResult?.steps);
|
|
370
|
+
collectCapabilitiesFromArtifactIndex(out, result?.workResult?.artifactIndex);
|
|
371
|
+
collectCapabilitiesFromArtifactIndex(out, result?.artifactIndex);
|
|
344
372
|
addCapabilityToken(out, result?.task?.capabilityKey);
|
|
345
373
|
addCapabilityToken(out, result?.task?.capability);
|
|
346
374
|
if (result?.task?.approvalContext && typeof result.task.approvalContext === 'object') {
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Soft-loop BID apply after workspace.createsystem (suite 002 / plan 512.4).
|
|
3
|
+
* @fileoverview Apply input.bidPath into builder-api workspace when Runtime COM
|
|
4
|
+
* cannot yet invoke template.applyintegrationdefinition (RA facade not refreshed).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const fs = require('../internal/fs-real-sync');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const {
|
|
12
|
+
loadCaseBidDocument,
|
|
13
|
+
resolveTargetSystemKey
|
|
14
|
+
} = require('./test-runner-bid-document');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @returns {string}
|
|
18
|
+
*/
|
|
19
|
+
function resolveBuilderApiBaseUrl() {
|
|
20
|
+
const fromEnv = String(process.env.BUILDER_API_URL || process.env.BUILDER_URL || '').trim();
|
|
21
|
+
if (fromEnv) {
|
|
22
|
+
return fromEnv.replace(/\/$/, '');
|
|
23
|
+
}
|
|
24
|
+
let developerId = 0;
|
|
25
|
+
try {
|
|
26
|
+
const yaml = require('js-yaml');
|
|
27
|
+
const cfgPath = path.join(
|
|
28
|
+
process.env.HOME || '',
|
|
29
|
+
'.aifabrix',
|
|
30
|
+
'config.yaml'
|
|
31
|
+
);
|
|
32
|
+
if (fs.existsSync(cfgPath)) {
|
|
33
|
+
const cfg = yaml.load(fs.readFileSync(cfgPath, 'utf8')) || {};
|
|
34
|
+
developerId = Number(cfg['developer-id'] || cfg.developerId || 0) || 0;
|
|
35
|
+
}
|
|
36
|
+
} catch (_err) {
|
|
37
|
+
developerId = 0;
|
|
38
|
+
}
|
|
39
|
+
return `http://localhost:${3005 + developerId * 100}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param {Object} authConfig
|
|
44
|
+
* @returns {string}
|
|
45
|
+
*/
|
|
46
|
+
function extractBearer(authConfig) {
|
|
47
|
+
if (!authConfig || typeof authConfig !== 'object') {
|
|
48
|
+
return '';
|
|
49
|
+
}
|
|
50
|
+
if (typeof authConfig.token === 'string' && authConfig.token.trim()) {
|
|
51
|
+
return authConfig.token.trim();
|
|
52
|
+
}
|
|
53
|
+
if (typeof authConfig.bearerToken === 'string' && authConfig.bearerToken.trim()) {
|
|
54
|
+
return authConfig.bearerToken.trim();
|
|
55
|
+
}
|
|
56
|
+
const header = authConfig.headers && authConfig.headers.Authorization;
|
|
57
|
+
const m = /^Bearer\s+(.+)$/i.exec(String(header || ''));
|
|
58
|
+
return m ? m[1].trim() : '';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @param {Object} testCase
|
|
63
|
+
* @param {Object} wait
|
|
64
|
+
* @returns {boolean}
|
|
65
|
+
*/
|
|
66
|
+
function shouldApplyBidAfterWait(testCase, wait) {
|
|
67
|
+
const bid = loadCaseBidDocument(testCase);
|
|
68
|
+
if (!bid) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
const capability = String(
|
|
72
|
+
wait.questionKey || wait.objectRef?.capabilityKey || wait.prompt || ''
|
|
73
|
+
).toLowerCase();
|
|
74
|
+
return (
|
|
75
|
+
capability.includes('createsystem') ||
|
|
76
|
+
capability.includes('applyintegrationdefinition')
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @param {Object} authConfig
|
|
82
|
+
* @param {Object} testCase
|
|
83
|
+
* @returns {Promise<Object|null>}
|
|
84
|
+
*/
|
|
85
|
+
async function applyCaseBidViaBuilderApi(authConfig, testCase) {
|
|
86
|
+
const bid = loadCaseBidDocument(testCase);
|
|
87
|
+
const systemKey = resolveTargetSystemKey(testCase);
|
|
88
|
+
const token = extractBearer(authConfig);
|
|
89
|
+
if (!bid || !systemKey || !token) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
const url = `${resolveBuilderApiBaseUrl()}/api/v1/builder/systems/${encodeURIComponent(systemKey)}/integration-definition/apply`;
|
|
93
|
+
const res = await fetch(url, {
|
|
94
|
+
method: 'POST',
|
|
95
|
+
headers: {
|
|
96
|
+
Authorization: `Bearer ${token}`,
|
|
97
|
+
'Content-Type': 'application/json'
|
|
98
|
+
},
|
|
99
|
+
body: JSON.stringify({ integrationDefinition: bid, force: true })
|
|
100
|
+
});
|
|
101
|
+
const text = await res.text();
|
|
102
|
+
let body = null;
|
|
103
|
+
try {
|
|
104
|
+
body = text ? JSON.parse(text) : null;
|
|
105
|
+
} catch (_err) {
|
|
106
|
+
body = { raw: text };
|
|
107
|
+
}
|
|
108
|
+
if (!res.ok) {
|
|
109
|
+
const err = new Error(
|
|
110
|
+
`BID apply failed HTTP ${res.status}: ${typeof body === 'object' ? JSON.stringify(body).slice(0, 300) : text}`
|
|
111
|
+
);
|
|
112
|
+
err.status = res.status;
|
|
113
|
+
throw err;
|
|
114
|
+
}
|
|
115
|
+
return body && body.data ? body.data : body;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
module.exports = {
|
|
119
|
+
resolveBuilderApiBaseUrl,
|
|
120
|
+
shouldApplyBidAfterWait,
|
|
121
|
+
applyCaseBidViaBuilderApi
|
|
122
|
+
};
|