@aifabrix/builder 2.55.0 → 2.55.2
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/lib/agent-kit/host-approve.js +48 -6
- package/lib/agent-kit/init.js +2 -2
- package/lib/agent-kit/remote-prompts.js +46 -13
- package/lib/agent-kit/run.js +1 -1
- package/lib/agent-kit/start.js +310 -0
- package/lib/app/deploy.js +7 -4
- package/lib/app/offer-create-from-template.js +184 -0
- package/lib/cli/setup-app.js +8 -1
- package/lib/cli/setup-auth.js +11 -2
- package/lib/commands/agent-kit-help.js +74 -4
- package/lib/commands/agent-kit.js +83 -12
- package/lib/commands/auth-status-user.js +99 -0
- package/lib/commands/auth-status.js +14 -4
- package/lib/commands/datasource-load-export-cli.js +7 -2
- package/lib/commands/datasource-test-trust-cli.js +5 -1
- package/lib/commands/governance-command-action.js +5 -4
- package/lib/commands/identity-membership-role-cache.js +6 -1
- package/lib/commands/lifecycle-command-action.js +16 -15
- package/lib/commands/login-credentials.js +8 -3
- package/lib/commands/login-device.js +14 -5
- package/lib/commands/login.js +14 -1
- package/lib/commands/logout.js +50 -15
- package/lib/commands/role-assistant.js +24 -12
- package/lib/commands/verify-governance-command-action.js +9 -7
- package/lib/commands/verify-operations-command-action.js +9 -8
- package/lib/commands/verify-trust-command-action.js +6 -5
- package/lib/external-system/download.js +1 -2
- package/lib/generator/helpers.js +12 -1
- package/lib/integration-definition/apply-static-enterprise.js +5 -2
- package/lib/role-assistant/knowledge-sync-settings-push.js +172 -0
- package/lib/role-assistant/knowledge-sync.js +9 -126
- package/lib/role-assistant/test-cases-evaluate.js +12 -1
- package/lib/role-assistant/test-cases-evidence.js +44 -5
- package/lib/role-assistant/test-cases-lifecycle.js +9 -3
- package/lib/role-assistant/test-runner.js +3 -0
- package/lib/schema/infra-parameter.schema.json +51 -3
- package/lib/schema/infra.parameter.yaml +476 -40
- package/lib/schema/type/document-storage.json +1 -1
- package/lib/utils/api-required-permissions.js +271 -0
- package/lib/utils/api.js +16 -13
- package/lib/utils/cli-json-exit.js +41 -0
- package/lib/utils/cli-utils.js +23 -5
- package/lib/utils/controller-url.js +78 -4
- package/lib/utils/deployment-errors.js +15 -0
- package/lib/utils/deployment-validation-helpers.js +4 -1
- package/lib/utils/device-code.js +31 -10
- package/lib/utils/error-formatters/error-parser.js +16 -1
- package/lib/utils/error-formatters/permission-errors.js +19 -5
- package/lib/utils/keycloak-realm-ready.js +5 -2
- package/lib/utils/logger.js +1 -0
- package/lib/utils/paths.js +26 -5
- package/lib/utils/secrets-helpers.js +2 -2
- package/lib/utils/write-stream-and-wait.js +63 -0
- package/package.json +20 -6
- package/templates/agent-kit/agent-kit.yaml +1 -1
- package/templates/agent-kit/instructions/AGENTKIT.md +25 -4
- package/templates/agent-kit/instructions/root.AGENTS.md +1 -1
- package/templates/agent-kit/skills/aifabrix-connected-system/SKILL.md +2 -1
- package/templates/agent-kit/skills/aifabrix-connected-system/references/delivery-gates.md +1 -1
- package/templates/agent-kit/skills/aifabrix-plan/SKILL.md +2 -1
- package/templates/agent-kit/skills/aifabrix-prove/SKILL.md +1 -0
- package/templates/agent-kit/skills/aifabrix-role-assistant/SKILL.md +1 -0
- package/templates/agent-kit/skills/shared/hosts.md +13 -26
- package/templates/agent-kit/skills/shared/login.md +16 -0
- package/templates/agent-kit/workspace/README.md +1 -1
- package/templates/applications/dataplane/application.yaml +1 -2
- package/templates/applications/dataplane/env.template +5 -5
- package/templates/applications/miso-controller/application.yaml +21 -2
- package/templates/applications/miso-controller/env.template +89 -17
- package/templates/applications/miso-controller/rbac.yaml +5 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Push role-assistant.yaml knowledge/debug/runtime settings to Assistants.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Map local Role Assistant settings onto dataplane Assistants PATCH
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const { updateAssistantSettings } = require('../api/assistants.api');
|
|
12
|
+
const {
|
|
13
|
+
readRoleAssistantSettings,
|
|
14
|
+
resolveDocumentStorageKeyFromRoleAssistantSettings,
|
|
15
|
+
resolveRoleAssistantEnvironmentSettings
|
|
16
|
+
} = require('./settings');
|
|
17
|
+
|
|
18
|
+
function resolveRoleAssistantSettingsEnvKey(environment) {
|
|
19
|
+
const token = String(environment || '').trim().toLowerCase();
|
|
20
|
+
return token === 'dev' || token === 'tst' || token === 'pro' ? token : 'dev';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Map role-assistant.yaml debug.* → Assistants settings PATCH fields.
|
|
25
|
+
* includePromptTrace → fullDebugEnabled (LLM prompt capture gate).
|
|
26
|
+
* enabled → debugEnabled (runtime debug traces).
|
|
27
|
+
* @param {Object|null|undefined} debugSection
|
|
28
|
+
* @returns {{ debugEnabled?: boolean, fullDebugEnabled?: boolean }}
|
|
29
|
+
*/
|
|
30
|
+
function mapRoleAssistantDebugToAssistantsSettings(debugSection) {
|
|
31
|
+
if (!debugSection || typeof debugSection !== 'object') {
|
|
32
|
+
return {};
|
|
33
|
+
}
|
|
34
|
+
const body = {};
|
|
35
|
+
if (typeof debugSection.enabled === 'boolean') {
|
|
36
|
+
body.debugEnabled = debugSection.enabled;
|
|
37
|
+
}
|
|
38
|
+
if (typeof debugSection.includePromptTrace === 'boolean') {
|
|
39
|
+
body.fullDebugEnabled = debugSection.includePromptTrace;
|
|
40
|
+
}
|
|
41
|
+
return body;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Map role-assistant.yaml runtime.* to the governed Assistants settings names.
|
|
46
|
+
* Provider selection remains platform-owned; the assistant may override only
|
|
47
|
+
* its workflow reasoning model and execution profile.
|
|
48
|
+
* @param {Object|null|undefined} runtimeSection
|
|
49
|
+
* @returns {{ workflowReasoningModel?: string, temperature?: number, maxLlmLoops?: number, maxToolLoops?: number }}
|
|
50
|
+
*/
|
|
51
|
+
function mapRoleAssistantRuntimeToAssistantsSettings(runtimeSection) {
|
|
52
|
+
if (!runtimeSection || typeof runtimeSection !== 'object') {
|
|
53
|
+
return {};
|
|
54
|
+
}
|
|
55
|
+
const body = {};
|
|
56
|
+
if (typeof runtimeSection.model === 'string' && runtimeSection.model.trim()) {
|
|
57
|
+
body.workflowReasoningModel = runtimeSection.model.trim();
|
|
58
|
+
}
|
|
59
|
+
if (typeof runtimeSection.temperature === 'number') {
|
|
60
|
+
body.temperature = runtimeSection.temperature;
|
|
61
|
+
}
|
|
62
|
+
if (Number.isInteger(runtimeSection.maxLoops)) {
|
|
63
|
+
body.maxLlmLoops = runtimeSection.maxLoops;
|
|
64
|
+
body.maxToolLoops = runtimeSection.maxLoops;
|
|
65
|
+
}
|
|
66
|
+
return body;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Push role-assistant.yaml knowledge + debug settings to dataplane Assistants.
|
|
71
|
+
* Called on upload/deploy so the operator UI and CLI stay aligned.
|
|
72
|
+
*/
|
|
73
|
+
function resolveAssistantSettingsPush(params) {
|
|
74
|
+
const {
|
|
75
|
+
systemKey,
|
|
76
|
+
environment = 'dev',
|
|
77
|
+
pathOptions = {}
|
|
78
|
+
} = params;
|
|
79
|
+
const settingsEnv = resolveRoleAssistantSettingsEnvKey(environment);
|
|
80
|
+
const settings = readRoleAssistantSettings(systemKey, { required: false, pathOptions });
|
|
81
|
+
if (!settings) {
|
|
82
|
+
return { result: { skipped: true, reason: 'missing-role-assistant-settings' } };
|
|
83
|
+
}
|
|
84
|
+
const section = resolveRoleAssistantEnvironmentSettings(settings, settingsEnv, {
|
|
85
|
+
required: false
|
|
86
|
+
});
|
|
87
|
+
if (!section) {
|
|
88
|
+
return { result: { skipped: true, reason: 'missing-env-settings' } };
|
|
89
|
+
}
|
|
90
|
+
const documentStorageKey =
|
|
91
|
+
resolveDocumentStorageKeyFromRoleAssistantSettings(settings, settingsEnv) || '';
|
|
92
|
+
const debugBody = mapRoleAssistantDebugToAssistantsSettings(section.debug);
|
|
93
|
+
const runtimeBody = mapRoleAssistantRuntimeToAssistantsSettings(section.runtime);
|
|
94
|
+
const settingsBody = { ...runtimeBody, ...debugBody };
|
|
95
|
+
if (!documentStorageKey && Object.keys(settingsBody).length === 0) {
|
|
96
|
+
return { result: { skipped: true, reason: 'no-document-storage-key', documentStorageKey: null } };
|
|
97
|
+
}
|
|
98
|
+
const patchBody = { ...settingsBody };
|
|
99
|
+
if (documentStorageKey) {
|
|
100
|
+
patchBody.documentStorageKey = documentStorageKey;
|
|
101
|
+
}
|
|
102
|
+
return { documentStorageKey, debugBody: settingsBody, patchBody };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function applyAssistantSettingsPush(dataplaneUrl, systemKey, authConfig, settingsPush) {
|
|
106
|
+
const { documentStorageKey, debugBody, patchBody } = settingsPush;
|
|
107
|
+
const hasDocumentStorageKey = documentStorageKey !== '';
|
|
108
|
+
const hasDebugSettings = Object.keys(debugBody).length > 0;
|
|
109
|
+
const assistantKey = String(systemKey || '').trim();
|
|
110
|
+
let response = await updateAssistantSettings(
|
|
111
|
+
dataplaneUrl,
|
|
112
|
+
assistantKey,
|
|
113
|
+
authConfig,
|
|
114
|
+
patchBody
|
|
115
|
+
);
|
|
116
|
+
if (response && response.success === false && hasDocumentStorageKey && hasDebugSettings) {
|
|
117
|
+
response = await updateAssistantSettings(
|
|
118
|
+
dataplaneUrl,
|
|
119
|
+
assistantKey,
|
|
120
|
+
authConfig,
|
|
121
|
+
debugBody
|
|
122
|
+
);
|
|
123
|
+
if (response && response.success === false) {
|
|
124
|
+
throw new Error(
|
|
125
|
+
response.formattedError ||
|
|
126
|
+
response.error ||
|
|
127
|
+
'Failed to update Assistants debug settings'
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
skipped: false,
|
|
132
|
+
documentStorageKey: null,
|
|
133
|
+
documentStoragePushFailed: true,
|
|
134
|
+
...debugBody
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
if (response && response.success === false) {
|
|
138
|
+
throw new Error(
|
|
139
|
+
response.formattedError ||
|
|
140
|
+
response.error ||
|
|
141
|
+
'Failed to update Knowledge document storage settings'
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
skipped: false,
|
|
146
|
+
documentStorageKey: documentStorageKey || null,
|
|
147
|
+
...debugBody
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async function pushRoleAssistantDocumentStorageSettings(params) {
|
|
152
|
+
const { systemKey, dataplaneUrl, authConfig, dryRun = false } = params;
|
|
153
|
+
const settingsPush = resolveAssistantSettingsPush(params);
|
|
154
|
+
if (settingsPush.result) {
|
|
155
|
+
return settingsPush.result;
|
|
156
|
+
}
|
|
157
|
+
const { documentStorageKey, debugBody } = settingsPush;
|
|
158
|
+
if (dryRun) {
|
|
159
|
+
return { skipped: false, dryRun: true, documentStorageKey: documentStorageKey || null, ...debugBody };
|
|
160
|
+
}
|
|
161
|
+
if (!dataplaneUrl || !authConfig) {
|
|
162
|
+
return { skipped: true, reason: 'missing-dataplane-auth' };
|
|
163
|
+
}
|
|
164
|
+
return applyAssistantSettingsPush(dataplaneUrl, systemKey, authConfig, settingsPush);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
module.exports = {
|
|
168
|
+
resolveRoleAssistantSettingsEnvKey,
|
|
169
|
+
mapRoleAssistantDebugToAssistantsSettings,
|
|
170
|
+
mapRoleAssistantRuntimeToAssistantsSettings,
|
|
171
|
+
pushRoleAssistantDocumentStorageSettings
|
|
172
|
+
};
|
|
@@ -15,8 +15,7 @@ const yaml = require('js-yaml');
|
|
|
15
15
|
const { listDocuments, validateDocuments, bulkDocuments } = require('../api/datasources-extended.api');
|
|
16
16
|
const {
|
|
17
17
|
extractDocumentStorageKeyFromAssistantDetails,
|
|
18
|
-
getAssistantDetails
|
|
19
|
-
updateAssistantSettings
|
|
18
|
+
getAssistantDetails
|
|
20
19
|
} = require('../api/assistants.api');
|
|
21
20
|
const { resolveExternalSystemPath } = require('../utils/app-path-resolve');
|
|
22
21
|
const { bareRoleKey } = require('../utils/role-assistant-paths');
|
|
@@ -24,9 +23,14 @@ const {
|
|
|
24
23
|
SYSTEM_KIND_DIGITAL_WORKER,
|
|
25
24
|
getRoleAssistantYamlPath,
|
|
26
25
|
readRoleAssistantSettings,
|
|
27
|
-
resolveDocumentStorageKeyFromRoleAssistantSettings
|
|
28
|
-
resolveRoleAssistantEnvironmentSettings
|
|
26
|
+
resolveDocumentStorageKeyFromRoleAssistantSettings
|
|
29
27
|
} = require('./settings');
|
|
28
|
+
const {
|
|
29
|
+
resolveRoleAssistantSettingsEnvKey,
|
|
30
|
+
mapRoleAssistantDebugToAssistantsSettings,
|
|
31
|
+
mapRoleAssistantRuntimeToAssistantsSettings,
|
|
32
|
+
pushRoleAssistantDocumentStorageSettings
|
|
33
|
+
} = require('./knowledge-sync-settings-push');
|
|
30
34
|
const {
|
|
31
35
|
knowledgeSearchMetadataFromFrontmatter,
|
|
32
36
|
splitMarkdownFrontmatter
|
|
@@ -87,123 +91,6 @@ async function resolveDocumentStorageKeyFromDataplane(dataplaneUrl, authConfig,
|
|
|
87
91
|
}
|
|
88
92
|
}
|
|
89
93
|
|
|
90
|
-
/**
|
|
91
|
-
* Map role-assistant.yaml debug.* → Assistants settings PATCH fields.
|
|
92
|
-
* includePromptTrace → fullDebugEnabled (LLM prompt capture gate).
|
|
93
|
-
* enabled → debugEnabled (runtime debug traces).
|
|
94
|
-
* @param {Object|null|undefined} debugSection
|
|
95
|
-
* @returns {{ debugEnabled?: boolean, fullDebugEnabled?: boolean }}
|
|
96
|
-
*/
|
|
97
|
-
function mapRoleAssistantDebugToAssistantsSettings(debugSection) {
|
|
98
|
-
if (!debugSection || typeof debugSection !== 'object') {
|
|
99
|
-
return {};
|
|
100
|
-
}
|
|
101
|
-
const body = {};
|
|
102
|
-
if (typeof debugSection.enabled === 'boolean') {
|
|
103
|
-
body.debugEnabled = debugSection.enabled;
|
|
104
|
-
}
|
|
105
|
-
if (typeof debugSection.includePromptTrace === 'boolean') {
|
|
106
|
-
body.fullDebugEnabled = debugSection.includePromptTrace;
|
|
107
|
-
}
|
|
108
|
-
return body;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Push role-assistant.yaml knowledge + debug settings to dataplane Assistants.
|
|
113
|
-
* Called on upload/deploy so the operator UI and CLI stay aligned.
|
|
114
|
-
*/
|
|
115
|
-
function resolveAssistantSettingsPush(params) {
|
|
116
|
-
const {
|
|
117
|
-
systemKey,
|
|
118
|
-
environment = 'dev',
|
|
119
|
-
pathOptions = {}
|
|
120
|
-
} = params;
|
|
121
|
-
const settingsEnv = resolveRoleAssistantSettingsEnvKey(environment);
|
|
122
|
-
const settings = readRoleAssistantSettings(systemKey, { required: false, pathOptions });
|
|
123
|
-
if (!settings) {
|
|
124
|
-
return { result: { skipped: true, reason: 'missing-role-assistant-settings' } };
|
|
125
|
-
}
|
|
126
|
-
const section = resolveRoleAssistantEnvironmentSettings(settings, settingsEnv, {
|
|
127
|
-
required: false
|
|
128
|
-
});
|
|
129
|
-
if (!section) {
|
|
130
|
-
return { result: { skipped: true, reason: 'missing-env-settings' } };
|
|
131
|
-
}
|
|
132
|
-
const documentStorageKey =
|
|
133
|
-
resolveDocumentStorageKeyFromRoleAssistantSettings(settings, settingsEnv) || '';
|
|
134
|
-
const debugBody = mapRoleAssistantDebugToAssistantsSettings(section.debug);
|
|
135
|
-
if (!documentStorageKey && Object.keys(debugBody).length === 0) {
|
|
136
|
-
return { result: { skipped: true, reason: 'no-document-storage-key', documentStorageKey: null } };
|
|
137
|
-
}
|
|
138
|
-
const patchBody = { ...debugBody };
|
|
139
|
-
if (documentStorageKey) {
|
|
140
|
-
patchBody.documentStorageKey = documentStorageKey;
|
|
141
|
-
}
|
|
142
|
-
return { documentStorageKey, debugBody, patchBody };
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
async function applyAssistantSettingsPush(dataplaneUrl, systemKey, authConfig, settingsPush) {
|
|
146
|
-
const { documentStorageKey, debugBody, patchBody } = settingsPush;
|
|
147
|
-
const hasDocumentStorageKey = documentStorageKey !== '';
|
|
148
|
-
const hasDebugSettings = Object.keys(debugBody).length > 0;
|
|
149
|
-
const assistantKey = String(systemKey || '').trim();
|
|
150
|
-
let response = await updateAssistantSettings(
|
|
151
|
-
dataplaneUrl,
|
|
152
|
-
assistantKey,
|
|
153
|
-
authConfig,
|
|
154
|
-
patchBody
|
|
155
|
-
);
|
|
156
|
-
if (response && response.success === false && hasDocumentStorageKey && hasDebugSettings) {
|
|
157
|
-
response = await updateAssistantSettings(
|
|
158
|
-
dataplaneUrl,
|
|
159
|
-
assistantKey,
|
|
160
|
-
authConfig,
|
|
161
|
-
debugBody
|
|
162
|
-
);
|
|
163
|
-
if (response && response.success === false) {
|
|
164
|
-
throw new Error(
|
|
165
|
-
response.formattedError ||
|
|
166
|
-
response.error ||
|
|
167
|
-
'Failed to update Assistants debug settings'
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
return {
|
|
171
|
-
skipped: false,
|
|
172
|
-
documentStorageKey: null,
|
|
173
|
-
documentStoragePushFailed: true,
|
|
174
|
-
...debugBody
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
if (response && response.success === false) {
|
|
178
|
-
throw new Error(
|
|
179
|
-
response.formattedError ||
|
|
180
|
-
response.error ||
|
|
181
|
-
'Failed to update Knowledge document storage settings'
|
|
182
|
-
);
|
|
183
|
-
}
|
|
184
|
-
return {
|
|
185
|
-
skipped: false,
|
|
186
|
-
documentStorageKey: documentStorageKey || null,
|
|
187
|
-
...debugBody
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
async function pushRoleAssistantDocumentStorageSettings(params) {
|
|
192
|
-
const { systemKey, dataplaneUrl, authConfig, dryRun = false } = params;
|
|
193
|
-
const settingsPush = resolveAssistantSettingsPush(params);
|
|
194
|
-
if (settingsPush.result) {
|
|
195
|
-
return settingsPush.result;
|
|
196
|
-
}
|
|
197
|
-
const { documentStorageKey, debugBody } = settingsPush;
|
|
198
|
-
if (dryRun) {
|
|
199
|
-
return { skipped: false, dryRun: true, documentStorageKey: documentStorageKey || null, ...debugBody };
|
|
200
|
-
}
|
|
201
|
-
if (!dataplaneUrl || !authConfig) {
|
|
202
|
-
return { skipped: true, reason: 'missing-dataplane-auth' };
|
|
203
|
-
}
|
|
204
|
-
return applyAssistantSettingsPush(dataplaneUrl, systemKey, authConfig, settingsPush);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
94
|
/**
|
|
208
95
|
* Resolve Knowledge document storage key.
|
|
209
96
|
* Order: role-assistant.yaml → dataplane Assistants settings → package dataSources.
|
|
@@ -341,11 +228,6 @@ function resolveDocumentFileName(row, index) {
|
|
|
341
228
|
return filePath.startsWith('/') ? filePath.slice(1) : filePath;
|
|
342
229
|
}
|
|
343
230
|
|
|
344
|
-
function resolveRoleAssistantSettingsEnvKey(environment) {
|
|
345
|
-
const token = String(environment || '').trim().toLowerCase();
|
|
346
|
-
return token === 'dev' || token === 'tst' || token === 'pro' ? token : 'dev';
|
|
347
|
-
}
|
|
348
|
-
|
|
349
231
|
function writeRoleAssistantSettingsFile(systemKey, docStorageKey, environment = 'dev', pathOptions = {}) {
|
|
350
232
|
const roleAssistantPath = resolveExternalSystemPath(systemKey, pathOptions);
|
|
351
233
|
const roleAssistantYamlPath = getRoleAssistantYamlPath(systemKey, { pathOptions });
|
|
@@ -477,6 +359,7 @@ module.exports = {
|
|
|
477
359
|
resolveRoleAssistantSettingsEnvKey,
|
|
478
360
|
resolveRoleAssistantDocumentStorageKey,
|
|
479
361
|
mapRoleAssistantDebugToAssistantsSettings,
|
|
362
|
+
mapRoleAssistantRuntimeToAssistantsSettings,
|
|
480
363
|
pushRoleAssistantDocumentStorageSettings,
|
|
481
364
|
importRoleAssistantKnowledge,
|
|
482
365
|
exportRoleAssistantKnowledge,
|
|
@@ -253,10 +253,21 @@ function collectCapabilityAssertions(capabilities, observedCapabilities, soft) {
|
|
|
253
253
|
return rows.map((row) => softWrapFailedAssertion(row, soft));
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
+
function evaluateExecutionIntegrity(observation) {
|
|
257
|
+
if (!observation.workResultError) {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
id: 'execution.integrity',
|
|
262
|
+
passed: false,
|
|
263
|
+
message: `Execution did not produce a readable result: ${observation.workResultError}`
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
256
267
|
function collectCaseAssertions(expected, observation, preflight = {}) {
|
|
257
268
|
const soft = expected.soft === true;
|
|
258
269
|
const observedCapabilities = observation.capabilities?.observed || [];
|
|
259
|
-
const assertions = [];
|
|
270
|
+
const assertions = [evaluateExecutionIntegrity(observation)].filter(Boolean);
|
|
260
271
|
const lifecycleAssertion = softWrapFailedAssertion(
|
|
261
272
|
evaluateLifecycleStateExpectation(expected.lifecycleState, observation.lifecycleState),
|
|
262
273
|
soft
|
|
@@ -55,6 +55,39 @@ function isActiveStatus(status, requiredStatus) {
|
|
|
55
55
|
return status === requiredStatus;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Dataplane Evidence is append-new versioned, never mutated in place
|
|
60
|
+
* (dataplane 506.2): once a row's content changes, its literal `key` is
|
|
61
|
+
* archived permanently and a new `<key>__vN` row becomes the current
|
|
62
|
+
* identity. A case authored against the original literal key must still
|
|
63
|
+
* resolve against that current versioned successor, not report it missing.
|
|
64
|
+
* `rows` here are already scoped to the case's roleKey+resourceType+status
|
|
65
|
+
* by `loadLiveEvidenceRows`, so any row whose key is exactly `<desired>__vN`
|
|
66
|
+
* is unambiguously that key's current version.
|
|
67
|
+
*/
|
|
68
|
+
function findVersionedSuccessor(desiredKey, byKey) {
|
|
69
|
+
const prefix = `${desiredKey}__v`;
|
|
70
|
+
let best = null;
|
|
71
|
+
let bestVersion = -1;
|
|
72
|
+
for (const [key, row] of byKey) {
|
|
73
|
+
if (!key.startsWith(prefix)) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const suffix = key.slice(prefix.length);
|
|
77
|
+
const version = Number(suffix);
|
|
78
|
+
if (!Number.isInteger(version) || version <= bestVersion) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
best = row;
|
|
82
|
+
bestVersion = version;
|
|
83
|
+
}
|
|
84
|
+
return best;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function resolveEvidenceRow(desiredKey, byKey) {
|
|
88
|
+
return byKey.get(desiredKey) || findVersionedSuccessor(desiredKey, byKey);
|
|
89
|
+
}
|
|
90
|
+
|
|
58
91
|
function findMissingEvidenceKeys(spec, rows) {
|
|
59
92
|
const byKey = new Map();
|
|
60
93
|
for (const row of rows) {
|
|
@@ -65,7 +98,7 @@ function findMissingEvidenceKeys(spec, rows) {
|
|
|
65
98
|
}
|
|
66
99
|
const missing = [];
|
|
67
100
|
for (const key of spec.requiredKeys) {
|
|
68
|
-
const row =
|
|
101
|
+
const row = resolveEvidenceRow(key, byKey);
|
|
69
102
|
if (!row) {
|
|
70
103
|
missing.push(`${key} (not in dataplane)`);
|
|
71
104
|
continue;
|
|
@@ -133,11 +166,15 @@ function evaluateEvidenceExpectations(evidenceSpec, observation) {
|
|
|
133
166
|
return [];
|
|
134
167
|
}
|
|
135
168
|
const preflight = observation?.evidencePreflight || {};
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
169
|
+
const liveByKey = new Map();
|
|
170
|
+
for (const row of Array.isArray(preflight.rows) ? preflight.rows : []) {
|
|
171
|
+
const key = rowKey(row);
|
|
172
|
+
if (key) {
|
|
173
|
+
liveByKey.set(key, row);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
139
176
|
return requiredKeys.map((key) => {
|
|
140
|
-
const passed =
|
|
177
|
+
const passed = Boolean(resolveEvidenceRow(key, liveByKey));
|
|
141
178
|
return {
|
|
142
179
|
id: `expected.evidence.requiredKeys:${key}`,
|
|
143
180
|
passed,
|
|
@@ -168,6 +205,8 @@ function evaluateForbiddenCapabilities(forbiddenList, observedCapabilities) {
|
|
|
168
205
|
|
|
169
206
|
module.exports = {
|
|
170
207
|
evidenceSpecFromCase,
|
|
208
|
+
findVersionedSuccessor,
|
|
209
|
+
resolveEvidenceRow,
|
|
171
210
|
findMissingEvidenceKeys,
|
|
172
211
|
assertRoleAssistantEvidencePreflight,
|
|
173
212
|
evaluateEvidenceExpectations,
|
|
@@ -274,13 +274,19 @@ function resolveLifecycleStateFromResult(result) {
|
|
|
274
274
|
}
|
|
275
275
|
|
|
276
276
|
function deriveLifecycleState(result, lifecycleVerdict) {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
277
|
+
// lifecycleVerdict is the Role Assistant's own operations/trust/governance
|
|
278
|
+
// certification status, not this case's execution outcome — a VERIFIED
|
|
279
|
+
// (published, trusted) Role Assistant can still run a case that fails,
|
|
280
|
+
// asks a question, or safe-stops. Always prefer a real structured signal
|
|
281
|
+
// from this execution's own result; the verdict is only a fallback default
|
|
282
|
+
// for when no signal exists at all (e.g. an empty/no-op result).
|
|
280
283
|
const structuredState = resolveLifecycleStateFromResult(result);
|
|
281
284
|
if (structuredState) {
|
|
282
285
|
return structuredState;
|
|
283
286
|
}
|
|
287
|
+
if (lifecycleVerdict === VERDICT.VERIFIED) {
|
|
288
|
+
return 'completed';
|
|
289
|
+
}
|
|
284
290
|
if (lifecycleVerdict === VERDICT.NOT_VERIFIED) return 'safe-stop';
|
|
285
291
|
return 'failed';
|
|
286
292
|
}
|
|
@@ -484,6 +484,9 @@ function lifecycleVerdictFromCaseExecution(executionResult, fallbackVerdict) {
|
|
|
484
484
|
if (statusToken === 'stopped' || statusToken === 'waiting' || statusToken === 'running') {
|
|
485
485
|
return VERDICT.NOT_VERIFIED;
|
|
486
486
|
}
|
|
487
|
+
if (statusToken === 'failed' || statusToken === 'cancelled' || statusToken === 'canceled') {
|
|
488
|
+
return VERDICT.FAILED;
|
|
489
|
+
}
|
|
487
490
|
return fallbackVerdict || VERDICT.FAILED;
|
|
488
491
|
}
|
|
489
492
|
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"scopeEnum": {
|
|
39
39
|
"type": "string",
|
|
40
|
-
"enum": ["infra", "app", "shared-service"]
|
|
40
|
+
"enum": ["infra", "app", "shared-service", "system"]
|
|
41
41
|
},
|
|
42
42
|
"generator": {
|
|
43
43
|
"type": "object",
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"randomBytes32",
|
|
51
51
|
"randomAlphanumeric",
|
|
52
52
|
"password",
|
|
53
|
+
"rsaKeyPair",
|
|
53
54
|
"emptyString",
|
|
54
55
|
"emptyAllowed",
|
|
55
56
|
"literal",
|
|
@@ -65,8 +66,20 @@
|
|
|
65
66
|
"minimum": 1,
|
|
66
67
|
"maximum": 512,
|
|
67
68
|
"description": "For randomAlphanumeric: character count (default 32). For password: default 8. Charset [a-zA-Z0-9]."
|
|
69
|
+
},
|
|
70
|
+
"pairId": { "type": "string", "minLength": 1 },
|
|
71
|
+
"part": { "type": "string", "enum": ["private", "public"] }
|
|
72
|
+
},
|
|
73
|
+
"allOf": [
|
|
74
|
+
{
|
|
75
|
+
"if": { "properties": { "type": { "const": "literal" } } },
|
|
76
|
+
"then": { "required": ["value"] }
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"if": { "properties": { "type": { "const": "rsaKeyPair" } } },
|
|
80
|
+
"then": { "required": ["pairId", "part"] }
|
|
68
81
|
}
|
|
69
|
-
|
|
82
|
+
]
|
|
70
83
|
},
|
|
71
84
|
"azureBlock": {
|
|
72
85
|
"type": "object",
|
|
@@ -74,6 +87,11 @@
|
|
|
74
87
|
"properties": {
|
|
75
88
|
"vaultSecretName": { "type": "string" },
|
|
76
89
|
"vaultSecretNamePattern": { "type": "string" },
|
|
90
|
+
"legacyVaultSecretNames": {
|
|
91
|
+
"type": "array",
|
|
92
|
+
"items": { "type": "string", "minLength": 1 },
|
|
93
|
+
"uniqueItems": true
|
|
94
|
+
},
|
|
77
95
|
"notes": { "type": "string" }
|
|
78
96
|
}
|
|
79
97
|
},
|
|
@@ -90,6 +108,20 @@
|
|
|
90
108
|
"type": "string",
|
|
91
109
|
"minLength": 1
|
|
92
110
|
},
|
|
111
|
+
"category": { "type": "string", "minLength": 1 },
|
|
112
|
+
"sensitive": { "type": "boolean" },
|
|
113
|
+
"valueSource": {
|
|
114
|
+
"type": "string",
|
|
115
|
+
"enum": [
|
|
116
|
+
"generated",
|
|
117
|
+
"onboardingInput",
|
|
118
|
+
"providerOutput",
|
|
119
|
+
"legacyMigration",
|
|
120
|
+
"optionalInput"
|
|
121
|
+
]
|
|
122
|
+
},
|
|
123
|
+
"requiredOnSystemOnboarding": { "type": "boolean" },
|
|
124
|
+
"ownerAppKey": { "type": "string", "minLength": 1 },
|
|
93
125
|
"scope": { "$ref": "#/definitions/scopeEnum" },
|
|
94
126
|
"generator": { "$ref": "#/definitions/generator" },
|
|
95
127
|
"ensureOn": {
|
|
@@ -100,7 +132,23 @@
|
|
|
100
132
|
"requiredForLocal": { "type": "boolean" },
|
|
101
133
|
"azure": { "$ref": "#/definitions/azureBlock" },
|
|
102
134
|
"notes": { "type": "string" }
|
|
103
|
-
}
|
|
135
|
+
},
|
|
136
|
+
"allOf": [
|
|
137
|
+
{
|
|
138
|
+
"if": {
|
|
139
|
+
"required": ["scope"],
|
|
140
|
+
"properties": { "scope": { "const": "system" } }
|
|
141
|
+
},
|
|
142
|
+
"then": {
|
|
143
|
+
"required": [
|
|
144
|
+
"category",
|
|
145
|
+
"sensitive",
|
|
146
|
+
"valueSource",
|
|
147
|
+
"requiredOnSystemOnboarding"
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
]
|
|
104
152
|
}
|
|
105
153
|
}
|
|
106
154
|
}
|