@topolo/sdk 0.14.4 → 0.15.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/README.md CHANGED
@@ -86,6 +86,66 @@ Every request sends:
86
86
  Combined with the credential identity, this makes every platform API call
87
87
  traceable to a specific agent invocation.
88
88
 
89
+ ### Actor provenance
90
+
91
+ `ActorEnvelope` is the versioned authority and provenance contract for work
92
+ performed by humans, Topolo-managed agents, external harness installations,
93
+ services, and declared browser automation. It always records the accountable
94
+ subject and actual performer independently and binds them to one organization,
95
+ task/run lineage, channel, assurance level, action, resource, and canonical
96
+ input hash.
97
+
98
+ ```ts
99
+ import {
100
+ parseActorEnvelope,
101
+ sha256CanonicalValue,
102
+ type ActorEnvelope,
103
+ } from '@topolo/sdk';
104
+
105
+ const actionInput = { designId: 'design_123', decision: 'approve' };
106
+ const actorEnvelope: ActorEnvelope = parseActorEnvelope({
107
+ schemaVersion: 1,
108
+ organizationId: 'org_acme',
109
+ accountableSubject: {
110
+ principalType: 'human',
111
+ principalId: 'usr_ashley',
112
+ displayName: 'Ashley Lane',
113
+ },
114
+ performer: {
115
+ principalType: 'external_agent',
116
+ principalId: 'installation_codex_macbook',
117
+ installationId: 'installation_codex_macbook',
118
+ provider: 'openai',
119
+ model: 'gpt-5',
120
+ },
121
+ delegation: {
122
+ taskId: 'task_123',
123
+ runId: 'run_456',
124
+ lineage: [
125
+ { principalType: 'human', principalId: 'usr_ashley' },
126
+ { principalType: 'external_agent', principalId: 'installation_codex_macbook' },
127
+ ],
128
+ },
129
+ channel: 'mcp',
130
+ assurance: { level: 'workload_identity', methods: ['oauth_client'] },
131
+ action: {
132
+ requestId: 'req_789',
133
+ actionId: 'app_topolo_design.designs.approve',
134
+ resourceType: 'design',
135
+ resourceId: 'design_123',
136
+ inputHash: await sha256CanonicalValue(actionInput),
137
+ },
138
+ issuedAt: new Date().toISOString(),
139
+ });
140
+ ```
141
+
142
+ The parser rejects unknown fields, unsupported principal types, partial
143
+ resource bindings, malformed hashes, and non-human performers without a
144
+ delegation chain. External agents require an installation and provider;
145
+ managed agents require an agent instance; browser automation requires both an
146
+ installation and a browser-session identity. `X-Topolo-Agent` remains useful
147
+ telemetry but is never trusted as provenance or approval authority.
148
+
89
149
  ## Modules
90
150
 
91
151
  | Surface | Methods |
package/dist/index.cjs CHANGED
@@ -21,6 +21,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  ACTION_CATALOG_DIGEST_ALGORITHM: () => ACTION_CATALOG_DIGEST_ALGORITHM,
24
+ ACTOR_ENVELOPE_VERSION: () => ACTOR_ENVELOPE_VERSION,
25
+ ActorEnvelopeValidationError: () => ActorEnvelopeValidationError,
24
26
  CrmModule: () => CrmModule,
25
27
  DEFAULT_APP_URLS: () => DEFAULT_APP_URLS,
26
28
  IdentityModule: () => IdentityModule,
@@ -42,10 +44,12 @@ __export(index_exports, {
42
44
  actionContractCompleteness: () => actionContractCompleteness,
43
45
  applicationEntryFromCatalog: () => applicationEntryFromCatalog,
44
46
  assertTopoloServiceUrlEnvironment: () => assertTopoloServiceUrlEnvironment,
47
+ canonicalJson: () => canonicalJson,
45
48
  canonicalTopoloErrorCode: () => canonicalTopoloErrorCode,
46
49
  canonicalTopoloRequestId: () => canonicalTopoloRequestId,
47
50
  canonicalTopoloRequired: () => canonicalTopoloRequired,
48
51
  canonicalTopoloRetryAfter: () => canonicalTopoloRetryAfter,
52
+ canonicalizeActorEnvelope: () => canonicalizeActorEnvelope,
49
53
  compactActionCatalogEntry: () => compactActionCatalogEntry,
50
54
  compactActionPlan: () => compactActionPlan,
51
55
  compactActionPreparation: () => compactActionPreparation,
@@ -69,6 +73,7 @@ __export(index_exports, {
69
73
  friendlyAppId: () => friendlyAppId,
70
74
  isTopoloWidgetOutputSchema: () => isTopoloWidgetOutputSchema,
71
75
  listApplicationDirectory: () => listApplicationDirectory,
76
+ parseActorEnvelope: () => parseActorEnvelope,
72
77
  parseTopoloActionUploadContract: () => parseTopoloActionUploadContract,
73
78
  preferExactActionMatches: () => preferExactActionMatches,
74
79
  prepareTopoloActionBase64UploadInput: () => prepareTopoloActionBase64UploadInput,
@@ -77,6 +82,7 @@ __export(index_exports, {
77
82
  resolveApplicationDirectoryEntry: () => resolveApplicationDirectoryEntry,
78
83
  resolveCatalogServiceUrl: () => resolveCatalogServiceUrl,
79
84
  resolveServiceUrl: () => resolveServiceUrl,
85
+ sha256CanonicalValue: () => sha256CanonicalValue,
80
86
  topoloErrorHint: () => topoloErrorHint,
81
87
  topoloServiceOrigins: () => topoloServiceOrigins,
82
88
  validateTopoloActionInput: () => validateTopoloActionInput,
@@ -250,10 +256,10 @@ var TopoloPermissionError = class extends TopoloSdkError {
250
256
  };
251
257
  function extractTopoloServiceErrorCode(body) {
252
258
  if (!body || typeof body !== "object" || Array.isArray(body)) return null;
253
- const record = body;
254
- const topLevel = canonicalTopoloErrorCode(record.code);
259
+ const record2 = body;
260
+ const topLevel = canonicalTopoloErrorCode(record2.code);
255
261
  if (topLevel) return topLevel;
256
- const nested = record.error;
262
+ const nested = record2.error;
257
263
  const nestedString = canonicalTopoloErrorCode(nested);
258
264
  if (nestedString) return nestedString;
259
265
  if (nested && typeof nested === "object" && !Array.isArray(nested)) {
@@ -268,14 +274,14 @@ function serviceErrorCode(body, fallback) {
268
274
  }
269
275
  function extractTopoloServiceErrorDetails(body) {
270
276
  if (!body || typeof body !== "object" || Array.isArray(body)) return void 0;
271
- const record = body;
272
- let candidate = record.details;
273
- const nested = record.error;
277
+ const record2 = body;
278
+ let candidate = record2.details;
279
+ const nested = record2.error;
274
280
  if (nested && typeof nested === "object" && !Array.isArray(nested)) {
275
281
  const nestedRecord = nested;
276
282
  if (candidate === void 0) candidate = nestedRecord.details ?? nestedRecord;
277
283
  }
278
- if (candidate === void 0) candidate = record;
284
+ if (candidate === void 0) candidate = record2;
279
285
  if (Array.isArray(candidate)) {
280
286
  const paths = canonicalTopoloValidationPaths(candidate);
281
287
  return paths.length ? { paths } : void 0;
@@ -327,8 +333,8 @@ function canonicalTopoloValidationPaths(issues) {
327
333
  const paths = [];
328
334
  for (const issue of issues) {
329
335
  if (!issue || typeof issue !== "object" || Array.isArray(issue)) continue;
330
- const record = issue;
331
- const path = canonicalTopoloValidationPath(record.field) ?? canonicalTopoloValidationPath(record.path);
336
+ const record2 = issue;
337
+ const path = canonicalTopoloValidationPath(record2.field) ?? canonicalTopoloValidationPath(record2.path);
332
338
  if (path && !paths.includes(path)) paths.push(path);
333
339
  if (paths.length === 32) break;
334
340
  }
@@ -1670,14 +1676,14 @@ var TopoloClient = class _TopoloClient {
1670
1676
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
1671
1677
  throw new TopoloSdkError("action_catalog_summary_unavailable", "Action catalog summary is unavailable.");
1672
1678
  }
1673
- const record = raw;
1674
- if (record.algorithm !== "sha256-v1" || typeof record.digest !== "string" || !/^[a-f0-9]{64}$/.test(record.digest) || !Number.isSafeInteger(record.actionCount) || Number(record.actionCount) < 0) {
1679
+ const record2 = raw;
1680
+ if (record2.algorithm !== "sha256-v1" || typeof record2.digest !== "string" || !/^[a-f0-9]{64}$/.test(record2.digest) || !Number.isSafeInteger(record2.actionCount) || Number(record2.actionCount) < 0) {
1675
1681
  throw new TopoloSdkError("action_catalog_summary_unavailable", "Action catalog summary is invalid.");
1676
1682
  }
1677
1683
  return {
1678
1684
  algorithm: "sha256-v1",
1679
- digest: record.digest,
1680
- actionCount: Number(record.actionCount)
1685
+ digest: record2.digest,
1686
+ actionCount: Number(record2.actionCount)
1681
1687
  };
1682
1688
  }
1683
1689
  /** @deprecated Prefer searchActions() so callers retain the continuation cursor. */
@@ -2310,10 +2316,10 @@ function extractRequired(body) {
2310
2316
  if (Array.isArray(maybe.required)) return canonicalTopoloRequired(maybe.required);
2311
2317
  for (const nested of [maybe.details, maybe.error]) {
2312
2318
  if (!nested || typeof nested !== "object" || Array.isArray(nested)) continue;
2313
- const record = nested;
2314
- if (Array.isArray(record.required)) return canonicalTopoloRequired(record.required);
2315
- if (record.details && typeof record.details === "object" && !Array.isArray(record.details)) {
2316
- const required = record.details.required;
2319
+ const record2 = nested;
2320
+ if (Array.isArray(record2.required)) return canonicalTopoloRequired(record2.required);
2321
+ if (record2.details && typeof record2.details === "object" && !Array.isArray(record2.details)) {
2322
+ const required = record2.details.required;
2317
2323
  if (Array.isArray(required)) return canonicalTopoloRequired(required);
2318
2324
  }
2319
2325
  }
@@ -2390,8 +2396,8 @@ function compactResultValue(value, depth, budget) {
2390
2396
  return value.length > ACTION_RESULT_MAX_ITEMS ? { count: value.length, items, omittedItems: value.length - ACTION_RESULT_MAX_ITEMS } : items;
2391
2397
  }
2392
2398
  if (typeof value === "object") {
2393
- const record = value;
2394
- const allKeys = Object.keys(record);
2399
+ const record2 = value;
2400
+ const allKeys = Object.keys(record2);
2395
2401
  const ranked = allKeys.sort((left, right) => resultKeyPriority(left) - resultKeyPriority(right));
2396
2402
  const prioritized = ranked.filter((key) => resultKeyPriority(key) < 2);
2397
2403
  const ordinary = ranked.filter((key) => resultKeyPriority(key) === 2);
@@ -2400,7 +2406,7 @@ function compactResultValue(value, depth, budget) {
2400
2406
  ...prioritized,
2401
2407
  ...ordinary.slice(0, ordinaryLimit)
2402
2408
  ].slice(0, ACTION_RESULT_MAX_KEYS);
2403
- const compact = Object.fromEntries(keys.map((key) => [key, compactResultValue(record[key], depth + 1, budget)]));
2409
+ const compact = Object.fromEntries(keys.map((key) => [key, compactResultValue(record2[key], depth + 1, budget)]));
2404
2410
  if (allKeys.length > keys.length) compact["_omittedKeys"] = allKeys.length - keys.length;
2405
2411
  return compact;
2406
2412
  }
@@ -2516,8 +2522,8 @@ function canonicalPermission(value, appId) {
2516
2522
  function stableJson(value) {
2517
2523
  if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
2518
2524
  if (value && typeof value === "object") {
2519
- const record = value;
2520
- return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${stableJson(record[key])}`).join(",")}}`;
2525
+ const record2 = value;
2526
+ return `{${Object.keys(record2).sort().map((key) => `${JSON.stringify(key)}:${stableJson(record2[key])}`).join(",")}}`;
2521
2527
  }
2522
2528
  return JSON.stringify(value);
2523
2529
  }
@@ -2658,8 +2664,8 @@ function resourceSchema(resource) {
2658
2664
  function derivedOutputSchema(action) {
2659
2665
  const resource = resourceFor(action);
2660
2666
  const operation = operationFor(action);
2661
- const record = resourceSchema(resource);
2662
- const records = { type: "array", items: record };
2667
+ const record2 = resourceSchema(resource);
2668
+ const records = { type: "array", items: record2 };
2663
2669
  const provenance = {
2664
2670
  "x-topolo-contract-source": "derived-action-metadata",
2665
2671
  "x-topolo-contract-precision": "structural"
@@ -2691,12 +2697,12 @@ function derivedOutputSchema(action) {
2691
2697
  title: `${action.title || action.name} response`,
2692
2698
  description: `Resource response returned by ${action.name}. The service may return the resource directly or in an envelope.`,
2693
2699
  oneOf: [
2694
- record,
2700
+ record2,
2695
2701
  {
2696
2702
  type: "object",
2697
2703
  properties: {
2698
- data: record,
2699
- [resource]: record
2704
+ data: record2,
2705
+ [resource]: record2
2700
2706
  },
2701
2707
  additionalProperties: true
2702
2708
  }
@@ -2711,7 +2717,7 @@ function derivedOutputSchema(action) {
2711
2717
  properties: {
2712
2718
  success: { type: "boolean" },
2713
2719
  id: { type: "string" },
2714
- data: { oneOf: [record, { type: "object", additionalProperties: true }] },
2720
+ data: { oneOf: [record2, { type: "object", additionalProperties: true }] },
2715
2721
  result: { type: "object", additionalProperties: true },
2716
2722
  message: { type: "string" }
2717
2723
  },
@@ -3010,6 +3016,218 @@ var IdentityModule = class {
3010
3016
  }
3011
3017
  };
3012
3018
 
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
+
3013
3231
  // src/modules/workspaces.ts
3014
3232
  var ACTIONS = {
3015
3233
  list: "app_topolo_auth.workspaces.list",
@@ -4501,6 +4719,8 @@ function createTopolo(options) {
4501
4719
  // Annotate the CommonJS export names for ESM import in node:
4502
4720
  0 && (module.exports = {
4503
4721
  ACTION_CATALOG_DIGEST_ALGORITHM,
4722
+ ACTOR_ENVELOPE_VERSION,
4723
+ ActorEnvelopeValidationError,
4504
4724
  CrmModule,
4505
4725
  DEFAULT_APP_URLS,
4506
4726
  IdentityModule,
@@ -4522,10 +4742,12 @@ function createTopolo(options) {
4522
4742
  actionContractCompleteness,
4523
4743
  applicationEntryFromCatalog,
4524
4744
  assertTopoloServiceUrlEnvironment,
4745
+ canonicalJson,
4525
4746
  canonicalTopoloErrorCode,
4526
4747
  canonicalTopoloRequestId,
4527
4748
  canonicalTopoloRequired,
4528
4749
  canonicalTopoloRetryAfter,
4750
+ canonicalizeActorEnvelope,
4529
4751
  compactActionCatalogEntry,
4530
4752
  compactActionPlan,
4531
4753
  compactActionPreparation,
@@ -4549,6 +4771,7 @@ function createTopolo(options) {
4549
4771
  friendlyAppId,
4550
4772
  isTopoloWidgetOutputSchema,
4551
4773
  listApplicationDirectory,
4774
+ parseActorEnvelope,
4552
4775
  parseTopoloActionUploadContract,
4553
4776
  preferExactActionMatches,
4554
4777
  prepareTopoloActionBase64UploadInput,
@@ -4557,6 +4780,7 @@ function createTopolo(options) {
4557
4780
  resolveApplicationDirectoryEntry,
4558
4781
  resolveCatalogServiceUrl,
4559
4782
  resolveServiceUrl,
4783
+ sha256CanonicalValue,
4560
4784
  topoloErrorHint,
4561
4785
  topoloServiceOrigins,
4562
4786
  validateTopoloActionInput,
package/dist/index.d.cts CHANGED
@@ -254,6 +254,7 @@ interface TopoloActionCatalogEntry {
254
254
  }
255
255
  interface TopoloActionAgentContract {
256
256
  docsUrl?: string;
257
+ requiredReleaseCapability?: string;
257
258
  resourceContext?: {
258
259
  kind?: string;
259
260
  required?: boolean;
@@ -901,6 +902,64 @@ declare class IdentityModule {
901
902
  whoami(): Promise<CredentialIntrospection>;
902
903
  }
903
904
 
905
+ declare const ACTOR_ENVELOPE_VERSION: 1;
906
+ type ActorPrincipalType = 'human' | 'managed_agent' | 'external_agent' | 'service' | 'browser_automation';
907
+ type AccountableSubjectType = 'human' | 'organization';
908
+ type ActorChannel = 'web' | 'mobile' | 'cli' | 'mcp' | 'api' | 'workflow' | 'browser_automation';
909
+ type ActorAssurance = 'authenticated' | 'workload_identity' | 'user_verified';
910
+ interface ActorIdentity {
911
+ principalType: ActorPrincipalType;
912
+ principalId: string;
913
+ displayName?: string;
914
+ installationId?: string;
915
+ agentInstanceId?: string;
916
+ browserSessionId?: string;
917
+ provider?: string;
918
+ model?: string;
919
+ }
920
+ interface AccountableSubject {
921
+ principalType: AccountableSubjectType;
922
+ principalId: string;
923
+ displayName?: string;
924
+ }
925
+ interface ActorDelegationHop {
926
+ principalType: ActorPrincipalType;
927
+ principalId: string;
928
+ }
929
+ interface ActorEnvelope {
930
+ schemaVersion: typeof ACTOR_ENVELOPE_VERSION;
931
+ organizationId: string;
932
+ accountableSubject: AccountableSubject;
933
+ performer: ActorIdentity;
934
+ delegation: {
935
+ taskId: string;
936
+ runId: string;
937
+ lineage: ActorDelegationHop[];
938
+ } | null;
939
+ channel: ActorChannel;
940
+ assurance: {
941
+ level: ActorAssurance;
942
+ methods: string[];
943
+ };
944
+ action: {
945
+ requestId: string;
946
+ actionId: string;
947
+ resourceType?: string;
948
+ resourceId?: string;
949
+ inputHash: string;
950
+ };
951
+ issuedAt: string;
952
+ expiresAt?: string;
953
+ }
954
+ declare class ActorEnvelopeValidationError extends Error {
955
+ readonly path: string;
956
+ constructor(path: string, message: string);
957
+ }
958
+ declare function parseActorEnvelope(value: unknown): ActorEnvelope;
959
+ declare function canonicalizeActorEnvelope(value: unknown): string;
960
+ declare function canonicalJson(value: unknown): string;
961
+ declare function sha256CanonicalValue(value: unknown): Promise<string>;
962
+
904
963
  interface TopoloWorkspace {
905
964
  id: string;
906
965
  appId: string;
@@ -1593,4 +1652,4 @@ declare function createTopolo(options: TopoloClientOptions): {
1593
1652
  };
1594
1653
  type Topolo = ReturnType<typeof createTopolo>;
1595
1654
 
1596
- export { ACTION_CATALOG_DIGEST_ALGORITHM, type ActionContractManifest, type ActionContractSource, type AgentIdentity, type AppApiId, type ApplicationCatalogEntry, type ApplicationDeployTarget, type ApplicationDirectory, type ApplicationDirectoryApplication, type ApplicationDirectoryClient, type ApplicationDirectorySource, type ApplicationId, type CredentialIntrospection, type CrmContactSummary, CrmModule, DEFAULT_APP_URLS, type DeviceAuthorizationResponse, IdentityModule, type ListContactsOptions, type ListContactsResult, type OAuthHelperOptions, type P2PActionDetail, type P2PActionRequestInput, type P2PActionRequestResult, type P2PActionRow, type P2PActionRun, type P2PCapability, type P2PConnection, type P2PHold, type P2PLedgerEntry, P2PModule, type P2PPolicy, type P2PPricingModel, type P2PSettlementBatch, type P2PSettlementGroup, type PublishCapabilityInput, type RequestOptions, type ServiceCatalogUrlEntry, TOPOLO_ENVIRONMENT_SERVICE_URLS, TOPOLO_RUNTIME_ENVIRONMENTS, TOPOLO_WIDGET_CONTRACT_VERSION, TOPOLO_WIDGET_ENDPOINT, TOPOLO_WIDGET_OUTPUT_SCHEMA, TOPOLO_WIDGET_REFRESH_INTERVAL_MS, type TokenResponse, type Topolo, type TopoloActionAgentContract, type TopoloActionCatalogEntry, type TopoloActionCatalogSummary, type TopoloActionDigestInput, type TopoloActionPlan, type TopoloActionPreparation, type TopoloActionUploadOptions, type TopoloActionValidationIssue, type TopoloActionValidationResult, type TopoloActionsWidget, type TopoloActivityWidget, type TopoloAgentExecutionContext, type TopoloApiKeyResourceMetadata, TopoloAuthError, type TopoloBinaryResponse, type TopoloBindableResource, type TopoloBindableResourceCatalog, type TopoloChartWidget, TopoloClient, type TopoloClientOptions, TopoloConfirmationRequiredError, type TopoloCredential, type TopoloDebugEvent, TopoloHttpError, type TopoloInlineBase64UploadContract, type TopoloJsonSchema, type TopoloNotificationsWidget, TopoloOAuth, TopoloPermissionError, type TopoloRuntimeEnvironment, TopoloSdkError, type TopoloServiceCatalogEntry, type TopoloStatsWidget, type TopoloWidget, type TopoloWidgetAccessibility, type TopoloWidgetActionBinding, type TopoloWidgetActionRecovery, type TopoloWidgetActivityItem, type TopoloWidgetApiError, type TopoloWidgetApiErrorResponse, type TopoloWidgetApiResponse, type TopoloWidgetApiSuccessResponse, type TopoloWidgetBase, type TopoloWidgetConfig, type TopoloWidgetConfiguration, type TopoloWidgetConfigurationField, type TopoloWidgetConfigurationOption, type TopoloWidgetContext, type TopoloWidgetContribution, type TopoloWidgetDatasetDefinition, type TopoloWidgetDimension, type TopoloWidgetDimensionDefinition, type TopoloWidgetDraft, type TopoloWidgetDrilldown, type TopoloWidgetErrorResponseOptions, type TopoloWidgetEventDefinition, type TopoloWidgetLifecycleStage, type TopoloWidgetLocalization, type TopoloWidgetMetric, type TopoloWidgetMetricAggregation, type TopoloWidgetMetricComparison, type TopoloWidgetMetricDefinition, type TopoloWidgetMetricSemantic, type TopoloWidgetNotificationItem, type TopoloWidgetPeriod, type TopoloWidgetPresentation, type TopoloWidgetRefreshPolicy, type TopoloWidgetResourceBinding, type TopoloWidgetResponseOptions, type TopoloWidgetSeries, type TopoloWidgetSeriesDefinition, type TopoloWidgetSeriesPoint, type TopoloWidgetSize, type TopoloWidgetState, type TopoloWidgetStatus, type TopoloWidgetType, type TopoloWidgetValidationResult, type TopoloWidgetVisualizationFamily, type TopoloWidgetWorkspaceSelector, type TopoloWorkspace, type TopoloWorkspaceListResult, type TopoloWorkspaceMutationResult, type TopoloWorkspacePolicy, WorkspacesModule, actionContractCompleteness, applicationEntryFromCatalog, assertTopoloServiceUrlEnvironment, canonicalTopoloErrorCode, canonicalTopoloRequestId, canonicalTopoloRequired, canonicalTopoloRetryAfter, compactActionCatalogEntry, compactActionPlan, compactActionPreparation, compactActionResult, compactActionValidation, createTopolo, createTopoloAgentExecutionContext, createTopoloWidgetError, createTopoloWidgetResponse, defineTopoloActionsWidget, defineTopoloActivityWidget, defineTopoloChartWidget, defineTopoloNotificationsWidget, defineTopoloStatsWidget, digestTopoloActionCatalog, encodeTopoloActionBase64, enrichActionContract, extractTopoloServiceErrorCode, extractTopoloServiceErrorDetails, formatDirectoryApplicationIds, friendlyAppId, isTopoloWidgetOutputSchema, listApplicationDirectory, parseTopoloActionUploadContract, preferExactActionMatches, prepareTopoloActionBase64UploadInput, prepareTopoloActionUploadInput, publicTopoloErrorMessage, resolveApplicationDirectoryEntry, resolveCatalogServiceUrl, resolveServiceUrl, topoloErrorHint, topoloServiceOrigins, validateTopoloActionInput, validateTopoloWidgetResponse };
1655
+ export { ACTION_CATALOG_DIGEST_ALGORITHM, ACTOR_ENVELOPE_VERSION, type AccountableSubject, type AccountableSubjectType, type ActionContractManifest, type ActionContractSource, type ActorAssurance, type ActorChannel, type ActorDelegationHop, type ActorEnvelope, ActorEnvelopeValidationError, type ActorIdentity, type ActorPrincipalType, type AgentIdentity, type AppApiId, type ApplicationCatalogEntry, type ApplicationDeployTarget, type ApplicationDirectory, type ApplicationDirectoryApplication, type ApplicationDirectoryClient, type ApplicationDirectorySource, type ApplicationId, type CredentialIntrospection, type CrmContactSummary, CrmModule, DEFAULT_APP_URLS, type DeviceAuthorizationResponse, IdentityModule, type ListContactsOptions, type ListContactsResult, type OAuthHelperOptions, type P2PActionDetail, type P2PActionRequestInput, type P2PActionRequestResult, type P2PActionRow, type P2PActionRun, type P2PCapability, type P2PConnection, type P2PHold, type P2PLedgerEntry, P2PModule, type P2PPolicy, type P2PPricingModel, type P2PSettlementBatch, type P2PSettlementGroup, type PublishCapabilityInput, type RequestOptions, type ServiceCatalogUrlEntry, TOPOLO_ENVIRONMENT_SERVICE_URLS, TOPOLO_RUNTIME_ENVIRONMENTS, TOPOLO_WIDGET_CONTRACT_VERSION, TOPOLO_WIDGET_ENDPOINT, TOPOLO_WIDGET_OUTPUT_SCHEMA, TOPOLO_WIDGET_REFRESH_INTERVAL_MS, type TokenResponse, type Topolo, type TopoloActionAgentContract, type TopoloActionCatalogEntry, type TopoloActionCatalogSummary, type TopoloActionDigestInput, type TopoloActionPlan, type TopoloActionPreparation, type TopoloActionUploadOptions, type TopoloActionValidationIssue, type TopoloActionValidationResult, type TopoloActionsWidget, type TopoloActivityWidget, type TopoloAgentExecutionContext, type TopoloApiKeyResourceMetadata, TopoloAuthError, type TopoloBinaryResponse, type TopoloBindableResource, type TopoloBindableResourceCatalog, type TopoloChartWidget, TopoloClient, type TopoloClientOptions, TopoloConfirmationRequiredError, type TopoloCredential, type TopoloDebugEvent, TopoloHttpError, type TopoloInlineBase64UploadContract, type TopoloJsonSchema, type TopoloNotificationsWidget, TopoloOAuth, TopoloPermissionError, type TopoloRuntimeEnvironment, TopoloSdkError, type TopoloServiceCatalogEntry, type TopoloStatsWidget, type TopoloWidget, type TopoloWidgetAccessibility, type TopoloWidgetActionBinding, type TopoloWidgetActionRecovery, type TopoloWidgetActivityItem, type TopoloWidgetApiError, type TopoloWidgetApiErrorResponse, type TopoloWidgetApiResponse, type TopoloWidgetApiSuccessResponse, type TopoloWidgetBase, type TopoloWidgetConfig, type TopoloWidgetConfiguration, type TopoloWidgetConfigurationField, type TopoloWidgetConfigurationOption, type TopoloWidgetContext, type TopoloWidgetContribution, type TopoloWidgetDatasetDefinition, type TopoloWidgetDimension, type TopoloWidgetDimensionDefinition, type TopoloWidgetDraft, type TopoloWidgetDrilldown, type TopoloWidgetErrorResponseOptions, type TopoloWidgetEventDefinition, type TopoloWidgetLifecycleStage, type TopoloWidgetLocalization, type TopoloWidgetMetric, type TopoloWidgetMetricAggregation, type TopoloWidgetMetricComparison, type TopoloWidgetMetricDefinition, type TopoloWidgetMetricSemantic, type TopoloWidgetNotificationItem, type TopoloWidgetPeriod, type TopoloWidgetPresentation, type TopoloWidgetRefreshPolicy, type TopoloWidgetResourceBinding, type TopoloWidgetResponseOptions, type TopoloWidgetSeries, type TopoloWidgetSeriesDefinition, type TopoloWidgetSeriesPoint, type TopoloWidgetSize, type TopoloWidgetState, type TopoloWidgetStatus, type TopoloWidgetType, type TopoloWidgetValidationResult, type TopoloWidgetVisualizationFamily, type TopoloWidgetWorkspaceSelector, type TopoloWorkspace, type TopoloWorkspaceListResult, type TopoloWorkspaceMutationResult, type TopoloWorkspacePolicy, WorkspacesModule, actionContractCompleteness, applicationEntryFromCatalog, assertTopoloServiceUrlEnvironment, canonicalJson, canonicalTopoloErrorCode, canonicalTopoloRequestId, canonicalTopoloRequired, canonicalTopoloRetryAfter, canonicalizeActorEnvelope, compactActionCatalogEntry, compactActionPlan, compactActionPreparation, compactActionResult, compactActionValidation, createTopolo, createTopoloAgentExecutionContext, createTopoloWidgetError, createTopoloWidgetResponse, defineTopoloActionsWidget, defineTopoloActivityWidget, defineTopoloChartWidget, defineTopoloNotificationsWidget, defineTopoloStatsWidget, digestTopoloActionCatalog, encodeTopoloActionBase64, enrichActionContract, extractTopoloServiceErrorCode, extractTopoloServiceErrorDetails, formatDirectoryApplicationIds, friendlyAppId, isTopoloWidgetOutputSchema, listApplicationDirectory, parseActorEnvelope, parseTopoloActionUploadContract, preferExactActionMatches, prepareTopoloActionBase64UploadInput, prepareTopoloActionUploadInput, publicTopoloErrorMessage, resolveApplicationDirectoryEntry, resolveCatalogServiceUrl, resolveServiceUrl, sha256CanonicalValue, topoloErrorHint, topoloServiceOrigins, validateTopoloActionInput, validateTopoloWidgetResponse };
package/dist/index.d.ts CHANGED
@@ -254,6 +254,7 @@ interface TopoloActionCatalogEntry {
254
254
  }
255
255
  interface TopoloActionAgentContract {
256
256
  docsUrl?: string;
257
+ requiredReleaseCapability?: string;
257
258
  resourceContext?: {
258
259
  kind?: string;
259
260
  required?: boolean;
@@ -901,6 +902,64 @@ declare class IdentityModule {
901
902
  whoami(): Promise<CredentialIntrospection>;
902
903
  }
903
904
 
905
+ declare const ACTOR_ENVELOPE_VERSION: 1;
906
+ type ActorPrincipalType = 'human' | 'managed_agent' | 'external_agent' | 'service' | 'browser_automation';
907
+ type AccountableSubjectType = 'human' | 'organization';
908
+ type ActorChannel = 'web' | 'mobile' | 'cli' | 'mcp' | 'api' | 'workflow' | 'browser_automation';
909
+ type ActorAssurance = 'authenticated' | 'workload_identity' | 'user_verified';
910
+ interface ActorIdentity {
911
+ principalType: ActorPrincipalType;
912
+ principalId: string;
913
+ displayName?: string;
914
+ installationId?: string;
915
+ agentInstanceId?: string;
916
+ browserSessionId?: string;
917
+ provider?: string;
918
+ model?: string;
919
+ }
920
+ interface AccountableSubject {
921
+ principalType: AccountableSubjectType;
922
+ principalId: string;
923
+ displayName?: string;
924
+ }
925
+ interface ActorDelegationHop {
926
+ principalType: ActorPrincipalType;
927
+ principalId: string;
928
+ }
929
+ interface ActorEnvelope {
930
+ schemaVersion: typeof ACTOR_ENVELOPE_VERSION;
931
+ organizationId: string;
932
+ accountableSubject: AccountableSubject;
933
+ performer: ActorIdentity;
934
+ delegation: {
935
+ taskId: string;
936
+ runId: string;
937
+ lineage: ActorDelegationHop[];
938
+ } | null;
939
+ channel: ActorChannel;
940
+ assurance: {
941
+ level: ActorAssurance;
942
+ methods: string[];
943
+ };
944
+ action: {
945
+ requestId: string;
946
+ actionId: string;
947
+ resourceType?: string;
948
+ resourceId?: string;
949
+ inputHash: string;
950
+ };
951
+ issuedAt: string;
952
+ expiresAt?: string;
953
+ }
954
+ declare class ActorEnvelopeValidationError extends Error {
955
+ readonly path: string;
956
+ constructor(path: string, message: string);
957
+ }
958
+ declare function parseActorEnvelope(value: unknown): ActorEnvelope;
959
+ declare function canonicalizeActorEnvelope(value: unknown): string;
960
+ declare function canonicalJson(value: unknown): string;
961
+ declare function sha256CanonicalValue(value: unknown): Promise<string>;
962
+
904
963
  interface TopoloWorkspace {
905
964
  id: string;
906
965
  appId: string;
@@ -1593,4 +1652,4 @@ declare function createTopolo(options: TopoloClientOptions): {
1593
1652
  };
1594
1653
  type Topolo = ReturnType<typeof createTopolo>;
1595
1654
 
1596
- export { ACTION_CATALOG_DIGEST_ALGORITHM, type ActionContractManifest, type ActionContractSource, type AgentIdentity, type AppApiId, type ApplicationCatalogEntry, type ApplicationDeployTarget, type ApplicationDirectory, type ApplicationDirectoryApplication, type ApplicationDirectoryClient, type ApplicationDirectorySource, type ApplicationId, type CredentialIntrospection, type CrmContactSummary, CrmModule, DEFAULT_APP_URLS, type DeviceAuthorizationResponse, IdentityModule, type ListContactsOptions, type ListContactsResult, type OAuthHelperOptions, type P2PActionDetail, type P2PActionRequestInput, type P2PActionRequestResult, type P2PActionRow, type P2PActionRun, type P2PCapability, type P2PConnection, type P2PHold, type P2PLedgerEntry, P2PModule, type P2PPolicy, type P2PPricingModel, type P2PSettlementBatch, type P2PSettlementGroup, type PublishCapabilityInput, type RequestOptions, type ServiceCatalogUrlEntry, TOPOLO_ENVIRONMENT_SERVICE_URLS, TOPOLO_RUNTIME_ENVIRONMENTS, TOPOLO_WIDGET_CONTRACT_VERSION, TOPOLO_WIDGET_ENDPOINT, TOPOLO_WIDGET_OUTPUT_SCHEMA, TOPOLO_WIDGET_REFRESH_INTERVAL_MS, type TokenResponse, type Topolo, type TopoloActionAgentContract, type TopoloActionCatalogEntry, type TopoloActionCatalogSummary, type TopoloActionDigestInput, type TopoloActionPlan, type TopoloActionPreparation, type TopoloActionUploadOptions, type TopoloActionValidationIssue, type TopoloActionValidationResult, type TopoloActionsWidget, type TopoloActivityWidget, type TopoloAgentExecutionContext, type TopoloApiKeyResourceMetadata, TopoloAuthError, type TopoloBinaryResponse, type TopoloBindableResource, type TopoloBindableResourceCatalog, type TopoloChartWidget, TopoloClient, type TopoloClientOptions, TopoloConfirmationRequiredError, type TopoloCredential, type TopoloDebugEvent, TopoloHttpError, type TopoloInlineBase64UploadContract, type TopoloJsonSchema, type TopoloNotificationsWidget, TopoloOAuth, TopoloPermissionError, type TopoloRuntimeEnvironment, TopoloSdkError, type TopoloServiceCatalogEntry, type TopoloStatsWidget, type TopoloWidget, type TopoloWidgetAccessibility, type TopoloWidgetActionBinding, type TopoloWidgetActionRecovery, type TopoloWidgetActivityItem, type TopoloWidgetApiError, type TopoloWidgetApiErrorResponse, type TopoloWidgetApiResponse, type TopoloWidgetApiSuccessResponse, type TopoloWidgetBase, type TopoloWidgetConfig, type TopoloWidgetConfiguration, type TopoloWidgetConfigurationField, type TopoloWidgetConfigurationOption, type TopoloWidgetContext, type TopoloWidgetContribution, type TopoloWidgetDatasetDefinition, type TopoloWidgetDimension, type TopoloWidgetDimensionDefinition, type TopoloWidgetDraft, type TopoloWidgetDrilldown, type TopoloWidgetErrorResponseOptions, type TopoloWidgetEventDefinition, type TopoloWidgetLifecycleStage, type TopoloWidgetLocalization, type TopoloWidgetMetric, type TopoloWidgetMetricAggregation, type TopoloWidgetMetricComparison, type TopoloWidgetMetricDefinition, type TopoloWidgetMetricSemantic, type TopoloWidgetNotificationItem, type TopoloWidgetPeriod, type TopoloWidgetPresentation, type TopoloWidgetRefreshPolicy, type TopoloWidgetResourceBinding, type TopoloWidgetResponseOptions, type TopoloWidgetSeries, type TopoloWidgetSeriesDefinition, type TopoloWidgetSeriesPoint, type TopoloWidgetSize, type TopoloWidgetState, type TopoloWidgetStatus, type TopoloWidgetType, type TopoloWidgetValidationResult, type TopoloWidgetVisualizationFamily, type TopoloWidgetWorkspaceSelector, type TopoloWorkspace, type TopoloWorkspaceListResult, type TopoloWorkspaceMutationResult, type TopoloWorkspacePolicy, WorkspacesModule, actionContractCompleteness, applicationEntryFromCatalog, assertTopoloServiceUrlEnvironment, canonicalTopoloErrorCode, canonicalTopoloRequestId, canonicalTopoloRequired, canonicalTopoloRetryAfter, compactActionCatalogEntry, compactActionPlan, compactActionPreparation, compactActionResult, compactActionValidation, createTopolo, createTopoloAgentExecutionContext, createTopoloWidgetError, createTopoloWidgetResponse, defineTopoloActionsWidget, defineTopoloActivityWidget, defineTopoloChartWidget, defineTopoloNotificationsWidget, defineTopoloStatsWidget, digestTopoloActionCatalog, encodeTopoloActionBase64, enrichActionContract, extractTopoloServiceErrorCode, extractTopoloServiceErrorDetails, formatDirectoryApplicationIds, friendlyAppId, isTopoloWidgetOutputSchema, listApplicationDirectory, parseTopoloActionUploadContract, preferExactActionMatches, prepareTopoloActionBase64UploadInput, prepareTopoloActionUploadInput, publicTopoloErrorMessage, resolveApplicationDirectoryEntry, resolveCatalogServiceUrl, resolveServiceUrl, topoloErrorHint, topoloServiceOrigins, validateTopoloActionInput, validateTopoloWidgetResponse };
1655
+ export { ACTION_CATALOG_DIGEST_ALGORITHM, ACTOR_ENVELOPE_VERSION, type AccountableSubject, type AccountableSubjectType, type ActionContractManifest, type ActionContractSource, type ActorAssurance, type ActorChannel, type ActorDelegationHop, type ActorEnvelope, ActorEnvelopeValidationError, type ActorIdentity, type ActorPrincipalType, type AgentIdentity, type AppApiId, type ApplicationCatalogEntry, type ApplicationDeployTarget, type ApplicationDirectory, type ApplicationDirectoryApplication, type ApplicationDirectoryClient, type ApplicationDirectorySource, type ApplicationId, type CredentialIntrospection, type CrmContactSummary, CrmModule, DEFAULT_APP_URLS, type DeviceAuthorizationResponse, IdentityModule, type ListContactsOptions, type ListContactsResult, type OAuthHelperOptions, type P2PActionDetail, type P2PActionRequestInput, type P2PActionRequestResult, type P2PActionRow, type P2PActionRun, type P2PCapability, type P2PConnection, type P2PHold, type P2PLedgerEntry, P2PModule, type P2PPolicy, type P2PPricingModel, type P2PSettlementBatch, type P2PSettlementGroup, type PublishCapabilityInput, type RequestOptions, type ServiceCatalogUrlEntry, TOPOLO_ENVIRONMENT_SERVICE_URLS, TOPOLO_RUNTIME_ENVIRONMENTS, TOPOLO_WIDGET_CONTRACT_VERSION, TOPOLO_WIDGET_ENDPOINT, TOPOLO_WIDGET_OUTPUT_SCHEMA, TOPOLO_WIDGET_REFRESH_INTERVAL_MS, type TokenResponse, type Topolo, type TopoloActionAgentContract, type TopoloActionCatalogEntry, type TopoloActionCatalogSummary, type TopoloActionDigestInput, type TopoloActionPlan, type TopoloActionPreparation, type TopoloActionUploadOptions, type TopoloActionValidationIssue, type TopoloActionValidationResult, type TopoloActionsWidget, type TopoloActivityWidget, type TopoloAgentExecutionContext, type TopoloApiKeyResourceMetadata, TopoloAuthError, type TopoloBinaryResponse, type TopoloBindableResource, type TopoloBindableResourceCatalog, type TopoloChartWidget, TopoloClient, type TopoloClientOptions, TopoloConfirmationRequiredError, type TopoloCredential, type TopoloDebugEvent, TopoloHttpError, type TopoloInlineBase64UploadContract, type TopoloJsonSchema, type TopoloNotificationsWidget, TopoloOAuth, TopoloPermissionError, type TopoloRuntimeEnvironment, TopoloSdkError, type TopoloServiceCatalogEntry, type TopoloStatsWidget, type TopoloWidget, type TopoloWidgetAccessibility, type TopoloWidgetActionBinding, type TopoloWidgetActionRecovery, type TopoloWidgetActivityItem, type TopoloWidgetApiError, type TopoloWidgetApiErrorResponse, type TopoloWidgetApiResponse, type TopoloWidgetApiSuccessResponse, type TopoloWidgetBase, type TopoloWidgetConfig, type TopoloWidgetConfiguration, type TopoloWidgetConfigurationField, type TopoloWidgetConfigurationOption, type TopoloWidgetContext, type TopoloWidgetContribution, type TopoloWidgetDatasetDefinition, type TopoloWidgetDimension, type TopoloWidgetDimensionDefinition, type TopoloWidgetDraft, type TopoloWidgetDrilldown, type TopoloWidgetErrorResponseOptions, type TopoloWidgetEventDefinition, type TopoloWidgetLifecycleStage, type TopoloWidgetLocalization, type TopoloWidgetMetric, type TopoloWidgetMetricAggregation, type TopoloWidgetMetricComparison, type TopoloWidgetMetricDefinition, type TopoloWidgetMetricSemantic, type TopoloWidgetNotificationItem, type TopoloWidgetPeriod, type TopoloWidgetPresentation, type TopoloWidgetRefreshPolicy, type TopoloWidgetResourceBinding, type TopoloWidgetResponseOptions, type TopoloWidgetSeries, type TopoloWidgetSeriesDefinition, type TopoloWidgetSeriesPoint, type TopoloWidgetSize, type TopoloWidgetState, type TopoloWidgetStatus, type TopoloWidgetType, type TopoloWidgetValidationResult, type TopoloWidgetVisualizationFamily, type TopoloWidgetWorkspaceSelector, type TopoloWorkspace, type TopoloWorkspaceListResult, type TopoloWorkspaceMutationResult, type TopoloWorkspacePolicy, WorkspacesModule, actionContractCompleteness, applicationEntryFromCatalog, assertTopoloServiceUrlEnvironment, canonicalJson, canonicalTopoloErrorCode, canonicalTopoloRequestId, canonicalTopoloRequired, canonicalTopoloRetryAfter, canonicalizeActorEnvelope, compactActionCatalogEntry, compactActionPlan, compactActionPreparation, compactActionResult, compactActionValidation, createTopolo, createTopoloAgentExecutionContext, createTopoloWidgetError, createTopoloWidgetResponse, defineTopoloActionsWidget, defineTopoloActivityWidget, defineTopoloChartWidget, defineTopoloNotificationsWidget, defineTopoloStatsWidget, digestTopoloActionCatalog, encodeTopoloActionBase64, enrichActionContract, extractTopoloServiceErrorCode, extractTopoloServiceErrorDetails, formatDirectoryApplicationIds, friendlyAppId, isTopoloWidgetOutputSchema, listApplicationDirectory, parseActorEnvelope, parseTopoloActionUploadContract, preferExactActionMatches, prepareTopoloActionBase64UploadInput, prepareTopoloActionUploadInput, publicTopoloErrorMessage, resolveApplicationDirectoryEntry, resolveCatalogServiceUrl, resolveServiceUrl, sha256CanonicalValue, topoloErrorHint, topoloServiceOrigins, validateTopoloActionInput, validateTopoloWidgetResponse };
package/dist/index.js CHANGED
@@ -164,10 +164,10 @@ var TopoloPermissionError = class extends TopoloSdkError {
164
164
  };
165
165
  function extractTopoloServiceErrorCode(body) {
166
166
  if (!body || typeof body !== "object" || Array.isArray(body)) return null;
167
- const record = body;
168
- const topLevel = canonicalTopoloErrorCode(record.code);
167
+ const record2 = body;
168
+ const topLevel = canonicalTopoloErrorCode(record2.code);
169
169
  if (topLevel) return topLevel;
170
- const nested = record.error;
170
+ const nested = record2.error;
171
171
  const nestedString = canonicalTopoloErrorCode(nested);
172
172
  if (nestedString) return nestedString;
173
173
  if (nested && typeof nested === "object" && !Array.isArray(nested)) {
@@ -182,14 +182,14 @@ function serviceErrorCode(body, fallback) {
182
182
  }
183
183
  function extractTopoloServiceErrorDetails(body) {
184
184
  if (!body || typeof body !== "object" || Array.isArray(body)) return void 0;
185
- const record = body;
186
- let candidate = record.details;
187
- const nested = record.error;
185
+ const record2 = body;
186
+ let candidate = record2.details;
187
+ const nested = record2.error;
188
188
  if (nested && typeof nested === "object" && !Array.isArray(nested)) {
189
189
  const nestedRecord = nested;
190
190
  if (candidate === void 0) candidate = nestedRecord.details ?? nestedRecord;
191
191
  }
192
- if (candidate === void 0) candidate = record;
192
+ if (candidate === void 0) candidate = record2;
193
193
  if (Array.isArray(candidate)) {
194
194
  const paths = canonicalTopoloValidationPaths(candidate);
195
195
  return paths.length ? { paths } : void 0;
@@ -241,8 +241,8 @@ function canonicalTopoloValidationPaths(issues) {
241
241
  const paths = [];
242
242
  for (const issue of issues) {
243
243
  if (!issue || typeof issue !== "object" || Array.isArray(issue)) continue;
244
- const record = issue;
245
- const path = canonicalTopoloValidationPath(record.field) ?? canonicalTopoloValidationPath(record.path);
244
+ const record2 = issue;
245
+ const path = canonicalTopoloValidationPath(record2.field) ?? canonicalTopoloValidationPath(record2.path);
246
246
  if (path && !paths.includes(path)) paths.push(path);
247
247
  if (paths.length === 32) break;
248
248
  }
@@ -1584,14 +1584,14 @@ var TopoloClient = class _TopoloClient {
1584
1584
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
1585
1585
  throw new TopoloSdkError("action_catalog_summary_unavailable", "Action catalog summary is unavailable.");
1586
1586
  }
1587
- const record = raw;
1588
- if (record.algorithm !== "sha256-v1" || typeof record.digest !== "string" || !/^[a-f0-9]{64}$/.test(record.digest) || !Number.isSafeInteger(record.actionCount) || Number(record.actionCount) < 0) {
1587
+ const record2 = raw;
1588
+ if (record2.algorithm !== "sha256-v1" || typeof record2.digest !== "string" || !/^[a-f0-9]{64}$/.test(record2.digest) || !Number.isSafeInteger(record2.actionCount) || Number(record2.actionCount) < 0) {
1589
1589
  throw new TopoloSdkError("action_catalog_summary_unavailable", "Action catalog summary is invalid.");
1590
1590
  }
1591
1591
  return {
1592
1592
  algorithm: "sha256-v1",
1593
- digest: record.digest,
1594
- actionCount: Number(record.actionCount)
1593
+ digest: record2.digest,
1594
+ actionCount: Number(record2.actionCount)
1595
1595
  };
1596
1596
  }
1597
1597
  /** @deprecated Prefer searchActions() so callers retain the continuation cursor. */
@@ -2224,10 +2224,10 @@ function extractRequired(body) {
2224
2224
  if (Array.isArray(maybe.required)) return canonicalTopoloRequired(maybe.required);
2225
2225
  for (const nested of [maybe.details, maybe.error]) {
2226
2226
  if (!nested || typeof nested !== "object" || Array.isArray(nested)) continue;
2227
- const record = nested;
2228
- if (Array.isArray(record.required)) return canonicalTopoloRequired(record.required);
2229
- if (record.details && typeof record.details === "object" && !Array.isArray(record.details)) {
2230
- const required = record.details.required;
2227
+ const record2 = nested;
2228
+ if (Array.isArray(record2.required)) return canonicalTopoloRequired(record2.required);
2229
+ if (record2.details && typeof record2.details === "object" && !Array.isArray(record2.details)) {
2230
+ const required = record2.details.required;
2231
2231
  if (Array.isArray(required)) return canonicalTopoloRequired(required);
2232
2232
  }
2233
2233
  }
@@ -2304,8 +2304,8 @@ function compactResultValue(value, depth, budget) {
2304
2304
  return value.length > ACTION_RESULT_MAX_ITEMS ? { count: value.length, items, omittedItems: value.length - ACTION_RESULT_MAX_ITEMS } : items;
2305
2305
  }
2306
2306
  if (typeof value === "object") {
2307
- const record = value;
2308
- const allKeys = Object.keys(record);
2307
+ const record2 = value;
2308
+ const allKeys = Object.keys(record2);
2309
2309
  const ranked = allKeys.sort((left, right) => resultKeyPriority(left) - resultKeyPriority(right));
2310
2310
  const prioritized = ranked.filter((key) => resultKeyPriority(key) < 2);
2311
2311
  const ordinary = ranked.filter((key) => resultKeyPriority(key) === 2);
@@ -2314,7 +2314,7 @@ function compactResultValue(value, depth, budget) {
2314
2314
  ...prioritized,
2315
2315
  ...ordinary.slice(0, ordinaryLimit)
2316
2316
  ].slice(0, ACTION_RESULT_MAX_KEYS);
2317
- const compact = Object.fromEntries(keys.map((key) => [key, compactResultValue(record[key], depth + 1, budget)]));
2317
+ const compact = Object.fromEntries(keys.map((key) => [key, compactResultValue(record2[key], depth + 1, budget)]));
2318
2318
  if (allKeys.length > keys.length) compact["_omittedKeys"] = allKeys.length - keys.length;
2319
2319
  return compact;
2320
2320
  }
@@ -2430,8 +2430,8 @@ function canonicalPermission(value, appId) {
2430
2430
  function stableJson(value) {
2431
2431
  if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
2432
2432
  if (value && typeof value === "object") {
2433
- const record = value;
2434
- return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${stableJson(record[key])}`).join(",")}}`;
2433
+ const record2 = value;
2434
+ return `{${Object.keys(record2).sort().map((key) => `${JSON.stringify(key)}:${stableJson(record2[key])}`).join(",")}}`;
2435
2435
  }
2436
2436
  return JSON.stringify(value);
2437
2437
  }
@@ -2572,8 +2572,8 @@ function resourceSchema(resource) {
2572
2572
  function derivedOutputSchema(action) {
2573
2573
  const resource = resourceFor(action);
2574
2574
  const operation = operationFor(action);
2575
- const record = resourceSchema(resource);
2576
- const records = { type: "array", items: record };
2575
+ const record2 = resourceSchema(resource);
2576
+ const records = { type: "array", items: record2 };
2577
2577
  const provenance = {
2578
2578
  "x-topolo-contract-source": "derived-action-metadata",
2579
2579
  "x-topolo-contract-precision": "structural"
@@ -2605,12 +2605,12 @@ function derivedOutputSchema(action) {
2605
2605
  title: `${action.title || action.name} response`,
2606
2606
  description: `Resource response returned by ${action.name}. The service may return the resource directly or in an envelope.`,
2607
2607
  oneOf: [
2608
- record,
2608
+ record2,
2609
2609
  {
2610
2610
  type: "object",
2611
2611
  properties: {
2612
- data: record,
2613
- [resource]: record
2612
+ data: record2,
2613
+ [resource]: record2
2614
2614
  },
2615
2615
  additionalProperties: true
2616
2616
  }
@@ -2625,7 +2625,7 @@ function derivedOutputSchema(action) {
2625
2625
  properties: {
2626
2626
  success: { type: "boolean" },
2627
2627
  id: { type: "string" },
2628
- data: { oneOf: [record, { type: "object", additionalProperties: true }] },
2628
+ data: { oneOf: [record2, { type: "object", additionalProperties: true }] },
2629
2629
  result: { type: "object", additionalProperties: true },
2630
2630
  message: { type: "string" }
2631
2631
  },
@@ -2924,6 +2924,218 @@ var IdentityModule = class {
2924
2924
  }
2925
2925
  };
2926
2926
 
2927
+ // src/actor-envelope.ts
2928
+ var ACTOR_ENVELOPE_VERSION = 1;
2929
+ var PRINCIPAL_TYPES = /* @__PURE__ */ new Set([
2930
+ "human",
2931
+ "managed_agent",
2932
+ "external_agent",
2933
+ "service",
2934
+ "browser_automation"
2935
+ ]);
2936
+ var ACCOUNTABLE_SUBJECT_TYPES = /* @__PURE__ */ new Set(["human", "organization"]);
2937
+ var CHANNELS = /* @__PURE__ */ new Set(["web", "mobile", "cli", "mcp", "api", "workflow", "browser_automation"]);
2938
+ var ASSURANCE_LEVELS = /* @__PURE__ */ new Set(["authenticated", "workload_identity", "user_verified"]);
2939
+ var HASH_PATTERN = /^sha256:[a-f0-9]{64}$/;
2940
+ var ActorEnvelopeValidationError = class extends Error {
2941
+ path;
2942
+ constructor(path, message) {
2943
+ super(`${path}: ${message}`);
2944
+ this.name = "ActorEnvelopeValidationError";
2945
+ this.path = path;
2946
+ }
2947
+ };
2948
+ function parseActorEnvelope(value) {
2949
+ const envelope = record(value, "actorEnvelope");
2950
+ exactKeys(envelope, [
2951
+ "schemaVersion",
2952
+ "organizationId",
2953
+ "accountableSubject",
2954
+ "performer",
2955
+ "delegation",
2956
+ "channel",
2957
+ "assurance",
2958
+ "action",
2959
+ "issuedAt",
2960
+ "expiresAt"
2961
+ ], "actorEnvelope");
2962
+ if (envelope.schemaVersion !== ACTOR_ENVELOPE_VERSION) {
2963
+ fail("actorEnvelope.schemaVersion", `must equal ${ACTOR_ENVELOPE_VERSION}`);
2964
+ }
2965
+ const accountableSubject = parseAccountableSubject(envelope.accountableSubject);
2966
+ const performer = parseIdentity(envelope.performer, "actorEnvelope.performer");
2967
+ const organizationId = text(envelope.organizationId, "actorEnvelope.organizationId");
2968
+ const channel = member(envelope.channel, CHANNELS, "actorEnvelope.channel");
2969
+ const issuedAt = timestamp(envelope.issuedAt, "actorEnvelope.issuedAt");
2970
+ const expiresAt = envelope.expiresAt === void 0 ? void 0 : timestamp(envelope.expiresAt, "actorEnvelope.expiresAt");
2971
+ if (expiresAt && Date.parse(expiresAt) <= Date.parse(issuedAt)) {
2972
+ fail("actorEnvelope.expiresAt", "must be later than issuedAt");
2973
+ }
2974
+ const assuranceValue = record(envelope.assurance, "actorEnvelope.assurance");
2975
+ exactKeys(assuranceValue, ["level", "methods"], "actorEnvelope.assurance");
2976
+ const assurance = {
2977
+ level: member(assuranceValue.level, ASSURANCE_LEVELS, "actorEnvelope.assurance.level"),
2978
+ methods: textArray(assuranceValue.methods, "actorEnvelope.assurance.methods")
2979
+ };
2980
+ const actionValue = record(envelope.action, "actorEnvelope.action");
2981
+ exactKeys(actionValue, ["requestId", "actionId", "resourceType", "resourceId", "inputHash"], "actorEnvelope.action");
2982
+ const inputHash = text(actionValue.inputHash, "actorEnvelope.action.inputHash");
2983
+ if (!HASH_PATTERN.test(inputHash)) fail("actorEnvelope.action.inputHash", "must be a lowercase sha256 digest");
2984
+ const action = {
2985
+ requestId: text(actionValue.requestId, "actorEnvelope.action.requestId"),
2986
+ actionId: text(actionValue.actionId, "actorEnvelope.action.actionId"),
2987
+ ...actionValue.resourceType === void 0 ? {} : { resourceType: text(actionValue.resourceType, "actorEnvelope.action.resourceType") },
2988
+ ...actionValue.resourceId === void 0 ? {} : { resourceId: text(actionValue.resourceId, "actorEnvelope.action.resourceId") },
2989
+ inputHash
2990
+ };
2991
+ if (action.resourceType === void 0 !== (action.resourceId === void 0)) {
2992
+ fail("actorEnvelope.action", "resourceType and resourceId must be provided together");
2993
+ }
2994
+ const delegation = parseDelegation(envelope.delegation);
2995
+ const directHuman = performer.principalType === "human" && performer.principalId === accountableSubject.principalId;
2996
+ if (directHuman && delegation !== null) fail("actorEnvelope.delegation", "must be null for direct human action");
2997
+ if (!directHuman && delegation === null) fail("actorEnvelope.delegation", "is required when performer differs from accountable subject");
2998
+ if (delegation) {
2999
+ const finalHop = delegation.lineage.at(-1);
3000
+ if (!finalHop || finalHop.principalId !== performer.principalId || finalHop.principalType !== performer.principalType) {
3001
+ fail("actorEnvelope.delegation.lineage", "must end with the performer");
3002
+ }
3003
+ }
3004
+ if (performer.principalType === "external_agent" && (!performer.installationId || !performer.provider)) {
3005
+ fail("actorEnvelope.performer", "external_agent requires installationId and provider");
3006
+ }
3007
+ if (performer.principalType === "managed_agent" && !performer.agentInstanceId) {
3008
+ fail("actorEnvelope.performer.agentInstanceId", "is required for managed_agent");
3009
+ }
3010
+ if (performer.principalType === "browser_automation" && (!performer.installationId || !performer.browserSessionId)) {
3011
+ fail("actorEnvelope.performer", "browser_automation requires installationId and browserSessionId");
3012
+ }
3013
+ return {
3014
+ schemaVersion: ACTOR_ENVELOPE_VERSION,
3015
+ organizationId,
3016
+ accountableSubject,
3017
+ performer,
3018
+ delegation,
3019
+ channel,
3020
+ assurance,
3021
+ action,
3022
+ issuedAt,
3023
+ ...expiresAt ? { expiresAt } : {}
3024
+ };
3025
+ }
3026
+ function canonicalizeActorEnvelope(value) {
3027
+ return canonicalJson(parseActorEnvelope(value));
3028
+ }
3029
+ function canonicalJson(value) {
3030
+ if (value === null) return "null";
3031
+ if (typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
3032
+ if (typeof value === "number") {
3033
+ if (!Number.isFinite(value)) throw new TypeError("Canonical JSON accepts finite numbers only.");
3034
+ return JSON.stringify(value);
3035
+ }
3036
+ if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
3037
+ if (typeof value !== "object" || !value || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) {
3038
+ throw new TypeError("Canonical JSON accepts JSON objects, arrays, and primitives only.");
3039
+ }
3040
+ const entries = Object.entries(value).filter(([, item]) => item !== void 0).sort(([left], [right]) => left.localeCompare(right));
3041
+ return `{${entries.map(([key, item]) => `${JSON.stringify(key)}:${canonicalJson(item)}`).join(",")}}`;
3042
+ }
3043
+ function parseAccountableSubject(value) {
3044
+ const path = "actorEnvelope.accountableSubject";
3045
+ const subject = record(value, path);
3046
+ exactKeys(subject, ["principalType", "principalId", "displayName"], path);
3047
+ return {
3048
+ principalType: member(subject.principalType, ACCOUNTABLE_SUBJECT_TYPES, `${path}.principalType`),
3049
+ principalId: text(subject.principalId, `${path}.principalId`),
3050
+ ...subject.displayName === void 0 ? {} : { displayName: text(subject.displayName, `${path}.displayName`) }
3051
+ };
3052
+ }
3053
+ async function sha256CanonicalValue(value) {
3054
+ const bytes = new TextEncoder().encode(canonicalJson(value));
3055
+ const digest = await crypto.subtle.digest("SHA-256", bytes);
3056
+ return `sha256:${Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("")}`;
3057
+ }
3058
+ function parseIdentity(value, path) {
3059
+ const identity = record(value, path);
3060
+ exactKeys(identity, [
3061
+ "principalType",
3062
+ "principalId",
3063
+ "displayName",
3064
+ "installationId",
3065
+ "agentInstanceId",
3066
+ "browserSessionId",
3067
+ "provider",
3068
+ "model"
3069
+ ], path);
3070
+ return {
3071
+ principalType: member(identity.principalType, PRINCIPAL_TYPES, `${path}.principalType`),
3072
+ principalId: text(identity.principalId, `${path}.principalId`),
3073
+ ...optionalTextFields(identity, path, [
3074
+ "displayName",
3075
+ "installationId",
3076
+ "agentInstanceId",
3077
+ "browserSessionId",
3078
+ "provider",
3079
+ "model"
3080
+ ])
3081
+ };
3082
+ }
3083
+ function parseDelegation(value) {
3084
+ if (value === null) return null;
3085
+ const delegation = record(value, "actorEnvelope.delegation");
3086
+ exactKeys(delegation, ["taskId", "runId", "lineage"], "actorEnvelope.delegation");
3087
+ if (!Array.isArray(delegation.lineage) || delegation.lineage.length === 0 || delegation.lineage.length > 16) {
3088
+ fail("actorEnvelope.delegation.lineage", "must contain between 1 and 16 hops");
3089
+ }
3090
+ return {
3091
+ taskId: text(delegation.taskId, "actorEnvelope.delegation.taskId"),
3092
+ runId: text(delegation.runId, "actorEnvelope.delegation.runId"),
3093
+ lineage: delegation.lineage.map((value2, index) => {
3094
+ const hop = record(value2, `actorEnvelope.delegation.lineage[${index}]`);
3095
+ exactKeys(hop, ["principalType", "principalId"], `actorEnvelope.delegation.lineage[${index}]`);
3096
+ return {
3097
+ principalType: member(hop.principalType, PRINCIPAL_TYPES, `actorEnvelope.delegation.lineage[${index}].principalType`),
3098
+ principalId: text(hop.principalId, `actorEnvelope.delegation.lineage[${index}].principalId`)
3099
+ };
3100
+ })
3101
+ };
3102
+ }
3103
+ function record(value, path) {
3104
+ if (!value || typeof value !== "object" || Array.isArray(value)) fail(path, "must be an object");
3105
+ return value;
3106
+ }
3107
+ function exactKeys(value, allowed, path) {
3108
+ const unknown = Object.keys(value).filter((key) => !allowed.includes(key));
3109
+ if (unknown.length) fail(path, `contains unknown field ${unknown[0]}`);
3110
+ }
3111
+ function text(value, path) {
3112
+ if (typeof value !== "string" || value.trim() !== value || value.length === 0 || value.length > 256) {
3113
+ fail(path, "must be a non-empty trimmed string of at most 256 characters");
3114
+ }
3115
+ return value;
3116
+ }
3117
+ function timestamp(value, path) {
3118
+ const result = text(value, path);
3119
+ if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/.test(result) || Number.isNaN(Date.parse(result))) {
3120
+ fail(path, "must be an RFC 3339 UTC timestamp");
3121
+ }
3122
+ return result;
3123
+ }
3124
+ function member(value, values, path) {
3125
+ if (typeof value !== "string" || !values.has(value)) fail(path, "contains an unsupported value");
3126
+ return value;
3127
+ }
3128
+ function textArray(value, path) {
3129
+ if (!Array.isArray(value) || value.length === 0 || value.length > 16) fail(path, "must contain between 1 and 16 values");
3130
+ return value.map((item, index) => text(item, `${path}[${index}]`));
3131
+ }
3132
+ function optionalTextFields(value, path, keys) {
3133
+ return Object.fromEntries(keys.flatMap((key) => value[key] === void 0 ? [] : [[key, text(value[key], `${path}.${key}`)]]));
3134
+ }
3135
+ function fail(path, message) {
3136
+ throw new ActorEnvelopeValidationError(path, message);
3137
+ }
3138
+
2927
3139
  // src/modules/workspaces.ts
2928
3140
  var ACTIONS = {
2929
3141
  list: "app_topolo_auth.workspaces.list",
@@ -4414,6 +4626,8 @@ function createTopolo(options) {
4414
4626
  }
4415
4627
  export {
4416
4628
  ACTION_CATALOG_DIGEST_ALGORITHM,
4629
+ ACTOR_ENVELOPE_VERSION,
4630
+ ActorEnvelopeValidationError,
4417
4631
  CrmModule,
4418
4632
  DEFAULT_APP_URLS,
4419
4633
  IdentityModule,
@@ -4435,10 +4649,12 @@ export {
4435
4649
  actionContractCompleteness,
4436
4650
  applicationEntryFromCatalog,
4437
4651
  assertTopoloServiceUrlEnvironment,
4652
+ canonicalJson,
4438
4653
  canonicalTopoloErrorCode,
4439
4654
  canonicalTopoloRequestId,
4440
4655
  canonicalTopoloRequired,
4441
4656
  canonicalTopoloRetryAfter,
4657
+ canonicalizeActorEnvelope,
4442
4658
  compactActionCatalogEntry,
4443
4659
  compactActionPlan,
4444
4660
  compactActionPreparation,
@@ -4462,6 +4678,7 @@ export {
4462
4678
  friendlyAppId,
4463
4679
  isTopoloWidgetOutputSchema,
4464
4680
  listApplicationDirectory,
4681
+ parseActorEnvelope,
4465
4682
  parseTopoloActionUploadContract,
4466
4683
  preferExactActionMatches,
4467
4684
  prepareTopoloActionBase64UploadInput,
@@ -4470,6 +4687,7 @@ export {
4470
4687
  resolveApplicationDirectoryEntry,
4471
4688
  resolveCatalogServiceUrl,
4472
4689
  resolveServiceUrl,
4690
+ sha256CanonicalValue,
4473
4691
  topoloErrorHint,
4474
4692
  topoloServiceOrigins,
4475
4693
  validateTopoloActionInput,
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@topolo/sdk",
3
- "version": "0.14.4",
4
- "topoloPublishedVersion": "0.14.4",
3
+ "packageManager": "pnpm@10.17.1",
4
+ "version": "0.15.0",
5
+ "topoloPublishedVersion": "0.15.0",
5
6
  "description": "Typed client SDK for the Topolo platform. Used by TopoloCli, TopoloMCP, and third-party agents.",
6
7
  "license": "UNLICENSED",
7
8
  "author": "Topolo",
@@ -32,7 +33,7 @@
32
33
  "test": "vitest run",
33
34
  "test:watch": "vitest",
34
35
  "prepublishOnly": "npm run build && npm run verify:package",
35
- "verify:package": "node ../../tooling/verify-npm-package.mjs .",
36
+ "verify:package": "npm pack --dry-run",
36
37
  "coverage": "vitest run --coverage"
37
38
  },
38
39
  "topolo_quality": {
@@ -50,7 +51,7 @@
50
51
  "tsconfig.json",
51
52
  "vitest.config.ts"
52
53
  ],
53
- "digest": "2bb3a53e5241cde11d06fe2bd355cac5cd9141b1b5ad5f71ebc2d621c1c33fb0"
54
+ "digest": "764b584c653234937a1ba11f34a898941c62ebd8bf973db6ed0869b7f4a11951"
54
55
  }
55
56
  }
56
57
  ]
@@ -64,5 +65,9 @@
64
65
  },
65
66
  "engines": {
66
67
  "node": ">=20"
68
+ },
69
+ "repository": {
70
+ "type": "git",
71
+ "url": "git+https://github.com/Topolo-io/topolo-sdk.git"
67
72
  }
68
73
  }