@topolo/sdk 0.20.0 → 0.21.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/dist/index.cjs CHANGED
@@ -1447,7 +1447,7 @@ var TopoloClient = class _TopoloClient {
1447
1447
  timeoutMs;
1448
1448
  fetchImpl;
1449
1449
  credentialProvider;
1450
- credentialLoadInFlight = null;
1450
+ credentialLoadsInFlight = /* @__PURE__ */ new Map();
1451
1451
  refreshCredential;
1452
1452
  refreshInFlight = null;
1453
1453
  debug;
@@ -1504,7 +1504,16 @@ var TopoloClient = class _TopoloClient {
1504
1504
  `Mutating ${method} requests require { confirm: true }. This guardrail prevents agents from issuing writes without an explicit human-in-the-loop acknowledgement.`
1505
1505
  );
1506
1506
  }
1507
- await this.loadCurrentCredential();
1507
+ const actionId = requestActionId(opts.headers);
1508
+ const taskId = opts.actorEnvelope?.delegation?.taskId ?? this.actorContext?.taskId;
1509
+ let requestCredential = await this.loadCurrentCredential({
1510
+ service: normalizeLookupKey(opts.service),
1511
+ method,
1512
+ path: opts.path,
1513
+ ...actionId ? { actionId } : {},
1514
+ ...taskId ? { taskId } : {},
1515
+ ...opts.resource ? { resource: opts.resource } : {}
1516
+ });
1508
1517
  const resolvedService = opts.baseUrl ? { serviceKey: normalizeLookupKey(opts.service), baseUrl: this.validatedServiceOrigin(opts.service, opts.baseUrl) } : await this.resolveRequestService(opts.service);
1509
1518
  const baseUrl = resolvedService.baseUrl;
1510
1519
  const url = new URL(opts.path, baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`);
@@ -1561,13 +1570,13 @@ var TopoloClient = class _TopoloClient {
1561
1570
  const signal = opts.signal ? mergeSignals(opts.signal, controller.signal) : controller.signal;
1562
1571
  try {
1563
1572
  const requestHeaders = new Headers(headers);
1564
- applyAuthHeaders(requestHeaders, this.credential);
1565
- if (this.credential.kind === "dpop_access_token") {
1573
+ applyAuthHeaders(requestHeaders, requestCredential);
1574
+ if (requestCredential.kind === "dpop_access_token") {
1566
1575
  requestHeaders.set("DPoP", await createDpopProof({
1567
- accessToken: this.credential.accessToken,
1576
+ accessToken: requestCredential.accessToken,
1568
1577
  method,
1569
1578
  targetUrl: urlStr,
1570
- privateJwk: this.credential.privateJwk
1579
+ privateJwk: requestCredential.privateJwk
1571
1580
  }));
1572
1581
  }
1573
1582
  return await this.fetchImpl(urlStr, {
@@ -1603,12 +1612,13 @@ var TopoloClient = class _TopoloClient {
1603
1612
  };
1604
1613
  let res;
1605
1614
  try {
1606
- const attemptedCredential = this.credential;
1615
+ const attemptedCredential = requestCredential;
1607
1616
  res = await fetchWithReadRetry();
1608
1617
  if (res.status === 401 && attemptedCredential.kind === "access_token" && this.refreshCredential) {
1609
1618
  await res.body?.cancel().catch(() => void 0);
1610
1619
  const refreshed = await this.refreshRejectedAccessToken(attemptedCredential.accessToken);
1611
1620
  if (refreshed) {
1621
+ requestCredential = refreshed;
1612
1622
  res = await fetchWithReadRetry();
1613
1623
  }
1614
1624
  }
@@ -1698,18 +1708,23 @@ var TopoloClient = class _TopoloClient {
1698
1708
  });
1699
1709
  return parsed;
1700
1710
  }
1701
- async loadCurrentCredential() {
1702
- if (!this.credentialProvider) return;
1703
- this.credentialLoadInFlight ??= this.credentialProvider().then((credential) => {
1704
- if (!credential) {
1705
- throw new TopoloAuthError("The configured Topolo credential is no longer available.");
1706
- }
1707
- this.credential = credential;
1708
- return credential;
1709
- }).finally(() => {
1710
- this.credentialLoadInFlight = null;
1711
- });
1712
- await this.credentialLoadInFlight;
1711
+ async loadCurrentCredential(context) {
1712
+ if (!this.credentialProvider) return this.credential;
1713
+ const key = JSON.stringify(context);
1714
+ let load = this.credentialLoadsInFlight.get(key);
1715
+ if (!load) {
1716
+ load = this.credentialProvider(context).then((credential) => {
1717
+ if (!credential) {
1718
+ throw new TopoloAuthError("The configured Topolo credential is no longer available.");
1719
+ }
1720
+ this.credential = credential;
1721
+ return credential;
1722
+ }).finally(() => {
1723
+ this.credentialLoadsInFlight.delete(key);
1724
+ });
1725
+ this.credentialLoadsInFlight.set(key, load);
1726
+ }
1727
+ return load;
1713
1728
  }
1714
1729
  async refreshRejectedAccessToken(attemptedAccessToken) {
1715
1730
  if (this.credential.kind === "access_token" && this.credential.accessToken !== attemptedAccessToken) {
@@ -2039,6 +2054,14 @@ var TopoloClient = class _TopoloClient {
2039
2054
  const entry = await this.getAction(action);
2040
2055
  return this.executeResolvedAction(entry, input, options);
2041
2056
  }
2057
+ async issueExternalAgentCredential(input) {
2058
+ const actionId = "app_topolo_auth.principal_credentials.issue";
2059
+ const entry = await this.getAction(actionId);
2060
+ if (entry.actionId !== actionId) {
2061
+ throw new TopoloSdkError("unexpected_action", "External agent credential issuance resolved an unexpected action.");
2062
+ }
2063
+ return this.executeResolvedAction(entry, input, { confirm: true }, true);
2064
+ }
2042
2065
  async uploadAction(action, content, input, options) {
2043
2066
  const entry = await this.getAction(action);
2044
2067
  const contract = parseTopoloActionUploadContract(entry.agentContract?.upload);
@@ -2170,7 +2193,7 @@ var TopoloClient = class _TopoloClient {
2170
2193
  }
2171
2194
  return this.executeResolvedAction(entry, input, options);
2172
2195
  }
2173
- async executeResolvedAction(entry, input, options) {
2196
+ async executeResolvedAction(entry, input, options, preserveSensitiveResult = false) {
2174
2197
  const agentAccess = entry.agentAccess ?? (entry.destructive ? "off" : entry.readOnly && !entry.requiresConfirmation ? "auto" : "confirm");
2175
2198
  if (agentAccess === "off") {
2176
2199
  throw new TopoloPermissionError(
@@ -2228,7 +2251,7 @@ var TopoloClient = class _TopoloClient {
2228
2251
  },
2229
2252
  confirm: options.confirm === true || entry.readOnly && !entry.destructive && !entry.requiresConfirmation
2230
2253
  });
2231
- return redactActionResult(result);
2254
+ return preserveSensitiveResult ? result : redactActionResult(result);
2232
2255
  }
2233
2256
  async buildVerifiedAgentActorEnvelope(actionId, input, resource) {
2234
2257
  if (!this.actorContext) return void 0;
@@ -2704,6 +2727,12 @@ function pickString(value) {
2704
2727
  }
2705
2728
  return void 0;
2706
2729
  }
2730
+ function requestActionId(headers) {
2731
+ const value = Object.entries(headers ?? {}).find(
2732
+ ([name]) => name.toLowerCase() === TOPOLO_ACTION_ID_HEADER.toLowerCase()
2733
+ )?.[1];
2734
+ return value?.trim() || void 0;
2735
+ }
2707
2736
  function extractRequired(body) {
2708
2737
  if (body && typeof body === "object") {
2709
2738
  const maybe = body;
package/dist/index.d.cts CHANGED
@@ -176,7 +176,7 @@ interface TopoloClientOptions {
176
176
  * Long-lived hosts use this to adopt context reauthentication and claim
177
177
  * changes without waiting for the previous token to fail with a 401.
178
178
  */
179
- credentialProvider?: () => Promise<TopoloCredential | null>;
179
+ credentialProvider?: (context: TopoloCredentialRequestContext) => Promise<TopoloCredential | null>;
180
180
  /**
181
181
  * Refresh a rejected access-token credential. When supplied, the client
182
182
  * retries one 401 response with the returned credential. Concurrent 401s
@@ -191,6 +191,17 @@ interface TopoloClientOptions {
191
191
  */
192
192
  debug?: (event: TopoloDebugEvent) => void;
193
193
  }
194
+ interface TopoloCredentialRequestContext {
195
+ service: string;
196
+ method: string;
197
+ path: string;
198
+ actionId?: string;
199
+ taskId?: string;
200
+ resource?: {
201
+ resourceType: string;
202
+ resourceId: string;
203
+ };
204
+ }
194
205
  type TopoloDebugEvent = {
195
206
  phase: 'request';
196
207
  method: string;
@@ -388,6 +399,24 @@ interface TopoloActionPreparation {
388
399
  missingFields: string[];
389
400
  plan: TopoloActionPlan;
390
401
  }
402
+ interface ExternalAgentCredentialIssueInput {
403
+ orgId: string;
404
+ principalId: string;
405
+ dpopJkt: string;
406
+ displayName?: string;
407
+ expiresAt?: number | null;
408
+ }
409
+ interface ExternalAgentCredentialIssueResult {
410
+ data: {
411
+ credential: {
412
+ id: string;
413
+ clientId: string;
414
+ clientSecret: string;
415
+ [key: string]: unknown;
416
+ };
417
+ };
418
+ [key: string]: unknown;
419
+ }
391
420
  interface TopoloCatalogPage {
392
421
  nextCursor: string | null;
393
422
  hasMore: boolean;
@@ -421,7 +450,7 @@ declare class TopoloClient {
421
450
  private readonly timeoutMs;
422
451
  private readonly fetchImpl;
423
452
  private readonly credentialProvider?;
424
- private credentialLoadInFlight;
453
+ private readonly credentialLoadsInFlight;
425
454
  private readonly refreshCredential?;
426
455
  private refreshInFlight;
427
456
  private readonly debug?;
@@ -502,6 +531,7 @@ declare class TopoloClient {
502
531
  };
503
532
  actorEnvelope?: ActorEnvelope;
504
533
  }): Promise<T>;
534
+ issueExternalAgentCredential(input: ExternalAgentCredentialIssueInput): Promise<ExternalAgentCredentialIssueResult>;
505
535
  uploadAction<T = unknown>(action: string, content: Uint8Array | ArrayBuffer, input: Record<string, unknown>, options: TopoloActionUploadOptions & {
506
536
  confirm?: boolean;
507
537
  resource?: {
@@ -1706,4 +1736,4 @@ declare function createTopolo(options: TopoloClientOptions): {
1706
1736
  };
1707
1737
  type Topolo = ReturnType<typeof createTopolo>;
1708
1738
 
1709
- export { ACTION_CATALOG_DIGEST_ALGORITHM, ACTOR_AUDIT_PROJECTION_VERSION, ACTOR_ENVELOPE_VERSION, type AccountableSubject, type AccountableSubjectType, type ActionContractManifest, type ActionContractSource, type ActorAssurance, type ActorAuditEventRole, type ActorAuditProjection, 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_ACTOR_ENVELOPE_HEADER, 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, calculateDpopJkt, canonicalJson, canonicalTopoloErrorCode, canonicalTopoloRequestId, canonicalTopoloRequired, canonicalTopoloRetryAfter, canonicalizeActorEnvelope, compactActionCatalogEntry, compactActionPlan, compactActionPreparation, compactActionResult, compactActionValidation, createDpopProof, createTopolo, createTopoloAgentExecutionContext, createTopoloWidgetError, createTopoloWidgetResponse, decodeActorEnvelopeHeader, defineTopoloActionsWidget, defineTopoloActivityWidget, defineTopoloChartWidget, defineTopoloNotificationsWidget, defineTopoloStatsWidget, digestTopoloActionCatalog, encodeActorEnvelopeHeader, encodeTopoloActionBase64, enrichActionContract, extractTopoloServiceErrorCode, extractTopoloServiceErrorDetails, formatDirectoryApplicationIds, friendlyAppId, isTopoloWidgetOutputSchema, listApplicationDirectory, parseActorEnvelope, parseTopoloActionUploadContract, preferExactActionMatches, prepareTopoloActionBase64UploadInput, prepareTopoloActionUploadInput, projectActorAuditEvent, publicTopoloErrorMessage, resolveApplicationDirectoryEntry, resolveCatalogServiceUrl, resolveServiceUrl, sha256CanonicalValue, topoloErrorHint, topoloServiceOrigins, validateTopoloActionInput, validateTopoloWidgetResponse };
1739
+ export { ACTION_CATALOG_DIGEST_ALGORITHM, ACTOR_AUDIT_PROJECTION_VERSION, ACTOR_ENVELOPE_VERSION, type AccountableSubject, type AccountableSubjectType, type ActionContractManifest, type ActionContractSource, type ActorAssurance, type ActorAuditEventRole, type ActorAuditProjection, 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, type ExternalAgentCredentialIssueInput, type ExternalAgentCredentialIssueResult, 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_ACTOR_ENVELOPE_HEADER, 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 TopoloCredentialRequestContext, 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, calculateDpopJkt, canonicalJson, canonicalTopoloErrorCode, canonicalTopoloRequestId, canonicalTopoloRequired, canonicalTopoloRetryAfter, canonicalizeActorEnvelope, compactActionCatalogEntry, compactActionPlan, compactActionPreparation, compactActionResult, compactActionValidation, createDpopProof, createTopolo, createTopoloAgentExecutionContext, createTopoloWidgetError, createTopoloWidgetResponse, decodeActorEnvelopeHeader, defineTopoloActionsWidget, defineTopoloActivityWidget, defineTopoloChartWidget, defineTopoloNotificationsWidget, defineTopoloStatsWidget, digestTopoloActionCatalog, encodeActorEnvelopeHeader, encodeTopoloActionBase64, enrichActionContract, extractTopoloServiceErrorCode, extractTopoloServiceErrorDetails, formatDirectoryApplicationIds, friendlyAppId, isTopoloWidgetOutputSchema, listApplicationDirectory, parseActorEnvelope, parseTopoloActionUploadContract, preferExactActionMatches, prepareTopoloActionBase64UploadInput, prepareTopoloActionUploadInput, projectActorAuditEvent, publicTopoloErrorMessage, resolveApplicationDirectoryEntry, resolveCatalogServiceUrl, resolveServiceUrl, sha256CanonicalValue, topoloErrorHint, topoloServiceOrigins, validateTopoloActionInput, validateTopoloWidgetResponse };
package/dist/index.d.ts CHANGED
@@ -176,7 +176,7 @@ interface TopoloClientOptions {
176
176
  * Long-lived hosts use this to adopt context reauthentication and claim
177
177
  * changes without waiting for the previous token to fail with a 401.
178
178
  */
179
- credentialProvider?: () => Promise<TopoloCredential | null>;
179
+ credentialProvider?: (context: TopoloCredentialRequestContext) => Promise<TopoloCredential | null>;
180
180
  /**
181
181
  * Refresh a rejected access-token credential. When supplied, the client
182
182
  * retries one 401 response with the returned credential. Concurrent 401s
@@ -191,6 +191,17 @@ interface TopoloClientOptions {
191
191
  */
192
192
  debug?: (event: TopoloDebugEvent) => void;
193
193
  }
194
+ interface TopoloCredentialRequestContext {
195
+ service: string;
196
+ method: string;
197
+ path: string;
198
+ actionId?: string;
199
+ taskId?: string;
200
+ resource?: {
201
+ resourceType: string;
202
+ resourceId: string;
203
+ };
204
+ }
194
205
  type TopoloDebugEvent = {
195
206
  phase: 'request';
196
207
  method: string;
@@ -388,6 +399,24 @@ interface TopoloActionPreparation {
388
399
  missingFields: string[];
389
400
  plan: TopoloActionPlan;
390
401
  }
402
+ interface ExternalAgentCredentialIssueInput {
403
+ orgId: string;
404
+ principalId: string;
405
+ dpopJkt: string;
406
+ displayName?: string;
407
+ expiresAt?: number | null;
408
+ }
409
+ interface ExternalAgentCredentialIssueResult {
410
+ data: {
411
+ credential: {
412
+ id: string;
413
+ clientId: string;
414
+ clientSecret: string;
415
+ [key: string]: unknown;
416
+ };
417
+ };
418
+ [key: string]: unknown;
419
+ }
391
420
  interface TopoloCatalogPage {
392
421
  nextCursor: string | null;
393
422
  hasMore: boolean;
@@ -421,7 +450,7 @@ declare class TopoloClient {
421
450
  private readonly timeoutMs;
422
451
  private readonly fetchImpl;
423
452
  private readonly credentialProvider?;
424
- private credentialLoadInFlight;
453
+ private readonly credentialLoadsInFlight;
425
454
  private readonly refreshCredential?;
426
455
  private refreshInFlight;
427
456
  private readonly debug?;
@@ -502,6 +531,7 @@ declare class TopoloClient {
502
531
  };
503
532
  actorEnvelope?: ActorEnvelope;
504
533
  }): Promise<T>;
534
+ issueExternalAgentCredential(input: ExternalAgentCredentialIssueInput): Promise<ExternalAgentCredentialIssueResult>;
505
535
  uploadAction<T = unknown>(action: string, content: Uint8Array | ArrayBuffer, input: Record<string, unknown>, options: TopoloActionUploadOptions & {
506
536
  confirm?: boolean;
507
537
  resource?: {
@@ -1706,4 +1736,4 @@ declare function createTopolo(options: TopoloClientOptions): {
1706
1736
  };
1707
1737
  type Topolo = ReturnType<typeof createTopolo>;
1708
1738
 
1709
- export { ACTION_CATALOG_DIGEST_ALGORITHM, ACTOR_AUDIT_PROJECTION_VERSION, ACTOR_ENVELOPE_VERSION, type AccountableSubject, type AccountableSubjectType, type ActionContractManifest, type ActionContractSource, type ActorAssurance, type ActorAuditEventRole, type ActorAuditProjection, 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_ACTOR_ENVELOPE_HEADER, 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, calculateDpopJkt, canonicalJson, canonicalTopoloErrorCode, canonicalTopoloRequestId, canonicalTopoloRequired, canonicalTopoloRetryAfter, canonicalizeActorEnvelope, compactActionCatalogEntry, compactActionPlan, compactActionPreparation, compactActionResult, compactActionValidation, createDpopProof, createTopolo, createTopoloAgentExecutionContext, createTopoloWidgetError, createTopoloWidgetResponse, decodeActorEnvelopeHeader, defineTopoloActionsWidget, defineTopoloActivityWidget, defineTopoloChartWidget, defineTopoloNotificationsWidget, defineTopoloStatsWidget, digestTopoloActionCatalog, encodeActorEnvelopeHeader, encodeTopoloActionBase64, enrichActionContract, extractTopoloServiceErrorCode, extractTopoloServiceErrorDetails, formatDirectoryApplicationIds, friendlyAppId, isTopoloWidgetOutputSchema, listApplicationDirectory, parseActorEnvelope, parseTopoloActionUploadContract, preferExactActionMatches, prepareTopoloActionBase64UploadInput, prepareTopoloActionUploadInput, projectActorAuditEvent, publicTopoloErrorMessage, resolveApplicationDirectoryEntry, resolveCatalogServiceUrl, resolveServiceUrl, sha256CanonicalValue, topoloErrorHint, topoloServiceOrigins, validateTopoloActionInput, validateTopoloWidgetResponse };
1739
+ export { ACTION_CATALOG_DIGEST_ALGORITHM, ACTOR_AUDIT_PROJECTION_VERSION, ACTOR_ENVELOPE_VERSION, type AccountableSubject, type AccountableSubjectType, type ActionContractManifest, type ActionContractSource, type ActorAssurance, type ActorAuditEventRole, type ActorAuditProjection, 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, type ExternalAgentCredentialIssueInput, type ExternalAgentCredentialIssueResult, 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_ACTOR_ENVELOPE_HEADER, 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 TopoloCredentialRequestContext, 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, calculateDpopJkt, canonicalJson, canonicalTopoloErrorCode, canonicalTopoloRequestId, canonicalTopoloRequired, canonicalTopoloRetryAfter, canonicalizeActorEnvelope, compactActionCatalogEntry, compactActionPlan, compactActionPreparation, compactActionResult, compactActionValidation, createDpopProof, createTopolo, createTopoloAgentExecutionContext, createTopoloWidgetError, createTopoloWidgetResponse, decodeActorEnvelopeHeader, defineTopoloActionsWidget, defineTopoloActivityWidget, defineTopoloChartWidget, defineTopoloNotificationsWidget, defineTopoloStatsWidget, digestTopoloActionCatalog, encodeActorEnvelopeHeader, encodeTopoloActionBase64, enrichActionContract, extractTopoloServiceErrorCode, extractTopoloServiceErrorDetails, formatDirectoryApplicationIds, friendlyAppId, isTopoloWidgetOutputSchema, listApplicationDirectory, parseActorEnvelope, parseTopoloActionUploadContract, preferExactActionMatches, prepareTopoloActionBase64UploadInput, prepareTopoloActionUploadInput, projectActorAuditEvent, publicTopoloErrorMessage, resolveApplicationDirectoryEntry, resolveCatalogServiceUrl, resolveServiceUrl, sha256CanonicalValue, topoloErrorHint, topoloServiceOrigins, validateTopoloActionInput, validateTopoloWidgetResponse };
package/dist/index.js CHANGED
@@ -1348,7 +1348,7 @@ var TopoloClient = class _TopoloClient {
1348
1348
  timeoutMs;
1349
1349
  fetchImpl;
1350
1350
  credentialProvider;
1351
- credentialLoadInFlight = null;
1351
+ credentialLoadsInFlight = /* @__PURE__ */ new Map();
1352
1352
  refreshCredential;
1353
1353
  refreshInFlight = null;
1354
1354
  debug;
@@ -1405,7 +1405,16 @@ var TopoloClient = class _TopoloClient {
1405
1405
  `Mutating ${method} requests require { confirm: true }. This guardrail prevents agents from issuing writes without an explicit human-in-the-loop acknowledgement.`
1406
1406
  );
1407
1407
  }
1408
- await this.loadCurrentCredential();
1408
+ const actionId = requestActionId(opts.headers);
1409
+ const taskId = opts.actorEnvelope?.delegation?.taskId ?? this.actorContext?.taskId;
1410
+ let requestCredential = await this.loadCurrentCredential({
1411
+ service: normalizeLookupKey(opts.service),
1412
+ method,
1413
+ path: opts.path,
1414
+ ...actionId ? { actionId } : {},
1415
+ ...taskId ? { taskId } : {},
1416
+ ...opts.resource ? { resource: opts.resource } : {}
1417
+ });
1409
1418
  const resolvedService = opts.baseUrl ? { serviceKey: normalizeLookupKey(opts.service), baseUrl: this.validatedServiceOrigin(opts.service, opts.baseUrl) } : await this.resolveRequestService(opts.service);
1410
1419
  const baseUrl = resolvedService.baseUrl;
1411
1420
  const url = new URL(opts.path, baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`);
@@ -1462,13 +1471,13 @@ var TopoloClient = class _TopoloClient {
1462
1471
  const signal = opts.signal ? mergeSignals(opts.signal, controller.signal) : controller.signal;
1463
1472
  try {
1464
1473
  const requestHeaders = new Headers(headers);
1465
- applyAuthHeaders(requestHeaders, this.credential);
1466
- if (this.credential.kind === "dpop_access_token") {
1474
+ applyAuthHeaders(requestHeaders, requestCredential);
1475
+ if (requestCredential.kind === "dpop_access_token") {
1467
1476
  requestHeaders.set("DPoP", await createDpopProof({
1468
- accessToken: this.credential.accessToken,
1477
+ accessToken: requestCredential.accessToken,
1469
1478
  method,
1470
1479
  targetUrl: urlStr,
1471
- privateJwk: this.credential.privateJwk
1480
+ privateJwk: requestCredential.privateJwk
1472
1481
  }));
1473
1482
  }
1474
1483
  return await this.fetchImpl(urlStr, {
@@ -1504,12 +1513,13 @@ var TopoloClient = class _TopoloClient {
1504
1513
  };
1505
1514
  let res;
1506
1515
  try {
1507
- const attemptedCredential = this.credential;
1516
+ const attemptedCredential = requestCredential;
1508
1517
  res = await fetchWithReadRetry();
1509
1518
  if (res.status === 401 && attemptedCredential.kind === "access_token" && this.refreshCredential) {
1510
1519
  await res.body?.cancel().catch(() => void 0);
1511
1520
  const refreshed = await this.refreshRejectedAccessToken(attemptedCredential.accessToken);
1512
1521
  if (refreshed) {
1522
+ requestCredential = refreshed;
1513
1523
  res = await fetchWithReadRetry();
1514
1524
  }
1515
1525
  }
@@ -1599,18 +1609,23 @@ var TopoloClient = class _TopoloClient {
1599
1609
  });
1600
1610
  return parsed;
1601
1611
  }
1602
- async loadCurrentCredential() {
1603
- if (!this.credentialProvider) return;
1604
- this.credentialLoadInFlight ??= this.credentialProvider().then((credential) => {
1605
- if (!credential) {
1606
- throw new TopoloAuthError("The configured Topolo credential is no longer available.");
1607
- }
1608
- this.credential = credential;
1609
- return credential;
1610
- }).finally(() => {
1611
- this.credentialLoadInFlight = null;
1612
- });
1613
- await this.credentialLoadInFlight;
1612
+ async loadCurrentCredential(context) {
1613
+ if (!this.credentialProvider) return this.credential;
1614
+ const key = JSON.stringify(context);
1615
+ let load = this.credentialLoadsInFlight.get(key);
1616
+ if (!load) {
1617
+ load = this.credentialProvider(context).then((credential) => {
1618
+ if (!credential) {
1619
+ throw new TopoloAuthError("The configured Topolo credential is no longer available.");
1620
+ }
1621
+ this.credential = credential;
1622
+ return credential;
1623
+ }).finally(() => {
1624
+ this.credentialLoadsInFlight.delete(key);
1625
+ });
1626
+ this.credentialLoadsInFlight.set(key, load);
1627
+ }
1628
+ return load;
1614
1629
  }
1615
1630
  async refreshRejectedAccessToken(attemptedAccessToken) {
1616
1631
  if (this.credential.kind === "access_token" && this.credential.accessToken !== attemptedAccessToken) {
@@ -1940,6 +1955,14 @@ var TopoloClient = class _TopoloClient {
1940
1955
  const entry = await this.getAction(action);
1941
1956
  return this.executeResolvedAction(entry, input, options);
1942
1957
  }
1958
+ async issueExternalAgentCredential(input) {
1959
+ const actionId = "app_topolo_auth.principal_credentials.issue";
1960
+ const entry = await this.getAction(actionId);
1961
+ if (entry.actionId !== actionId) {
1962
+ throw new TopoloSdkError("unexpected_action", "External agent credential issuance resolved an unexpected action.");
1963
+ }
1964
+ return this.executeResolvedAction(entry, input, { confirm: true }, true);
1965
+ }
1943
1966
  async uploadAction(action, content, input, options) {
1944
1967
  const entry = await this.getAction(action);
1945
1968
  const contract = parseTopoloActionUploadContract(entry.agentContract?.upload);
@@ -2071,7 +2094,7 @@ var TopoloClient = class _TopoloClient {
2071
2094
  }
2072
2095
  return this.executeResolvedAction(entry, input, options);
2073
2096
  }
2074
- async executeResolvedAction(entry, input, options) {
2097
+ async executeResolvedAction(entry, input, options, preserveSensitiveResult = false) {
2075
2098
  const agentAccess = entry.agentAccess ?? (entry.destructive ? "off" : entry.readOnly && !entry.requiresConfirmation ? "auto" : "confirm");
2076
2099
  if (agentAccess === "off") {
2077
2100
  throw new TopoloPermissionError(
@@ -2129,7 +2152,7 @@ var TopoloClient = class _TopoloClient {
2129
2152
  },
2130
2153
  confirm: options.confirm === true || entry.readOnly && !entry.destructive && !entry.requiresConfirmation
2131
2154
  });
2132
- return redactActionResult(result);
2155
+ return preserveSensitiveResult ? result : redactActionResult(result);
2133
2156
  }
2134
2157
  async buildVerifiedAgentActorEnvelope(actionId, input, resource) {
2135
2158
  if (!this.actorContext) return void 0;
@@ -2605,6 +2628,12 @@ function pickString(value) {
2605
2628
  }
2606
2629
  return void 0;
2607
2630
  }
2631
+ function requestActionId(headers) {
2632
+ const value = Object.entries(headers ?? {}).find(
2633
+ ([name]) => name.toLowerCase() === TOPOLO_ACTION_ID_HEADER.toLowerCase()
2634
+ )?.[1];
2635
+ return value?.trim() || void 0;
2636
+ }
2608
2637
  function extractRequired(body) {
2609
2638
  if (body && typeof body === "object") {
2610
2639
  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.20.0",
5
- "topoloPublishedVersion": "0.20.0",
4
+ "version": "0.21.0",
5
+ "topoloPublishedVersion": "0.21.0",
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",