@mesh-tech/mesh-cli 0.17.0 → 0.18.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/dist/bin/mesh.js +426 -77
- package/dist/bin/mesh.js.map +4 -4
- package/dist/build-info.json +2 -2
- package/dist/src/commands/workflow.d.ts.map +1 -1
- package/dist/src/commands/workflow.js +26 -9
- package/dist/src/commands/workflow.js.map +1 -1
- package/fragments/base/package.json.hbs +1 -0
- package/package.json +4 -5
- package/skills/core/SKILL.md +1 -1
package/dist/bin/mesh.js
CHANGED
|
@@ -809,8 +809,8 @@ var init_seed = __esm({
|
|
|
809
809
|
// libs/mesh-cli/src/commands/local/helpers.ts
|
|
810
810
|
import * as net from "net";
|
|
811
811
|
async function upsertLocalSecret(secretId, value, client) {
|
|
812
|
-
const { SecretsManagerClient:
|
|
813
|
-
const sm = client ?? new
|
|
812
|
+
const { SecretsManagerClient: SecretsManagerClient10, CreateSecretCommand: CreateSecretCommand4, PutSecretValueCommand: PutSecretValueCommand4 } = await import("@aws-sdk/client-secrets-manager");
|
|
813
|
+
const sm = client ?? new SecretsManagerClient10(LOCAL_AWS_CONFIG);
|
|
814
814
|
const secretString = JSON.stringify(value);
|
|
815
815
|
try {
|
|
816
816
|
await sm.send(new CreateSecretCommand4({ Name: secretId, SecretString: secretString }));
|
|
@@ -6316,12 +6316,12 @@ async function fetchRemoteExternalCredentials(tenant, env, external, profile) {
|
|
|
6316
6316
|
const region = process.env.MESH_PLATFORM_REGION ?? process.env.AWS_REGION ?? "us-east-2";
|
|
6317
6317
|
const fallbackProfile = !process.env.AWS_ACCESS_KEY_ID && !process.env.AWS_PROFILE ? process.env.MESH_AWS_PROFILE ?? profile : void 0;
|
|
6318
6318
|
try {
|
|
6319
|
-
const { SecretsManagerClient:
|
|
6319
|
+
const { SecretsManagerClient: SecretsManagerClient10, GetSecretValueCommand: GetSecretValueCommand10 } = await import("@aws-sdk/client-secrets-manager");
|
|
6320
6320
|
if (fallbackProfile) process.env.AWS_PROFILE = fallbackProfile;
|
|
6321
|
-
const sm = new
|
|
6321
|
+
const sm = new SecretsManagerClient10({ region });
|
|
6322
6322
|
let res;
|
|
6323
6323
|
try {
|
|
6324
|
-
res = await sm.send(new
|
|
6324
|
+
res = await sm.send(new GetSecretValueCommand10({ SecretId: secretId }));
|
|
6325
6325
|
} finally {
|
|
6326
6326
|
if (fallbackProfile) delete process.env.AWS_PROFILE;
|
|
6327
6327
|
}
|
|
@@ -6976,13 +6976,13 @@ async function writeRegistryParams(cliClientId, awsConfig) {
|
|
|
6976
6976
|
}
|
|
6977
6977
|
async function ensureOpsHubAdmin(pat, awsConfig) {
|
|
6978
6978
|
const {
|
|
6979
|
-
SecretsManagerClient:
|
|
6980
|
-
GetSecretValueCommand:
|
|
6979
|
+
SecretsManagerClient: SecretsManagerClient10,
|
|
6980
|
+
GetSecretValueCommand: GetSecretValueCommand10,
|
|
6981
6981
|
CreateSecretCommand: CreateSecretCommand4,
|
|
6982
6982
|
PutSecretValueCommand: PutSecretValueCommand4
|
|
6983
6983
|
} = await import("@aws-sdk/client-secrets-manager");
|
|
6984
|
-
const sm = new
|
|
6985
|
-
const existing = await sm.send(new
|
|
6984
|
+
const sm = new SecretsManagerClient10(awsConfig);
|
|
6985
|
+
const existing = await sm.send(new GetSecretValueCommand10({ SecretId: OPS_HUB_SECRET_ID })).catch(() => null);
|
|
6986
6986
|
if (existing?.SecretString) {
|
|
6987
6987
|
logSuccess("Hub admin key already provisioned (Zitadel writes enabled)");
|
|
6988
6988
|
return;
|
|
@@ -7242,9 +7242,9 @@ async function ensureM2mCaller(pat, tenant, app, orgId, projectId, roles) {
|
|
|
7242
7242
|
return false;
|
|
7243
7243
|
}
|
|
7244
7244
|
async function authSecretExists(tenant, app, service) {
|
|
7245
|
-
const { SecretsManagerClient:
|
|
7246
|
-
const sm = new
|
|
7247
|
-
return sm.send(new
|
|
7245
|
+
const { SecretsManagerClient: SecretsManagerClient10, GetSecretValueCommand: GetSecretValueCommand10 } = await import("@aws-sdk/client-secrets-manager");
|
|
7246
|
+
const sm = new SecretsManagerClient10(LOCAL_AWS_CONFIG);
|
|
7247
|
+
return sm.send(new GetSecretValueCommand10({ SecretId: authSecretPath(tenant, app, service) })).then(
|
|
7248
7248
|
() => true,
|
|
7249
7249
|
() => false
|
|
7250
7250
|
);
|
|
@@ -17500,25 +17500,63 @@ var init_exec2 = __esm({
|
|
|
17500
17500
|
}
|
|
17501
17501
|
});
|
|
17502
17502
|
|
|
17503
|
+
// libs/secrets/src/index.ts
|
|
17504
|
+
import {
|
|
17505
|
+
SecretsManagerClient as SecretsManagerClient5,
|
|
17506
|
+
GetSecretValueCommand as GetSecretValueCommand5
|
|
17507
|
+
} from "@aws-sdk/client-secrets-manager";
|
|
17508
|
+
function instanceIndexSecretId(secretPrefix) {
|
|
17509
|
+
return `${secretPrefix}/${INSTANCE_INDEX_SUFFIX}`;
|
|
17510
|
+
}
|
|
17511
|
+
function isInstanceKey(key) {
|
|
17512
|
+
return key.length > 0 && !key.includes("/") && !key.startsWith(".") && !key.endsWith(".config");
|
|
17513
|
+
}
|
|
17514
|
+
function instanceKeyFromSecretName(secretPrefix, secretName) {
|
|
17515
|
+
if (!secretName.startsWith(`${secretPrefix}/`)) return null;
|
|
17516
|
+
const key = secretName.slice(secretPrefix.length + 1);
|
|
17517
|
+
return isInstanceKey(key) ? key : null;
|
|
17518
|
+
}
|
|
17519
|
+
function parseInstanceIndex(secretString) {
|
|
17520
|
+
let parsed;
|
|
17521
|
+
try {
|
|
17522
|
+
parsed = JSON.parse(secretString);
|
|
17523
|
+
} catch {
|
|
17524
|
+
parsed = void 0;
|
|
17525
|
+
}
|
|
17526
|
+
const instances = parsed?.instances;
|
|
17527
|
+
if (!Array.isArray(instances) || !instances.every((k) => typeof k === "string")) {
|
|
17528
|
+
throw new Error(
|
|
17529
|
+
`Malformed instance index (expected {"instances": string[]}). Rebuild it with: mesh secrets reindex external/<name>`
|
|
17530
|
+
);
|
|
17531
|
+
}
|
|
17532
|
+
return instances.filter(isInstanceKey);
|
|
17533
|
+
}
|
|
17534
|
+
function buildInstanceIndexValue(keys) {
|
|
17535
|
+
const instances = [...new Set([...keys].filter(isInstanceKey))].sort();
|
|
17536
|
+
const index = { version: 1, instances };
|
|
17537
|
+
return JSON.stringify(index);
|
|
17538
|
+
}
|
|
17539
|
+
var INSTANCE_INDEX_SUFFIX;
|
|
17540
|
+
var init_src3 = __esm({
|
|
17541
|
+
"libs/secrets/src/index.ts"() {
|
|
17542
|
+
"use strict";
|
|
17543
|
+
INSTANCE_INDEX_SUFFIX = ".index";
|
|
17544
|
+
}
|
|
17545
|
+
});
|
|
17546
|
+
|
|
17503
17547
|
// libs/mesh-cli/src/commands/secrets/set.ts
|
|
17504
17548
|
import {
|
|
17505
17549
|
SSMClient as SSMClient2,
|
|
17506
17550
|
GetParametersByPathCommand
|
|
17507
17551
|
} from "@aws-sdk/client-ssm";
|
|
17508
17552
|
import {
|
|
17509
|
-
SecretsManagerClient as
|
|
17510
|
-
GetSecretValueCommand as
|
|
17553
|
+
SecretsManagerClient as SecretsManagerClient6,
|
|
17554
|
+
GetSecretValueCommand as GetSecretValueCommand6,
|
|
17511
17555
|
PutSecretValueCommand,
|
|
17512
17556
|
CreateSecretCommand
|
|
17513
17557
|
} from "@aws-sdk/client-secrets-manager";
|
|
17514
17558
|
import input from "@inquirer/input";
|
|
17515
17559
|
import password from "@inquirer/password";
|
|
17516
|
-
import {
|
|
17517
|
-
buildInstanceIndexValue,
|
|
17518
|
-
instanceIndexSecretId,
|
|
17519
|
-
isInstanceKey,
|
|
17520
|
-
parseInstanceIndex
|
|
17521
|
-
} from "@mesh-tech/secrets";
|
|
17522
17560
|
async function ensureAwsCredentialsForStack(stack) {
|
|
17523
17561
|
if (process.env.AWS_ACCESS_KEY_ID || process.env.AWS_SESSION_TOKEN) return;
|
|
17524
17562
|
if (!stack) return;
|
|
@@ -17658,7 +17696,7 @@ async function setCommand(servicePath, opts) {
|
|
|
17658
17696
|
const region = opts.region ?? process.env.AWS_REGION ?? "us-east-2";
|
|
17659
17697
|
await ensureAwsCredentialsForStack(stackOpt ?? context.stage);
|
|
17660
17698
|
const ssmClient = new SSMClient2({ region });
|
|
17661
|
-
const smClient = new
|
|
17699
|
+
const smClient = new SecretsManagerClient6({ region });
|
|
17662
17700
|
const services = await discoverExternalServices(
|
|
17663
17701
|
ssmClient,
|
|
17664
17702
|
context.tenant,
|
|
@@ -17712,7 +17750,7 @@ Usage: mesh secrets set external/<name>`);
|
|
|
17712
17750
|
let existing = {};
|
|
17713
17751
|
try {
|
|
17714
17752
|
const response = await smClient.send(
|
|
17715
|
-
new
|
|
17753
|
+
new GetSecretValueCommand6({ SecretId: secretId })
|
|
17716
17754
|
);
|
|
17717
17755
|
if (response.SecretString) {
|
|
17718
17756
|
existing = JSON.parse(response.SecretString);
|
|
@@ -17824,7 +17862,7 @@ async function addKeyToInstanceIndex(client, secretPrefix, key, serviceName) {
|
|
|
17824
17862
|
try {
|
|
17825
17863
|
let keys = [];
|
|
17826
17864
|
try {
|
|
17827
|
-
const res = await client.send(new
|
|
17865
|
+
const res = await client.send(new GetSecretValueCommand6({ SecretId: indexId }));
|
|
17828
17866
|
keys = parseInstanceIndex(res.SecretString ?? "");
|
|
17829
17867
|
} catch (err) {
|
|
17830
17868
|
if (!isResourceNotFound(err)) throw err;
|
|
@@ -17891,6 +17929,7 @@ async function writeConfigMirror(client, secretId, schema, merged, meta) {
|
|
|
17891
17929
|
var init_set = __esm({
|
|
17892
17930
|
"libs/mesh-cli/src/commands/secrets/set.ts"() {
|
|
17893
17931
|
"use strict";
|
|
17932
|
+
init_src3();
|
|
17894
17933
|
init_context();
|
|
17895
17934
|
init_log();
|
|
17896
17935
|
init_stack_flag();
|
|
@@ -17902,18 +17941,12 @@ var init_set = __esm({
|
|
|
17902
17941
|
// libs/mesh-cli/src/commands/secrets/reindex.ts
|
|
17903
17942
|
import { SSMClient as SSMClient3 } from "@aws-sdk/client-ssm";
|
|
17904
17943
|
import {
|
|
17905
|
-
SecretsManagerClient as
|
|
17944
|
+
SecretsManagerClient as SecretsManagerClient7,
|
|
17906
17945
|
ListSecretsCommand,
|
|
17907
|
-
GetSecretValueCommand as
|
|
17946
|
+
GetSecretValueCommand as GetSecretValueCommand7,
|
|
17908
17947
|
PutSecretValueCommand as PutSecretValueCommand2,
|
|
17909
17948
|
CreateSecretCommand as CreateSecretCommand2
|
|
17910
17949
|
} from "@aws-sdk/client-secrets-manager";
|
|
17911
|
-
import {
|
|
17912
|
-
buildInstanceIndexValue as buildInstanceIndexValue2,
|
|
17913
|
-
instanceIndexSecretId as instanceIndexSecretId2,
|
|
17914
|
-
instanceKeyFromSecretName,
|
|
17915
|
-
parseInstanceIndex as parseInstanceIndex2
|
|
17916
|
-
} from "@mesh-tech/secrets";
|
|
17917
17950
|
async function scanInstanceKeys(client, secretPrefix) {
|
|
17918
17951
|
const keys = [];
|
|
17919
17952
|
let nextToken;
|
|
@@ -17941,7 +17974,7 @@ async function reindexCommand(servicePath, opts) {
|
|
|
17941
17974
|
const region = opts.region ?? process.env.AWS_REGION ?? "us-east-2";
|
|
17942
17975
|
await ensureAwsCredentialsForStack(stackOpt ?? context.stage);
|
|
17943
17976
|
const ssmClient = new SSMClient3({ region });
|
|
17944
|
-
const smClient = new
|
|
17977
|
+
const smClient = new SecretsManagerClient7({ region });
|
|
17945
17978
|
const services = await discoverExternalServices(
|
|
17946
17979
|
ssmClient,
|
|
17947
17980
|
context.tenant,
|
|
@@ -17970,15 +18003,15 @@ Usage: mesh secrets reindex external/<name>`);
|
|
|
17970
18003
|
process.exit(1);
|
|
17971
18004
|
}
|
|
17972
18005
|
const secretPrefix = svc.meta.secretPrefix;
|
|
17973
|
-
const indexId =
|
|
18006
|
+
const indexId = instanceIndexSecretId(secretPrefix);
|
|
17974
18007
|
const actual = [...new Set(await scanInstanceKeys(smClient, secretPrefix))].sort();
|
|
17975
18008
|
let listed = [];
|
|
17976
18009
|
let indexExists = true;
|
|
17977
18010
|
let malformed = false;
|
|
17978
18011
|
try {
|
|
17979
|
-
const res = await smClient.send(new
|
|
18012
|
+
const res = await smClient.send(new GetSecretValueCommand7({ SecretId: indexId }));
|
|
17980
18013
|
try {
|
|
17981
|
-
listed =
|
|
18014
|
+
listed = parseInstanceIndex(res.SecretString ?? "");
|
|
17982
18015
|
} catch {
|
|
17983
18016
|
malformed = true;
|
|
17984
18017
|
logInfo(`Existing index at ${indexId} is malformed \u2014 rebuilding from scratch.`);
|
|
@@ -18005,8 +18038,8 @@ Usage: mesh secrets reindex external/<name>`);
|
|
|
18005
18038
|
logSuccess(`Index rebuilt: ${indexId} now lists ${actual.length} instance(s).`);
|
|
18006
18039
|
}
|
|
18007
18040
|
async function writeInstanceIndex(client, secretPrefix, serviceName, keys) {
|
|
18008
|
-
const indexId =
|
|
18009
|
-
const secretString =
|
|
18041
|
+
const indexId = instanceIndexSecretId(secretPrefix);
|
|
18042
|
+
const secretString = buildInstanceIndexValue(keys);
|
|
18010
18043
|
try {
|
|
18011
18044
|
await client.send(
|
|
18012
18045
|
new PutSecretValueCommand2({ SecretId: indexId, SecretString: secretString })
|
|
@@ -18032,6 +18065,7 @@ async function writeInstanceIndex(client, secretPrefix, serviceName, keys) {
|
|
|
18032
18065
|
var init_reindex = __esm({
|
|
18033
18066
|
"libs/mesh-cli/src/commands/secrets/reindex.ts"() {
|
|
18034
18067
|
"use strict";
|
|
18068
|
+
init_src3();
|
|
18035
18069
|
init_context();
|
|
18036
18070
|
init_log();
|
|
18037
18071
|
init_stack_flag();
|
|
@@ -18045,8 +18079,8 @@ import {
|
|
|
18045
18079
|
GetParametersByPathCommand as GetParametersByPathCommand2
|
|
18046
18080
|
} from "@aws-sdk/client-ssm";
|
|
18047
18081
|
import {
|
|
18048
|
-
SecretsManagerClient as
|
|
18049
|
-
GetSecretValueCommand as
|
|
18082
|
+
SecretsManagerClient as SecretsManagerClient8,
|
|
18083
|
+
GetSecretValueCommand as GetSecretValueCommand8,
|
|
18050
18084
|
PutSecretValueCommand as PutSecretValueCommand3,
|
|
18051
18085
|
CreateSecretCommand as CreateSecretCommand3,
|
|
18052
18086
|
ListSecretsCommand as ListSecretsCommand2
|
|
@@ -18135,7 +18169,7 @@ function isResourceNotFound2(err) {
|
|
|
18135
18169
|
}
|
|
18136
18170
|
async function readSecret(client, secretId) {
|
|
18137
18171
|
try {
|
|
18138
|
-
const res = await client.send(new
|
|
18172
|
+
const res = await client.send(new GetSecretValueCommand8({ SecretId: secretId }));
|
|
18139
18173
|
return res.SecretString ? JSON.parse(res.SecretString) : null;
|
|
18140
18174
|
} catch (err) {
|
|
18141
18175
|
if (isResourceNotFound2(err)) return null;
|
|
@@ -18161,7 +18195,7 @@ async function writeSecret2(client, secretId, values, description) {
|
|
|
18161
18195
|
}
|
|
18162
18196
|
async function secretExists(client, secretId) {
|
|
18163
18197
|
try {
|
|
18164
|
-
await client.send(new
|
|
18198
|
+
await client.send(new GetSecretValueCommand8({ SecretId: secretId }));
|
|
18165
18199
|
return true;
|
|
18166
18200
|
} catch (err) {
|
|
18167
18201
|
if (isResourceNotFound2(err)) return false;
|
|
@@ -18241,7 +18275,7 @@ async function migrateConfigCommand(opts) {
|
|
|
18241
18275
|
const context = detectContext(resolveStackOption(opts));
|
|
18242
18276
|
const region = opts.region ?? process.env.AWS_REGION ?? "us-east-2";
|
|
18243
18277
|
const ssmClient = new SSMClient4({ region });
|
|
18244
|
-
const smClient = new
|
|
18278
|
+
const smClient = new SecretsManagerClient8({ region });
|
|
18245
18279
|
logInfo(`Migrating .config mirrors for ${context.tenant}/${context.platformEnv}`);
|
|
18246
18280
|
if (opts.dryRun) logInfo("DRY-RUN mode \u2014 no writes");
|
|
18247
18281
|
if (opts.force) logInfo("FORCE mode \u2014 overwrite existing .config");
|
|
@@ -20174,8 +20208,8 @@ import * as fs35 from "fs";
|
|
|
20174
20208
|
import * as os12 from "os";
|
|
20175
20209
|
import * as path42 from "path";
|
|
20176
20210
|
import {
|
|
20177
|
-
SecretsManagerClient as
|
|
20178
|
-
GetSecretValueCommand as
|
|
20211
|
+
SecretsManagerClient as SecretsManagerClient9,
|
|
20212
|
+
GetSecretValueCommand as GetSecretValueCommand9
|
|
20179
20213
|
} from "@aws-sdk/client-secrets-manager";
|
|
20180
20214
|
function resolveTenantEnv(options) {
|
|
20181
20215
|
if (options.tenant && options.env) {
|
|
@@ -20438,10 +20472,10 @@ async function tunnelExternal(name, options) {
|
|
|
20438
20472
|
const { appTenant, appStage } = resolveCredentialAxis(options);
|
|
20439
20473
|
const secretId = externalSecretId(appTenant, appStage, name, key);
|
|
20440
20474
|
const setHint = `mesh secrets set external/${name}${key ? ` --key=${key}` : ""}`;
|
|
20441
|
-
const sm = new
|
|
20475
|
+
const sm = new SecretsManagerClient9({});
|
|
20442
20476
|
let creds;
|
|
20443
20477
|
try {
|
|
20444
|
-
const out = await sm.send(new
|
|
20478
|
+
const out = await sm.send(new GetSecretValueCommand9({ SecretId: secretId }));
|
|
20445
20479
|
creds = JSON.parse(out.SecretString ?? "{}");
|
|
20446
20480
|
} catch (err) {
|
|
20447
20481
|
logError(
|
|
@@ -21134,7 +21168,9 @@ function computeHappyPath(nodes, edges) {
|
|
|
21134
21168
|
);
|
|
21135
21169
|
const allEndIds = new Set(endNodes.map((n) => n.id));
|
|
21136
21170
|
function bfs(targetIds, allowExceptional) {
|
|
21137
|
-
const queue = [
|
|
21171
|
+
const queue = [
|
|
21172
|
+
{ id: startNode.id, path: [startNode.id] }
|
|
21173
|
+
];
|
|
21138
21174
|
const visited = /* @__PURE__ */ new Set([startNode.id]);
|
|
21139
21175
|
while (queue.length > 0) {
|
|
21140
21176
|
const { id, path: path44 } = queue.shift();
|
|
@@ -21155,7 +21191,8 @@ function computeHappyPath(nodes, edges) {
|
|
|
21155
21191
|
});
|
|
21156
21192
|
for (const neighbor of sorted) {
|
|
21157
21193
|
if (visited.has(neighbor.to)) continue;
|
|
21158
|
-
if (!allowExceptional && (neighbor.isExceptional || neighbor.isTimeout || failureEndIds.has(neighbor.to)))
|
|
21194
|
+
if (!allowExceptional && (neighbor.isExceptional || neighbor.isTimeout || failureEndIds.has(neighbor.to)))
|
|
21195
|
+
continue;
|
|
21159
21196
|
visited.add(neighbor.to);
|
|
21160
21197
|
queue.push({ id: neighbor.to, path: [...path44, neighbor.to] });
|
|
21161
21198
|
}
|
|
@@ -21164,6 +21201,37 @@ function computeHappyPath(nodes, edges) {
|
|
|
21164
21201
|
}
|
|
21165
21202
|
return bfs(successEndIds, false) ?? bfs(allEndIds, false) ?? bfs(allEndIds, true) ?? [];
|
|
21166
21203
|
}
|
|
21204
|
+
function isProcessArtifactProvenance(value) {
|
|
21205
|
+
return typeof value === "object" && value !== null && value.source === "process-artifact";
|
|
21206
|
+
}
|
|
21207
|
+
function childGraphsOf(node) {
|
|
21208
|
+
const graphs = [];
|
|
21209
|
+
const withChild = node;
|
|
21210
|
+
if (withChild.childGraph) graphs.push(withChild.childGraph);
|
|
21211
|
+
const withBacking = node;
|
|
21212
|
+
if (withBacking.backing?.backingGraph) graphs.push(withBacking.backing.backingGraph);
|
|
21213
|
+
return graphs;
|
|
21214
|
+
}
|
|
21215
|
+
function walkProcessNodes(ir, scope = []) {
|
|
21216
|
+
const out = [];
|
|
21217
|
+
for (const node of ir.nodes) {
|
|
21218
|
+
if (isProcessArtifactProvenance(node.provenance)) {
|
|
21219
|
+
out.push({ nodeId: node.id, scope, node, provenance: node.provenance });
|
|
21220
|
+
}
|
|
21221
|
+
for (const child of childGraphsOf(node)) {
|
|
21222
|
+
out.push(...walkProcessNodes(child, [...scope, node.id]));
|
|
21223
|
+
}
|
|
21224
|
+
}
|
|
21225
|
+
return out;
|
|
21226
|
+
}
|
|
21227
|
+
function findProcessNodesByCommand(ir, command) {
|
|
21228
|
+
return walkProcessNodes(ir).filter((m) => m.provenance.bind?.commands?.includes(command));
|
|
21229
|
+
}
|
|
21230
|
+
function findProcessNodesByElementId(ir, elementId, element) {
|
|
21231
|
+
return walkProcessNodes(ir).filter(
|
|
21232
|
+
(m) => m.provenance.elementId === elementId && (element === void 0 || m.provenance.element === element)
|
|
21233
|
+
);
|
|
21234
|
+
}
|
|
21167
21235
|
function cloneWorkflow(workflow) {
|
|
21168
21236
|
return JSON.parse(JSON.stringify(workflow));
|
|
21169
21237
|
}
|
|
@@ -21215,13 +21283,17 @@ function sanitizeMainPath(workflow, mainPath) {
|
|
|
21215
21283
|
}
|
|
21216
21284
|
function getChildGraph(node) {
|
|
21217
21285
|
if ("childGraph" in node && node.childGraph) return node.childGraph;
|
|
21218
|
-
if ("backing" in node && node.backing?.backingGraph)
|
|
21286
|
+
if ("backing" in node && node.backing?.backingGraph)
|
|
21287
|
+
return node.backing.backingGraph;
|
|
21219
21288
|
return null;
|
|
21220
21289
|
}
|
|
21221
21290
|
function setChildGraph(node, childGraph) {
|
|
21222
21291
|
if ("childGraph" in node) return { ...node, childGraph };
|
|
21223
21292
|
if ("backing" in node && node.backing?.backingGraph) {
|
|
21224
|
-
return {
|
|
21293
|
+
return {
|
|
21294
|
+
...node,
|
|
21295
|
+
backing: { ...node.backing, backingGraph: childGraph }
|
|
21296
|
+
};
|
|
21225
21297
|
}
|
|
21226
21298
|
return { ...node, childGraph };
|
|
21227
21299
|
}
|
|
@@ -21378,7 +21450,9 @@ function wrapIntoGroup(workflow, nodeIds, groupId, label, groupType) {
|
|
|
21378
21450
|
let mainBody = inParentMain.length ? inParentMain : nodeIds;
|
|
21379
21451
|
let mainTail = [];
|
|
21380
21452
|
if (successExit) {
|
|
21381
|
-
const exitSources = new Set(
|
|
21453
|
+
const exitSources = new Set(
|
|
21454
|
+
exitChildEdges.filter((e) => e.to === successExit.id).map((e) => e.from)
|
|
21455
|
+
);
|
|
21382
21456
|
const adj = /* @__PURE__ */ new Map();
|
|
21383
21457
|
for (const e of internal) {
|
|
21384
21458
|
if (e.isExceptional || e.isTimeout) continue;
|
|
@@ -21417,7 +21491,11 @@ function wrapIntoGroup(workflow, nodeIds, groupId, label, groupType) {
|
|
|
21417
21491
|
childGraph = {
|
|
21418
21492
|
name: label,
|
|
21419
21493
|
description: "",
|
|
21420
|
-
nodes: [
|
|
21494
|
+
nodes: [
|
|
21495
|
+
{ id: startId, type: "start", label: "Start" },
|
|
21496
|
+
...groupedNodes,
|
|
21497
|
+
...extraChildNodes
|
|
21498
|
+
],
|
|
21421
21499
|
edges: [
|
|
21422
21500
|
{ from: startId, to: entry, isMainPath: true },
|
|
21423
21501
|
...internal.map(markMain),
|
|
@@ -21426,7 +21504,13 @@ function wrapIntoGroup(workflow, nodeIds, groupId, label, groupType) {
|
|
|
21426
21504
|
mainPath: [startId, ...mainBody, ...mainTail]
|
|
21427
21505
|
};
|
|
21428
21506
|
}
|
|
21429
|
-
const groupNode = {
|
|
21507
|
+
const groupNode = {
|
|
21508
|
+
id: groupId,
|
|
21509
|
+
type: "group",
|
|
21510
|
+
groupType,
|
|
21511
|
+
label,
|
|
21512
|
+
childGraph
|
|
21513
|
+
};
|
|
21430
21514
|
const newNodes = [];
|
|
21431
21515
|
let placed = false;
|
|
21432
21516
|
for (const n of workflow.nodes) {
|
|
@@ -21472,7 +21556,10 @@ function applyWorkflowPatch(workflow, patch) {
|
|
|
21472
21556
|
return applyScopedPatch(workflow, patch.scope, patch);
|
|
21473
21557
|
}
|
|
21474
21558
|
if (patch.op === "batch") {
|
|
21475
|
-
return patch.patches.reduce(
|
|
21559
|
+
return patch.patches.reduce(
|
|
21560
|
+
(current, operation) => applyWorkflowPatch(current, operation),
|
|
21561
|
+
workflow
|
|
21562
|
+
);
|
|
21476
21563
|
}
|
|
21477
21564
|
if (patch.op === "replace") {
|
|
21478
21565
|
return cloneWorkflow(patch.workflow);
|
|
@@ -21506,7 +21593,9 @@ function applyWorkflowPatch(workflow, patch) {
|
|
|
21506
21593
|
next.mainPath = next.mainPath.filter((nodeId) => nodeId !== patch.nodeId);
|
|
21507
21594
|
const shouldRemoveEdges = patch.removeAttachedEdges ?? true;
|
|
21508
21595
|
if (shouldRemoveEdges) {
|
|
21509
|
-
next.edges = next.edges.filter(
|
|
21596
|
+
next.edges = next.edges.filter(
|
|
21597
|
+
(edge) => edge.from !== patch.nodeId && edge.to !== patch.nodeId
|
|
21598
|
+
);
|
|
21510
21599
|
}
|
|
21511
21600
|
return next;
|
|
21512
21601
|
}
|
|
@@ -21554,7 +21643,13 @@ function applyWorkflowPatch(workflow, patch) {
|
|
|
21554
21643
|
return next;
|
|
21555
21644
|
}
|
|
21556
21645
|
case "group": {
|
|
21557
|
-
return wrapIntoGroup(
|
|
21646
|
+
return wrapIntoGroup(
|
|
21647
|
+
next,
|
|
21648
|
+
patch.nodeIds,
|
|
21649
|
+
patch.groupId,
|
|
21650
|
+
patch.label,
|
|
21651
|
+
patch.groupType ?? "function"
|
|
21652
|
+
);
|
|
21558
21653
|
}
|
|
21559
21654
|
case "setMainPath": {
|
|
21560
21655
|
next.mainPath = sanitizeMainPath(next, patch.mainPath);
|
|
@@ -21852,6 +21947,78 @@ var init_change_counts = __esm({
|
|
|
21852
21947
|
|
|
21853
21948
|
// libs/workflow-model/src/process-artifact.ts
|
|
21854
21949
|
import { z as z4 } from "zod";
|
|
21950
|
+
function outcomeTriggers(outcome) {
|
|
21951
|
+
const raw = Array.isArray(outcome.when) ? outcome.when : [outcome.when];
|
|
21952
|
+
return raw.map((trigger) => {
|
|
21953
|
+
if ("predicate" in trigger) return { kind: "predicate", name: trigger.predicate };
|
|
21954
|
+
if ("timeoutOf" in trigger) return { kind: "timeout", name: trigger.timeoutOf };
|
|
21955
|
+
return { kind: "command", name: trigger.command };
|
|
21956
|
+
});
|
|
21957
|
+
}
|
|
21958
|
+
function resolveSubstepActor(artifact, stage, substep) {
|
|
21959
|
+
const actorId = substep.actor ?? stage.actor;
|
|
21960
|
+
if (!actorId) return void 0;
|
|
21961
|
+
const actor = artifact.process.actors[actorId];
|
|
21962
|
+
if (!actor) return void 0;
|
|
21963
|
+
return {
|
|
21964
|
+
id: actorId,
|
|
21965
|
+
label: actor.label,
|
|
21966
|
+
...actor.category ? { category: actor.category } : {},
|
|
21967
|
+
...substep.selector ?? actor.selector ? { selector: substep.selector ?? actor.selector } : {},
|
|
21968
|
+
...actor.cardinality ? { cardinality: actor.cardinality } : {}
|
|
21969
|
+
};
|
|
21970
|
+
}
|
|
21971
|
+
function resolveActorRef(artifact, actorId) {
|
|
21972
|
+
const actor = artifact.process.actors[actorId];
|
|
21973
|
+
if (!actor) return void 0;
|
|
21974
|
+
return {
|
|
21975
|
+
id: actorId,
|
|
21976
|
+
label: actor.label,
|
|
21977
|
+
...actor.category ? { category: actor.category } : {},
|
|
21978
|
+
...actor.selector ? { selector: actor.selector } : {},
|
|
21979
|
+
...actor.cardinality ? { cardinality: actor.cardinality } : {}
|
|
21980
|
+
};
|
|
21981
|
+
}
|
|
21982
|
+
function buildProcessManifest(artifact, outcomeNodeIds) {
|
|
21983
|
+
const { process: process2 } = artifact;
|
|
21984
|
+
const actors = {};
|
|
21985
|
+
for (const actorId of Object.keys(process2.actors)) {
|
|
21986
|
+
actors[actorId] = resolveActorRef(artifact, actorId);
|
|
21987
|
+
}
|
|
21988
|
+
let selectors;
|
|
21989
|
+
if (process2.selectors) {
|
|
21990
|
+
selectors = {};
|
|
21991
|
+
for (const [name, selector] of Object.entries(process2.selectors)) {
|
|
21992
|
+
selectors[name] = {
|
|
21993
|
+
name,
|
|
21994
|
+
label: selector.label,
|
|
21995
|
+
...selector.description ? { description: selector.description } : {}
|
|
21996
|
+
};
|
|
21997
|
+
}
|
|
21998
|
+
}
|
|
21999
|
+
const outcomes = process2.outcomes.map((outcome) => {
|
|
22000
|
+
const nodeId = outcomeNodeIds?.get(outcome.id);
|
|
22001
|
+
return {
|
|
22002
|
+
id: outcome.id,
|
|
22003
|
+
label: outcome.label,
|
|
22004
|
+
kind: outcome.kind,
|
|
22005
|
+
triggers: outcomeTriggers(outcome),
|
|
22006
|
+
...outcome.description ? { description: outcome.description } : {},
|
|
22007
|
+
...nodeId ? { nodeId } : {}
|
|
22008
|
+
};
|
|
22009
|
+
});
|
|
22010
|
+
const pointOfNoReturnStage = process2.stages.find((stage) => stage.pointOfNoReturn);
|
|
22011
|
+
return {
|
|
22012
|
+
source: "process-artifact",
|
|
22013
|
+
artifactVersion: process2.version,
|
|
22014
|
+
revision: process2.revision,
|
|
22015
|
+
workflowType: process2.workflowType,
|
|
22016
|
+
actors,
|
|
22017
|
+
...selectors ? { selectors } : {},
|
|
22018
|
+
outcomes,
|
|
22019
|
+
...pointOfNoReturnStage ? { pointOfNoReturnStageId: pointOfNoReturnStage.id } : {}
|
|
22020
|
+
};
|
|
22021
|
+
}
|
|
21855
22022
|
function formatPath(path44) {
|
|
21856
22023
|
return path44.length > 0 ? z4.core.toDotPath(path44) : "(root)";
|
|
21857
22024
|
}
|
|
@@ -21871,19 +22038,74 @@ function issueToDiagnostic(issue) {
|
|
|
21871
22038
|
path: path44
|
|
21872
22039
|
};
|
|
21873
22040
|
}
|
|
22041
|
+
function upgradeV1(artifact) {
|
|
22042
|
+
const diagnostics = [
|
|
22043
|
+
{
|
|
22044
|
+
severity: "warning",
|
|
22045
|
+
code: "DEPRECATED_ARTIFACT_VERSION",
|
|
22046
|
+
message: `process.version: artifact is version 1; upgraded in memory to version ${CURRENT_PROCESS_VERSION}. Migrate the file (add process.revision, declare actor categories/selectors) \u2014 version 1 is a deprecated input, not a second authoring format.`,
|
|
22047
|
+
path: "process.version"
|
|
22048
|
+
},
|
|
22049
|
+
{
|
|
22050
|
+
severity: "warning",
|
|
22051
|
+
code: "MISSING_PROCESS_REVISION",
|
|
22052
|
+
message: `process.revision: version 1 has no revision; recorded as "${UNVERSIONED_REVISION}". Anything pinned to this artifact cannot name which version of the process it ran.`,
|
|
22053
|
+
path: "process.revision"
|
|
22054
|
+
}
|
|
22055
|
+
];
|
|
22056
|
+
const process2 = artifact.process;
|
|
22057
|
+
const actors = {};
|
|
22058
|
+
for (const [actorId, actor] of Object.entries(process2.actors)) {
|
|
22059
|
+
const legacyCategory = LEGACY_V1_ACTOR_CATEGORY[actorId];
|
|
22060
|
+
actors[actorId] = {
|
|
22061
|
+
...actor,
|
|
22062
|
+
...actor.category === void 0 && legacyCategory ? { category: legacyCategory } : {}
|
|
22063
|
+
};
|
|
22064
|
+
}
|
|
22065
|
+
return {
|
|
22066
|
+
artifact: {
|
|
22067
|
+
...artifact,
|
|
22068
|
+
process: {
|
|
22069
|
+
...process2,
|
|
22070
|
+
version: CURRENT_PROCESS_VERSION,
|
|
22071
|
+
revision: UNVERSIONED_REVISION,
|
|
22072
|
+
actors
|
|
22073
|
+
}
|
|
22074
|
+
},
|
|
22075
|
+
diagnostics
|
|
22076
|
+
};
|
|
22077
|
+
}
|
|
21874
22078
|
function parseProcessArtifact(json) {
|
|
21875
22079
|
const result = processArtifactSchema.safeParse(json);
|
|
21876
|
-
if (result.success) {
|
|
21877
|
-
return {
|
|
22080
|
+
if (!result.success) {
|
|
22081
|
+
return { diagnostics: result.error.issues.map(issueToDiagnostic) };
|
|
22082
|
+
}
|
|
22083
|
+
if (result.data.process.version < CURRENT_PROCESS_VERSION) {
|
|
22084
|
+
return upgradeV1(result.data);
|
|
21878
22085
|
}
|
|
21879
|
-
return {
|
|
22086
|
+
return { artifact: result.data, diagnostics: [] };
|
|
21880
22087
|
}
|
|
21881
|
-
var actorSchema, substepBindSchema, substepSchema, outcomeWhenSchema, outcomeSchema, stageCompleteSchema, stageSchema, processBlockSchema, processArtifactSchema;
|
|
22088
|
+
var CURRENT_PROCESS_VERSION, SUPPORTED_PROCESS_VERSIONS, UNVERSIONED_REVISION, LEGACY_V1_ACTOR_CATEGORY, actorSchema, selectorSchema, substepBindSchema, substepSchema, outcomeTriggerSchema, outcomeWhenSchema, outcomeSchema, stageCompleteSchema, stageSchema, processBlockSchema, processArtifactSchema;
|
|
21882
22089
|
var init_process_artifact = __esm({
|
|
21883
22090
|
"libs/workflow-model/src/process-artifact.ts"() {
|
|
21884
22091
|
"use strict";
|
|
22092
|
+
CURRENT_PROCESS_VERSION = 2;
|
|
22093
|
+
SUPPORTED_PROCESS_VERSIONS = [1, 2];
|
|
22094
|
+
UNVERSIONED_REVISION = "unversioned";
|
|
22095
|
+
LEGACY_V1_ACTOR_CATEGORY = {
|
|
22096
|
+
customer: "human",
|
|
22097
|
+
banker: "approval",
|
|
22098
|
+
system: "data"
|
|
22099
|
+
};
|
|
21885
22100
|
actorSchema = z4.object({
|
|
21886
|
-
label: z4.string()
|
|
22101
|
+
label: z4.string(),
|
|
22102
|
+
category: z4.string().min(1).optional(),
|
|
22103
|
+
selector: z4.string().min(1).optional(),
|
|
22104
|
+
cardinality: z4.enum(["one", "many"]).optional()
|
|
22105
|
+
}).strict();
|
|
22106
|
+
selectorSchema = z4.object({
|
|
22107
|
+
label: z4.string(),
|
|
22108
|
+
description: z4.string().optional()
|
|
21887
22109
|
}).strict();
|
|
21888
22110
|
substepBindSchema = z4.object({
|
|
21889
22111
|
commands: z4.array(z4.string()).optional(),
|
|
@@ -21901,11 +22123,30 @@ var init_process_artifact = __esm({
|
|
|
21901
22123
|
id: z4.string(),
|
|
21902
22124
|
label: z4.string(),
|
|
21903
22125
|
actor: z4.string().optional(),
|
|
22126
|
+
/**
|
|
22127
|
+
* Overrides the actor's own `selector` for this substep only — the case
|
|
22128
|
+
* where one cast entry is resolved differently at one step (a handoff
|
|
22129
|
+
* target, an escalation pool). Must be declared in `process.selectors`.
|
|
22130
|
+
*/
|
|
22131
|
+
selector: z4.string().min(1).optional(),
|
|
21904
22132
|
bind: substepBindSchema
|
|
21905
22133
|
}).strict();
|
|
22134
|
+
outcomeTriggerSchema = z4.union([
|
|
22135
|
+
z4.object({ predicate: z4.string().min(1) }).strict(),
|
|
22136
|
+
z4.object({ timeoutOf: z4.string().min(1) }).strict(),
|
|
22137
|
+
z4.object({ command: z4.string().min(1) }).strict()
|
|
22138
|
+
]);
|
|
21906
22139
|
outcomeWhenSchema = z4.union([
|
|
21907
|
-
|
|
21908
|
-
z4.
|
|
22140
|
+
outcomeTriggerSchema,
|
|
22141
|
+
z4.array(outcomeTriggerSchema).superRefine((triggers, ctx) => {
|
|
22142
|
+
if (triggers.length === 0) {
|
|
22143
|
+
ctx.addIssue({
|
|
22144
|
+
code: "custom",
|
|
22145
|
+
message: "when must declare at least one trigger",
|
|
22146
|
+
params: { code: "EMPTY_OUTCOME_TRIGGER" }
|
|
22147
|
+
});
|
|
22148
|
+
}
|
|
22149
|
+
})
|
|
21909
22150
|
]);
|
|
21910
22151
|
outcomeSchema = z4.object({
|
|
21911
22152
|
id: z4.string(),
|
|
@@ -21928,20 +22169,64 @@ var init_process_artifact = __esm({
|
|
|
21928
22169
|
}).strict();
|
|
21929
22170
|
processBlockSchema = z4.object({
|
|
21930
22171
|
version: z4.number(),
|
|
22172
|
+
/**
|
|
22173
|
+
* Pinned identity of this authored content. Opaque to the platform —
|
|
22174
|
+
* a date, a semver, a content hash, a monotonic counter all work. What
|
|
22175
|
+
* matters is that changing the process changes it, so an execution can
|
|
22176
|
+
* be pinned to the revision it started under. Required from V2; a V1
|
|
22177
|
+
* artifact is upgraded with {@link UNVERSIONED_REVISION} and a warning.
|
|
22178
|
+
*/
|
|
22179
|
+
revision: z4.string().min(1).optional(),
|
|
21931
22180
|
workflowType: z4.string(),
|
|
21932
22181
|
actors: z4.record(z4.string(), actorSchema),
|
|
22182
|
+
/** Named selector registry — every `selector` reference resolves here. */
|
|
22183
|
+
selectors: z4.record(z4.string(), selectorSchema).optional(),
|
|
21933
22184
|
stages: z4.array(stageSchema),
|
|
21934
22185
|
outcomes: z4.array(outcomeSchema),
|
|
21935
22186
|
internalCommands: z4.array(z4.string()).optional()
|
|
21936
22187
|
}).strict().superRefine((process2, ctx) => {
|
|
21937
|
-
if (process2.version
|
|
22188
|
+
if (!SUPPORTED_PROCESS_VERSIONS.includes(process2.version)) {
|
|
21938
22189
|
ctx.addIssue({
|
|
21939
22190
|
code: "custom",
|
|
21940
22191
|
path: ["version"],
|
|
21941
|
-
message: `Unsupported process.version ${JSON.stringify(process2.version)}; this parser
|
|
22192
|
+
message: `Unsupported process.version ${JSON.stringify(process2.version)}; this parser understands ${SUPPORTED_PROCESS_VERSIONS.join(" and ")}. Upgrade the parser or downgrade the artifact.`,
|
|
21942
22193
|
params: { code: "UNSUPPORTED_VERSION" }
|
|
21943
22194
|
});
|
|
21944
22195
|
}
|
|
22196
|
+
if (process2.version >= CURRENT_PROCESS_VERSION && process2.revision === void 0) {
|
|
22197
|
+
ctx.addIssue({
|
|
22198
|
+
code: "custom",
|
|
22199
|
+
path: ["revision"],
|
|
22200
|
+
message: `process.revision is required from version ${CURRENT_PROCESS_VERSION}. Give this authored content a pinned identity (a date, a semver, or a content hash) so an execution can name the revision it is running.`,
|
|
22201
|
+
params: { code: "MISSING_PROCESS_REVISION" }
|
|
22202
|
+
});
|
|
22203
|
+
}
|
|
22204
|
+
const declaredSelectors = new Set(Object.keys(process2.selectors ?? {}));
|
|
22205
|
+
const checkActor = (actorId, path44) => {
|
|
22206
|
+
if (actorId === void 0) return;
|
|
22207
|
+
if (!Object.prototype.hasOwnProperty.call(process2.actors, actorId)) {
|
|
22208
|
+
ctx.addIssue({
|
|
22209
|
+
code: "custom",
|
|
22210
|
+
path: path44,
|
|
22211
|
+
message: `Actor "${actorId}" is referenced at ${z4.core.toDotPath(path44)} but not declared in process.actors. Declare the actor (label, and optionally category/selector) or fix the reference.`,
|
|
22212
|
+
params: { code: "UNDECLARED_ACTOR" }
|
|
22213
|
+
});
|
|
22214
|
+
}
|
|
22215
|
+
};
|
|
22216
|
+
const checkSelector = (selector, path44) => {
|
|
22217
|
+
if (selector === void 0) return;
|
|
22218
|
+
if (!declaredSelectors.has(selector)) {
|
|
22219
|
+
ctx.addIssue({
|
|
22220
|
+
code: "custom",
|
|
22221
|
+
path: path44,
|
|
22222
|
+
message: `Selector "${selector}" is referenced at ${z4.core.toDotPath(path44)} but not declared in process.selectors. Declare the selector or fix the reference.`,
|
|
22223
|
+
params: { code: "UNDECLARED_SELECTOR" }
|
|
22224
|
+
});
|
|
22225
|
+
}
|
|
22226
|
+
};
|
|
22227
|
+
for (const [actorId, actor] of Object.entries(process2.actors)) {
|
|
22228
|
+
checkSelector(actor.selector, ["actors", actorId, "selector"]);
|
|
22229
|
+
}
|
|
21945
22230
|
const SAME_KIND_CODE = {
|
|
21946
22231
|
stage: "DUPLICATE_STAGE_ID",
|
|
21947
22232
|
substep: "DUPLICATE_SUBSTEP_ID",
|
|
@@ -21966,8 +22251,17 @@ var init_process_artifact = __esm({
|
|
|
21966
22251
|
};
|
|
21967
22252
|
process2.stages.forEach((stage, stageIndex) => {
|
|
21968
22253
|
checkId(stage.id, "stage", ["stages", stageIndex, "id"]);
|
|
22254
|
+
checkActor(stage.actor, ["stages", stageIndex, "actor"]);
|
|
21969
22255
|
stage.substeps?.forEach((substep, substepIndex) => {
|
|
21970
22256
|
checkId(substep.id, "substep", ["stages", stageIndex, "substeps", substepIndex, "id"]);
|
|
22257
|
+
checkActor(substep.actor, ["stages", stageIndex, "substeps", substepIndex, "actor"]);
|
|
22258
|
+
checkSelector(substep.selector, [
|
|
22259
|
+
"stages",
|
|
22260
|
+
stageIndex,
|
|
22261
|
+
"substeps",
|
|
22262
|
+
substepIndex,
|
|
22263
|
+
"selector"
|
|
22264
|
+
]);
|
|
21971
22265
|
});
|
|
21972
22266
|
});
|
|
21973
22267
|
process2.outcomes.forEach((outcome, outcomeIndex) => {
|
|
@@ -21990,7 +22284,7 @@ function stagePath(stageIndex) {
|
|
|
21990
22284
|
function substepPath(stageIndex, substepIndex) {
|
|
21991
22285
|
return `${stagePath(stageIndex)}.substeps[${substepIndex}]`;
|
|
21992
22286
|
}
|
|
21993
|
-
function lintProcess(artifact, inventory, predicateNames) {
|
|
22287
|
+
function lintProcess(artifact, inventory, predicateNames, options = {}) {
|
|
21994
22288
|
const diagnostics = [];
|
|
21995
22289
|
const process2 = artifact.process;
|
|
21996
22290
|
const commandNames = new Set(inventory.commands.map((c) => c.name));
|
|
@@ -22009,6 +22303,19 @@ function lintProcess(artifact, inventory, predicateNames) {
|
|
|
22009
22303
|
});
|
|
22010
22304
|
}
|
|
22011
22305
|
};
|
|
22306
|
+
if (options.selectorNames) {
|
|
22307
|
+
const selectorSet = new Set(options.selectorNames);
|
|
22308
|
+
for (const [name] of Object.entries(process2.selectors ?? {})) {
|
|
22309
|
+
if (!selectorSet.has(name)) {
|
|
22310
|
+
diagnostics.push({
|
|
22311
|
+
severity: "error",
|
|
22312
|
+
code: "UNKNOWN_SELECTOR",
|
|
22313
|
+
message: `Selector "${name}" declared at process.selectors.${name} is not in the selector registry; the application has no rule resolving it to subjects.`,
|
|
22314
|
+
path: `process.selectors.${name}`
|
|
22315
|
+
});
|
|
22316
|
+
}
|
|
22317
|
+
}
|
|
22318
|
+
}
|
|
22012
22319
|
process2.stages.forEach((stage, stageIndex) => {
|
|
22013
22320
|
const predicatePath = `${stagePath(stageIndex)}.complete.predicate`;
|
|
22014
22321
|
const predicate = stage.complete?.predicate;
|
|
@@ -22050,9 +22357,25 @@ function lintProcess(artifact, inventory, predicateNames) {
|
|
|
22050
22357
|
});
|
|
22051
22358
|
});
|
|
22052
22359
|
process2.outcomes.forEach((outcome, outcomeIndex) => {
|
|
22053
|
-
|
|
22054
|
-
|
|
22055
|
-
|
|
22360
|
+
const whenPath = `process.outcomes[${outcomeIndex}].when`;
|
|
22361
|
+
outcomeTriggers(outcome).forEach((trigger, triggerIndex) => {
|
|
22362
|
+
const path44 = Array.isArray(outcome.when) ? `${whenPath}[${triggerIndex}]` : whenPath;
|
|
22363
|
+
if (trigger.kind === "predicate") {
|
|
22364
|
+
checkPredicate(trigger.name, `${path44}.predicate`);
|
|
22365
|
+
} else if (trigger.kind === "command") {
|
|
22366
|
+
if (!boundCommandPaths.has(trigger.name)) {
|
|
22367
|
+
boundCommandPaths.set(trigger.name, `${path44}.command`);
|
|
22368
|
+
}
|
|
22369
|
+
if (!commandNames.has(trigger.name)) {
|
|
22370
|
+
diagnostics.push({
|
|
22371
|
+
severity: "error",
|
|
22372
|
+
code: "BOUND_COMMAND_NOT_IN_INVENTORY",
|
|
22373
|
+
message: `Command "${trigger.name}" triggering outcome "${outcome.id}" (${path44}.command) does not exist in the inventory.`,
|
|
22374
|
+
path: `${path44}.command`
|
|
22375
|
+
});
|
|
22376
|
+
}
|
|
22377
|
+
}
|
|
22378
|
+
});
|
|
22056
22379
|
});
|
|
22057
22380
|
const hasSuccessOutcome = process2.outcomes.some((o) => o.kind === "success");
|
|
22058
22381
|
const hasFailureOutcome = process2.outcomes.some((o) => o.kind === "failure");
|
|
@@ -22097,7 +22420,7 @@ function lintProcess(artifact, inventory, predicateNames) {
|
|
|
22097
22420
|
diagnostics.push({
|
|
22098
22421
|
severity: "error",
|
|
22099
22422
|
code: "UNBOUND_INVENTORY_COMMAND",
|
|
22100
|
-
message: `Inventory command "${command.name}" is neither bound by any substep nor listed in process.internalCommands.`,
|
|
22423
|
+
message: `Inventory command "${command.name}" is neither bound by any substep, nor named as an outcome trigger, nor listed in process.internalCommands.`,
|
|
22101
22424
|
path: "process.internalCommands"
|
|
22102
22425
|
});
|
|
22103
22426
|
}
|
|
@@ -22115,28 +22438,39 @@ function lintProcess(artifact, inventory, predicateNames) {
|
|
|
22115
22438
|
var init_process_lint = __esm({
|
|
22116
22439
|
"libs/workflow-model/src/process-lint.ts"() {
|
|
22117
22440
|
"use strict";
|
|
22441
|
+
init_process_artifact();
|
|
22118
22442
|
}
|
|
22119
22443
|
});
|
|
22120
22444
|
|
|
22121
22445
|
// libs/workflow-model/src/index.ts
|
|
22122
22446
|
var src_exports2 = {};
|
|
22123
22447
|
__export(src_exports2, {
|
|
22448
|
+
CURRENT_PROCESS_VERSION: () => CURRENT_PROCESS_VERSION,
|
|
22449
|
+
SUPPORTED_PROCESS_VERSIONS: () => SUPPORTED_PROCESS_VERSIONS,
|
|
22450
|
+
UNVERSIONED_REVISION: () => UNVERSIONED_REVISION,
|
|
22124
22451
|
WorkflowPatchError: () => WorkflowPatchError,
|
|
22125
22452
|
WorkflowPatchStream: () => WorkflowPatchStream,
|
|
22126
22453
|
applyPreviewPatch: () => applyPreviewPatch,
|
|
22127
22454
|
applyWorkflowPatch: () => applyWorkflowPatch,
|
|
22128
22455
|
applyWorkflowPatches: () => applyWorkflowPatches,
|
|
22456
|
+
buildProcessManifest: () => buildProcessManifest,
|
|
22129
22457
|
computeHappyPath: () => computeHappyPath,
|
|
22130
22458
|
countChanges: () => countChanges,
|
|
22131
22459
|
describeChanges: () => describeChanges,
|
|
22132
22460
|
emptyWorkflowIR: () => emptyWorkflowIR,
|
|
22461
|
+
findProcessNodesByCommand: () => findProcessNodesByCommand,
|
|
22462
|
+
findProcessNodesByElementId: () => findProcessNodesByElementId,
|
|
22133
22463
|
lintProcess: () => lintProcess,
|
|
22464
|
+
outcomeTriggers: () => outcomeTriggers,
|
|
22134
22465
|
parseProcessArtifact: () => parseProcessArtifact,
|
|
22135
22466
|
processArtifactSchema: () => processArtifactSchema,
|
|
22467
|
+
resolveActorRef: () => resolveActorRef,
|
|
22468
|
+
resolveSubstepActor: () => resolveSubstepActor,
|
|
22136
22469
|
validateWorkflowIR: () => validateWorkflowIR,
|
|
22137
|
-
validateWorkflowPatches: () => validateWorkflowPatches
|
|
22470
|
+
validateWorkflowPatches: () => validateWorkflowPatches,
|
|
22471
|
+
walkProcessNodes: () => walkProcessNodes
|
|
22138
22472
|
});
|
|
22139
|
-
var
|
|
22473
|
+
var init_src4 = __esm({
|
|
22140
22474
|
"libs/workflow-model/src/index.ts"() {
|
|
22141
22475
|
"use strict";
|
|
22142
22476
|
init_workflow_ir();
|
|
@@ -22358,6 +22692,9 @@ async function uploadToS3(bucket, appName, workflows) {
|
|
|
22358
22692
|
})
|
|
22359
22693
|
);
|
|
22360
22694
|
}
|
|
22695
|
+
function parseNameList(value) {
|
|
22696
|
+
return value ? value.split(",").map((name) => name.trim()).filter((name) => name.length > 0) : void 0;
|
|
22697
|
+
}
|
|
22361
22698
|
function registerWorkflowCommands(program2) {
|
|
22362
22699
|
const workflow = program2.command("workflow").description("Workflow tooling \u2014 IR extraction, visualization");
|
|
22363
22700
|
workflow.command("extract-ir <path>").description(
|
|
@@ -22464,13 +22801,16 @@ function registerWorkflowCommands(program2) {
|
|
|
22464
22801
|
}
|
|
22465
22802
|
});
|
|
22466
22803
|
workflow.command("lint-process <path>").description(
|
|
22467
|
-
"Lint a process artifact's bindings against the as-built code inventory\n\nReuses the inventory extraction's aux/activity discovery, resolves the process\nartifact (--process, or the same sibling process/*.process.json discovery\nextract-ir uses), then runs parseProcessArtifact + lintProcess against it.\n\nWithout --predicates, the CLI cannot verify
|
|
22804
|
+
"Lint a process artifact's bindings against the as-built code inventory\n\nReuses the inventory extraction's aux/activity discovery, resolves the process\nartifact (--process, or the same sibling process/*.process.json discovery\nextract-ir uses), then runs parseProcessArtifact + lintProcess against it.\n\nWithout --predicates / --selectors, the CLI cannot verify those names against the\nworker's registries (it has no way to execute them) \u2014 the corresponding findings\nare skipped and a note is printed; every other rule (bindings, coverage, ids,\nactors, outcomes, workflowType) still runs. Pass both for full conformance, or rely\non the worker's own process-conformance test which has the registries in-process."
|
|
22468
22805
|
).option(
|
|
22469
22806
|
"--process <path>",
|
|
22470
22807
|
"Path to a process artifact JSON file. Absent this flag, a sibling process/*.process.json is auto-discovered per workflow file."
|
|
22471
22808
|
).option(
|
|
22472
22809
|
"--predicates <names>",
|
|
22473
22810
|
"Comma-separated named-predicate registry (enables UNKNOWN_PREDICATE checks)"
|
|
22811
|
+
).option(
|
|
22812
|
+
"--selectors <names>",
|
|
22813
|
+
"Comma-separated named-selector registry (enables UNKNOWN_SELECTOR checks)"
|
|
22474
22814
|
).action(async (targetPath, opts) => {
|
|
22475
22815
|
try {
|
|
22476
22816
|
const resolvedPath = path43.resolve(targetPath);
|
|
@@ -22499,8 +22839,8 @@ function registerWorkflowCommands(program2) {
|
|
|
22499
22839
|
let parseProcessArtifact2;
|
|
22500
22840
|
let lintProcess2;
|
|
22501
22841
|
try {
|
|
22502
|
-
({ parseProcessArtifact: parseProcessArtifact2 } = await Promise.resolve().then(() => (
|
|
22503
|
-
({ lintProcess: lintProcess2 } = await Promise.resolve().then(() => (
|
|
22842
|
+
({ parseProcessArtifact: parseProcessArtifact2 } = await Promise.resolve().then(() => (init_src4(), src_exports2)));
|
|
22843
|
+
({ lintProcess: lintProcess2 } = await Promise.resolve().then(() => (init_src4(), src_exports2)));
|
|
22504
22844
|
} catch {
|
|
22505
22845
|
logError(
|
|
22506
22846
|
"Cannot resolve @mesh-tech/workflow-model (parseProcessArtifact / lintProcess).\nIt is bundled into the published CLI \u2014 on a registry install this means a broken install; reinstall the CLI. In the monorepo, run the scoped install (pnpm bootstrap:worktree @mesh-tech/mesh-cli)."
|
|
@@ -22508,12 +22848,16 @@ function registerWorkflowCommands(program2) {
|
|
|
22508
22848
|
process.exitCode = 1;
|
|
22509
22849
|
return;
|
|
22510
22850
|
}
|
|
22511
|
-
const predicateNames = opts.predicates
|
|
22851
|
+
const predicateNames = parseNameList(opts.predicates);
|
|
22852
|
+
const selectorNames = parseNameList(opts.selectors);
|
|
22512
22853
|
if (!predicateNames) {
|
|
22513
22854
|
logWarn(
|
|
22514
22855
|
"predicate checks skipped \u2014 pass --predicates or run the worker conformance test"
|
|
22515
22856
|
);
|
|
22516
22857
|
}
|
|
22858
|
+
if (!selectorNames) {
|
|
22859
|
+
logWarn("selector checks skipped \u2014 pass --selectors or run the worker conformance test");
|
|
22860
|
+
}
|
|
22517
22861
|
logInfo(`Linting process artifact(s) against ${resolvedPath}`);
|
|
22518
22862
|
const results = runLintExtraction(resolvedPath, extractorPath, resolvedProcessPath);
|
|
22519
22863
|
if (!results || results.length === 0) {
|
|
@@ -22535,7 +22879,12 @@ ${inventory.workflowType} (${sourceFile})`);
|
|
|
22535
22879
|
const { artifact, diagnostics: parseDiagnostics } = parseProcessArtifact2(processArtifact);
|
|
22536
22880
|
let diagnostics = parseDiagnostics;
|
|
22537
22881
|
if (artifact) {
|
|
22538
|
-
const lintDiagnostics = lintProcess2(
|
|
22882
|
+
const lintDiagnostics = lintProcess2(
|
|
22883
|
+
artifact,
|
|
22884
|
+
inventory,
|
|
22885
|
+
predicateNames ?? [],
|
|
22886
|
+
selectorNames ? { selectorNames } : {}
|
|
22887
|
+
);
|
|
22539
22888
|
const reportable = predicateNames ? lintDiagnostics : lintDiagnostics.filter((d) => d.code !== "UNKNOWN_PREDICATE");
|
|
22540
22889
|
diagnostics = diagnostics.concat(reportable);
|
|
22541
22890
|
}
|