@aifabrix/builder 2.55.2 → 2.57.0
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/session-report.js +76 -0
- package/lib/agent-kit/start.js +124 -57
- package/lib/agent-kit/tmux-sessions.js +163 -0
- package/lib/api/environments.api.js +38 -0
- package/lib/api/marketplace-bootstrap.api.js +31 -0
- package/lib/api/pipeline.api.js +32 -3
- package/lib/app/deploy.js +6 -5
- package/lib/cli/setup-app.js +7 -6
- package/lib/cli/setup-environment.js +76 -19
- package/lib/cli/setup-external-system-help.js +15 -3
- package/lib/cli/setup-external-system.js +21 -3
- package/lib/commands/agent-kit-help.js +32 -15
- package/lib/commands/agent-kit.js +90 -8
- package/lib/commands/repair-datasource-auto-rbac.js +4 -9
- package/lib/commands/upload-openapi-sync-followup.js +59 -0
- package/lib/commands/upload-qualification-client.js +131 -0
- package/lib/commands/upload-qualification-followups.js +104 -0
- package/lib/commands/upload-qualification-poll.js +143 -0
- package/lib/commands/upload.js +37 -156
- package/lib/deployment/deploy-poll-ui.js +14 -10
- package/lib/deployment/deployer-status.js +4 -4
- package/lib/deployment/installation/azure-infra-stage.js +160 -0
- package/lib/deployment/installation/azure-preflight.js +102 -0
- package/lib/deployment/installation/azure-readiness.js +71 -0
- package/lib/deployment/installation/docker-register.js +112 -0
- package/lib/deployment/installation/environment-auth.js +76 -0
- package/lib/deployment/installation/environment-manifest.js +165 -0
- package/lib/deployment/installation/environment-stage.js +191 -0
- package/lib/deployment/installation/index.js +39 -0
- package/lib/deployment/installation/infra-catalog.js +165 -0
- package/lib/deployment/installation/infra-manifest.js +161 -0
- package/lib/deployment/installation/infra-projection.js +86 -0
- package/lib/deployment/installation/public-ip.js +65 -0
- package/lib/deployment/installation/stage-input.js +169 -0
- package/lib/deployment/installation/stage-output.js +53 -0
- package/lib/deployment/installation/workspace-env.js +76 -0
- package/lib/deployment/installation/workspace-files.js +178 -0
- package/lib/deployment/installation/workspace-schema.js +40 -0
- package/lib/deployment/installation/workspace-secrets.js +66 -0
- package/lib/deployment/installation/workspace.js +128 -0
- package/lib/deployment/marketplace-environment.js +305 -0
- package/lib/external-system/deploy.js +46 -51
- package/lib/generator/builders.js +4 -0
- package/lib/generator/helpers.js +55 -99
- package/lib/generator/index.js +0 -4
- package/lib/generator/split-variables.js +11 -5
- package/lib/internal/fs-real-sync.js +29 -0
- package/lib/programmatic/builder-api-request.js +8 -4
- package/lib/programmatic/capability-registry.js +2 -0
- package/lib/programmatic/get-deploy-status.js +45 -0
- package/lib/programmatic/get-upload-status.js +45 -0
- package/lib/programmatic/http-accepted-response.js +31 -0
- package/lib/programmatic/openapi-descriptions.js +14 -4
- package/lib/programmatic/request-timeout.js +21 -15
- package/lib/programmatic/route-handler-map.js +6 -0
- package/lib/programmatic/run-deploy.js +7 -3
- package/lib/programmatic/run-upload.js +11 -7
- package/lib/role-assistant/package-validate.js +4 -0
- package/lib/role-assistant/test-runner-clarification-resubmit.js +149 -0
- package/lib/role-assistant/test-runner.js +14 -17
- package/lib/schema/application-schema.json +20 -2
- package/lib/schema/infra-parameter.schema.json +7 -0
- package/lib/schema/infra.parameter.yaml +32 -43
- package/lib/schema/infrastructure-schema.json +1480 -399
- package/lib/schema/installation-environment.schema.json +601 -0
- package/lib/utils/cli-utils.js +3 -2
- package/lib/utils/qualification-poll-ui.js +136 -0
- package/lib/utils/variable-transformer.js +3 -0
- package/lib/validation/required-variables.js +41 -0
- package/lib/validation/validator.js +8 -5
- package/package.json +7 -2
- package/templates/README.md +4 -0
- package/templates/agent-kit/instructions/AGENTKIT.md +6 -6
- package/templates/agent-kit/skills/shared/hosts.md +10 -10
- package/templates/applications/builder-api/env.template +4 -0
- package/templates/applications/dataplane/application.yaml +1 -1
- package/templates/applications/dataplane/env.template +1 -1
- package/templates/applications/keycloak/Dockerfile +12 -5
- package/templates/applications/keycloak/application.yaml +2 -2
- package/templates/applications/keycloak/cimd-lenient-parse/AbstractClientIdMetadataDocumentExecutor.java +3 -3
- package/templates/applications/keycloak/cimd-lenient-parse/SOURCE.md +6 -6
- package/templates/applications/keycloak/env.template +13 -1
- package/templates/applications/miso-controller/application.yaml +3 -2
- package/templates/applications/miso-controller/env.template +28 -22
- package/templates/marketplace/createUiDefinition.json +77 -0
- package/templates/marketplace/install.parameters.example.json +9 -0
- package/templates/marketplace/main.json +4087 -0
- package/lib/generator/deploy-manifest-azure-kv.js +0 -81
|
@@ -12,8 +12,11 @@ const { uploadExternalSystem } = require('../commands/upload');
|
|
|
12
12
|
const { runWithWorkspaceContext } = require('./workspace-context');
|
|
13
13
|
const { mergeProgrammaticOptions } = require('./command-options');
|
|
14
14
|
const { touchWorkspaceMeta } = require('./workspace-meta');
|
|
15
|
+
const { createHttpAcceptedResult } = require('./http-accepted-response');
|
|
15
16
|
|
|
16
17
|
/**
|
|
18
|
+
* Builder-api web callers never block on the qualification ladder (plan 191.0 task 3) — always
|
|
19
|
+
* submit async and return 202 with the resumable job id immediately; poll via getUploadStatus.
|
|
17
20
|
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
18
21
|
* @param {Object} [options]
|
|
19
22
|
* @param {boolean} [options.force]
|
|
@@ -24,16 +27,17 @@ const { touchWorkspaceMeta } = require('./workspace-meta');
|
|
|
24
27
|
* @returns {Promise<Object|void>}
|
|
25
28
|
*/
|
|
26
29
|
async function runUpload(ctx, options = {}) {
|
|
27
|
-
const merged = mergeProgrammaticOptions(ctx, options);
|
|
30
|
+
const merged = mergeProgrammaticOptions(ctx, { ...options, wait: false });
|
|
28
31
|
return runWithWorkspaceContext(ctx, async() => {
|
|
29
32
|
const result = await uploadExternalSystem(ctx.systemKey, merged);
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
lastOperation: 'upload',
|
|
33
|
-
lastUploadId: result?.uploadId || null
|
|
34
|
-
});
|
|
33
|
+
if (options.dryRun) {
|
|
34
|
+
return result;
|
|
35
35
|
}
|
|
36
|
-
|
|
36
|
+
touchWorkspaceMeta(ctx, {
|
|
37
|
+
lastOperation: 'upload',
|
|
38
|
+
lastUploadId: result?.jobId || null
|
|
39
|
+
});
|
|
40
|
+
return createHttpAcceptedResult(result);
|
|
37
41
|
});
|
|
38
42
|
}
|
|
39
43
|
|
|
@@ -10,6 +10,7 @@ const fs = require('../internal/fs-real-sync');
|
|
|
10
10
|
const { validateExternalFile, parseJsonFileContent } = require('../validation/validate-external-file');
|
|
11
11
|
const { listTestCaseFiles } = require('./test-cases');
|
|
12
12
|
const { validateTestCaseFile } = require('./test-case-validate');
|
|
13
|
+
const { shouldSkipEvidencePayload } = require('./evidence-sync');
|
|
13
14
|
|
|
14
15
|
const SETTINGS_TYPE = 'role-assistant-settings';
|
|
15
16
|
const EMPTY_TESTS_SKIP = 'tests/: skipped (no test cases)';
|
|
@@ -59,6 +60,9 @@ function validateEvidenceJsonFile(filePath) {
|
|
|
59
60
|
if (parseResult.error) {
|
|
60
61
|
return { ...parseResult.error, file: filePath, type: 'evidence' };
|
|
61
62
|
}
|
|
63
|
+
if (shouldSkipEvidencePayload(filePath, parseResult.parsed)) {
|
|
64
|
+
return { valid: true, errors: [], warnings: [], file: filePath, type: 'evidence' };
|
|
65
|
+
}
|
|
62
66
|
const rows = evidenceRows(parseResult.parsed);
|
|
63
67
|
const errors = [];
|
|
64
68
|
if (!rows) {
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resubmit work.start with a businessRoleRef when an omitted-RA case's
|
|
3
|
+
* free-text message gets a synchronous clarificationRequired rejection.
|
|
4
|
+
* @fileoverview Extracted from test-runner.js (file-size)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
function normalizeToken(value) {
|
|
10
|
+
if (typeof value !== 'string') {
|
|
11
|
+
return '';
|
|
12
|
+
}
|
|
13
|
+
return value
|
|
14
|
+
.trim()
|
|
15
|
+
.toLowerCase()
|
|
16
|
+
.replace(/[^a-z0-9]+/g, '');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function isRoleAssistantClarificationRequired(startResponse) {
|
|
20
|
+
return normalizeToken(startResponse?.status) === 'clarificationrequired';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function extractProcessExecutionId(startResponse) {
|
|
24
|
+
const candidates = [
|
|
25
|
+
startResponse?.work?.processExecutionId,
|
|
26
|
+
startResponse?.intent?.processExecutionId,
|
|
27
|
+
startResponse?.processExecutionId,
|
|
28
|
+
startResponse?.status?.processExecutionId
|
|
29
|
+
];
|
|
30
|
+
for (const row of candidates) {
|
|
31
|
+
if (typeof row === 'string' && row.trim()) {
|
|
32
|
+
return row.trim();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return '';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function findRuntimeRoleAssistantAnswerValue(testCase) {
|
|
39
|
+
const answers = Array.isArray(testCase?.answers) ? testCase.answers : [];
|
|
40
|
+
for (const candidate of answers) {
|
|
41
|
+
const when = candidate && typeof candidate === 'object' ? candidate.when : null;
|
|
42
|
+
const questionKey = when && typeof when === 'object' ? when.questionKey : null;
|
|
43
|
+
if (normalizeToken(questionKey) !== 'runtimeroleassistant') {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const value = candidate.value;
|
|
47
|
+
if (typeof value === 'string' && value.trim()) {
|
|
48
|
+
return value.trim();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return '';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* work.start with an omitted businessRoleRef and an ambiguous free-text
|
|
56
|
+
* message can return a *synchronous* `clarificationRequired` rejection with
|
|
57
|
+
* no task/processExecutionId at all -- there is nothing to `respond`/
|
|
58
|
+
* `continue` against yet. A case authored for this "omitted RA" scenario
|
|
59
|
+
* (input.businessRoleRef omitted, answers[].when.questionKey:
|
|
60
|
+
* runtimeRoleAssistant) is asserting the *next* work.start call should carry
|
|
61
|
+
* that answer's businessRoleRef, not that this one can be answered in place.
|
|
62
|
+
* Resubmit once with it before giving up.
|
|
63
|
+
*
|
|
64
|
+
* @param {object} params
|
|
65
|
+
* @param {(dataplaneUrl: string, authConfig: object, body: object) => Promise<object>} params.startWorkIntent
|
|
66
|
+
* @param {string} params.dataplaneUrl
|
|
67
|
+
* @param {object} params.authConfig
|
|
68
|
+
* @param {object} params.startPayload
|
|
69
|
+
* @param {object} params.testCase
|
|
70
|
+
* @param {string} params.roleKey
|
|
71
|
+
* @param {(prefix: string) => string} params.buildRuntimeId
|
|
72
|
+
* @returns {Promise<object|null>} the resubmitted start response, or null when no answer matched
|
|
73
|
+
*/
|
|
74
|
+
async function resubmitStartWithRoleAssistantAnswer({
|
|
75
|
+
startWorkIntent,
|
|
76
|
+
dataplaneUrl,
|
|
77
|
+
authConfig,
|
|
78
|
+
startPayload,
|
|
79
|
+
testCase,
|
|
80
|
+
roleKey,
|
|
81
|
+
buildRuntimeId
|
|
82
|
+
}) {
|
|
83
|
+
const roleAssistantAnswer = findRuntimeRoleAssistantAnswerValue(testCase);
|
|
84
|
+
if (!roleAssistantAnswer) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
return startWorkIntent(dataplaneUrl, authConfig, {
|
|
88
|
+
...startPayload,
|
|
89
|
+
// The rejected first call already recorded its submissionId as an
|
|
90
|
+
// idempotency key server-side (live-reproduced: reusing it here 409s
|
|
91
|
+
// with "submissionId was already used for a different request") --
|
|
92
|
+
// this resubmission is a genuinely new request, not a retry of the
|
|
93
|
+
// same one.
|
|
94
|
+
submissionId: buildRuntimeId(`ra-${roleKey}`),
|
|
95
|
+
businessRoleRef: roleAssistantAnswer
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Start a free-text role-assistant case, resubmitting once with a matching
|
|
101
|
+
* `runtimeRoleAssistant` answer if the first call comes back as a
|
|
102
|
+
* synchronous clarification rejection with no processExecutionId.
|
|
103
|
+
*
|
|
104
|
+
* @param {object} params
|
|
105
|
+
* @param {(dataplaneUrl: string, authConfig: object, body: object) => Promise<object>} params.startWorkIntent
|
|
106
|
+
* @param {string} params.dataplaneUrl
|
|
107
|
+
* @param {object} params.authConfig
|
|
108
|
+
* @param {object} params.startPayload
|
|
109
|
+
* @param {object} params.testCase
|
|
110
|
+
* @param {string} params.roleKey
|
|
111
|
+
* @param {(prefix: string) => string} params.buildRuntimeId
|
|
112
|
+
* @returns {Promise<{startResponse: object, processExecutionId: string}>}
|
|
113
|
+
*/
|
|
114
|
+
async function startRoleAssistantCaseWithClarificationResubmit({
|
|
115
|
+
startWorkIntent,
|
|
116
|
+
dataplaneUrl,
|
|
117
|
+
authConfig,
|
|
118
|
+
startPayload,
|
|
119
|
+
testCase,
|
|
120
|
+
roleKey,
|
|
121
|
+
buildRuntimeId
|
|
122
|
+
}) {
|
|
123
|
+
let startResponse = await startWorkIntent(dataplaneUrl, authConfig, startPayload);
|
|
124
|
+
let processExecutionId = extractProcessExecutionId(startResponse);
|
|
125
|
+
if (!processExecutionId && isRoleAssistantClarificationRequired(startResponse)) {
|
|
126
|
+
const resubmitted = await resubmitStartWithRoleAssistantAnswer({
|
|
127
|
+
startWorkIntent,
|
|
128
|
+
dataplaneUrl,
|
|
129
|
+
authConfig,
|
|
130
|
+
startPayload,
|
|
131
|
+
testCase,
|
|
132
|
+
roleKey,
|
|
133
|
+
buildRuntimeId
|
|
134
|
+
});
|
|
135
|
+
if (resubmitted) {
|
|
136
|
+
startResponse = resubmitted;
|
|
137
|
+
processExecutionId = extractProcessExecutionId(startResponse);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return { startResponse, processExecutionId };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
module.exports = {
|
|
144
|
+
isRoleAssistantClarificationRequired,
|
|
145
|
+
findRuntimeRoleAssistantAnswerValue,
|
|
146
|
+
resubmitStartWithRoleAssistantAnswer,
|
|
147
|
+
startRoleAssistantCaseWithClarificationResubmit,
|
|
148
|
+
extractProcessExecutionId
|
|
149
|
+
};
|
|
@@ -25,6 +25,10 @@ const {
|
|
|
25
25
|
resolveInputMessage
|
|
26
26
|
} = require('./test-runner-start-payload');
|
|
27
27
|
const { pickHumanRespondBody } = require('./test-runner-respond-body');
|
|
28
|
+
const {
|
|
29
|
+
startRoleAssistantCaseWithClarificationResubmit,
|
|
30
|
+
extractProcessExecutionId
|
|
31
|
+
} = require('./test-runner-clarification-resubmit');
|
|
28
32
|
const TERMINAL_STATUSES = new Set(['completed', 'stopped']);
|
|
29
33
|
const WAITING_STATUS = 'waiting';
|
|
30
34
|
|
|
@@ -73,21 +77,6 @@ function isExecutableRoleAssistantCase(testCase) {
|
|
|
73
77
|
return false;
|
|
74
78
|
}
|
|
75
79
|
|
|
76
|
-
function extractProcessExecutionId(startResponse) {
|
|
77
|
-
const candidates = [
|
|
78
|
-
startResponse?.work?.processExecutionId,
|
|
79
|
-
startResponse?.intent?.processExecutionId,
|
|
80
|
-
startResponse?.processExecutionId,
|
|
81
|
-
startResponse?.status?.processExecutionId
|
|
82
|
-
];
|
|
83
|
-
for (const row of candidates) {
|
|
84
|
-
if (typeof row === 'string' && row.trim()) {
|
|
85
|
-
return row.trim();
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return '';
|
|
89
|
-
}
|
|
90
|
-
|
|
91
80
|
function isTerminalStatus(statusValue) {
|
|
92
81
|
return TERMINAL_STATUSES.has(normalizeToken(statusValue));
|
|
93
82
|
}
|
|
@@ -420,8 +409,16 @@ async function runRoleAssistantCaseLifecycle(roleKey, testCase, runtimeContext,
|
|
|
420
409
|
return runWorkHubCaseLifecycle(roleKey, testCase, runtimeContext, runnerOptions);
|
|
421
410
|
}
|
|
422
411
|
const startPayload = buildStartIntentPayload(roleKey, testCase);
|
|
423
|
-
const startResponse = await
|
|
424
|
-
|
|
412
|
+
const { startResponse, processExecutionId } = await startRoleAssistantCaseWithClarificationResubmit({
|
|
413
|
+
startWorkIntent,
|
|
414
|
+
extractProcessExecutionId,
|
|
415
|
+
dataplaneUrl,
|
|
416
|
+
authConfig,
|
|
417
|
+
startPayload,
|
|
418
|
+
testCase,
|
|
419
|
+
roleKey,
|
|
420
|
+
buildRuntimeId
|
|
421
|
+
});
|
|
425
422
|
if (!processExecutionId) {
|
|
426
423
|
throw new Error(
|
|
427
424
|
'work.start missing processExecutionId; use input.executionPath: workHub for free-text RA cases.'
|
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
"key": "application-schema",
|
|
8
8
|
"name": "Application Configuration Schema",
|
|
9
9
|
"description": "JSON schema for validating AI Fabrix application configuration files",
|
|
10
|
-
"version": "1.
|
|
10
|
+
"version": "1.7.0",
|
|
11
11
|
"type": "schema",
|
|
12
12
|
"category": "infrastructure",
|
|
13
13
|
"author": "AI Fabrix Team",
|
|
14
14
|
"createdAt": "2024-01-01T00:00:00Z",
|
|
15
|
-
"updatedAt": "2026-
|
|
15
|
+
"updatedAt": "2026-09-16T00:00:00Z",
|
|
16
16
|
"compatibility": {
|
|
17
17
|
"minVersion": "1.0.0",
|
|
18
18
|
"maxVersion": "2.0.0",
|
|
@@ -30,6 +30,14 @@
|
|
|
30
30
|
"external-datasource.schema.json"
|
|
31
31
|
],
|
|
32
32
|
"changelog": [
|
|
33
|
+
{
|
|
34
|
+
"version": "1.7.0",
|
|
35
|
+
"date": "2026-09-16T00:00:00Z",
|
|
36
|
+
"changes": [
|
|
37
|
+
"Added optional top-level required: unique environment-variable names the application needs in every deployment target. Absent or empty keeps existing behavior."
|
|
38
|
+
],
|
|
39
|
+
"breaking": false
|
|
40
|
+
},
|
|
33
41
|
{
|
|
34
42
|
"version": "1.6.2",
|
|
35
43
|
"date": "2026-08-06T00:00:00Z",
|
|
@@ -937,6 +945,16 @@
|
|
|
937
945
|
"$ref": "aifabrix://schema/external-datasource.schema.json"
|
|
938
946
|
}
|
|
939
947
|
},
|
|
948
|
+
"required": {
|
|
949
|
+
"type": "array",
|
|
950
|
+
"description": "Environment-variable names this application requires in every deployment target. Each name must be declared by the application configuration (env.template) and resolve before deployment. Absent or empty means no extra requirement.",
|
|
951
|
+
"uniqueItems": true,
|
|
952
|
+
"items": {
|
|
953
|
+
"type": "string",
|
|
954
|
+
"pattern": "^[A-Z_][A-Z0-9_]*$",
|
|
955
|
+
"maxLength": 255
|
|
956
|
+
}
|
|
957
|
+
},
|
|
940
958
|
"environmentScopedResources": {
|
|
941
959
|
"type": "boolean",
|
|
942
960
|
"description": "When true, this application supports environment-scoped resource names (Key Vault key prefixes, Redis DB index, local Docker container and Traefik paths) when useEnvironmentScopedResources is activated in ~/.aifabrix/config.yaml and the target environment is dev or tst. Does not apply to pro. Used to share Postgres/Docker across dev/tst without collisions."
|
|
@@ -122,6 +122,13 @@
|
|
|
122
122
|
},
|
|
123
123
|
"requiredOnSystemOnboarding": { "type": "boolean" },
|
|
124
124
|
"ownerAppKey": { "type": "string", "minLength": 1 },
|
|
125
|
+
"sharedWithAppKeys": {
|
|
126
|
+
"type": "array",
|
|
127
|
+
"items": { "type": "string", "minLength": 1 },
|
|
128
|
+
"minItems": 1,
|
|
129
|
+
"uniqueItems": true,
|
|
130
|
+
"description": "Named applications, other than ownerAppKey, that may read this value."
|
|
131
|
+
},
|
|
125
132
|
"scope": { "$ref": "#/definitions/scopeEnum" },
|
|
126
133
|
"generator": { "$ref": "#/definitions/generator" },
|
|
127
134
|
"ensureOn": {
|
|
@@ -435,6 +435,13 @@ parameters:
|
|
|
435
435
|
|
|
436
436
|
- key: miso-controller-secrets-encryptionKeyVault
|
|
437
437
|
ownerAppKey: miso-controller
|
|
438
|
+
# Plan 227.4: the data plane must hold the same key. It hands this value to MisoClient so
|
|
439
|
+
# the controller's encrypt/decrypt service interoperates, and a credential encrypted by one
|
|
440
|
+
# side is decrypted by the other. The read was already happening in the shipped template
|
|
441
|
+
# and the policy denied it. Declared rather than silently permitted, and kept to the one
|
|
442
|
+
# application that needs it instead of moving the key to a scope that grants everyone.
|
|
443
|
+
sharedWithAppKeys:
|
|
444
|
+
- dataplane
|
|
438
445
|
scope: app
|
|
439
446
|
generator:
|
|
440
447
|
type: randomBytes32
|
|
@@ -460,19 +467,18 @@ parameters:
|
|
|
460
467
|
notes: >-
|
|
461
468
|
JWT signing secret; generated on first ensure. Azure Bicep typically uses `${prefix}-secrets-jwtKeyVault`.
|
|
462
469
|
|
|
463
|
-
# LICENSE_JWT=kv://miso-controller-jwt-licenseKeyVault —
|
|
464
|
-
#
|
|
470
|
+
# LICENSE_JWT=kv://miso-controller-jwt-licenseKeyVault — empty means Community edition.
|
|
471
|
+
# Set only to a real signed offline licence JWT.
|
|
465
472
|
- key: miso-controller-jwt-licenseKeyVault
|
|
466
473
|
ownerAppKey: miso-controller
|
|
467
474
|
scope: app
|
|
468
475
|
generator:
|
|
469
|
-
type:
|
|
470
|
-
value: 'DEVELOPMENT'
|
|
476
|
+
type: emptyString
|
|
471
477
|
ensureOn: [upInfra, resolveApp]
|
|
472
478
|
azure:
|
|
473
479
|
notes: >-
|
|
474
|
-
|
|
475
|
-
|
|
480
|
+
Empty means the unlicensed Community edition (DEV, size S, shared resources).
|
|
481
|
+
Override only with a real signed offline license JWT.
|
|
476
482
|
|
|
477
483
|
# Exact entry so this is not caught by *KeyVault → randomBytes32 (invalid email).
|
|
478
484
|
- key: miso-controller-admin-emailKeyVault
|
|
@@ -619,22 +625,7 @@ parameters:
|
|
|
619
625
|
vaultSecretName: dataplane-client-secretKeyVault
|
|
620
626
|
notes: Per-app OAuth client secret for dataplane; generated on first ensure.
|
|
621
627
|
|
|
622
|
-
# Mori / telemetry
|
|
623
|
-
# MORI_AUTH_METHOD=kv://mori-controller-auth-methodKeyVault — local default apiKey.
|
|
624
|
-
- key: mori-controller-auth-methodKeyVault
|
|
625
|
-
category: Mori
|
|
626
|
-
sensitive: false
|
|
627
|
-
valueSource: optionalInput
|
|
628
|
-
requiredOnSystemOnboarding: false
|
|
629
|
-
scope: system
|
|
630
|
-
generator:
|
|
631
|
-
type: literal
|
|
632
|
-
value: 'apiKey'
|
|
633
|
-
ensureOn: [upInfra, resolveApp]
|
|
634
|
-
azure:
|
|
635
|
-
notes: >-
|
|
636
|
-
Local/dev default apiKey. Override when using Mori basic auth or other methods.
|
|
637
|
-
|
|
628
|
+
# Mori / telemetry is optional for an unlicensed Community installation.
|
|
638
629
|
- key: mori-controller-api-keyKeyVault
|
|
639
630
|
category: Mori
|
|
640
631
|
sensitive: true
|
|
@@ -647,19 +638,8 @@ parameters:
|
|
|
647
638
|
azure:
|
|
648
639
|
notes: Empty locally; set when calling Mori with API key auth.
|
|
649
640
|
|
|
650
|
-
-
|
|
651
|
-
|
|
652
|
-
sensitive: false
|
|
653
|
-
valueSource: optionalInput
|
|
654
|
-
requiredOnSystemOnboarding: false
|
|
655
|
-
scope: system
|
|
656
|
-
generator:
|
|
657
|
-
type: emptyString
|
|
658
|
-
ensureOn: [upInfra, resolveApp]
|
|
659
|
-
azure:
|
|
660
|
-
notes: Empty locally; Mori basic auth optional.
|
|
661
|
-
|
|
662
|
-
- key: mori-controller-basic-passwordKeyVault
|
|
641
|
+
# Public, but a security-critical trust anchor. Never derive it from a pasted JWT.
|
|
642
|
+
- key: mori-license-public-keyKeyVault
|
|
663
643
|
category: Mori
|
|
664
644
|
sensitive: true
|
|
665
645
|
valueSource: optionalInput
|
|
@@ -669,7 +649,8 @@ parameters:
|
|
|
669
649
|
type: emptyString
|
|
670
650
|
ensureOn: [upInfra, resolveApp]
|
|
671
651
|
azure:
|
|
672
|
-
|
|
652
|
+
vaultSecretName: mori-license-public-keyKeyVault
|
|
653
|
+
notes: Trusted Mori SPKI PEM public key, provisioned by the installer or issuer release identity.
|
|
673
654
|
|
|
674
655
|
- key: appinsights-connectionStringKeyVault
|
|
675
656
|
category: Observability
|
|
@@ -843,8 +824,9 @@ parameters:
|
|
|
843
824
|
type: databaseUrl
|
|
844
825
|
ensureOn: [upInfra, resolveApp]
|
|
845
826
|
azure:
|
|
846
|
-
|
|
827
|
+
vaultSecretNamePattern: '{appKey}-databases-{index}-urlKeyVault'
|
|
847
828
|
legacyVaultSecretNames:
|
|
829
|
+
- '{key}'
|
|
848
830
|
- '{serviceName}-databases-0-urlKeyVault'
|
|
849
831
|
|
|
850
832
|
- key: databases-miso-controller-0-passwordKeyVault
|
|
@@ -854,7 +836,9 @@ parameters:
|
|
|
854
836
|
type: databasePassword
|
|
855
837
|
ensureOn: [upInfra, resolveApp]
|
|
856
838
|
azure:
|
|
857
|
-
|
|
839
|
+
vaultSecretNamePattern: '{appKey}-databases-{index}-passwordKeyVault'
|
|
840
|
+
legacyVaultSecretNames:
|
|
841
|
+
- '{key}'
|
|
858
842
|
|
|
859
843
|
- key: databases-miso-controller-1-urlKeyVault
|
|
860
844
|
ownerAppKey: miso-controller
|
|
@@ -863,8 +847,9 @@ parameters:
|
|
|
863
847
|
type: databaseUrl
|
|
864
848
|
ensureOn: [upInfra, resolveApp]
|
|
865
849
|
azure:
|
|
866
|
-
|
|
850
|
+
vaultSecretNamePattern: '{appKey}-databases-{index}-urlKeyVault'
|
|
867
851
|
legacyVaultSecretNames:
|
|
852
|
+
- '{key}'
|
|
868
853
|
- '{serviceName}-databases-1-urlKeyVault'
|
|
869
854
|
|
|
870
855
|
- key: databases-miso-controller-1-passwordKeyVault
|
|
@@ -874,7 +859,9 @@ parameters:
|
|
|
874
859
|
type: databasePassword
|
|
875
860
|
ensureOn: [upInfra, resolveApp]
|
|
876
861
|
azure:
|
|
877
|
-
|
|
862
|
+
vaultSecretNamePattern: '{appKey}-databases-{index}-passwordKeyVault'
|
|
863
|
+
legacyVaultSecretNames:
|
|
864
|
+
- '{key}'
|
|
878
865
|
|
|
879
866
|
# Per-index database secrets. Index must match requires.databases order in application.yaml.
|
|
880
867
|
- keyPattern: '^databases-[a-z0-9-]+-\d+-urlKeyVault$'
|
|
@@ -883,9 +870,10 @@ parameters:
|
|
|
883
870
|
type: databaseUrl
|
|
884
871
|
ensureOn: [upInfra, resolveApp]
|
|
885
872
|
azure:
|
|
873
|
+
vaultSecretNamePattern: '{appKey}-databases-{index}-urlKeyVault'
|
|
886
874
|
legacyVaultSecretNames:
|
|
887
|
-
- '{
|
|
888
|
-
notes: The
|
|
875
|
+
- '{key}'
|
|
876
|
+
notes: The manifest key stays logical; the app-prefixed name is the physical vault key.
|
|
889
877
|
|
|
890
878
|
- keyPattern: '^databases-[a-z0-9-]+-\d+-passwordKeyVault$'
|
|
891
879
|
scope: app
|
|
@@ -893,8 +881,9 @@ parameters:
|
|
|
893
881
|
type: databasePassword
|
|
894
882
|
ensureOn: [upInfra, resolveApp]
|
|
895
883
|
azure:
|
|
884
|
+
vaultSecretNamePattern: '{appKey}-databases-{index}-passwordKeyVault'
|
|
896
885
|
legacyVaultSecretNames:
|
|
897
|
-
- '{
|
|
886
|
+
- '{key}'
|
|
898
887
|
|
|
899
888
|
# Keycloak and other *-url keys (non-database).
|
|
900
889
|
- keyPattern: '^keycloak-.+-url$'
|