@topolo/sdk 0.16.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/dist/index.cjs +75 -4
- package/dist/index.d.cts +17 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +75 -4
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1381,6 +1381,7 @@ var NEGATIVE_CACHE_TTL_MS = 60 * 1e3;
|
|
|
1381
1381
|
var TopoloClient = class _TopoloClient {
|
|
1382
1382
|
credential;
|
|
1383
1383
|
agent;
|
|
1384
|
+
actorContext;
|
|
1384
1385
|
serviceUrls;
|
|
1385
1386
|
environment;
|
|
1386
1387
|
appIds;
|
|
@@ -1411,6 +1412,11 @@ var TopoloClient = class _TopoloClient {
|
|
|
1411
1412
|
if (!options.agent?.clientName) throw new TopoloAuthError("agent.clientName is required");
|
|
1412
1413
|
this.credential = options.credential;
|
|
1413
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;
|
|
1414
1420
|
this.environment = options.environment;
|
|
1415
1421
|
this.serviceUrls = options.environment ? topoloServiceOrigins(options.serviceUrls, options.environment) : options.serviceUrls;
|
|
1416
1422
|
this.appIds = options.appIds;
|
|
@@ -2126,8 +2132,9 @@ var TopoloClient = class _TopoloClient {
|
|
|
2126
2132
|
);
|
|
2127
2133
|
}
|
|
2128
2134
|
const mapped = mapActionInput(entry, input);
|
|
2129
|
-
|
|
2130
|
-
|
|
2135
|
+
const resolvedActorEnvelope = options.actorEnvelope ?? await this.buildVerifiedAgentActorEnvelope(entry.actionId, input, options.resource);
|
|
2136
|
+
if (resolvedActorEnvelope) {
|
|
2137
|
+
const actorEnvelope = parseActorEnvelope(resolvedActorEnvelope);
|
|
2131
2138
|
if (actorEnvelope.action.actionId !== entry.actionId) {
|
|
2132
2139
|
throw new TopoloSdkError("actor_envelope_action_mismatch", "Actor envelope actionId does not match the executed action.");
|
|
2133
2140
|
}
|
|
@@ -2148,7 +2155,7 @@ var TopoloClient = class _TopoloClient {
|
|
|
2148
2155
|
...mapped.query ? { query: mapped.query } : {},
|
|
2149
2156
|
...mapped.body !== void 0 ? { body: mapped.body } : {},
|
|
2150
2157
|
...options.resource ? { resource: options.resource } : {},
|
|
2151
|
-
...
|
|
2158
|
+
...resolvedActorEnvelope ? { actorEnvelope: resolvedActorEnvelope } : {},
|
|
2152
2159
|
headers: {
|
|
2153
2160
|
[TOPOLO_ACTION_ID_HEADER]: entry.actionId,
|
|
2154
2161
|
[TOPOLO_ACTION_NAME_HEADER]: entry.name
|
|
@@ -2157,6 +2164,56 @@ var TopoloClient = class _TopoloClient {
|
|
|
2157
2164
|
});
|
|
2158
2165
|
return redactActionResult(result);
|
|
2159
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
|
+
}
|
|
2160
2217
|
/**
|
|
2161
2218
|
* Introspect the current credential. Returns the caller's resolved identity,
|
|
2162
2219
|
* organization, and permission set. Used by CLI `whoami` and by MCP to gate
|
|
@@ -2184,7 +2241,18 @@ var TopoloClient = class _TopoloClient {
|
|
|
2184
2241
|
email: user.email,
|
|
2185
2242
|
name: user.name ?? null,
|
|
2186
2243
|
role: user.role ?? (kind === "api_key" ? "service" : "member"),
|
|
2187
|
-
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
|
+
} : {}
|
|
2188
2256
|
},
|
|
2189
2257
|
organization: organization ? {
|
|
2190
2258
|
id: organization.id,
|
|
@@ -2549,6 +2617,9 @@ function normalizeCredentialAuthorizationMode(value, kind) {
|
|
|
2549
2617
|
if (value === "context_rbac" || value === "oauth_scopes" || value === "session_rbac") return value;
|
|
2550
2618
|
return "unknown";
|
|
2551
2619
|
}
|
|
2620
|
+
function normalizeAgentPrincipalType(value) {
|
|
2621
|
+
return value === "agent_employee" || value === "external_agent" ? value : null;
|
|
2622
|
+
}
|
|
2552
2623
|
function describeError(body, fallback) {
|
|
2553
2624
|
if (body && typeof body === "object") {
|
|
2554
2625
|
const maybe = body;
|
package/dist/index.d.cts
CHANGED
|
@@ -146,6 +146,12 @@ declare function encodeTopoloActionBase64(bytes: Uint8Array): string;
|
|
|
146
146
|
interface TopoloClientOptions {
|
|
147
147
|
credential: TopoloCredential;
|
|
148
148
|
agent: AgentIdentity;
|
|
149
|
+
/** Host surface used to attribute actions performed with verified agent credentials. */
|
|
150
|
+
actorContext?: {
|
|
151
|
+
channel: ActorChannel;
|
|
152
|
+
taskId?: string;
|
|
153
|
+
runId?: string;
|
|
154
|
+
};
|
|
149
155
|
/** Per-service URL overrides. Useful for staging/dev. */
|
|
150
156
|
serviceUrls?: Record<string, string>;
|
|
151
157
|
/** Explicit environment used to reject cross-environment service and action origins. */
|
|
@@ -403,6 +409,7 @@ interface TopoloCatalogSearchOptions {
|
|
|
403
409
|
declare class TopoloClient {
|
|
404
410
|
private credential;
|
|
405
411
|
private readonly agent;
|
|
412
|
+
private readonly actorContext?;
|
|
406
413
|
private readonly serviceUrls?;
|
|
407
414
|
private readonly environment?;
|
|
408
415
|
private readonly appIds?;
|
|
@@ -534,6 +541,7 @@ declare class TopoloClient {
|
|
|
534
541
|
actorEnvelope?: ActorEnvelope;
|
|
535
542
|
}): Promise<T>;
|
|
536
543
|
private executeResolvedAction;
|
|
544
|
+
private buildVerifiedAgentActorEnvelope;
|
|
537
545
|
/**
|
|
538
546
|
* Introspect the current credential. Returns the caller's resolved identity,
|
|
539
547
|
* organization, and permission set. Used by CLI `whoami` and by MCP to gate
|
|
@@ -554,6 +562,15 @@ interface CredentialIntrospection {
|
|
|
554
562
|
name: string | null;
|
|
555
563
|
role: string;
|
|
556
564
|
permissions: string[];
|
|
565
|
+
principalId?: string | null;
|
|
566
|
+
principalType?: 'agent_employee' | 'external_agent' | null;
|
|
567
|
+
accountableUserId?: string | null;
|
|
568
|
+
agentInstanceId?: string | null;
|
|
569
|
+
installationId?: string | null;
|
|
570
|
+
provider?: string | null;
|
|
571
|
+
model?: string | null;
|
|
572
|
+
serviceScopes?: string[];
|
|
573
|
+
policyRef?: string | null;
|
|
557
574
|
};
|
|
558
575
|
organization: {
|
|
559
576
|
id: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -146,6 +146,12 @@ declare function encodeTopoloActionBase64(bytes: Uint8Array): string;
|
|
|
146
146
|
interface TopoloClientOptions {
|
|
147
147
|
credential: TopoloCredential;
|
|
148
148
|
agent: AgentIdentity;
|
|
149
|
+
/** Host surface used to attribute actions performed with verified agent credentials. */
|
|
150
|
+
actorContext?: {
|
|
151
|
+
channel: ActorChannel;
|
|
152
|
+
taskId?: string;
|
|
153
|
+
runId?: string;
|
|
154
|
+
};
|
|
149
155
|
/** Per-service URL overrides. Useful for staging/dev. */
|
|
150
156
|
serviceUrls?: Record<string, string>;
|
|
151
157
|
/** Explicit environment used to reject cross-environment service and action origins. */
|
|
@@ -403,6 +409,7 @@ interface TopoloCatalogSearchOptions {
|
|
|
403
409
|
declare class TopoloClient {
|
|
404
410
|
private credential;
|
|
405
411
|
private readonly agent;
|
|
412
|
+
private readonly actorContext?;
|
|
406
413
|
private readonly serviceUrls?;
|
|
407
414
|
private readonly environment?;
|
|
408
415
|
private readonly appIds?;
|
|
@@ -534,6 +541,7 @@ declare class TopoloClient {
|
|
|
534
541
|
actorEnvelope?: ActorEnvelope;
|
|
535
542
|
}): Promise<T>;
|
|
536
543
|
private executeResolvedAction;
|
|
544
|
+
private buildVerifiedAgentActorEnvelope;
|
|
537
545
|
/**
|
|
538
546
|
* Introspect the current credential. Returns the caller's resolved identity,
|
|
539
547
|
* organization, and permission set. Used by CLI `whoami` and by MCP to gate
|
|
@@ -554,6 +562,15 @@ interface CredentialIntrospection {
|
|
|
554
562
|
name: string | null;
|
|
555
563
|
role: string;
|
|
556
564
|
permissions: string[];
|
|
565
|
+
principalId?: string | null;
|
|
566
|
+
principalType?: 'agent_employee' | 'external_agent' | null;
|
|
567
|
+
accountableUserId?: string | null;
|
|
568
|
+
agentInstanceId?: string | null;
|
|
569
|
+
installationId?: string | null;
|
|
570
|
+
provider?: string | null;
|
|
571
|
+
model?: string | null;
|
|
572
|
+
serviceScopes?: string[];
|
|
573
|
+
policyRef?: string | null;
|
|
557
574
|
};
|
|
558
575
|
organization: {
|
|
559
576
|
id: string;
|
package/dist/index.js
CHANGED
|
@@ -1286,6 +1286,7 @@ var NEGATIVE_CACHE_TTL_MS = 60 * 1e3;
|
|
|
1286
1286
|
var TopoloClient = class _TopoloClient {
|
|
1287
1287
|
credential;
|
|
1288
1288
|
agent;
|
|
1289
|
+
actorContext;
|
|
1289
1290
|
serviceUrls;
|
|
1290
1291
|
environment;
|
|
1291
1292
|
appIds;
|
|
@@ -1316,6 +1317,11 @@ var TopoloClient = class _TopoloClient {
|
|
|
1316
1317
|
if (!options.agent?.clientName) throw new TopoloAuthError("agent.clientName is required");
|
|
1317
1318
|
this.credential = options.credential;
|
|
1318
1319
|
this.agent = options.agent;
|
|
1320
|
+
this.actorContext = options.actorContext ? {
|
|
1321
|
+
channel: options.actorContext.channel,
|
|
1322
|
+
taskId: options.actorContext.taskId ?? `task_${generateRequestId()}`,
|
|
1323
|
+
runId: options.actorContext.runId ?? `run_${generateRequestId()}`
|
|
1324
|
+
} : void 0;
|
|
1319
1325
|
this.environment = options.environment;
|
|
1320
1326
|
this.serviceUrls = options.environment ? topoloServiceOrigins(options.serviceUrls, options.environment) : options.serviceUrls;
|
|
1321
1327
|
this.appIds = options.appIds;
|
|
@@ -2031,8 +2037,9 @@ var TopoloClient = class _TopoloClient {
|
|
|
2031
2037
|
);
|
|
2032
2038
|
}
|
|
2033
2039
|
const mapped = mapActionInput(entry, input);
|
|
2034
|
-
|
|
2035
|
-
|
|
2040
|
+
const resolvedActorEnvelope = options.actorEnvelope ?? await this.buildVerifiedAgentActorEnvelope(entry.actionId, input, options.resource);
|
|
2041
|
+
if (resolvedActorEnvelope) {
|
|
2042
|
+
const actorEnvelope = parseActorEnvelope(resolvedActorEnvelope);
|
|
2036
2043
|
if (actorEnvelope.action.actionId !== entry.actionId) {
|
|
2037
2044
|
throw new TopoloSdkError("actor_envelope_action_mismatch", "Actor envelope actionId does not match the executed action.");
|
|
2038
2045
|
}
|
|
@@ -2053,7 +2060,7 @@ var TopoloClient = class _TopoloClient {
|
|
|
2053
2060
|
...mapped.query ? { query: mapped.query } : {},
|
|
2054
2061
|
...mapped.body !== void 0 ? { body: mapped.body } : {},
|
|
2055
2062
|
...options.resource ? { resource: options.resource } : {},
|
|
2056
|
-
...
|
|
2063
|
+
...resolvedActorEnvelope ? { actorEnvelope: resolvedActorEnvelope } : {},
|
|
2057
2064
|
headers: {
|
|
2058
2065
|
[TOPOLO_ACTION_ID_HEADER]: entry.actionId,
|
|
2059
2066
|
[TOPOLO_ACTION_NAME_HEADER]: entry.name
|
|
@@ -2062,6 +2069,56 @@ var TopoloClient = class _TopoloClient {
|
|
|
2062
2069
|
});
|
|
2063
2070
|
return redactActionResult(result);
|
|
2064
2071
|
}
|
|
2072
|
+
async buildVerifiedAgentActorEnvelope(actionId, input, resource) {
|
|
2073
|
+
if (!this.actorContext) return void 0;
|
|
2074
|
+
const identity = await this.introspect();
|
|
2075
|
+
const principalType = identity.user.principalType;
|
|
2076
|
+
if (principalType !== "agent_employee" && principalType !== "external_agent") return void 0;
|
|
2077
|
+
if (!identity.organization || !identity.user.accountableUserId || !identity.user.principalId) {
|
|
2078
|
+
throw new TopoloSdkError(
|
|
2079
|
+
"incomplete_agent_identity",
|
|
2080
|
+
"Verified agent credentials must resolve an organization, accountable user, and principal id."
|
|
2081
|
+
);
|
|
2082
|
+
}
|
|
2083
|
+
const performer = principalType === "external_agent" ? {
|
|
2084
|
+
principalType: "external_agent",
|
|
2085
|
+
principalId: identity.user.principalId,
|
|
2086
|
+
installationId: identity.user.installationId ?? void 0,
|
|
2087
|
+
provider: identity.user.provider ?? void 0,
|
|
2088
|
+
model: identity.user.model ?? void 0
|
|
2089
|
+
} : {
|
|
2090
|
+
principalType: "managed_agent",
|
|
2091
|
+
principalId: identity.user.principalId,
|
|
2092
|
+
agentInstanceId: identity.user.agentInstanceId ?? void 0,
|
|
2093
|
+
model: identity.user.model ?? void 0
|
|
2094
|
+
};
|
|
2095
|
+
if (performer.principalType === "external_agent" && (!performer.installationId || !performer.provider) || performer.principalType === "managed_agent" && !performer.agentInstanceId) {
|
|
2096
|
+
throw new TopoloSdkError(
|
|
2097
|
+
"incomplete_agent_identity",
|
|
2098
|
+
"Verified agent credentials are missing the performer identity required for provenance."
|
|
2099
|
+
);
|
|
2100
|
+
}
|
|
2101
|
+
return parseActorEnvelope({
|
|
2102
|
+
schemaVersion: 1,
|
|
2103
|
+
organizationId: identity.organization.id,
|
|
2104
|
+
accountableSubject: { principalType: "human", principalId: identity.user.accountableUserId },
|
|
2105
|
+
performer,
|
|
2106
|
+
delegation: {
|
|
2107
|
+
taskId: this.actorContext.taskId,
|
|
2108
|
+
runId: this.actorContext.runId,
|
|
2109
|
+
lineage: [{ principalType: performer.principalType, principalId: performer.principalId }]
|
|
2110
|
+
},
|
|
2111
|
+
channel: this.actorContext.channel,
|
|
2112
|
+
assurance: { level: "workload_identity", methods: ["client_credentials"] },
|
|
2113
|
+
action: {
|
|
2114
|
+
requestId: generateRequestId(),
|
|
2115
|
+
actionId,
|
|
2116
|
+
...resource ? resource : {},
|
|
2117
|
+
inputHash: await sha256CanonicalValue(input)
|
|
2118
|
+
},
|
|
2119
|
+
issuedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2120
|
+
});
|
|
2121
|
+
}
|
|
2065
2122
|
/**
|
|
2066
2123
|
* Introspect the current credential. Returns the caller's resolved identity,
|
|
2067
2124
|
* organization, and permission set. Used by CLI `whoami` and by MCP to gate
|
|
@@ -2089,7 +2146,18 @@ var TopoloClient = class _TopoloClient {
|
|
|
2089
2146
|
email: user.email,
|
|
2090
2147
|
name: user.name ?? null,
|
|
2091
2148
|
role: user.role ?? (kind === "api_key" ? "service" : "member"),
|
|
2092
|
-
permissions: payload.permissions ?? user.permissions ?? []
|
|
2149
|
+
permissions: payload.permissions ?? user.permissions ?? [],
|
|
2150
|
+
...normalizeAgentPrincipalType(user.principalType) ? {
|
|
2151
|
+
principalId: readOptionalString(user.principalId),
|
|
2152
|
+
principalType: normalizeAgentPrincipalType(user.principalType),
|
|
2153
|
+
accountableUserId: readOptionalString(user.accountableUserId),
|
|
2154
|
+
agentInstanceId: readOptionalString(user.agentInstanceId),
|
|
2155
|
+
installationId: readOptionalString(user.installationId),
|
|
2156
|
+
provider: readOptionalString(user.provider),
|
|
2157
|
+
model: readOptionalString(user.model),
|
|
2158
|
+
serviceScopes: stringArray(user.serviceScopes),
|
|
2159
|
+
policyRef: readOptionalString(user.policyRef)
|
|
2160
|
+
} : {}
|
|
2093
2161
|
},
|
|
2094
2162
|
organization: organization ? {
|
|
2095
2163
|
id: organization.id,
|
|
@@ -2454,6 +2522,9 @@ function normalizeCredentialAuthorizationMode(value, kind) {
|
|
|
2454
2522
|
if (value === "context_rbac" || value === "oauth_scopes" || value === "session_rbac") return value;
|
|
2455
2523
|
return "unknown";
|
|
2456
2524
|
}
|
|
2525
|
+
function normalizeAgentPrincipalType(value) {
|
|
2526
|
+
return value === "agent_employee" || value === "external_agent" ? value : null;
|
|
2527
|
+
}
|
|
2457
2528
|
function describeError(body, fallback) {
|
|
2458
2529
|
if (body && typeof body === "object") {
|
|
2459
2530
|
const maybe = body;
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topolo/sdk",
|
|
3
3
|
"packageManager": "pnpm@10.17.1",
|
|
4
|
-
"version": "0.
|
|
5
|
-
"topoloPublishedVersion": "0.
|
|
4
|
+
"version": "0.17.1",
|
|
5
|
+
"topoloPublishedVersion": "0.17.1",
|
|
6
6
|
"description": "Typed client SDK for the Topolo platform. Used by TopoloCli, TopoloMCP, and third-party agents.",
|
|
7
7
|
"license": "UNLICENSED",
|
|
8
8
|
"author": "Topolo",
|