@topolo/sdk 0.11.8 → 0.11.10

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
@@ -1818,7 +1818,7 @@ var TopoloClient = class _TopoloClient {
1818
1818
  }
1819
1819
  const mapped = mapActionInput(entry, input);
1820
1820
  const service = entry.appSlug || entry.appId;
1821
- return this.request({
1821
+ const result = await this.request({
1822
1822
  service,
1823
1823
  ...entry.apiBaseUrl ? { baseUrl: entry.apiBaseUrl } : {},
1824
1824
  method: entry.method,
@@ -1832,6 +1832,7 @@ var TopoloClient = class _TopoloClient {
1832
1832
  },
1833
1833
  confirm: options.confirm === true || entry.readOnly && !entry.destructive && !entry.requiresConfirmation
1834
1834
  });
1835
+ return redactActionResult(result);
1835
1836
  }
1836
1837
  /**
1837
1838
  * Introspect the current credential. Returns the caller's resolved identity,
@@ -1955,6 +1956,18 @@ function readOptionalString(value) {
1955
1956
  function isRecord3(value) {
1956
1957
  return typeof value === "object" && value !== null && !Array.isArray(value);
1957
1958
  }
1959
+ function redactActionResult(value) {
1960
+ if (Array.isArray(value)) return value.map(redactActionResult);
1961
+ if (!isRecord3(value)) return value;
1962
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [
1963
+ key,
1964
+ isSensitiveActionResultKey(key) ? "[REDACTED]" : redactActionResult(item)
1965
+ ]));
1966
+ }
1967
+ function isSensitiveActionResultKey(key) {
1968
+ const normalized = key.toLowerCase().replace(/[^a-z0-9]/g, "");
1969
+ return ["authorization", "cookie", "setcookie", "proxyauthorization", "capability"].includes(normalized) || /(token|secret|password|privatekey|apikey)$/.test(normalized);
1970
+ }
1958
1971
  function resolveConfiguredServiceUrl(slug, serviceUrls) {
1959
1972
  for (const serviceKey of serviceKeyCandidates2(slug)) {
1960
1973
  const configured = serviceUrls?.[serviceKey];
package/dist/index.js CHANGED
@@ -1735,7 +1735,7 @@ var TopoloClient = class _TopoloClient {
1735
1735
  }
1736
1736
  const mapped = mapActionInput(entry, input);
1737
1737
  const service = entry.appSlug || entry.appId;
1738
- return this.request({
1738
+ const result = await this.request({
1739
1739
  service,
1740
1740
  ...entry.apiBaseUrl ? { baseUrl: entry.apiBaseUrl } : {},
1741
1741
  method: entry.method,
@@ -1749,6 +1749,7 @@ var TopoloClient = class _TopoloClient {
1749
1749
  },
1750
1750
  confirm: options.confirm === true || entry.readOnly && !entry.destructive && !entry.requiresConfirmation
1751
1751
  });
1752
+ return redactActionResult(result);
1752
1753
  }
1753
1754
  /**
1754
1755
  * Introspect the current credential. Returns the caller's resolved identity,
@@ -1872,6 +1873,18 @@ function readOptionalString(value) {
1872
1873
  function isRecord3(value) {
1873
1874
  return typeof value === "object" && value !== null && !Array.isArray(value);
1874
1875
  }
1876
+ function redactActionResult(value) {
1877
+ if (Array.isArray(value)) return value.map(redactActionResult);
1878
+ if (!isRecord3(value)) return value;
1879
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [
1880
+ key,
1881
+ isSensitiveActionResultKey(key) ? "[REDACTED]" : redactActionResult(item)
1882
+ ]));
1883
+ }
1884
+ function isSensitiveActionResultKey(key) {
1885
+ const normalized = key.toLowerCase().replace(/[^a-z0-9]/g, "");
1886
+ return ["authorization", "cookie", "setcookie", "proxyauthorization", "capability"].includes(normalized) || /(token|secret|password|privatekey|apikey)$/.test(normalized);
1887
+ }
1875
1888
  function resolveConfiguredServiceUrl(slug, serviceUrls) {
1876
1889
  for (const serviceKey of serviceKeyCandidates2(slug)) {
1877
1890
  const configured = serviceUrls?.[serviceKey];
@@ -612,52 +612,58 @@ async function refreshCredentialIfNeeded(environment = selectedEnvironment(), op
612
612
  if (process.env[`${prefix}_API_KEY`] || process.env[`${prefix}_ACCESS_TOKEN`] || environment === "production" && process.env.TOPOLO_API_KEY || environment === "production" && process.env.TOPOLO_ACCESS_TOKEN) {
613
613
  return resolveCredential(environment);
614
614
  }
615
- const config = await readConfig();
616
- const profile = profileForEnvironment(config, environment);
617
- const cred = profile.credential;
618
- if (!cred || cred.kind !== "access_token") return cred ?? null;
619
- if (!cred.refreshToken || !profile.oauthClientId) return cred;
620
- const now = Math.floor(Date.now() / 1e3);
621
- if (!options.force && cred.expiresAt && cred.expiresAt - REFRESH_SKEW_SECONDS > now) return cred;
622
- const serviceUrls = resolveServiceUrls(profile.serviceUrls, environment);
623
- if (environment === "local" && !serviceUrls?.auth) {
624
- throw new TopoloSdkError(
625
- "environment_service_url_required",
626
- "Local Topolo credential refresh requires an explicit local Auth service origin."
627
- );
628
- }
629
- try {
630
- const oauth = new TopoloOAuth({
631
- serviceUrls
632
- });
633
- const tokens = await oauth.refreshToken({
634
- clientId: profile.oauthClientId,
635
- refreshToken: cred.refreshToken
636
- });
637
- const refreshed = {
638
- kind: "access_token",
639
- accessToken: tokens.access_token,
640
- ...tokens.refresh_token ? { refreshToken: tokens.refresh_token } : { refreshToken: cred.refreshToken },
641
- expiresAt: Math.floor(Date.now() / 1e3) + tokens.expires_in
642
- };
643
- const activeContext = profile.activeContext;
644
- const activeEntry = activeContext ? profile.contexts?.[activeContext] : void 0;
645
- const updated = activeContext && activeEntry ? writeProfileConfig(config, environment, {
646
- credential: refreshed,
647
- contexts: {
648
- ...profile.contexts ?? {},
649
- [activeContext]: {
650
- ...activeEntry,
651
- credential: refreshed,
652
- oauthClientId: activeEntry.oauthClientId ?? profile.oauthClientId
615
+ const observed = profileForEnvironment(await readConfig(), environment).credential;
616
+ return withConfigWriteLock(async () => {
617
+ const config = await readConfig();
618
+ const profile = profileForEnvironment(config, environment);
619
+ const cred = profile.credential;
620
+ if (!cred || cred.kind !== "access_token") return cred ?? null;
621
+ if (!cred.refreshToken || !profile.oauthClientId) return cred;
622
+ if (options.force && observed?.kind === "access_token" && observed.accessToken !== cred.accessToken) {
623
+ return cred;
624
+ }
625
+ const now = Math.floor(Date.now() / 1e3);
626
+ if (!options.force && cred.expiresAt && cred.expiresAt - REFRESH_SKEW_SECONDS > now) return cred;
627
+ const serviceUrls = resolveServiceUrls(profile.serviceUrls, environment);
628
+ if (environment === "local" && !serviceUrls?.auth) {
629
+ throw new TopoloSdkError(
630
+ "environment_service_url_required",
631
+ "Local Topolo credential refresh requires an explicit local Auth service origin."
632
+ );
633
+ }
634
+ try {
635
+ const oauth = new TopoloOAuth({
636
+ serviceUrls
637
+ });
638
+ const tokens = await oauth.refreshToken({
639
+ clientId: profile.oauthClientId,
640
+ refreshToken: cred.refreshToken
641
+ });
642
+ const refreshed = {
643
+ kind: "access_token",
644
+ accessToken: tokens.access_token,
645
+ ...tokens.refresh_token ? { refreshToken: tokens.refresh_token } : { refreshToken: cred.refreshToken },
646
+ expiresAt: Math.floor(Date.now() / 1e3) + tokens.expires_in
647
+ };
648
+ const activeContext = profile.activeContext;
649
+ const activeEntry = activeContext ? profile.contexts?.[activeContext] : void 0;
650
+ const updated = activeContext && activeEntry ? writeProfileConfig(config, environment, {
651
+ credential: refreshed,
652
+ contexts: {
653
+ ...profile.contexts ?? {},
654
+ [activeContext]: {
655
+ ...activeEntry,
656
+ credential: refreshed,
657
+ oauthClientId: activeEntry.oauthClientId ?? profile.oauthClientId
658
+ }
653
659
  }
654
- }
655
- }) : environment === "production" && !config.profiles?.production ? { ...config, credential: refreshed } : writeProfileConfig(config, environment, { credential: refreshed });
656
- await writeConfig(updated);
657
- return refreshed;
658
- } catch {
659
- return cred;
660
- }
660
+ }) : environment === "production" && !config.profiles?.production ? { ...config, credential: refreshed } : writeProfileConfig(config, environment, { credential: refreshed });
661
+ await writeConfig(updated);
662
+ return refreshed;
663
+ } catch {
664
+ return cred;
665
+ }
666
+ });
661
667
  }
662
668
  async function refreshContextCredentialIfNeeded(environment, key, options = {}) {
663
669
  return withConfigWriteLock(async () => {
@@ -565,52 +565,58 @@ async function refreshCredentialIfNeeded(environment = selectedEnvironment(), op
565
565
  if (process.env[`${prefix}_API_KEY`] || process.env[`${prefix}_ACCESS_TOKEN`] || environment === "production" && process.env.TOPOLO_API_KEY || environment === "production" && process.env.TOPOLO_ACCESS_TOKEN) {
566
566
  return resolveCredential(environment);
567
567
  }
568
- const config = await readConfig();
569
- const profile = profileForEnvironment(config, environment);
570
- const cred = profile.credential;
571
- if (!cred || cred.kind !== "access_token") return cred ?? null;
572
- if (!cred.refreshToken || !profile.oauthClientId) return cred;
573
- const now = Math.floor(Date.now() / 1e3);
574
- if (!options.force && cred.expiresAt && cred.expiresAt - REFRESH_SKEW_SECONDS > now) return cred;
575
- const serviceUrls = resolveServiceUrls(profile.serviceUrls, environment);
576
- if (environment === "local" && !serviceUrls?.auth) {
577
- throw new TopoloSdkError(
578
- "environment_service_url_required",
579
- "Local Topolo credential refresh requires an explicit local Auth service origin."
580
- );
581
- }
582
- try {
583
- const oauth = new TopoloOAuth({
584
- serviceUrls
585
- });
586
- const tokens = await oauth.refreshToken({
587
- clientId: profile.oauthClientId,
588
- refreshToken: cred.refreshToken
589
- });
590
- const refreshed = {
591
- kind: "access_token",
592
- accessToken: tokens.access_token,
593
- ...tokens.refresh_token ? { refreshToken: tokens.refresh_token } : { refreshToken: cred.refreshToken },
594
- expiresAt: Math.floor(Date.now() / 1e3) + tokens.expires_in
595
- };
596
- const activeContext = profile.activeContext;
597
- const activeEntry = activeContext ? profile.contexts?.[activeContext] : void 0;
598
- const updated = activeContext && activeEntry ? writeProfileConfig(config, environment, {
599
- credential: refreshed,
600
- contexts: {
601
- ...profile.contexts ?? {},
602
- [activeContext]: {
603
- ...activeEntry,
604
- credential: refreshed,
605
- oauthClientId: activeEntry.oauthClientId ?? profile.oauthClientId
568
+ const observed = profileForEnvironment(await readConfig(), environment).credential;
569
+ return withConfigWriteLock(async () => {
570
+ const config = await readConfig();
571
+ const profile = profileForEnvironment(config, environment);
572
+ const cred = profile.credential;
573
+ if (!cred || cred.kind !== "access_token") return cred ?? null;
574
+ if (!cred.refreshToken || !profile.oauthClientId) return cred;
575
+ if (options.force && observed?.kind === "access_token" && observed.accessToken !== cred.accessToken) {
576
+ return cred;
577
+ }
578
+ const now = Math.floor(Date.now() / 1e3);
579
+ if (!options.force && cred.expiresAt && cred.expiresAt - REFRESH_SKEW_SECONDS > now) return cred;
580
+ const serviceUrls = resolveServiceUrls(profile.serviceUrls, environment);
581
+ if (environment === "local" && !serviceUrls?.auth) {
582
+ throw new TopoloSdkError(
583
+ "environment_service_url_required",
584
+ "Local Topolo credential refresh requires an explicit local Auth service origin."
585
+ );
586
+ }
587
+ try {
588
+ const oauth = new TopoloOAuth({
589
+ serviceUrls
590
+ });
591
+ const tokens = await oauth.refreshToken({
592
+ clientId: profile.oauthClientId,
593
+ refreshToken: cred.refreshToken
594
+ });
595
+ const refreshed = {
596
+ kind: "access_token",
597
+ accessToken: tokens.access_token,
598
+ ...tokens.refresh_token ? { refreshToken: tokens.refresh_token } : { refreshToken: cred.refreshToken },
599
+ expiresAt: Math.floor(Date.now() / 1e3) + tokens.expires_in
600
+ };
601
+ const activeContext = profile.activeContext;
602
+ const activeEntry = activeContext ? profile.contexts?.[activeContext] : void 0;
603
+ const updated = activeContext && activeEntry ? writeProfileConfig(config, environment, {
604
+ credential: refreshed,
605
+ contexts: {
606
+ ...profile.contexts ?? {},
607
+ [activeContext]: {
608
+ ...activeEntry,
609
+ credential: refreshed,
610
+ oauthClientId: activeEntry.oauthClientId ?? profile.oauthClientId
611
+ }
606
612
  }
607
- }
608
- }) : environment === "production" && !config.profiles?.production ? { ...config, credential: refreshed } : writeProfileConfig(config, environment, { credential: refreshed });
609
- await writeConfig(updated);
610
- return refreshed;
611
- } catch {
612
- return cred;
613
- }
613
+ }) : environment === "production" && !config.profiles?.production ? { ...config, credential: refreshed } : writeProfileConfig(config, environment, { credential: refreshed });
614
+ await writeConfig(updated);
615
+ return refreshed;
616
+ } catch {
617
+ return cred;
618
+ }
619
+ });
614
620
  }
615
621
  async function refreshContextCredentialIfNeeded(environment, key, options = {}) {
616
622
  return withConfigWriteLock(async () => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@topolo/sdk",
3
- "version": "0.11.8",
4
- "topoloPublishedVersion": "0.11.8",
3
+ "version": "0.11.10",
4
+ "topoloPublishedVersion": "0.11.10",
5
5
  "description": "Typed client SDK for the Topolo platform. Used by TopoloCli, TopoloMCP, and third-party agents.",
6
6
  "license": "UNLICENSED",
7
7
  "author": "Topolo",