@aifabrix/builder 2.50.0 → 2.51.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/.cursor/plans/Done/157.1-security-quality-violations-by-type.csv +374 -0
- package/.cursor/rules/assistant-driven-integration-build.mdc +40 -0
- package/integration/hubspot-test/create-hubspot.js +1 -16
- package/jest.isolated-projects.js +77 -1
- package/jest.projects.js +5 -426
- package/lib/api/assistants.api.js +67 -0
- package/lib/api/datasources-extended.api.js +6 -6
- package/lib/api/evidence-authoring-helpers.js +267 -0
- package/lib/api/evidence-authoring.api.js +337 -0
- package/lib/api/evidence-kinds.api.js +128 -0
- package/lib/api/evidence.api.js +57 -1
- package/lib/api/index.js +24 -7
- package/lib/api/pipeline.api.js +47 -3
- package/lib/api/records-bulk.api.js +28 -3
- package/lib/api/resource-types.api.js +4 -4
- package/lib/api/roles.api.js +121 -0
- package/lib/api/types/evidence-kinds.types.js +42 -0
- package/lib/api/types/evidence.types.js +156 -8
- package/lib/api/types/roles.types.js +36 -0
- package/lib/api/work.api.js +283 -0
- package/lib/app/certification-verify-rows.js +1 -1
- package/lib/app/run-deploy-job.js +108 -0
- package/lib/app/run-helpers.js +10 -3
- package/lib/app/run.js +8 -0
- package/lib/app/show.js +2 -2
- package/lib/certification/merge-certification-from-artifact.js +1 -1
- package/lib/channels/add-channel.js +54 -23
- package/lib/channels/approval-guides/chatgpt.js +8 -7
- package/lib/channels/approval-guides/microsoft-copilot.js +7 -8
- package/lib/channels/channel-artifact-generator.js +16 -3
- package/lib/channels/channel-credential.js +3 -1
- package/lib/channels/channel-probe-evidence.js +79 -0
- package/lib/channels/channel-probe.js +265 -13
- package/lib/channels/channel-runtime-resolver.js +120 -29
- package/lib/channels/channel-status-display.js +44 -0
- package/lib/channels/channel-targets.js +7 -0
- package/lib/channels/chatgpt-runtime-contract.js +29 -0
- package/lib/channels/microsoft-copilot-package.js +280 -0
- package/lib/channels/runtime-tool-catalog.js +165 -0
- package/lib/cli/index.js +6 -0
- package/lib/cli/setup-app.js +26 -5
- package/lib/cli/setup-dev.js +23 -7
- package/lib/cli/setup-external-system-help.js +8 -2
- package/lib/cli/setup-external-system.js +12 -0
- package/lib/cli/setup-utility-help-after.js +12 -0
- package/lib/cli/setup-utility-validate.js +41 -2
- package/lib/commands/app-test.js +2 -14
- package/lib/commands/datasource-load-export-cli.js +6 -1
- package/lib/commands/deploy-gate-failure-details.js +23 -0
- package/lib/commands/deploy-gate-orchestrator.js +64 -18
- package/lib/commands/dev-cli-handlers.js +6 -3
- package/lib/commands/dev-down.js +2 -6
- package/lib/commands/dev-init.js +7 -109
- package/lib/commands/dev-refresh.js +197 -0
- package/lib/commands/evidence-kind.js +478 -0
- package/lib/commands/governance-command-action.js +4 -2
- package/lib/commands/governance-generate-external.js +56 -21
- package/lib/commands/lifecycle-external.js +10 -4
- package/lib/commands/repair-datasource-apply.js +10 -1
- package/lib/commands/repair-datasource-run.js +4 -2
- package/lib/commands/repair-datasource-test-payload.js +80 -19
- package/lib/commands/repair-datasource-webhooks-sync-bridge.js +42 -3
- package/lib/commands/repair-internal.js +9 -1
- package/lib/commands/repair-openapi-export.js +1 -1
- package/lib/commands/repair-openapi-sync.js +43 -18
- package/lib/commands/resource-type.js +101 -18
- package/lib/commands/role-assistant.js +313 -0
- package/lib/commands/role.js +452 -0
- package/lib/commands/setup.js +1 -1
- package/lib/commands/upload-data-sync-finalize.js +5 -4
- package/lib/commands/upload-sidecar-followups.js +144 -47
- package/lib/commands/upload.js +43 -6
- package/lib/commands/validate-json.js +230 -0
- package/lib/commands/verify-governance-combined-external.js +73 -9
- package/lib/commands/verify-governance-db.js +80 -25
- package/lib/commands/verify-governance-external.js +29 -5
- package/lib/commands/verify-operations-step-plan.js +78 -40
- package/lib/commands/wizard-core-helpers.js +7 -3
- package/lib/commands/wizard-core.js +78 -9
- package/lib/core/audit-logger.js +1 -1
- package/lib/core/secrets-load.js +1 -3
- package/lib/datasource/bulk-loader-run-batches.js +4 -2
- package/lib/datasource/bulk-loader-service.js +5 -1
- package/lib/datasource/capability/relate-operations.js +1 -1
- package/lib/datasource/datasource-validate-summary.js +2 -2
- package/lib/datasource/validate.js +13 -6
- package/lib/external-system/deploy-helpers.js +35 -1
- package/lib/external-system/deploy.js +23 -10
- package/lib/external-system/download-helpers.js +111 -2
- package/lib/external-system/download-role-assistant.js +55 -0
- package/lib/external-system/download.js +45 -26
- package/lib/external-system/test-helpers.js +1 -1
- package/lib/external-system/test.js +39 -3
- package/lib/generator/builders.js +3 -0
- package/lib/generator/helpers.js +13 -5
- package/lib/generator/split-variables.js +9 -3
- package/lib/generator/wizard.js +51 -4
- package/lib/infrastructure/helpers-docker-check.js +6 -0
- package/lib/infrastructure/helpers.js +1 -1
- package/lib/lifecycle/access-control-abac.js +121 -0
- package/lib/lifecycle/lifecycle-governance-options.js +4 -1
- package/lib/lifecycle/product-model.js +3 -2
- package/lib/lifecycle/report-display.js +14 -2
- package/lib/programmatic/auth-config.js +3 -2
- package/lib/programmatic/bearer-auth.js +1 -1
- package/lib/programmatic/capability-registry.js +20 -1
- package/lib/programmatic/command-options.js +1 -0
- package/lib/programmatic/enterprise-mcp-client.js +18 -2
- package/lib/programmatic/index.js +4 -0
- package/lib/programmatic/manifest-patch-section.js +48 -9
- package/lib/programmatic/manifest-section-registry-data.js +3 -2
- package/lib/programmatic/manifest-section-registry.js +18 -1
- package/lib/programmatic/openapi-apply-result-schemas.js +44 -0
- package/lib/programmatic/openapi-component-schemas.js +16 -1
- package/lib/programmatic/openapi-description-enricher.js +3 -1
- package/lib/programmatic/openapi-descriptions.js +55 -5
- package/lib/programmatic/openapi-evidence-schemas.js +161 -0
- package/lib/programmatic/openapi-manifest-schemas.js +6 -2
- package/lib/programmatic/openapi-operation-bindings.js +99 -0
- package/lib/programmatic/openapi-request-schemas.js +36 -1
- package/lib/programmatic/openapi-result-schemas.js +29 -12
- package/lib/programmatic/openapi-schema-descriptions-certify.js +5 -1
- package/lib/programmatic/openapi-schema-descriptions-core.js +6 -3
- package/lib/programmatic/openapi-schema-descriptions-evidence.js +156 -0
- package/lib/programmatic/openapi-schema-descriptions-manifest.js +4 -3
- package/lib/programmatic/openapi-schema-descriptions-operations.js +70 -0
- package/lib/programmatic/openapi-schema-helpers.js +16 -1
- package/lib/programmatic/openapi-spec.js +48 -29
- package/lib/programmatic/orchestration-openapi-meta.js +5 -0
- package/lib/programmatic/request-timeout.js +3 -0
- package/lib/programmatic/route-handler-map.js +89 -2
- package/lib/programmatic/run-certify.js +15 -2
- package/lib/programmatic/run-deploy.js +74 -0
- package/lib/programmatic/run-evidence-authoring.js +80 -0
- package/lib/programmatic/run-protection.js +124 -0
- package/lib/programmatic/run-repository-emcp.js +11 -3
- package/lib/programmatic/run-template-workspace.js +42 -2
- package/lib/programmatic/workspace-context.js +6 -0
- package/lib/protection/auth-context.js +48 -6
- package/lib/protection/paths.js +22 -0
- package/lib/protection/run-protection-create-helpers.js +22 -1
- package/lib/protection/run-protection-create.js +1 -1
- package/lib/protection/sync-after-upload.js +1 -1
- package/lib/resolvers/evidence-kind-file.js +230 -0
- package/lib/resolvers/resource-type-file.js +36 -1
- package/lib/resolvers/role-file.js +227 -0
- package/lib/role-assistant/evidence-sync.js +450 -0
- package/lib/role-assistant/github-workflow.js +96 -0
- package/lib/role-assistant/knowledge-sync.js +465 -0
- package/lib/role-assistant/settings.js +126 -0
- package/lib/role-assistant/test-cases-evaluate.js +170 -0
- package/lib/role-assistant/test-cases-honesty.js +184 -0
- package/lib/role-assistant/test-cases.js +364 -0
- package/lib/role-assistant/test-runner-workhub-answers.js +203 -0
- package/lib/role-assistant/test-runner-workhub.js +385 -0
- package/lib/role-assistant/test-runner.js +500 -0
- package/lib/schema/application-schema.json +36 -2
- package/lib/schema/deployment-rules.yaml +1 -0
- package/lib/schema/external-datasource.schema.json +121 -4
- package/lib/schema/external-system.schema.json +20 -6
- package/lib/schema/infra.parameter.yaml +45 -1
- package/lib/schema/role-assistant-settings.schema.json +108 -0
- package/lib/schema/type/credential-field-registry.json +19 -3
- package/lib/utils/api.js +52 -21
- package/lib/utils/app-path-resolve.js +72 -24
- package/lib/utils/app-register-config.js +4 -3
- package/lib/utils/authentication-shape.js +3 -1
- package/lib/utils/cli-sync-options.js +59 -3
- package/lib/utils/cli-utils.js +11 -3
- package/lib/utils/deployment-validation.js +28 -3
- package/lib/utils/dev-ca-install.js +5 -6
- package/lib/utils/dev-config.js +2 -2
- package/lib/utils/dev-list-sort.js +145 -0
- package/lib/utils/dev-platform-tls.js +0 -63
- package/lib/utils/docker-build.js +46 -27
- package/lib/utils/docker-daemon-tls-ca.js +1 -1
- package/lib/utils/docker-exec.js +91 -6
- package/lib/utils/docker-run-ephemeral.js +55 -0
- package/lib/utils/enterprise-knowledge-paths.js +29 -12
- package/lib/utils/env-copy-keycloak.js +196 -0
- package/lib/utils/env-copy.js +35 -4
- package/lib/utils/error-formatters/error-parser.js +0 -3
- package/lib/utils/external-env-template.js +1 -1
- package/lib/utils/external-system-readiness-compact-blocks.js +28 -1
- package/lib/utils/external-system-readiness-compact-display.js +3 -0
- package/lib/utils/health-check-request.js +2 -3
- package/lib/utils/help-builder.js +4 -0
- package/lib/utils/image-name.js +22 -4
- package/lib/utils/logger.js +37 -4
- package/lib/utils/manifest-source-emit.js +1 -1
- package/lib/utils/paths.js +98 -26
- package/lib/utils/pipeline-upload-auth-retry.js +19 -3
- package/lib/utils/postgres-platform-bootstrap.js +24 -17
- package/lib/utils/postgres-wipe.js +5 -2
- package/lib/utils/remote-dev-auth.js +39 -4
- package/lib/utils/resolve-docker-image-ref.js +36 -6
- package/lib/utils/role-assistant-paths.js +98 -0
- package/lib/utils/schema-loader.js +41 -0
- package/lib/utils/schema-resolver.js +36 -4
- package/lib/utils/token-manager.js +47 -22
- package/lib/utils/upload-sync-options.js +17 -3
- package/lib/utils/url-declarative-resolve-load-doc.js +38 -1
- package/lib/validation/external-manifest-validator.js +31 -8
- package/lib/validation/openapi-contract-surface-validator.js +4 -0
- package/lib/validation/validate-external-file.js +8 -1
- package/lib/validation/validator.js +6 -5
- package/package.json +35 -12
- package/scripts/export-builder-api-evidence.js +3 -3
- package/scripts/lib/plan-actor.js +2 -2
- package/scripts/lib/plan-meta.js +1 -1
- package/scripts/lib/plan-parse.js +1 -1
- package/scripts/lib/plan-prevalidate-gates.js +12 -1
- package/scripts/lib/plan-run-report.js +13 -2
- package/scripts/pnpm/lib/resolve-aifabrix-bin.mjs +10 -10
- package/templates/applications/dataplane/application.yaml +47 -17
- package/templates/applications/dataplane/env.template +28 -9
- package/templates/applications/dataplane/rbac.yaml +78 -2
- package/templates/applications/miso-controller/application.yaml +10 -1
- package/templates/applications/miso-controller/env.template +13 -8
- package/templates/applications/miso-controller/rbac.yaml +72 -0
- package/templates/channels/chatgpt/install.template.md.hbs +42 -24
- package/templates/channels/chatgpt/integration/README.md +10 -7
- package/templates/channels/chatgpt/integration/application.json +2 -2
- package/templates/channels/chatgpt/integration/chatgpt-system.json +3 -3
- package/templates/channels/chatgpt/integration/env.template +1 -1
- package/templates/channels/chatgpt/manifest.template.json.hbs +36 -5
- package/templates/channels/microsoft-copilot/ai-plugin.template.json.hbs +28 -0
- package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +22 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +32 -22
- package/templates/channels/microsoft-copilot/integration/README.md +9 -7
- package/templates/channels/microsoft-copilot/integration/application.json +2 -2
- package/templates/channels/microsoft-copilot/integration/env.template +1 -1
- package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +7 -6
- package/templates/channels/microsoft-copilot/manifest.template.json.hbs +34 -6
- package/templates/channels/slack/integration/slack-system.json +60 -2
- package/templates/python/requirements.txt +1 -1
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Role Assistant workspace path helpers.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Paths under role-assistant/ for Role Assistant packages
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const os = require('os');
|
|
13
|
+
const { nodeFs } = require('../internal/node-fs');
|
|
14
|
+
|
|
15
|
+
const WORKSPACE_ROLE_ASSISTANT = 'role-assistant';
|
|
16
|
+
const SYSTEM_KIND_DIGITAL_WORKER = 'digitalWorker';
|
|
17
|
+
|
|
18
|
+
function getMaterializationParent() {
|
|
19
|
+
const work = process.env.AIFABRIX_WORK;
|
|
20
|
+
if (work && typeof work === 'string' && work.trim()) {
|
|
21
|
+
return path.resolve(work.trim());
|
|
22
|
+
}
|
|
23
|
+
if (process.env.AIFABRIX_HOME && typeof process.env.AIFABRIX_HOME === 'string') {
|
|
24
|
+
return path.resolve(process.env.AIFABRIX_HOME.trim());
|
|
25
|
+
}
|
|
26
|
+
return path.join(os.homedir(), '.aifabrix');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function getCwdRoleAssistantRoot() {
|
|
30
|
+
const p = path.join(path.resolve(process.cwd()), WORKSPACE_ROLE_ASSISTANT);
|
|
31
|
+
try {
|
|
32
|
+
const disk = nodeFs();
|
|
33
|
+
if (disk.existsSync(p)) {
|
|
34
|
+
const st = disk.statSync(p);
|
|
35
|
+
if (st && typeof st.isDirectory === 'function' && st.isDirectory()) {
|
|
36
|
+
return p;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
} catch {
|
|
40
|
+
// ignore
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function getRoleAssistantRoot() {
|
|
46
|
+
const cwdRoot = getCwdRoleAssistantRoot();
|
|
47
|
+
if (cwdRoot) {
|
|
48
|
+
return cwdRoot;
|
|
49
|
+
}
|
|
50
|
+
return path.join(getMaterializationParent(), WORKSPACE_ROLE_ASSISTANT);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function isExistingDirectory(disk, dirPath) {
|
|
54
|
+
try {
|
|
55
|
+
if (!dirPath || !disk.existsSync(dirPath)) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
const st = disk.statSync(dirPath);
|
|
59
|
+
return Boolean(st && typeof st.isDirectory === 'function' && st.isDirectory());
|
|
60
|
+
} catch {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Resolves role-assistant/<roleKey> with cwd-first behavior.
|
|
67
|
+
* @param {string} roleKey
|
|
68
|
+
* @returns {string}
|
|
69
|
+
*/
|
|
70
|
+
function getRoleAssistantPath(roleKey) {
|
|
71
|
+
if (!roleKey || typeof roleKey !== 'string') {
|
|
72
|
+
throw new Error('Role key is required and must be a string');
|
|
73
|
+
}
|
|
74
|
+
const disk = nodeFs();
|
|
75
|
+
const cwdRoot = getCwdRoleAssistantRoot();
|
|
76
|
+
const matPath = path.join(getMaterializationParent(), WORKSPACE_ROLE_ASSISTANT, roleKey);
|
|
77
|
+
if (cwdRoot) {
|
|
78
|
+
const cwdPath = path.join(cwdRoot, roleKey);
|
|
79
|
+
if (isExistingDirectory(disk, cwdPath)) {
|
|
80
|
+
return cwdPath;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (isExistingDirectory(disk, matPath)) {
|
|
84
|
+
return matPath;
|
|
85
|
+
}
|
|
86
|
+
if (cwdRoot) {
|
|
87
|
+
return path.join(cwdRoot, roleKey);
|
|
88
|
+
}
|
|
89
|
+
return matPath;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
module.exports = {
|
|
93
|
+
WORKSPACE_ROLE_ASSISTANT,
|
|
94
|
+
SYSTEM_KIND_DIGITAL_WORKER,
|
|
95
|
+
getCwdRoleAssistantRoot,
|
|
96
|
+
getRoleAssistantRoot,
|
|
97
|
+
getRoleAssistantPath
|
|
98
|
+
};
|
|
@@ -18,6 +18,7 @@ const addFormats = require('ajv-formats');
|
|
|
18
18
|
// These are reset when module is reloaded (for testing)
|
|
19
19
|
let externalSystemValidator = null;
|
|
20
20
|
let externalDataSourceValidator = null;
|
|
21
|
+
let roleAssistantSettingsValidator = null;
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Reset validators cache (for testing)
|
|
@@ -26,6 +27,7 @@ let externalDataSourceValidator = null;
|
|
|
26
27
|
function resetValidators() {
|
|
27
28
|
externalSystemValidator = null;
|
|
28
29
|
externalDataSourceValidator = null;
|
|
30
|
+
roleAssistantSettingsValidator = null;
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
/**
|
|
@@ -138,6 +140,38 @@ function loadExternalDataSourceSchema() {
|
|
|
138
140
|
return externalDataSourceValidator;
|
|
139
141
|
}
|
|
140
142
|
|
|
143
|
+
/**
|
|
144
|
+
* Loads and compiles role-assistant settings schema.
|
|
145
|
+
* @function loadRoleAssistantSettingsSchema
|
|
146
|
+
* @returns {Function}
|
|
147
|
+
*/
|
|
148
|
+
function loadRoleAssistantSettingsSchema() {
|
|
149
|
+
if (roleAssistantSettingsValidator) {
|
|
150
|
+
return roleAssistantSettingsValidator;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const schemaPath = path.join(__dirname, '..', 'schema', 'role-assistant-settings.schema.json');
|
|
154
|
+
let schema;
|
|
155
|
+
try {
|
|
156
|
+
const schemaContent = fsRealSync.readFileSync(schemaPath, 'utf8');
|
|
157
|
+
schema = JSON.parse(schemaContent);
|
|
158
|
+
} catch (error) {
|
|
159
|
+
try {
|
|
160
|
+
schema = require('../schema/role-assistant-settings.schema.json');
|
|
161
|
+
} catch {
|
|
162
|
+
if (error && error.code === 'ENOENT') {
|
|
163
|
+
throw new Error(`Role assistant settings schema not found: ${schemaPath}`);
|
|
164
|
+
}
|
|
165
|
+
throw new Error(`Invalid JSON in role-assistant-settings.schema.json: ${error.message}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const ajv = new Ajv({ allErrors: true, strict: false, strictSchema: false });
|
|
170
|
+
addFormats(ajv);
|
|
171
|
+
roleAssistantSettingsValidator = ajv.compile(schema);
|
|
172
|
+
return roleAssistantSettingsValidator;
|
|
173
|
+
}
|
|
174
|
+
|
|
141
175
|
/**
|
|
142
176
|
* Detect schema type from $id field
|
|
143
177
|
* @param {Object} parsed - Parsed JSON object
|
|
@@ -157,6 +191,9 @@ function detectFromId(parsed) {
|
|
|
157
191
|
if (parsed.$id.includes('application-schema')) {
|
|
158
192
|
return 'application';
|
|
159
193
|
}
|
|
194
|
+
if (parsed.$id.includes('role-assistant-settings')) {
|
|
195
|
+
return 'role-assistant-settings';
|
|
196
|
+
}
|
|
160
197
|
|
|
161
198
|
return null;
|
|
162
199
|
}
|
|
@@ -239,6 +276,9 @@ function detectFromApplicationFields(parsed) {
|
|
|
239
276
|
*/
|
|
240
277
|
function detectFromFilename(filePath) {
|
|
241
278
|
const fileName = path.basename(filePath).toLowerCase();
|
|
279
|
+
if (fileName === 'role-assistant.yaml' || fileName === 'role-assistant.yml') {
|
|
280
|
+
return 'role-assistant-settings';
|
|
281
|
+
}
|
|
242
282
|
if (fileName.includes('external-system') || fileName.includes('external_system')) {
|
|
243
283
|
return 'external-system';
|
|
244
284
|
}
|
|
@@ -347,6 +387,7 @@ function detectSchemaType(filePath, content) {
|
|
|
347
387
|
module.exports = {
|
|
348
388
|
loadExternalSystemSchema,
|
|
349
389
|
loadExternalDataSourceSchema,
|
|
390
|
+
loadRoleAssistantSettingsSchema,
|
|
350
391
|
registerExternalDatasourceAjvDependencies,
|
|
351
392
|
detectSchemaType,
|
|
352
393
|
detectSchemaTypeFromParsed,
|
|
@@ -175,6 +175,18 @@ function resolveDatasourceFiles(schemaBasePath, datasourceFiles) {
|
|
|
175
175
|
return datasourceFiles.map(fileName => resolveSingleExternalFile(schemaBasePath, fileName, 'datasource'));
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
+
function resolveRoleAssistantSettingsFile(appPath) {
|
|
179
|
+
const yamlPath = path.join(appPath, 'role-assistant.yaml');
|
|
180
|
+
if (fs.existsSync(yamlPath)) {
|
|
181
|
+
return resolveSingleExternalFile(appPath, 'role-assistant.yaml', 'role-assistant-settings');
|
|
182
|
+
}
|
|
183
|
+
const ymlPath = path.join(appPath, 'role-assistant.yml');
|
|
184
|
+
if (fs.existsSync(ymlPath)) {
|
|
185
|
+
return resolveSingleExternalFile(appPath, 'role-assistant.yml', 'role-assistant-settings');
|
|
186
|
+
}
|
|
187
|
+
return resolveSingleExternalFile(appPath, 'role-assistant.yaml', 'role-assistant-settings');
|
|
188
|
+
}
|
|
189
|
+
|
|
178
190
|
/**
|
|
179
191
|
* @param {string} schemaBasePath
|
|
180
192
|
* @param {string[]} systemFileNames
|
|
@@ -282,6 +294,21 @@ async function loadAndValidateVariables(appPath) {
|
|
|
282
294
|
}
|
|
283
295
|
}
|
|
284
296
|
|
|
297
|
+
function readSystemKindFromFirstSystemFile(schemaBasePath, systemFileNames) {
|
|
298
|
+
if (!systemFileNames.length) {
|
|
299
|
+
return '';
|
|
300
|
+
}
|
|
301
|
+
try {
|
|
302
|
+
const firstSystemPath = path.join(schemaBasePath, systemFileNames[0]);
|
|
303
|
+
const parsedSystem = loadConfigFile(firstSystemPath);
|
|
304
|
+
return parsedSystem && typeof parsedSystem.systemKind === 'string'
|
|
305
|
+
? parsedSystem.systemKind
|
|
306
|
+
: '';
|
|
307
|
+
} catch {
|
|
308
|
+
return '';
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
285
312
|
async function resolveExternalFiles(appName, options = {}) {
|
|
286
313
|
if (!appName || typeof appName !== 'string') {
|
|
287
314
|
throw new Error('App name is required and must be a string');
|
|
@@ -295,15 +322,20 @@ async function resolveExternalFiles(appName, options = {}) {
|
|
|
295
322
|
}
|
|
296
323
|
|
|
297
324
|
const schemaBasePath = await resolveSchemaBasePath(appName, options);
|
|
298
|
-
const
|
|
325
|
+
const systemFileNames = variables.externalIntegration.systems || [];
|
|
326
|
+
const systemFiles = resolveSystemFiles(schemaBasePath, systemFileNames);
|
|
327
|
+
const systemKind = readSystemKindFromFirstSystemFile(schemaBasePath, systemFileNames);
|
|
299
328
|
const orderedNames = orderDatasourceFileNamesBySystemKeys(
|
|
300
329
|
schemaBasePath,
|
|
301
|
-
|
|
330
|
+
systemFileNames,
|
|
302
331
|
variables.externalIntegration.dataSources || []
|
|
303
332
|
);
|
|
304
333
|
const datasourceFiles = resolveDatasourceFiles(schemaBasePath, orderedNames);
|
|
305
|
-
|
|
306
|
-
|
|
334
|
+
const extraFiles = [];
|
|
335
|
+
if (String(systemKind).trim() === 'digitalWorker') {
|
|
336
|
+
extraFiles.push(resolveRoleAssistantSettingsFile(appPath));
|
|
337
|
+
}
|
|
338
|
+
return [...systemFiles, ...datasourceFiles, ...extraFiles];
|
|
307
339
|
}
|
|
308
340
|
|
|
309
341
|
module.exports = {
|
|
@@ -408,37 +408,62 @@ function applyLabDataplaneApiKeyBearer(authConfig) {
|
|
|
408
408
|
return authConfig;
|
|
409
409
|
}
|
|
410
410
|
|
|
411
|
+
function looksLikeJwtBearer(token) {
|
|
412
|
+
const existing = token ? String(token) : '';
|
|
413
|
+
return existing.split('.').length === 3 && existing.length > 80;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function preferClientCredentialsDeploymentAuth() {
|
|
417
|
+
return String(process.env.AIFABRIX_DEPLOYMENT_AUTH || '').toLowerCase() === 'client-credentials';
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* @param {Object} authConfig
|
|
422
|
+
* @returns {boolean} true when a substitution was applied
|
|
423
|
+
*/
|
|
424
|
+
function trySubstituteEnvApiKeyBearer(authConfig) {
|
|
425
|
+
if (!process.env.API_KEY) {
|
|
426
|
+
return false;
|
|
427
|
+
}
|
|
428
|
+
const apiKey = String(process.env.API_KEY);
|
|
429
|
+
if (authConfig.type === 'bearer' && authConfig.token !== apiKey) {
|
|
430
|
+
authConfig.token = apiKey;
|
|
431
|
+
return true;
|
|
432
|
+
}
|
|
433
|
+
if (authConfig.type === 'client-token') {
|
|
434
|
+
authConfig.type = 'bearer';
|
|
435
|
+
authConfig.token = apiKey;
|
|
436
|
+
return true;
|
|
437
|
+
}
|
|
438
|
+
if (!authConfig.token) {
|
|
439
|
+
authConfig.type = 'bearer';
|
|
440
|
+
authConfig.token = apiKey;
|
|
441
|
+
return true;
|
|
442
|
+
}
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
445
|
+
|
|
411
446
|
function requireBearerForDataplanePipeline(authConfig) {
|
|
447
|
+
if (!authConfig || typeof authConfig !== 'object') {
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
412
450
|
if (authConfig.type === 'client-token' && authConfig.token) {
|
|
413
451
|
return;
|
|
414
452
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
if (!preferAppClientToken && process.env.API_KEY) {
|
|
420
|
-
const apiKey = String(process.env.API_KEY);
|
|
421
|
-
if (authConfig.type === 'bearer' && authConfig.token !== apiKey) {
|
|
422
|
-
authConfig.token = apiKey;
|
|
423
|
-
return;
|
|
424
|
-
}
|
|
425
|
-
if (authConfig.type === 'client-token') {
|
|
426
|
-
authConfig.type = 'bearer';
|
|
427
|
-
authConfig.token = apiKey;
|
|
428
|
-
return;
|
|
429
|
-
}
|
|
453
|
+
// Token-forward (builder-api / bearerForward): never substitute lab API_KEY for the caller JWT.
|
|
454
|
+
if (authConfig.preserveBearer && authConfig.token) {
|
|
455
|
+
return;
|
|
430
456
|
}
|
|
431
|
-
|
|
432
|
-
if (authConfig.token) {
|
|
457
|
+
// Enterprise path: keep a real OAuth JWT; do not overwrite with process.env.API_KEY.
|
|
458
|
+
if (looksLikeJwtBearer(authConfig.token)) {
|
|
433
459
|
return;
|
|
434
460
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
461
|
+
if (!preferClientCredentialsDeploymentAuth() && trySubstituteEnvApiKeyBearer(authConfig)) {
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
if (authConfig.token) {
|
|
439
465
|
return;
|
|
440
466
|
}
|
|
441
|
-
|
|
442
467
|
if (authConfig.clientId || authConfig.clientSecret) {
|
|
443
468
|
throw new Error(
|
|
444
469
|
'Dataplane pipeline endpoints require OAuth2 (Bearer token) or x-client-token. ' +
|
|
@@ -10,9 +10,10 @@
|
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* @param {Object} [options] - CLI options from test / sync callers
|
|
13
|
-
* @returns {{ minimal: true, verbose: boolean, silentResolve: true, syncMode: true, force?: true }}
|
|
13
|
+
* @returns {{ minimal: true, verbose: boolean, silentResolve: true, syncMode: true, force?: true, authConfig?: Object, dataplaneUrl?: string, environment?: string }}
|
|
14
14
|
*/
|
|
15
15
|
function buildMinimalUploadSyncOptions(options = {}) {
|
|
16
|
+
const deployPreflight = options.uploadContext === 'deploy-preflight';
|
|
16
17
|
const out = {
|
|
17
18
|
minimal: true,
|
|
18
19
|
// CLI -v on verify-* / test-* is for run output, not preflight upload banners.
|
|
@@ -20,14 +21,27 @@ function buildMinimalUploadSyncOptions(options = {}) {
|
|
|
20
21
|
silentResolve: true,
|
|
21
22
|
syncMode: true,
|
|
22
23
|
skipDataSync: true,
|
|
23
|
-
suppressPipelineSpinner:
|
|
24
|
+
suppressPipelineSpinner:
|
|
25
|
+
options.suppressPipelineSpinner === true || deployPreflight === true
|
|
24
26
|
};
|
|
25
27
|
if (options.force === true) {
|
|
26
28
|
out.force = true;
|
|
27
29
|
}
|
|
28
|
-
if (options.suppressSummary === true) {
|
|
30
|
+
if (options.suppressSummary === true || deployPreflight === true) {
|
|
29
31
|
out.suppressSummary = true;
|
|
30
32
|
}
|
|
33
|
+
if (deployPreflight) {
|
|
34
|
+
out.uploadContext = 'deploy-preflight';
|
|
35
|
+
}
|
|
36
|
+
// Builder-api / programmatic callers: keep request Bearer — do not fall back to
|
|
37
|
+
// getDeploymentAuth against a stale mount AIFABRIX_CONFIG device token.
|
|
38
|
+
if (options.authConfig && options.dataplaneUrl) {
|
|
39
|
+
out.authConfig = options.authConfig;
|
|
40
|
+
out.dataplaneUrl = options.dataplaneUrl;
|
|
41
|
+
if (options.environment) {
|
|
42
|
+
out.environment = options.environment;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
31
45
|
return out;
|
|
32
46
|
}
|
|
33
47
|
|
|
@@ -25,6 +25,42 @@ function tryReadApplicationYamlAt(cfgPath) {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* @param {unknown} value
|
|
30
|
+
* @returns {boolean}
|
|
31
|
+
*/
|
|
32
|
+
function isPositivePortValue(value) {
|
|
33
|
+
if (typeof value === 'number' && value > 0) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
return typeof value === 'string' && /^\d+$/.test(String(value).trim());
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* True when a manifest can authoritatively supply listen/port for url:// expansion.
|
|
41
|
+
* External-system `application.json` (upload payload) has no HTTP listen port — using it
|
|
42
|
+
* for `url://builder-api-internal` falls through to {@link DECLARATIVE_URL_INFRA_DEFAULTS}
|
|
43
|
+
* (3000) and breaks Docker CIP against the real builder-api container (3005).
|
|
44
|
+
*
|
|
45
|
+
* @param {object|null|undefined} doc
|
|
46
|
+
* @returns {boolean}
|
|
47
|
+
*/
|
|
48
|
+
function isDeclarativeUrlPortAuthorityDoc(doc) {
|
|
49
|
+
if (!doc || typeof doc !== 'object') {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
if ((doc.app && doc.app.type) === 'external') {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
if (doc.externalIntegration && typeof doc.externalIntegration === 'object') {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return (
|
|
59
|
+
isPositivePortValue(doc.port) ||
|
|
60
|
+
isPositivePortValue(doc.build && doc.build.containerPort)
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
28
64
|
/**
|
|
29
65
|
* Candidate paths for cross-app url:// resolution (low → high priority).
|
|
30
66
|
* Platform system apps prefer materialized `~/.aifabrix-work|home/builder` over CLI package `builder/` stubs.
|
|
@@ -83,7 +119,7 @@ function loadApplicationYamlDocForUrlResolve(appKey, ctx, pathsUtil) {
|
|
|
83
119
|
if (appKey === current && ctx.variablesPath) {
|
|
84
120
|
const vp = path.resolve(String(ctx.variablesPath));
|
|
85
121
|
const fromVars = tryReadApplicationYamlAt(vp);
|
|
86
|
-
if (fromVars) {
|
|
122
|
+
if (isDeclarativeUrlPortAuthorityDoc(fromVars)) {
|
|
87
123
|
return fromVars;
|
|
88
124
|
}
|
|
89
125
|
}
|
|
@@ -105,5 +141,6 @@ function loadApplicationYamlDocForUrlResolve(appKey, ctx, pathsUtil) {
|
|
|
105
141
|
|
|
106
142
|
module.exports = {
|
|
107
143
|
collectApplicationYamlPathsForUrlResolve,
|
|
144
|
+
isDeclarativeUrlPortAuthorityDoc,
|
|
108
145
|
loadApplicationYamlDocForUrlResolve
|
|
109
146
|
};
|
|
@@ -217,6 +217,36 @@ function validateDatasourceSystemKeyAlignment(manifest, errors) {
|
|
|
217
217
|
});
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
+
/**
|
|
221
|
+
* Vendor OpenAPI contract surface is for Connected Systems. Role Assistants
|
|
222
|
+
* (digitalWorker) promote settings + Evidence — skip blocking OpenAPI vendor checks.
|
|
223
|
+
* @param {Object} manifest
|
|
224
|
+
* @param {Object} options
|
|
225
|
+
* @param {string[]} errors
|
|
226
|
+
* @param {string[]} warnings
|
|
227
|
+
*/
|
|
228
|
+
function applyExternalContractSurfaceChecks(manifest, options, errors, warnings) {
|
|
229
|
+
if (manifest.type !== 'external' || !Array.isArray(manifest.dataSources) || !manifest.system?.key) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const appPath = options.appPath;
|
|
233
|
+
if (typeof appPath !== 'string' || !appPath) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const systemKind =
|
|
237
|
+
typeof manifest.system.systemKind === 'string' ? manifest.system.systemKind.trim() : '';
|
|
238
|
+
if (systemKind === 'digitalWorker') {
|
|
239
|
+
warnings.push(
|
|
240
|
+
'Role Assistant (digitalWorker): vendor OpenAPI contract checks skipped ' +
|
|
241
|
+
'(settings + evidence path; run repair --api only when binding vendor OpenAPI).'
|
|
242
|
+
);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
const contract = validateAppContractSurface(appPath, manifest.system.key, manifest.dataSources);
|
|
246
|
+
errors.push(...contract.errors);
|
|
247
|
+
warnings.push(...contract.warnings);
|
|
248
|
+
}
|
|
249
|
+
|
|
220
250
|
/**
|
|
221
251
|
* Validates controller deployment manifest for external systems
|
|
222
252
|
* Validates manifest structure and inline system/dataSources against their schemas
|
|
@@ -251,14 +281,7 @@ async function validateControllerManifest(manifest, options = {}) {
|
|
|
251
281
|
validateDatasources(manifest, ajv, externalDatasourceSchema, errors, warnings);
|
|
252
282
|
validateDatasourceSystemKeyAlignment(manifest, errors);
|
|
253
283
|
errors.push(...validateManifestRuntimeConfiguration(manifest));
|
|
254
|
-
|
|
255
|
-
const appPath = options.appPath;
|
|
256
|
-
if (typeof appPath === 'string' && appPath) {
|
|
257
|
-
const contract = validateAppContractSurface(appPath, manifest.system.key, manifest.dataSources);
|
|
258
|
-
errors.push(...contract.errors);
|
|
259
|
-
warnings.push(...contract.warnings);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
284
|
+
applyExternalContractSurfaceChecks(manifest, options, errors, warnings);
|
|
262
285
|
validateConditionalRequirements(manifest, errors, warnings);
|
|
263
286
|
validateRequiredFields(manifest, errors);
|
|
264
287
|
|
|
@@ -307,6 +307,10 @@ function resolveCachedVendorSpec(documentKey, prefix, appPath, systemKey, vendor
|
|
|
307
307
|
function validateServiceContractVendorOpenApi(ds, prefix, appPath, systemKey, vendorCache) {
|
|
308
308
|
const errors = [];
|
|
309
309
|
const warnings = [];
|
|
310
|
+
// Python/CIP handlers without a vendor OpenAPI binding are valid serviceContracts.
|
|
311
|
+
if (!hasVendorOpenapiOnManifest(ds)) {
|
|
312
|
+
return { errors, warnings };
|
|
313
|
+
}
|
|
310
314
|
const documentKey =
|
|
311
315
|
typeof ds.openapi?.documentKey === 'string' ? ds.openapi.documentKey.trim() : '';
|
|
312
316
|
if (!documentKey) {
|
|
@@ -10,7 +10,11 @@
|
|
|
10
10
|
|
|
11
11
|
const fs = require('fs');
|
|
12
12
|
const yaml = require('js-yaml');
|
|
13
|
-
const {
|
|
13
|
+
const {
|
|
14
|
+
loadExternalSystemSchema,
|
|
15
|
+
loadExternalDataSourceSchema,
|
|
16
|
+
loadRoleAssistantSettingsSchema
|
|
17
|
+
} = require('../utils/schema-loader');
|
|
14
18
|
const { formatValidationErrors } = require('../utils/error-formatter');
|
|
15
19
|
const { validateFieldReferences } = require('../datasource/field-reference-validator');
|
|
16
20
|
const { validateAbac } = require('../datasource/abac-validator');
|
|
@@ -53,6 +57,9 @@ function getValidatorForType(normalizedType) {
|
|
|
53
57
|
if (normalizedType === 'datasource') {
|
|
54
58
|
return loadExternalDataSourceSchema();
|
|
55
59
|
}
|
|
60
|
+
if (normalizedType === 'role-assistant-settings') {
|
|
61
|
+
return loadRoleAssistantSettingsSchema();
|
|
62
|
+
}
|
|
56
63
|
throw new Error(`Unknown file type: ${normalizedType}`);
|
|
57
64
|
}
|
|
58
65
|
|
|
@@ -223,10 +223,11 @@ async function validateRbac(appName, options = {}) {
|
|
|
223
223
|
throw new Error(`Invalid syntax in ${basename}: ${error.message}`);
|
|
224
224
|
}
|
|
225
225
|
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
];
|
|
226
|
+
const [roleErrors, permissionErrors] = await Promise.all([
|
|
227
|
+
Promise.resolve(validateRoles(rbac.roles)),
|
|
228
|
+
Promise.resolve(validatePermissions(rbac.permissions))
|
|
229
|
+
]);
|
|
230
|
+
const errors = [...roleErrors, ...permissionErrors];
|
|
230
231
|
|
|
231
232
|
return {
|
|
232
233
|
valid: errors.length === 0,
|
|
@@ -275,7 +276,7 @@ async function validateEnvTemplate(appName, options = {}) {
|
|
|
275
276
|
if (!trimmed.includes('=')) {
|
|
276
277
|
errors.push(`Line ${index + 1}: Invalid environment variable format (missing =)`);
|
|
277
278
|
} else {
|
|
278
|
-
const [key
|
|
279
|
+
const [key] = trimmed.split('=', 2);
|
|
279
280
|
// Trim key to handle whitespace issues
|
|
280
281
|
// Empty values are allowed (_value can be empty string or undefined)
|
|
281
282
|
const trimmedKey = key ? key.trim() : '';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aifabrix/builder",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.51.1",
|
|
4
4
|
"description": "AI Fabrix Builder — CLI and developer scripts (pnpm + af)",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -85,36 +85,59 @@
|
|
|
85
85
|
"cache": true,
|
|
86
86
|
"temp-dir": ".nyc_output"
|
|
87
87
|
},
|
|
88
|
+
"overrides": {
|
|
89
|
+
"@babel/core": "^7.29.7",
|
|
90
|
+
"@babel/plugin-transform-modules-systemjs": "^7.29.7",
|
|
91
|
+
"fast-uri": "^4.1.0",
|
|
92
|
+
"flatted": "^3.4.2",
|
|
93
|
+
"follow-redirects": "^1.16.0",
|
|
94
|
+
"form-data": "^4.0.6",
|
|
95
|
+
"lodash": "^4.18.1",
|
|
96
|
+
"minimatch": "^10.2.5",
|
|
97
|
+
"picomatch": "^4.0.5",
|
|
98
|
+
"qs": "^6.15.3"
|
|
99
|
+
},
|
|
88
100
|
"pnpm": {
|
|
89
101
|
"overrides": {
|
|
90
|
-
"@bcoe/v8-coverage": "^1.0.2"
|
|
102
|
+
"@bcoe/v8-coverage": "^1.0.2",
|
|
103
|
+
"@babel/core": "^7.29.7",
|
|
104
|
+
"@babel/plugin-transform-modules-systemjs": "^7.29.7",
|
|
105
|
+
"fast-uri": "^4.1.0",
|
|
106
|
+
"flatted": "^3.4.2",
|
|
107
|
+
"follow-redirects": "^1.16.0",
|
|
108
|
+
"form-data": "^4.0.6",
|
|
109
|
+
"lodash": "^4.18.1",
|
|
110
|
+
"minimatch": "^10.2.5",
|
|
111
|
+
"picomatch": "^4.0.5",
|
|
112
|
+
"qs": "^6.15.3"
|
|
91
113
|
}
|
|
92
114
|
},
|
|
93
115
|
"dependencies": {
|
|
94
116
|
"@aifabrix/miso-client": "^4.19.0",
|
|
95
|
-
"
|
|
117
|
+
"adm-zip": "^0.6.0",
|
|
118
|
+
"ajv": "^8.20.0",
|
|
96
119
|
"ajv-formats": "^3.0.1",
|
|
97
|
-
"axios": "^1.
|
|
120
|
+
"axios": "^1.18.1",
|
|
98
121
|
"chalk": "^4.1.2",
|
|
99
122
|
"commander": "^11.1.0",
|
|
100
|
-
"handlebars": "^4.7.
|
|
123
|
+
"handlebars": "^4.7.9",
|
|
101
124
|
"inquirer": "^8.2.5",
|
|
102
125
|
"inquirer-autocomplete-prompt": "^2.0.0",
|
|
103
|
-
"js-yaml": "^4.
|
|
126
|
+
"js-yaml": "^4.3.0",
|
|
104
127
|
"ora": "^5.4.1",
|
|
105
|
-
"yaml": "^2.
|
|
128
|
+
"yaml": "^2.9.0"
|
|
106
129
|
},
|
|
107
130
|
"devDependencies": {
|
|
108
131
|
"@babel/plugin-syntax-optional-chaining": "^7.8.3",
|
|
109
|
-
"@babel/preset-env": "^7.29.
|
|
132
|
+
"@babel/preset-env": "^7.29.7",
|
|
110
133
|
"@bcoe/v8-coverage": "^1.0.2",
|
|
111
|
-
"@nestjs/common": "^
|
|
112
|
-
"@nestjs/core": "^
|
|
113
|
-
"@nestjs/platform-express": "^
|
|
134
|
+
"@nestjs/common": "^11.1.28",
|
|
135
|
+
"@nestjs/core": "^11.1.28",
|
|
136
|
+
"@nestjs/platform-express": "^11.1.28",
|
|
114
137
|
"@types/node": "^20.10.0",
|
|
115
138
|
"cross-env": "^10.1.0",
|
|
116
139
|
"eslint": "^8.55.0",
|
|
117
|
-
"jest": "^30.2
|
|
140
|
+
"jest": "^30.4.2",
|
|
118
141
|
"markdownlint-cli": "^0.49.0",
|
|
119
142
|
"nyc": "^18.0.0",
|
|
120
143
|
"reflect-metadata": "^0.2.2",
|
|
@@ -18,8 +18,8 @@ const DEFAULT_OUT = path.join(
|
|
|
18
18
|
'..',
|
|
19
19
|
'aifabrix-dataplane',
|
|
20
20
|
'integration',
|
|
21
|
-
'
|
|
22
|
-
'
|
|
21
|
+
'builder-api',
|
|
22
|
+
'builder-api-evidence.json'
|
|
23
23
|
);
|
|
24
24
|
|
|
25
25
|
const EVIDENCE_PATTERNS = path.join(REPO_ROOT, 'docs', 'builder-help', 'evidence-patterns.json');
|
|
@@ -238,7 +238,7 @@ function rowsFromManifestGuides() {
|
|
|
238
238
|
title: 'Section quality and missing inputs',
|
|
239
239
|
when: 'GET manifest section returns quality.missingInputs',
|
|
240
240
|
expectedBehavior:
|
|
241
|
-
'Collect required missing inputs from the user before PATCH. Do not guess values.
|
|
241
|
+
'Collect required missing inputs from the user before PATCH. Do not guess values. sectionReadToken from GET is optional on PATCH (server re-reads when omitted; stale token returns 409). Prefer GET when you need quality or missingInputs.',
|
|
242
242
|
order: 17
|
|
243
243
|
})
|
|
244
244
|
];
|
|
@@ -80,9 +80,9 @@ function loadActor() {
|
|
|
80
80
|
function saveActor(displayName, email) {
|
|
81
81
|
const actorPath = resolveActorPath();
|
|
82
82
|
fs.mkdirSync(path.dirname(actorPath), { recursive: true });
|
|
83
|
-
const lines = [`displayName:
|
|
83
|
+
const lines = [`displayName: ${JSON.stringify(displayName)}`];
|
|
84
84
|
if (email) {
|
|
85
|
-
lines.push(`email:
|
|
85
|
+
lines.push(`email: ${JSON.stringify(email)}`);
|
|
86
86
|
}
|
|
87
87
|
fs.writeFileSync(actorPath, `${lines.join('\n')}\n`, 'utf8');
|
|
88
88
|
return actorPath;
|
package/scripts/lib/plan-meta.js
CHANGED
|
@@ -87,7 +87,7 @@ function patchPlanMeta(planPath, key, value) {
|
|
|
87
87
|
die('Plan has no frontmatter to patch');
|
|
88
88
|
}
|
|
89
89
|
let yaml = match[1];
|
|
90
|
-
const quoted =
|
|
90
|
+
const quoted = JSON.stringify(String(value));
|
|
91
91
|
const re = new RegExp(`^${key}:.*$`, 'm');
|
|
92
92
|
if (re.test(yaml)) {
|
|
93
93
|
yaml = yaml.replace(re, `${key}: ${quoted}`);
|
|
@@ -111,7 +111,7 @@ function loadPlanFile(planPath) {
|
|
|
111
111
|
if (!match) {
|
|
112
112
|
return null;
|
|
113
113
|
}
|
|
114
|
-
const meta = parseSimpleYaml(match[1])
|
|
114
|
+
const meta = parseSimpleYaml(match[1]);
|
|
115
115
|
if (Array.isArray(meta.todos)) {
|
|
116
116
|
meta.todos = normalizeTodos(meta.todos);
|
|
117
117
|
}
|