@topolo/sdk 0.15.0 → 0.17.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/README.md +14 -0
- package/dist/index.cjs +333 -214
- package/dist/index.d.cts +83 -59
- package/dist/index.d.ts +83 -59
- package/dist/index.js +330 -214
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -137,6 +137,16 @@ const actorEnvelope: ActorEnvelope = parseActorEnvelope({
|
|
|
137
137
|
},
|
|
138
138
|
issuedAt: new Date().toISOString(),
|
|
139
139
|
});
|
|
140
|
+
|
|
141
|
+
await topolo.client.callAction(
|
|
142
|
+
actorEnvelope.action.actionId,
|
|
143
|
+
actionInput,
|
|
144
|
+
{
|
|
145
|
+
actorEnvelope,
|
|
146
|
+
resource: { resourceType: 'design', resourceId: 'design_123' },
|
|
147
|
+
confirm: true,
|
|
148
|
+
},
|
|
149
|
+
);
|
|
140
150
|
```
|
|
141
151
|
|
|
142
152
|
The parser rejects unknown fields, unsupported principal types, partial
|
|
@@ -145,6 +155,10 @@ delegation chain. External agents require an installation and provider;
|
|
|
145
155
|
managed agents require an agent instance; browser automation requires both an
|
|
146
156
|
installation and a browser-session identity. `X-Topolo-Agent` remains useful
|
|
147
157
|
telemetry but is never trusted as provenance or approval authority.
|
|
158
|
+
`callAction` and `readAction` validate the envelope against the exact action,
|
|
159
|
+
input and resource before sending its canonical base64url representation in
|
|
160
|
+
`X-Topolo-Actor-Envelope`; the envelope request ID also becomes the transport
|
|
161
|
+
request ID.
|
|
148
162
|
|
|
149
163
|
## Modules
|
|
150
164
|
|
package/dist/index.cjs
CHANGED
|
@@ -27,6 +27,7 @@ __export(index_exports, {
|
|
|
27
27
|
DEFAULT_APP_URLS: () => DEFAULT_APP_URLS,
|
|
28
28
|
IdentityModule: () => IdentityModule,
|
|
29
29
|
P2PModule: () => P2PModule,
|
|
30
|
+
TOPOLO_ACTOR_ENVELOPE_HEADER: () => TOPOLO_ACTOR_ENVELOPE_HEADER,
|
|
30
31
|
TOPOLO_ENVIRONMENT_SERVICE_URLS: () => TOPOLO_ENVIRONMENT_SERVICE_URLS,
|
|
31
32
|
TOPOLO_RUNTIME_ENVIRONMENTS: () => TOPOLO_RUNTIME_ENVIRONMENTS,
|
|
32
33
|
TOPOLO_WIDGET_CONTRACT_VERSION: () => TOPOLO_WIDGET_CONTRACT_VERSION,
|
|
@@ -59,12 +60,14 @@ __export(index_exports, {
|
|
|
59
60
|
createTopoloAgentExecutionContext: () => createTopoloAgentExecutionContext,
|
|
60
61
|
createTopoloWidgetError: () => createTopoloWidgetError,
|
|
61
62
|
createTopoloWidgetResponse: () => createTopoloWidgetResponse,
|
|
63
|
+
decodeActorEnvelopeHeader: () => decodeActorEnvelopeHeader,
|
|
62
64
|
defineTopoloActionsWidget: () => defineTopoloActionsWidget,
|
|
63
65
|
defineTopoloActivityWidget: () => defineTopoloActivityWidget,
|
|
64
66
|
defineTopoloChartWidget: () => defineTopoloChartWidget,
|
|
65
67
|
defineTopoloNotificationsWidget: () => defineTopoloNotificationsWidget,
|
|
66
68
|
defineTopoloStatsWidget: () => defineTopoloStatsWidget,
|
|
67
69
|
digestTopoloActionCatalog: () => digestTopoloActionCatalog,
|
|
70
|
+
encodeActorEnvelopeHeader: () => encodeActorEnvelopeHeader,
|
|
68
71
|
encodeTopoloActionBase64: () => encodeTopoloActionBase64,
|
|
69
72
|
enrichActionContract: () => enrichActionContract,
|
|
70
73
|
extractTopoloServiceErrorCode: () => extractTopoloServiceErrorCode,
|
|
@@ -935,6 +938,242 @@ function isMultipleOf(value, divisor) {
|
|
|
935
938
|
return Math.abs(quotient - Math.round(quotient)) < Number.EPSILON * Math.max(1, Math.abs(quotient)) * 4;
|
|
936
939
|
}
|
|
937
940
|
|
|
941
|
+
// src/actor-envelope.ts
|
|
942
|
+
var ACTOR_ENVELOPE_VERSION = 1;
|
|
943
|
+
var TOPOLO_ACTOR_ENVELOPE_HEADER = "X-Topolo-Actor-Envelope";
|
|
944
|
+
var PRINCIPAL_TYPES = /* @__PURE__ */ new Set([
|
|
945
|
+
"human",
|
|
946
|
+
"managed_agent",
|
|
947
|
+
"external_agent",
|
|
948
|
+
"service",
|
|
949
|
+
"browser_automation"
|
|
950
|
+
]);
|
|
951
|
+
var ACCOUNTABLE_SUBJECT_TYPES = /* @__PURE__ */ new Set(["human", "organization"]);
|
|
952
|
+
var CHANNELS = /* @__PURE__ */ new Set(["web", "mobile", "cli", "mcp", "api", "workflow", "browser_automation"]);
|
|
953
|
+
var ASSURANCE_LEVELS = /* @__PURE__ */ new Set(["authenticated", "workload_identity", "user_verified"]);
|
|
954
|
+
var HASH_PATTERN = /^sha256:[a-f0-9]{64}$/;
|
|
955
|
+
var ActorEnvelopeValidationError = class extends Error {
|
|
956
|
+
path;
|
|
957
|
+
constructor(path, message) {
|
|
958
|
+
super(`${path}: ${message}`);
|
|
959
|
+
this.name = "ActorEnvelopeValidationError";
|
|
960
|
+
this.path = path;
|
|
961
|
+
}
|
|
962
|
+
};
|
|
963
|
+
function parseActorEnvelope(value) {
|
|
964
|
+
const envelope = record(value, "actorEnvelope");
|
|
965
|
+
exactKeys(envelope, [
|
|
966
|
+
"schemaVersion",
|
|
967
|
+
"organizationId",
|
|
968
|
+
"accountableSubject",
|
|
969
|
+
"performer",
|
|
970
|
+
"delegation",
|
|
971
|
+
"channel",
|
|
972
|
+
"assurance",
|
|
973
|
+
"action",
|
|
974
|
+
"issuedAt",
|
|
975
|
+
"expiresAt"
|
|
976
|
+
], "actorEnvelope");
|
|
977
|
+
if (envelope.schemaVersion !== ACTOR_ENVELOPE_VERSION) {
|
|
978
|
+
fail("actorEnvelope.schemaVersion", `must equal ${ACTOR_ENVELOPE_VERSION}`);
|
|
979
|
+
}
|
|
980
|
+
const accountableSubject = parseAccountableSubject(envelope.accountableSubject);
|
|
981
|
+
const performer = parseIdentity(envelope.performer, "actorEnvelope.performer");
|
|
982
|
+
const organizationId = text(envelope.organizationId, "actorEnvelope.organizationId");
|
|
983
|
+
const channel = member(envelope.channel, CHANNELS, "actorEnvelope.channel");
|
|
984
|
+
const issuedAt = timestamp(envelope.issuedAt, "actorEnvelope.issuedAt");
|
|
985
|
+
const expiresAt = envelope.expiresAt === void 0 ? void 0 : timestamp(envelope.expiresAt, "actorEnvelope.expiresAt");
|
|
986
|
+
if (expiresAt && Date.parse(expiresAt) <= Date.parse(issuedAt)) {
|
|
987
|
+
fail("actorEnvelope.expiresAt", "must be later than issuedAt");
|
|
988
|
+
}
|
|
989
|
+
const assuranceValue = record(envelope.assurance, "actorEnvelope.assurance");
|
|
990
|
+
exactKeys(assuranceValue, ["level", "methods"], "actorEnvelope.assurance");
|
|
991
|
+
const assurance = {
|
|
992
|
+
level: member(assuranceValue.level, ASSURANCE_LEVELS, "actorEnvelope.assurance.level"),
|
|
993
|
+
methods: textArray(assuranceValue.methods, "actorEnvelope.assurance.methods")
|
|
994
|
+
};
|
|
995
|
+
const actionValue = record(envelope.action, "actorEnvelope.action");
|
|
996
|
+
exactKeys(actionValue, ["requestId", "actionId", "resourceType", "resourceId", "inputHash"], "actorEnvelope.action");
|
|
997
|
+
const inputHash = text(actionValue.inputHash, "actorEnvelope.action.inputHash");
|
|
998
|
+
if (!HASH_PATTERN.test(inputHash)) fail("actorEnvelope.action.inputHash", "must be a lowercase sha256 digest");
|
|
999
|
+
const action = {
|
|
1000
|
+
requestId: text(actionValue.requestId, "actorEnvelope.action.requestId"),
|
|
1001
|
+
actionId: text(actionValue.actionId, "actorEnvelope.action.actionId"),
|
|
1002
|
+
...actionValue.resourceType === void 0 ? {} : { resourceType: text(actionValue.resourceType, "actorEnvelope.action.resourceType") },
|
|
1003
|
+
...actionValue.resourceId === void 0 ? {} : { resourceId: text(actionValue.resourceId, "actorEnvelope.action.resourceId") },
|
|
1004
|
+
inputHash
|
|
1005
|
+
};
|
|
1006
|
+
if (action.resourceType === void 0 !== (action.resourceId === void 0)) {
|
|
1007
|
+
fail("actorEnvelope.action", "resourceType and resourceId must be provided together");
|
|
1008
|
+
}
|
|
1009
|
+
const delegation = parseDelegation(envelope.delegation);
|
|
1010
|
+
const directHuman = performer.principalType === "human" && performer.principalId === accountableSubject.principalId;
|
|
1011
|
+
if (directHuman && delegation !== null) fail("actorEnvelope.delegation", "must be null for direct human action");
|
|
1012
|
+
if (!directHuman && delegation === null) fail("actorEnvelope.delegation", "is required when performer differs from accountable subject");
|
|
1013
|
+
if (delegation) {
|
|
1014
|
+
const finalHop = delegation.lineage.at(-1);
|
|
1015
|
+
if (!finalHop || finalHop.principalId !== performer.principalId || finalHop.principalType !== performer.principalType) {
|
|
1016
|
+
fail("actorEnvelope.delegation.lineage", "must end with the performer");
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
if (performer.principalType === "external_agent" && (!performer.installationId || !performer.provider)) {
|
|
1020
|
+
fail("actorEnvelope.performer", "external_agent requires installationId and provider");
|
|
1021
|
+
}
|
|
1022
|
+
if (performer.principalType === "managed_agent" && !performer.agentInstanceId) {
|
|
1023
|
+
fail("actorEnvelope.performer.agentInstanceId", "is required for managed_agent");
|
|
1024
|
+
}
|
|
1025
|
+
if (performer.principalType === "browser_automation" && (!performer.installationId || !performer.browserSessionId)) {
|
|
1026
|
+
fail("actorEnvelope.performer", "browser_automation requires installationId and browserSessionId");
|
|
1027
|
+
}
|
|
1028
|
+
return {
|
|
1029
|
+
schemaVersion: ACTOR_ENVELOPE_VERSION,
|
|
1030
|
+
organizationId,
|
|
1031
|
+
accountableSubject,
|
|
1032
|
+
performer,
|
|
1033
|
+
delegation,
|
|
1034
|
+
channel,
|
|
1035
|
+
assurance,
|
|
1036
|
+
action,
|
|
1037
|
+
issuedAt,
|
|
1038
|
+
...expiresAt ? { expiresAt } : {}
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
function canonicalizeActorEnvelope(value) {
|
|
1042
|
+
return canonicalJson(parseActorEnvelope(value));
|
|
1043
|
+
}
|
|
1044
|
+
function encodeActorEnvelopeHeader(value) {
|
|
1045
|
+
const bytes = new TextEncoder().encode(canonicalizeActorEnvelope(value));
|
|
1046
|
+
const binary = Array.from(bytes, (byte) => String.fromCharCode(byte)).join("");
|
|
1047
|
+
return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
|
|
1048
|
+
}
|
|
1049
|
+
function decodeActorEnvelopeHeader(value) {
|
|
1050
|
+
if (!/^[A-Za-z0-9_-]+$/.test(value)) {
|
|
1051
|
+
fail("actorEnvelopeHeader", "must be unpadded base64url");
|
|
1052
|
+
}
|
|
1053
|
+
const padded = value.replaceAll("-", "+").replaceAll("_", "/") + "=".repeat((4 - value.length % 4) % 4);
|
|
1054
|
+
let bytes;
|
|
1055
|
+
try {
|
|
1056
|
+
bytes = Uint8Array.from(atob(padded), (character) => character.charCodeAt(0));
|
|
1057
|
+
} catch {
|
|
1058
|
+
fail("actorEnvelopeHeader", "must be valid base64url");
|
|
1059
|
+
}
|
|
1060
|
+
try {
|
|
1061
|
+
return parseActorEnvelope(JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes)));
|
|
1062
|
+
} catch (error) {
|
|
1063
|
+
if (error instanceof ActorEnvelopeValidationError) throw error;
|
|
1064
|
+
fail("actorEnvelopeHeader", "must contain a valid UTF-8 actor envelope");
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
function canonicalJson(value) {
|
|
1068
|
+
if (value === null) return "null";
|
|
1069
|
+
if (typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
|
|
1070
|
+
if (typeof value === "number") {
|
|
1071
|
+
if (!Number.isFinite(value)) throw new TypeError("Canonical JSON accepts finite numbers only.");
|
|
1072
|
+
return JSON.stringify(value);
|
|
1073
|
+
}
|
|
1074
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
1075
|
+
if (typeof value !== "object" || !value || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) {
|
|
1076
|
+
throw new TypeError("Canonical JSON accepts JSON objects, arrays, and primitives only.");
|
|
1077
|
+
}
|
|
1078
|
+
const entries = Object.entries(value).filter(([, item]) => item !== void 0).sort(([left], [right]) => left.localeCompare(right));
|
|
1079
|
+
return `{${entries.map(([key, item]) => `${JSON.stringify(key)}:${canonicalJson(item)}`).join(",")}}`;
|
|
1080
|
+
}
|
|
1081
|
+
function parseAccountableSubject(value) {
|
|
1082
|
+
const path = "actorEnvelope.accountableSubject";
|
|
1083
|
+
const subject = record(value, path);
|
|
1084
|
+
exactKeys(subject, ["principalType", "principalId", "displayName"], path);
|
|
1085
|
+
return {
|
|
1086
|
+
principalType: member(subject.principalType, ACCOUNTABLE_SUBJECT_TYPES, `${path}.principalType`),
|
|
1087
|
+
principalId: text(subject.principalId, `${path}.principalId`),
|
|
1088
|
+
...subject.displayName === void 0 ? {} : { displayName: text(subject.displayName, `${path}.displayName`) }
|
|
1089
|
+
};
|
|
1090
|
+
}
|
|
1091
|
+
async function sha256CanonicalValue(value) {
|
|
1092
|
+
const bytes = new TextEncoder().encode(canonicalJson(value));
|
|
1093
|
+
const digest = await crypto.subtle.digest("SHA-256", bytes);
|
|
1094
|
+
return `sha256:${Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("")}`;
|
|
1095
|
+
}
|
|
1096
|
+
function parseIdentity(value, path) {
|
|
1097
|
+
const identity = record(value, path);
|
|
1098
|
+
exactKeys(identity, [
|
|
1099
|
+
"principalType",
|
|
1100
|
+
"principalId",
|
|
1101
|
+
"displayName",
|
|
1102
|
+
"installationId",
|
|
1103
|
+
"agentInstanceId",
|
|
1104
|
+
"browserSessionId",
|
|
1105
|
+
"provider",
|
|
1106
|
+
"model"
|
|
1107
|
+
], path);
|
|
1108
|
+
return {
|
|
1109
|
+
principalType: member(identity.principalType, PRINCIPAL_TYPES, `${path}.principalType`),
|
|
1110
|
+
principalId: text(identity.principalId, `${path}.principalId`),
|
|
1111
|
+
...optionalTextFields(identity, path, [
|
|
1112
|
+
"displayName",
|
|
1113
|
+
"installationId",
|
|
1114
|
+
"agentInstanceId",
|
|
1115
|
+
"browserSessionId",
|
|
1116
|
+
"provider",
|
|
1117
|
+
"model"
|
|
1118
|
+
])
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
function parseDelegation(value) {
|
|
1122
|
+
if (value === null) return null;
|
|
1123
|
+
const delegation = record(value, "actorEnvelope.delegation");
|
|
1124
|
+
exactKeys(delegation, ["taskId", "runId", "lineage"], "actorEnvelope.delegation");
|
|
1125
|
+
if (!Array.isArray(delegation.lineage) || delegation.lineage.length === 0 || delegation.lineage.length > 16) {
|
|
1126
|
+
fail("actorEnvelope.delegation.lineage", "must contain between 1 and 16 hops");
|
|
1127
|
+
}
|
|
1128
|
+
return {
|
|
1129
|
+
taskId: text(delegation.taskId, "actorEnvelope.delegation.taskId"),
|
|
1130
|
+
runId: text(delegation.runId, "actorEnvelope.delegation.runId"),
|
|
1131
|
+
lineage: delegation.lineage.map((value2, index) => {
|
|
1132
|
+
const hop = record(value2, `actorEnvelope.delegation.lineage[${index}]`);
|
|
1133
|
+
exactKeys(hop, ["principalType", "principalId"], `actorEnvelope.delegation.lineage[${index}]`);
|
|
1134
|
+
return {
|
|
1135
|
+
principalType: member(hop.principalType, PRINCIPAL_TYPES, `actorEnvelope.delegation.lineage[${index}].principalType`),
|
|
1136
|
+
principalId: text(hop.principalId, `actorEnvelope.delegation.lineage[${index}].principalId`)
|
|
1137
|
+
};
|
|
1138
|
+
})
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
function record(value, path) {
|
|
1142
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) fail(path, "must be an object");
|
|
1143
|
+
return value;
|
|
1144
|
+
}
|
|
1145
|
+
function exactKeys(value, allowed, path) {
|
|
1146
|
+
const unknown = Object.keys(value).filter((key) => !allowed.includes(key));
|
|
1147
|
+
if (unknown.length) fail(path, `contains unknown field ${unknown[0]}`);
|
|
1148
|
+
}
|
|
1149
|
+
function text(value, path) {
|
|
1150
|
+
if (typeof value !== "string" || value.trim() !== value || value.length === 0 || value.length > 256) {
|
|
1151
|
+
fail(path, "must be a non-empty trimmed string of at most 256 characters");
|
|
1152
|
+
}
|
|
1153
|
+
return value;
|
|
1154
|
+
}
|
|
1155
|
+
function timestamp(value, path) {
|
|
1156
|
+
const result = text(value, path);
|
|
1157
|
+
if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/.test(result) || Number.isNaN(Date.parse(result))) {
|
|
1158
|
+
fail(path, "must be an RFC 3339 UTC timestamp");
|
|
1159
|
+
}
|
|
1160
|
+
return result;
|
|
1161
|
+
}
|
|
1162
|
+
function member(value, values, path) {
|
|
1163
|
+
if (typeof value !== "string" || !values.has(value)) fail(path, "contains an unsupported value");
|
|
1164
|
+
return value;
|
|
1165
|
+
}
|
|
1166
|
+
function textArray(value, path) {
|
|
1167
|
+
if (!Array.isArray(value) || value.length === 0 || value.length > 16) fail(path, "must contain between 1 and 16 values");
|
|
1168
|
+
return value.map((item, index) => text(item, `${path}[${index}]`));
|
|
1169
|
+
}
|
|
1170
|
+
function optionalTextFields(value, path, keys) {
|
|
1171
|
+
return Object.fromEntries(keys.flatMap((key) => value[key] === void 0 ? [] : [[key, text(value[key], `${path}.${key}`)]]));
|
|
1172
|
+
}
|
|
1173
|
+
function fail(path, message) {
|
|
1174
|
+
throw new ActorEnvelopeValidationError(path, message);
|
|
1175
|
+
}
|
|
1176
|
+
|
|
938
1177
|
// src/action-upload.ts
|
|
939
1178
|
function parseTopoloActionUploadContract(value) {
|
|
940
1179
|
if (!isRecord2(value) || value.profile !== "inline-base64" && value.profile !== "url-session") {
|
|
@@ -1142,6 +1381,7 @@ var NEGATIVE_CACHE_TTL_MS = 60 * 1e3;
|
|
|
1142
1381
|
var TopoloClient = class _TopoloClient {
|
|
1143
1382
|
credential;
|
|
1144
1383
|
agent;
|
|
1384
|
+
actorContext;
|
|
1145
1385
|
serviceUrls;
|
|
1146
1386
|
environment;
|
|
1147
1387
|
appIds;
|
|
@@ -1172,6 +1412,11 @@ var TopoloClient = class _TopoloClient {
|
|
|
1172
1412
|
if (!options.agent?.clientName) throw new TopoloAuthError("agent.clientName is required");
|
|
1173
1413
|
this.credential = options.credential;
|
|
1174
1414
|
this.agent = options.agent;
|
|
1415
|
+
this.actorContext = options.actorContext ? {
|
|
1416
|
+
channel: options.actorContext.channel,
|
|
1417
|
+
taskId: options.actorContext.taskId ?? `task_${generateRequestId()}`,
|
|
1418
|
+
runId: options.actorContext.runId ?? `run_${generateRequestId()}`
|
|
1419
|
+
} : void 0;
|
|
1175
1420
|
this.environment = options.environment;
|
|
1176
1421
|
this.serviceUrls = options.environment ? topoloServiceOrigins(options.serviceUrls, options.environment) : options.serviceUrls;
|
|
1177
1422
|
this.appIds = options.appIds;
|
|
@@ -1225,11 +1470,15 @@ var TopoloClient = class _TopoloClient {
|
|
|
1225
1470
|
const platformAppId = resolveConfiguredAppId(resolvedService.serviceKey, this.appIds);
|
|
1226
1471
|
if (platformAppId) headers.set("X-App-ID", platformAppId);
|
|
1227
1472
|
applyAuthHeaders(headers, this.credential);
|
|
1228
|
-
const
|
|
1473
|
+
const actorEnvelope = opts.actorEnvelope === void 0 ? void 0 : parseActorEnvelope(opts.actorEnvelope);
|
|
1474
|
+
const requestId = actorEnvelope?.action.requestId ?? generateRequestId();
|
|
1229
1475
|
applyAuditHeaders(headers, this.agent, requestId);
|
|
1230
1476
|
if (opts.headers) {
|
|
1231
1477
|
for (const [k, v] of Object.entries(opts.headers)) headers.set(k, v);
|
|
1232
1478
|
}
|
|
1479
|
+
if (actorEnvelope) {
|
|
1480
|
+
headers.set(TOPOLO_ACTOR_ENVELOPE_HEADER, encodeActorEnvelopeHeader(actorEnvelope));
|
|
1481
|
+
}
|
|
1233
1482
|
if (opts.resource) {
|
|
1234
1483
|
const resourceType = opts.resource.resourceType.trim();
|
|
1235
1484
|
const resourceId = opts.resource.resourceId.trim();
|
|
@@ -1883,6 +2132,20 @@ var TopoloClient = class _TopoloClient {
|
|
|
1883
2132
|
);
|
|
1884
2133
|
}
|
|
1885
2134
|
const mapped = mapActionInput(entry, input);
|
|
2135
|
+
const resolvedActorEnvelope = options.actorEnvelope ?? await this.buildVerifiedAgentActorEnvelope(entry.actionId, input, options.resource);
|
|
2136
|
+
if (resolvedActorEnvelope) {
|
|
2137
|
+
const actorEnvelope = parseActorEnvelope(resolvedActorEnvelope);
|
|
2138
|
+
if (actorEnvelope.action.actionId !== entry.actionId) {
|
|
2139
|
+
throw new TopoloSdkError("actor_envelope_action_mismatch", "Actor envelope actionId does not match the executed action.");
|
|
2140
|
+
}
|
|
2141
|
+
if (actorEnvelope.action.inputHash !== await sha256CanonicalValue(input)) {
|
|
2142
|
+
throw new TopoloSdkError("actor_envelope_input_mismatch", "Actor envelope inputHash does not match the executed action input.");
|
|
2143
|
+
}
|
|
2144
|
+
const envelopeResource = actorEnvelope.action.resourceType && actorEnvelope.action.resourceId ? { resourceType: actorEnvelope.action.resourceType, resourceId: actorEnvelope.action.resourceId } : void 0;
|
|
2145
|
+
if (envelopeResource?.resourceType !== options.resource?.resourceType || envelopeResource?.resourceId !== options.resource?.resourceId) {
|
|
2146
|
+
throw new TopoloSdkError("actor_envelope_resource_mismatch", "Actor envelope resource does not match the executed action resource.");
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
1886
2149
|
const service = entry.appSlug || entry.appId;
|
|
1887
2150
|
const result = await this.request({
|
|
1888
2151
|
service,
|
|
@@ -1892,6 +2155,7 @@ var TopoloClient = class _TopoloClient {
|
|
|
1892
2155
|
...mapped.query ? { query: mapped.query } : {},
|
|
1893
2156
|
...mapped.body !== void 0 ? { body: mapped.body } : {},
|
|
1894
2157
|
...options.resource ? { resource: options.resource } : {},
|
|
2158
|
+
...resolvedActorEnvelope ? { actorEnvelope: resolvedActorEnvelope } : {},
|
|
1895
2159
|
headers: {
|
|
1896
2160
|
[TOPOLO_ACTION_ID_HEADER]: entry.actionId,
|
|
1897
2161
|
[TOPOLO_ACTION_NAME_HEADER]: entry.name
|
|
@@ -1900,6 +2164,56 @@ var TopoloClient = class _TopoloClient {
|
|
|
1900
2164
|
});
|
|
1901
2165
|
return redactActionResult(result);
|
|
1902
2166
|
}
|
|
2167
|
+
async buildVerifiedAgentActorEnvelope(actionId, input, resource) {
|
|
2168
|
+
if (!this.actorContext) return void 0;
|
|
2169
|
+
const identity = await this.introspect();
|
|
2170
|
+
const principalType = identity.user.principalType;
|
|
2171
|
+
if (principalType !== "agent_employee" && principalType !== "external_agent") return void 0;
|
|
2172
|
+
if (!identity.organization || !identity.user.accountableUserId || !identity.user.principalId) {
|
|
2173
|
+
throw new TopoloSdkError(
|
|
2174
|
+
"incomplete_agent_identity",
|
|
2175
|
+
"Verified agent credentials must resolve an organization, accountable user, and principal id."
|
|
2176
|
+
);
|
|
2177
|
+
}
|
|
2178
|
+
const performer = principalType === "external_agent" ? {
|
|
2179
|
+
principalType: "external_agent",
|
|
2180
|
+
principalId: identity.user.principalId,
|
|
2181
|
+
installationId: identity.user.installationId ?? void 0,
|
|
2182
|
+
provider: identity.user.provider ?? void 0,
|
|
2183
|
+
model: identity.user.model ?? void 0
|
|
2184
|
+
} : {
|
|
2185
|
+
principalType: "managed_agent",
|
|
2186
|
+
principalId: identity.user.principalId,
|
|
2187
|
+
agentInstanceId: identity.user.agentInstanceId ?? void 0,
|
|
2188
|
+
model: identity.user.model ?? void 0
|
|
2189
|
+
};
|
|
2190
|
+
if (performer.principalType === "external_agent" && (!performer.installationId || !performer.provider) || performer.principalType === "managed_agent" && !performer.agentInstanceId) {
|
|
2191
|
+
throw new TopoloSdkError(
|
|
2192
|
+
"incomplete_agent_identity",
|
|
2193
|
+
"Verified agent credentials are missing the performer identity required for provenance."
|
|
2194
|
+
);
|
|
2195
|
+
}
|
|
2196
|
+
return parseActorEnvelope({
|
|
2197
|
+
schemaVersion: 1,
|
|
2198
|
+
organizationId: identity.organization.id,
|
|
2199
|
+
accountableSubject: { principalType: "human", principalId: identity.user.accountableUserId },
|
|
2200
|
+
performer,
|
|
2201
|
+
delegation: {
|
|
2202
|
+
taskId: this.actorContext.taskId,
|
|
2203
|
+
runId: this.actorContext.runId,
|
|
2204
|
+
lineage: [{ principalType: performer.principalType, principalId: performer.principalId }]
|
|
2205
|
+
},
|
|
2206
|
+
channel: this.actorContext.channel,
|
|
2207
|
+
assurance: { level: "workload_identity", methods: ["client_credentials"] },
|
|
2208
|
+
action: {
|
|
2209
|
+
requestId: generateRequestId(),
|
|
2210
|
+
actionId,
|
|
2211
|
+
...resource ? resource : {},
|
|
2212
|
+
inputHash: await sha256CanonicalValue(input)
|
|
2213
|
+
},
|
|
2214
|
+
issuedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2215
|
+
});
|
|
2216
|
+
}
|
|
1903
2217
|
/**
|
|
1904
2218
|
* Introspect the current credential. Returns the caller's resolved identity,
|
|
1905
2219
|
* organization, and permission set. Used by CLI `whoami` and by MCP to gate
|
|
@@ -1927,7 +2241,18 @@ var TopoloClient = class _TopoloClient {
|
|
|
1927
2241
|
email: user.email,
|
|
1928
2242
|
name: user.name ?? null,
|
|
1929
2243
|
role: user.role ?? (kind === "api_key" ? "service" : "member"),
|
|
1930
|
-
permissions: payload.permissions ?? user.permissions ?? []
|
|
2244
|
+
permissions: payload.permissions ?? user.permissions ?? [],
|
|
2245
|
+
...normalizeAgentPrincipalType(user.principalType) ? {
|
|
2246
|
+
principalId: readOptionalString(user.principalId),
|
|
2247
|
+
principalType: normalizeAgentPrincipalType(user.principalType),
|
|
2248
|
+
accountableUserId: readOptionalString(user.accountableUserId),
|
|
2249
|
+
agentInstanceId: readOptionalString(user.agentInstanceId),
|
|
2250
|
+
installationId: readOptionalString(user.installationId),
|
|
2251
|
+
provider: readOptionalString(user.provider),
|
|
2252
|
+
model: readOptionalString(user.model),
|
|
2253
|
+
serviceScopes: stringArray(user.serviceScopes),
|
|
2254
|
+
policyRef: readOptionalString(user.policyRef)
|
|
2255
|
+
} : {}
|
|
1931
2256
|
},
|
|
1932
2257
|
organization: organization ? {
|
|
1933
2258
|
id: organization.id,
|
|
@@ -2292,6 +2617,9 @@ function normalizeCredentialAuthorizationMode(value, kind) {
|
|
|
2292
2617
|
if (value === "context_rbac" || value === "oauth_scopes" || value === "session_rbac") return value;
|
|
2293
2618
|
return "unknown";
|
|
2294
2619
|
}
|
|
2620
|
+
function normalizeAgentPrincipalType(value) {
|
|
2621
|
+
return value === "agent_employee" || value === "external_agent" ? value : null;
|
|
2622
|
+
}
|
|
2295
2623
|
function describeError(body, fallback) {
|
|
2296
2624
|
if (body && typeof body === "object") {
|
|
2297
2625
|
const maybe = body;
|
|
@@ -3016,218 +3344,6 @@ var IdentityModule = class {
|
|
|
3016
3344
|
}
|
|
3017
3345
|
};
|
|
3018
3346
|
|
|
3019
|
-
// src/actor-envelope.ts
|
|
3020
|
-
var ACTOR_ENVELOPE_VERSION = 1;
|
|
3021
|
-
var PRINCIPAL_TYPES = /* @__PURE__ */ new Set([
|
|
3022
|
-
"human",
|
|
3023
|
-
"managed_agent",
|
|
3024
|
-
"external_agent",
|
|
3025
|
-
"service",
|
|
3026
|
-
"browser_automation"
|
|
3027
|
-
]);
|
|
3028
|
-
var ACCOUNTABLE_SUBJECT_TYPES = /* @__PURE__ */ new Set(["human", "organization"]);
|
|
3029
|
-
var CHANNELS = /* @__PURE__ */ new Set(["web", "mobile", "cli", "mcp", "api", "workflow", "browser_automation"]);
|
|
3030
|
-
var ASSURANCE_LEVELS = /* @__PURE__ */ new Set(["authenticated", "workload_identity", "user_verified"]);
|
|
3031
|
-
var HASH_PATTERN = /^sha256:[a-f0-9]{64}$/;
|
|
3032
|
-
var ActorEnvelopeValidationError = class extends Error {
|
|
3033
|
-
path;
|
|
3034
|
-
constructor(path, message) {
|
|
3035
|
-
super(`${path}: ${message}`);
|
|
3036
|
-
this.name = "ActorEnvelopeValidationError";
|
|
3037
|
-
this.path = path;
|
|
3038
|
-
}
|
|
3039
|
-
};
|
|
3040
|
-
function parseActorEnvelope(value) {
|
|
3041
|
-
const envelope = record(value, "actorEnvelope");
|
|
3042
|
-
exactKeys(envelope, [
|
|
3043
|
-
"schemaVersion",
|
|
3044
|
-
"organizationId",
|
|
3045
|
-
"accountableSubject",
|
|
3046
|
-
"performer",
|
|
3047
|
-
"delegation",
|
|
3048
|
-
"channel",
|
|
3049
|
-
"assurance",
|
|
3050
|
-
"action",
|
|
3051
|
-
"issuedAt",
|
|
3052
|
-
"expiresAt"
|
|
3053
|
-
], "actorEnvelope");
|
|
3054
|
-
if (envelope.schemaVersion !== ACTOR_ENVELOPE_VERSION) {
|
|
3055
|
-
fail("actorEnvelope.schemaVersion", `must equal ${ACTOR_ENVELOPE_VERSION}`);
|
|
3056
|
-
}
|
|
3057
|
-
const accountableSubject = parseAccountableSubject(envelope.accountableSubject);
|
|
3058
|
-
const performer = parseIdentity(envelope.performer, "actorEnvelope.performer");
|
|
3059
|
-
const organizationId = text(envelope.organizationId, "actorEnvelope.organizationId");
|
|
3060
|
-
const channel = member(envelope.channel, CHANNELS, "actorEnvelope.channel");
|
|
3061
|
-
const issuedAt = timestamp(envelope.issuedAt, "actorEnvelope.issuedAt");
|
|
3062
|
-
const expiresAt = envelope.expiresAt === void 0 ? void 0 : timestamp(envelope.expiresAt, "actorEnvelope.expiresAt");
|
|
3063
|
-
if (expiresAt && Date.parse(expiresAt) <= Date.parse(issuedAt)) {
|
|
3064
|
-
fail("actorEnvelope.expiresAt", "must be later than issuedAt");
|
|
3065
|
-
}
|
|
3066
|
-
const assuranceValue = record(envelope.assurance, "actorEnvelope.assurance");
|
|
3067
|
-
exactKeys(assuranceValue, ["level", "methods"], "actorEnvelope.assurance");
|
|
3068
|
-
const assurance = {
|
|
3069
|
-
level: member(assuranceValue.level, ASSURANCE_LEVELS, "actorEnvelope.assurance.level"),
|
|
3070
|
-
methods: textArray(assuranceValue.methods, "actorEnvelope.assurance.methods")
|
|
3071
|
-
};
|
|
3072
|
-
const actionValue = record(envelope.action, "actorEnvelope.action");
|
|
3073
|
-
exactKeys(actionValue, ["requestId", "actionId", "resourceType", "resourceId", "inputHash"], "actorEnvelope.action");
|
|
3074
|
-
const inputHash = text(actionValue.inputHash, "actorEnvelope.action.inputHash");
|
|
3075
|
-
if (!HASH_PATTERN.test(inputHash)) fail("actorEnvelope.action.inputHash", "must be a lowercase sha256 digest");
|
|
3076
|
-
const action = {
|
|
3077
|
-
requestId: text(actionValue.requestId, "actorEnvelope.action.requestId"),
|
|
3078
|
-
actionId: text(actionValue.actionId, "actorEnvelope.action.actionId"),
|
|
3079
|
-
...actionValue.resourceType === void 0 ? {} : { resourceType: text(actionValue.resourceType, "actorEnvelope.action.resourceType") },
|
|
3080
|
-
...actionValue.resourceId === void 0 ? {} : { resourceId: text(actionValue.resourceId, "actorEnvelope.action.resourceId") },
|
|
3081
|
-
inputHash
|
|
3082
|
-
};
|
|
3083
|
-
if (action.resourceType === void 0 !== (action.resourceId === void 0)) {
|
|
3084
|
-
fail("actorEnvelope.action", "resourceType and resourceId must be provided together");
|
|
3085
|
-
}
|
|
3086
|
-
const delegation = parseDelegation(envelope.delegation);
|
|
3087
|
-
const directHuman = performer.principalType === "human" && performer.principalId === accountableSubject.principalId;
|
|
3088
|
-
if (directHuman && delegation !== null) fail("actorEnvelope.delegation", "must be null for direct human action");
|
|
3089
|
-
if (!directHuman && delegation === null) fail("actorEnvelope.delegation", "is required when performer differs from accountable subject");
|
|
3090
|
-
if (delegation) {
|
|
3091
|
-
const finalHop = delegation.lineage.at(-1);
|
|
3092
|
-
if (!finalHop || finalHop.principalId !== performer.principalId || finalHop.principalType !== performer.principalType) {
|
|
3093
|
-
fail("actorEnvelope.delegation.lineage", "must end with the performer");
|
|
3094
|
-
}
|
|
3095
|
-
}
|
|
3096
|
-
if (performer.principalType === "external_agent" && (!performer.installationId || !performer.provider)) {
|
|
3097
|
-
fail("actorEnvelope.performer", "external_agent requires installationId and provider");
|
|
3098
|
-
}
|
|
3099
|
-
if (performer.principalType === "managed_agent" && !performer.agentInstanceId) {
|
|
3100
|
-
fail("actorEnvelope.performer.agentInstanceId", "is required for managed_agent");
|
|
3101
|
-
}
|
|
3102
|
-
if (performer.principalType === "browser_automation" && (!performer.installationId || !performer.browserSessionId)) {
|
|
3103
|
-
fail("actorEnvelope.performer", "browser_automation requires installationId and browserSessionId");
|
|
3104
|
-
}
|
|
3105
|
-
return {
|
|
3106
|
-
schemaVersion: ACTOR_ENVELOPE_VERSION,
|
|
3107
|
-
organizationId,
|
|
3108
|
-
accountableSubject,
|
|
3109
|
-
performer,
|
|
3110
|
-
delegation,
|
|
3111
|
-
channel,
|
|
3112
|
-
assurance,
|
|
3113
|
-
action,
|
|
3114
|
-
issuedAt,
|
|
3115
|
-
...expiresAt ? { expiresAt } : {}
|
|
3116
|
-
};
|
|
3117
|
-
}
|
|
3118
|
-
function canonicalizeActorEnvelope(value) {
|
|
3119
|
-
return canonicalJson(parseActorEnvelope(value));
|
|
3120
|
-
}
|
|
3121
|
-
function canonicalJson(value) {
|
|
3122
|
-
if (value === null) return "null";
|
|
3123
|
-
if (typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
|
|
3124
|
-
if (typeof value === "number") {
|
|
3125
|
-
if (!Number.isFinite(value)) throw new TypeError("Canonical JSON accepts finite numbers only.");
|
|
3126
|
-
return JSON.stringify(value);
|
|
3127
|
-
}
|
|
3128
|
-
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
3129
|
-
if (typeof value !== "object" || !value || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) {
|
|
3130
|
-
throw new TypeError("Canonical JSON accepts JSON objects, arrays, and primitives only.");
|
|
3131
|
-
}
|
|
3132
|
-
const entries = Object.entries(value).filter(([, item]) => item !== void 0).sort(([left], [right]) => left.localeCompare(right));
|
|
3133
|
-
return `{${entries.map(([key, item]) => `${JSON.stringify(key)}:${canonicalJson(item)}`).join(",")}}`;
|
|
3134
|
-
}
|
|
3135
|
-
function parseAccountableSubject(value) {
|
|
3136
|
-
const path = "actorEnvelope.accountableSubject";
|
|
3137
|
-
const subject = record(value, path);
|
|
3138
|
-
exactKeys(subject, ["principalType", "principalId", "displayName"], path);
|
|
3139
|
-
return {
|
|
3140
|
-
principalType: member(subject.principalType, ACCOUNTABLE_SUBJECT_TYPES, `${path}.principalType`),
|
|
3141
|
-
principalId: text(subject.principalId, `${path}.principalId`),
|
|
3142
|
-
...subject.displayName === void 0 ? {} : { displayName: text(subject.displayName, `${path}.displayName`) }
|
|
3143
|
-
};
|
|
3144
|
-
}
|
|
3145
|
-
async function sha256CanonicalValue(value) {
|
|
3146
|
-
const bytes = new TextEncoder().encode(canonicalJson(value));
|
|
3147
|
-
const digest = await crypto.subtle.digest("SHA-256", bytes);
|
|
3148
|
-
return `sha256:${Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("")}`;
|
|
3149
|
-
}
|
|
3150
|
-
function parseIdentity(value, path) {
|
|
3151
|
-
const identity = record(value, path);
|
|
3152
|
-
exactKeys(identity, [
|
|
3153
|
-
"principalType",
|
|
3154
|
-
"principalId",
|
|
3155
|
-
"displayName",
|
|
3156
|
-
"installationId",
|
|
3157
|
-
"agentInstanceId",
|
|
3158
|
-
"browserSessionId",
|
|
3159
|
-
"provider",
|
|
3160
|
-
"model"
|
|
3161
|
-
], path);
|
|
3162
|
-
return {
|
|
3163
|
-
principalType: member(identity.principalType, PRINCIPAL_TYPES, `${path}.principalType`),
|
|
3164
|
-
principalId: text(identity.principalId, `${path}.principalId`),
|
|
3165
|
-
...optionalTextFields(identity, path, [
|
|
3166
|
-
"displayName",
|
|
3167
|
-
"installationId",
|
|
3168
|
-
"agentInstanceId",
|
|
3169
|
-
"browserSessionId",
|
|
3170
|
-
"provider",
|
|
3171
|
-
"model"
|
|
3172
|
-
])
|
|
3173
|
-
};
|
|
3174
|
-
}
|
|
3175
|
-
function parseDelegation(value) {
|
|
3176
|
-
if (value === null) return null;
|
|
3177
|
-
const delegation = record(value, "actorEnvelope.delegation");
|
|
3178
|
-
exactKeys(delegation, ["taskId", "runId", "lineage"], "actorEnvelope.delegation");
|
|
3179
|
-
if (!Array.isArray(delegation.lineage) || delegation.lineage.length === 0 || delegation.lineage.length > 16) {
|
|
3180
|
-
fail("actorEnvelope.delegation.lineage", "must contain between 1 and 16 hops");
|
|
3181
|
-
}
|
|
3182
|
-
return {
|
|
3183
|
-
taskId: text(delegation.taskId, "actorEnvelope.delegation.taskId"),
|
|
3184
|
-
runId: text(delegation.runId, "actorEnvelope.delegation.runId"),
|
|
3185
|
-
lineage: delegation.lineage.map((value2, index) => {
|
|
3186
|
-
const hop = record(value2, `actorEnvelope.delegation.lineage[${index}]`);
|
|
3187
|
-
exactKeys(hop, ["principalType", "principalId"], `actorEnvelope.delegation.lineage[${index}]`);
|
|
3188
|
-
return {
|
|
3189
|
-
principalType: member(hop.principalType, PRINCIPAL_TYPES, `actorEnvelope.delegation.lineage[${index}].principalType`),
|
|
3190
|
-
principalId: text(hop.principalId, `actorEnvelope.delegation.lineage[${index}].principalId`)
|
|
3191
|
-
};
|
|
3192
|
-
})
|
|
3193
|
-
};
|
|
3194
|
-
}
|
|
3195
|
-
function record(value, path) {
|
|
3196
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) fail(path, "must be an object");
|
|
3197
|
-
return value;
|
|
3198
|
-
}
|
|
3199
|
-
function exactKeys(value, allowed, path) {
|
|
3200
|
-
const unknown = Object.keys(value).filter((key) => !allowed.includes(key));
|
|
3201
|
-
if (unknown.length) fail(path, `contains unknown field ${unknown[0]}`);
|
|
3202
|
-
}
|
|
3203
|
-
function text(value, path) {
|
|
3204
|
-
if (typeof value !== "string" || value.trim() !== value || value.length === 0 || value.length > 256) {
|
|
3205
|
-
fail(path, "must be a non-empty trimmed string of at most 256 characters");
|
|
3206
|
-
}
|
|
3207
|
-
return value;
|
|
3208
|
-
}
|
|
3209
|
-
function timestamp(value, path) {
|
|
3210
|
-
const result = text(value, path);
|
|
3211
|
-
if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/.test(result) || Number.isNaN(Date.parse(result))) {
|
|
3212
|
-
fail(path, "must be an RFC 3339 UTC timestamp");
|
|
3213
|
-
}
|
|
3214
|
-
return result;
|
|
3215
|
-
}
|
|
3216
|
-
function member(value, values, path) {
|
|
3217
|
-
if (typeof value !== "string" || !values.has(value)) fail(path, "contains an unsupported value");
|
|
3218
|
-
return value;
|
|
3219
|
-
}
|
|
3220
|
-
function textArray(value, path) {
|
|
3221
|
-
if (!Array.isArray(value) || value.length === 0 || value.length > 16) fail(path, "must contain between 1 and 16 values");
|
|
3222
|
-
return value.map((item, index) => text(item, `${path}[${index}]`));
|
|
3223
|
-
}
|
|
3224
|
-
function optionalTextFields(value, path, keys) {
|
|
3225
|
-
return Object.fromEntries(keys.flatMap((key) => value[key] === void 0 ? [] : [[key, text(value[key], `${path}.${key}`)]]));
|
|
3226
|
-
}
|
|
3227
|
-
function fail(path, message) {
|
|
3228
|
-
throw new ActorEnvelopeValidationError(path, message);
|
|
3229
|
-
}
|
|
3230
|
-
|
|
3231
3347
|
// src/modules/workspaces.ts
|
|
3232
3348
|
var ACTIONS = {
|
|
3233
3349
|
list: "app_topolo_auth.workspaces.list",
|
|
@@ -4725,6 +4841,7 @@ function createTopolo(options) {
|
|
|
4725
4841
|
DEFAULT_APP_URLS,
|
|
4726
4842
|
IdentityModule,
|
|
4727
4843
|
P2PModule,
|
|
4844
|
+
TOPOLO_ACTOR_ENVELOPE_HEADER,
|
|
4728
4845
|
TOPOLO_ENVIRONMENT_SERVICE_URLS,
|
|
4729
4846
|
TOPOLO_RUNTIME_ENVIRONMENTS,
|
|
4730
4847
|
TOPOLO_WIDGET_CONTRACT_VERSION,
|
|
@@ -4757,12 +4874,14 @@ function createTopolo(options) {
|
|
|
4757
4874
|
createTopoloAgentExecutionContext,
|
|
4758
4875
|
createTopoloWidgetError,
|
|
4759
4876
|
createTopoloWidgetResponse,
|
|
4877
|
+
decodeActorEnvelopeHeader,
|
|
4760
4878
|
defineTopoloActionsWidget,
|
|
4761
4879
|
defineTopoloActivityWidget,
|
|
4762
4880
|
defineTopoloChartWidget,
|
|
4763
4881
|
defineTopoloNotificationsWidget,
|
|
4764
4882
|
defineTopoloStatsWidget,
|
|
4765
4883
|
digestTopoloActionCatalog,
|
|
4884
|
+
encodeActorEnvelopeHeader,
|
|
4766
4885
|
encodeTopoloActionBase64,
|
|
4767
4886
|
enrichActionContract,
|
|
4768
4887
|
extractTopoloServiceErrorCode,
|