@vm0/cli 9.215.1 → 9.215.3

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.
Files changed (79) hide show
  1. package/{agent-H6EHGFPZ.js → agent-AZQKRG4B.js} +4 -4
  2. package/{automation-QV3AWLCI.js → automation-ZIEV4Q72.js} +2 -2
  3. package/{banking-HZVGHSLM.js → banking-2CDU223M.js} +2 -2
  4. package/{chunk-LRUD7ROI.js → chunk-2MYK53HJ.js} +2 -2
  5. package/{chunk-L6GC6AUS.js → chunk-DMAXHLSM.js} +25 -5
  6. package/chunk-DMAXHLSM.js.map +1 -0
  7. package/{chunk-PSFY2ETN.js → chunk-EWITRIWZ.js} +2 -2
  8. package/{chunk-R2HX7TVW.js → chunk-GBGNRPZ5.js} +3 -3
  9. package/{chunk-A6UR5VOC.js → chunk-LCMCP2WQ.js} +2 -2
  10. package/{chunk-ZXOCKNRI.js → chunk-QE6HJUL2.js} +3 -3
  11. package/{chunk-KZJ4S6U5.js → chunk-RVZTMBZ7.js} +2 -2
  12. package/{chunk-DQDALBWF.js → chunk-SS5WCV7W.js} +13 -7
  13. package/{chunk-DQDALBWF.js.map → chunk-SS5WCV7W.js.map} +1 -1
  14. package/{chunk-INN5SRMT.js → chunk-WL7EL2UG.js} +2 -2
  15. package/{computer-use-ZKUBXP6V.js → computer-use-AZPPQK7I.js} +2 -2
  16. package/{connector-ZSGIGADY.js → connector-NADUUXPW.js} +3 -3
  17. package/{credit-VMJYM4DD.js → credit-JHOMWMFK.js} +2 -2
  18. package/{developer-support-EVU3TTCS.js → developer-support-U7JULAYC.js} +2 -2
  19. package/{doctor-NL5HUJ6F.js → doctor-A7V3ZJEY.js} +272 -33
  20. package/doctor-A7V3ZJEY.js.map +1 -0
  21. package/{generate-KNCZMJNB.js → generate-2SJTN5W2.js} +3 -3
  22. package/{github-2MLRXIUS.js → github-GRU4EHAJ.js} +2 -2
  23. package/{goal-JWNBPZMQ.js → goal-GURJHZXL.js} +2 -2
  24. package/{host-XCU3JVEP.js → host-GYT2IEH4.js} +2 -2
  25. package/index.js +13 -13
  26. package/{logs-VLNWK6EJ.js → logs-N3PNIAGS.js} +6 -6
  27. package/{maps-UUYNXLCH.js → maps-D5QH3GHE.js} +2 -2
  28. package/{model-XQ6PKJLP.js → model-MM25EQUD.js} +3 -3
  29. package/{model-provider-ZDVTD7R5.js → model-provider-5OZ222EJ.js} +3 -3
  30. package/{org-IFSQQBDR.js → org-QBMRMNB4.js} +2 -2
  31. package/package.json +1 -1
  32. package/{phone-KCBQJ424.js → phone-FXXNTGIC.js} +2 -2
  33. package/{preference-2L2WBMTL.js → preference-KHMX4NLR.js} +2 -2
  34. package/{resource-WLS4LTR3.js → resource-EZHY7PAW.js} +2 -2
  35. package/{search-6NLSGHYB.js → search-PXKNMVKT.js} +6 -6
  36. package/{secret-3ZXJAPVT.js → secret-Y32Q5NUL.js} +3 -3
  37. package/{slack-QIMOKJW4.js → slack-DTGXXB4X.js} +2 -2
  38. package/{telegram-HYFTWR3Y.js → telegram-SXAGLUSM.js} +2 -2
  39. package/{variable-BJEI7JVT.js → variable-POHEUC5N.js} +2 -2
  40. package/{web-T4YMNTPC.js → web-NHHGB5F5.js} +2 -2
  41. package/{whoami-NTKQA7XK.js → whoami-QVS4BRD6.js} +4 -4
  42. package/{workflow-Q6PLLIZ3.js → workflow-65JJ6IXI.js} +2 -2
  43. package/zero.js +30 -30
  44. package/chunk-L6GC6AUS.js.map +0 -1
  45. package/doctor-NL5HUJ6F.js.map +0 -1
  46. /package/{agent-H6EHGFPZ.js.map → agent-AZQKRG4B.js.map} +0 -0
  47. /package/{automation-QV3AWLCI.js.map → automation-ZIEV4Q72.js.map} +0 -0
  48. /package/{banking-HZVGHSLM.js.map → banking-2CDU223M.js.map} +0 -0
  49. /package/{chunk-LRUD7ROI.js.map → chunk-2MYK53HJ.js.map} +0 -0
  50. /package/{chunk-PSFY2ETN.js.map → chunk-EWITRIWZ.js.map} +0 -0
  51. /package/{chunk-R2HX7TVW.js.map → chunk-GBGNRPZ5.js.map} +0 -0
  52. /package/{chunk-A6UR5VOC.js.map → chunk-LCMCP2WQ.js.map} +0 -0
  53. /package/{chunk-ZXOCKNRI.js.map → chunk-QE6HJUL2.js.map} +0 -0
  54. /package/{chunk-KZJ4S6U5.js.map → chunk-RVZTMBZ7.js.map} +0 -0
  55. /package/{chunk-INN5SRMT.js.map → chunk-WL7EL2UG.js.map} +0 -0
  56. /package/{computer-use-ZKUBXP6V.js.map → computer-use-AZPPQK7I.js.map} +0 -0
  57. /package/{connector-ZSGIGADY.js.map → connector-NADUUXPW.js.map} +0 -0
  58. /package/{credit-VMJYM4DD.js.map → credit-JHOMWMFK.js.map} +0 -0
  59. /package/{developer-support-EVU3TTCS.js.map → developer-support-U7JULAYC.js.map} +0 -0
  60. /package/{generate-KNCZMJNB.js.map → generate-2SJTN5W2.js.map} +0 -0
  61. /package/{github-2MLRXIUS.js.map → github-GRU4EHAJ.js.map} +0 -0
  62. /package/{goal-JWNBPZMQ.js.map → goal-GURJHZXL.js.map} +0 -0
  63. /package/{host-XCU3JVEP.js.map → host-GYT2IEH4.js.map} +0 -0
  64. /package/{logs-VLNWK6EJ.js.map → logs-N3PNIAGS.js.map} +0 -0
  65. /package/{maps-UUYNXLCH.js.map → maps-D5QH3GHE.js.map} +0 -0
  66. /package/{model-XQ6PKJLP.js.map → model-MM25EQUD.js.map} +0 -0
  67. /package/{model-provider-ZDVTD7R5.js.map → model-provider-5OZ222EJ.js.map} +0 -0
  68. /package/{org-IFSQQBDR.js.map → org-QBMRMNB4.js.map} +0 -0
  69. /package/{phone-KCBQJ424.js.map → phone-FXXNTGIC.js.map} +0 -0
  70. /package/{preference-2L2WBMTL.js.map → preference-KHMX4NLR.js.map} +0 -0
  71. /package/{resource-WLS4LTR3.js.map → resource-EZHY7PAW.js.map} +0 -0
  72. /package/{search-6NLSGHYB.js.map → search-PXKNMVKT.js.map} +0 -0
  73. /package/{secret-3ZXJAPVT.js.map → secret-Y32Q5NUL.js.map} +0 -0
  74. /package/{slack-QIMOKJW4.js.map → slack-DTGXXB4X.js.map} +0 -0
  75. /package/{telegram-HYFTWR3Y.js.map → telegram-SXAGLUSM.js.map} +0 -0
  76. /package/{variable-BJEI7JVT.js.map → variable-POHEUC5N.js.map} +0 -0
  77. /package/{web-T4YMNTPC.js.map → web-NHHGB5F5.js.map} +0 -0
  78. /package/{whoami-NTKQA7XK.js.map → whoami-QVS4BRD6.js.map} +0 -0
  79. /package/{workflow-Q6PLLIZ3.js.map → workflow-65JJ6IXI.js.map} +0 -0
@@ -3,7 +3,7 @@ import { createRequire as __createRequire } from "node:module";
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  UNKNOWN_PERMISSION_GRANT
6
- } from "./chunk-L6GC6AUS.js";
6
+ } from "./chunk-DMAXHLSM.js";
7
7
  import {
8
8
  init_esm_shims
9
9
  } from "./chunk-DIRAZ3YX.js";
@@ -3078,4 +3078,4 @@ export {
3078
3078
  resolveFirewallMetadataPolicies,
3079
3079
  permissionGrantsToFirewallPolicies
3080
3080
  };
3081
- //# sourceMappingURL=chunk-INN5SRMT.js.map
3081
+ //# sourceMappingURL=chunk-WL7EL2UG.js.map
@@ -6,7 +6,7 @@ import {
6
6
  createComputerUseWriteCommand,
7
7
  fetchComputerUseScreenshot,
8
8
  getComputerUseCommand
9
- } from "./chunk-L6GC6AUS.js";
9
+ } from "./chunk-DMAXHLSM.js";
10
10
  import {
11
11
  ApiRequestError,
12
12
  withErrorHandler
@@ -472,4 +472,4 @@ export {
472
472
  formatComputerUseResultForConsole,
473
473
  zeroComputerUseCommand
474
474
  };
475
- //# sourceMappingURL=computer-use-ZKUBXP6V.js.map
475
+ //# sourceMappingURL=computer-use-AZPPQK7I.js.map
@@ -13,7 +13,7 @@ import {
13
13
  getConnectorAuthMethodScopeDiff,
14
14
  getConnectorEnvBindingEntries,
15
15
  hasRequiredConnectorAuthMethodScopes
16
- } from "./chunk-LRUD7ROI.js";
16
+ } from "./chunk-2MYK53HJ.js";
17
17
  import {
18
18
  CONNECTOR_TYPES,
19
19
  CONNECTOR_TYPE_KEYS,
@@ -28,7 +28,7 @@ import {
28
28
  listZeroConnectors,
29
29
  listZeroCustomConnectors,
30
30
  searchZeroConnectors
31
- } from "./chunk-L6GC6AUS.js";
31
+ } from "./chunk-DMAXHLSM.js";
32
32
  import "./chunk-LTDQISD7.js";
33
33
  import {
34
34
  withErrorHandler
@@ -845,4 +845,4 @@ var zeroConnectorCommand = new Command().name("connector").description("Check th
845
845
  export {
846
846
  zeroConnectorCommand
847
847
  };
848
- //# sourceMappingURL=connector-ZSGIGADY.js.map
848
+ //# sourceMappingURL=connector-NADUUXPW.js.map
@@ -7,7 +7,7 @@ import {
7
7
  import {
8
8
  createZeroCreditCheckout,
9
9
  getZeroOrgMembers
10
- } from "./chunk-L6GC6AUS.js";
10
+ } from "./chunk-DMAXHLSM.js";
11
11
  import "./chunk-LTDQISD7.js";
12
12
  import {
13
13
  withErrorHandler
@@ -87,4 +87,4 @@ var zeroCreditCommand = new Command().name("credit").description("Create a Strip
87
87
  export {
88
88
  zeroCreditCommand
89
89
  };
90
- //# sourceMappingURL=credit-VMJYM4DD.js.map
90
+ //# sourceMappingURL=credit-JHOMWMFK.js.map
@@ -4,7 +4,7 @@ const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  requestDeveloperSupportConsent,
6
6
  submitDeveloperSupport
7
- } from "./chunk-L6GC6AUS.js";
7
+ } from "./chunk-DMAXHLSM.js";
8
8
  import "./chunk-LTDQISD7.js";
9
9
  import {
10
10
  withErrorHandler
@@ -61,4 +61,4 @@ Notes:
61
61
  export {
62
62
  zeroDeveloperSupportCommand
63
63
  };
64
- //# sourceMappingURL=developer-support-EVU3TTCS.js.map
64
+ //# sourceMappingURL=developer-support-U7JULAYC.js.map
@@ -5,7 +5,7 @@ import {
5
5
  findFirewallMetadataPermission,
6
6
  getFirewallPermissionSummary,
7
7
  loadFirewallPermissionMetadata
8
- } from "./chunk-INN5SRMT.js";
8
+ } from "./chunk-WL7EL2UG.js";
9
9
  import {
10
10
  getPlatformOrigin,
11
11
  toPlatformUrl
@@ -13,11 +13,11 @@ import {
13
13
  import {
14
14
  findMatchingRoutingPermissions,
15
15
  matchFirewallBaseUrl
16
- } from "./chunk-A6UR5VOC.js";
16
+ } from "./chunk-LCMCP2WQ.js";
17
17
  import {
18
18
  getConnectorEnvBindingEntries,
19
19
  getDiagnosticConnectorTypeForRuntimeEnvName
20
- } from "./chunk-LRUD7ROI.js";
20
+ } from "./chunk-2MYK53HJ.js";
21
21
  import {
22
22
  CONNECTOR_TYPES,
23
23
  UNKNOWN_PERMISSION_GRANT,
@@ -28,9 +28,10 @@ import {
28
28
  getZeroOrg,
29
29
  getZeroOrgMembers,
30
30
  getZeroRunContext,
31
+ hasUnsafeFirewallPath,
31
32
  resolveFirewallBaseUrlTemplate,
32
33
  searchZeroConnectors
33
- } from "./chunk-L6GC6AUS.js";
34
+ } from "./chunk-DMAXHLSM.js";
34
35
  import "./chunk-LTDQISD7.js";
35
36
  import {
36
37
  ApiRequestError,
@@ -7803,8 +7804,9 @@ init_esm_shims();
7803
7804
  var COMPUTER_USE_CONNECTOR_REF = "computer-use";
7804
7805
  var COMPUTER_USE_CAPABILITY = "computer-use:write";
7805
7806
  var COMPUTER_USE_PATH_PREFIX = "/computer-use";
7807
+ var COMPUTER_USE_PATH_PREFIX_WITH_SLASH = `${COMPUTER_USE_PATH_PREFIX}/`;
7806
7808
  function isComputerUsePermissionTarget(target) {
7807
- return target.connectorRef === COMPUTER_USE_CONNECTOR_REF || target.permission === COMPUTER_USE_CAPABILITY || target.path?.startsWith(COMPUTER_USE_PATH_PREFIX) === true;
7809
+ return target.connectorRef === COMPUTER_USE_CONNECTOR_REF || target.permission === COMPUTER_USE_CAPABILITY || target.path === COMPUTER_USE_PATH_PREFIX || target.path?.startsWith(COMPUTER_USE_PATH_PREFIX_WITH_SLASH) === true;
7808
7810
  }
7809
7811
  function printComputerUsePermissionGuidance() {
7810
7812
  console.log("Computer Use access is not managed as a connector permission.");
@@ -7823,6 +7825,226 @@ function printComputerUsePermissionGuidance() {
7823
7825
  function unknownPermissionChangeCommand2(connectorRef) {
7824
7826
  return `zero doctor permission-change ${connectorRef} --permission ${UNKNOWN_PERMISSION_GRANT} --enable --duration 1h`;
7825
7827
  }
7828
+ var BASE_URL_VAR_PATTERN = /\$\{\{\s*vars\.([a-zA-Z_][a-zA-Z0-9_]*)\s*\}\}/g;
7829
+ var WHOLE_BASE_URL_VAR_PATTERN = /^\$\{\{\s*vars\.([a-zA-Z_][a-zA-Z0-9_]*)\s*\}\}$/;
7830
+ var VALID_DENIED_METHODS = /* @__PURE__ */ new Set([
7831
+ "GET",
7832
+ "POST",
7833
+ "PUT",
7834
+ "PATCH",
7835
+ "DELETE",
7836
+ "HEAD",
7837
+ "OPTIONS"
7838
+ ]);
7839
+ function pathOnlyError() {
7840
+ return new Error(
7841
+ "permission-deny now requires --url because method/path alone can match the wrong API base."
7842
+ );
7843
+ }
7844
+ function invalidUrlError() {
7845
+ return new Error(
7846
+ "permission-deny requires --url to be a valid absolute http or https URL."
7847
+ );
7848
+ }
7849
+ function invalidMethodError() {
7850
+ return new Error(
7851
+ "permission-deny requires --method to be one of GET, POST, PUT, PATCH, DELETE, HEAD, or OPTIONS."
7852
+ );
7853
+ }
7854
+ function unsafePathError() {
7855
+ return new Error(
7856
+ "permission-deny cannot diagnose unsafe URL paths because they are blocked before permission policy evaluation."
7857
+ );
7858
+ }
7859
+ function parseDeniedMethod(method) {
7860
+ const upperMethod = method.toUpperCase();
7861
+ if (!VALID_DENIED_METHODS.has(upperMethod)) {
7862
+ throw invalidMethodError();
7863
+ }
7864
+ return upperMethod;
7865
+ }
7866
+ function rawAuthorityFromDeniedUrl(url) {
7867
+ const schemeEnd = url.indexOf("://");
7868
+ if (schemeEnd === -1) return null;
7869
+ const authorityStart = schemeEnd + 3;
7870
+ let authorityEnd = url.length;
7871
+ for (const delimiter of ["/", "?", "#"]) {
7872
+ const index = url.indexOf(delimiter, authorityStart);
7873
+ if (index !== -1) authorityEnd = Math.min(authorityEnd, index);
7874
+ }
7875
+ return url.slice(authorityStart, authorityEnd);
7876
+ }
7877
+ function rawAuthorityHasUnsafeSyntax(url) {
7878
+ const authority = rawAuthorityFromDeniedUrl(url);
7879
+ if (authority === null) return false;
7880
+ return authority === "" || authority.includes("\\") || authority.includes("%") || [...authority].some((char) => {
7881
+ return char.charCodeAt(0) > 127;
7882
+ });
7883
+ }
7884
+ function parseDeniedUrl(url) {
7885
+ if (!url.includes("://") || /\s/.test(url) || rawAuthorityHasUnsafeSyntax(url)) {
7886
+ throw invalidUrlError();
7887
+ }
7888
+ try {
7889
+ const parsed = new URL(url);
7890
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
7891
+ throw invalidUrlError();
7892
+ }
7893
+ if (parsed.username !== "" || parsed.password !== "") {
7894
+ throw invalidUrlError();
7895
+ }
7896
+ return parsed;
7897
+ } catch {
7898
+ throw invalidUrlError();
7899
+ }
7900
+ }
7901
+ function baseUrlTemplateVarNames(base) {
7902
+ return [...base.matchAll(BASE_URL_VAR_PATTERN)].map((match) => {
7903
+ return match[1];
7904
+ });
7905
+ }
7906
+ function wholeBaseUrlTemplateVarName(base) {
7907
+ return WHOLE_BASE_URL_VAR_PATTERN.exec(base)?.[1] ?? null;
7908
+ }
7909
+ function resolveBaseUrlTemplateFromEnv(base) {
7910
+ const names = baseUrlTemplateVarNames(base);
7911
+ if (names.length === 0) return base;
7912
+ let missing = false;
7913
+ const resolved = base.replace(
7914
+ BASE_URL_VAR_PATTERN,
7915
+ (_match, name) => {
7916
+ const value = process.env[name];
7917
+ if (!value) {
7918
+ missing = true;
7919
+ return "";
7920
+ }
7921
+ return value;
7922
+ }
7923
+ );
7924
+ return missing ? null : resolved;
7925
+ }
7926
+ function baseUrlTemplateToPattern(base) {
7927
+ if (baseUrlTemplateVarNames(base).length === 0) return null;
7928
+ const pattern = base.replace(BASE_URL_VAR_PATTERN, (_match, name) => {
7929
+ return `{${name}}`;
7930
+ });
7931
+ return pattern.includes("://") ? pattern : null;
7932
+ }
7933
+ function connectorRefHostToken(connectorRef) {
7934
+ return connectorRef.toLowerCase().replaceAll(/[^a-z0-9]/g, "");
7935
+ }
7936
+ function hostLabelToken(label) {
7937
+ return label.toLowerCase().replaceAll(/[^a-z0-9]/g, "");
7938
+ }
7939
+ function hostLabelMatchesConnectorRef(label, connectorRef) {
7940
+ const normalizedConnectorRef = connectorRef.toLowerCase();
7941
+ const token = connectorRefHostToken(connectorRef);
7942
+ const normalizedLabel = label.toLowerCase();
7943
+ if (normalizedConnectorRef === token) {
7944
+ return normalizedLabel === token;
7945
+ }
7946
+ return hostLabelToken(normalizedLabel) === token;
7947
+ }
7948
+ function hostnameMatchesConnectorRef(url, connectorRef) {
7949
+ const token = connectorRefHostToken(connectorRef);
7950
+ if (token.length < 3) return false;
7951
+ const labels = (url.hostname || "").toLowerCase().replace(/\.$/, "").split(".").filter((part) => {
7952
+ return part !== "";
7953
+ });
7954
+ if (labels.length < 2) return false;
7955
+ return hostLabelMatchesConnectorRef(labels[labels.length - 2], connectorRef);
7956
+ }
7957
+ function stripUrlQueryAndFragment(url) {
7958
+ const queryIndex = url.indexOf("?");
7959
+ const fragmentIndex = url.indexOf("#");
7960
+ let end = url.length;
7961
+ if (queryIndex !== -1) end = Math.min(end, queryIndex);
7962
+ if (fragmentIndex !== -1) end = Math.min(end, fragmentIndex);
7963
+ return url.slice(0, end);
7964
+ }
7965
+ function rawPathFromDeniedUrl(url) {
7966
+ const urlWithoutQuery = stripUrlQueryAndFragment(url);
7967
+ const schemeEnd = urlWithoutQuery.indexOf("://");
7968
+ const authorityStart = schemeEnd === -1 ? 0 : schemeEnd + 3;
7969
+ const pathStart = urlWithoutQuery.indexOf("/", authorityStart);
7970
+ return pathStart === -1 ? "/" : urlWithoutQuery.slice(pathStart);
7971
+ }
7972
+ function matchApiBaseUrl(url, apiBase) {
7973
+ const directMatch = matchFirewallBaseUrl(url, apiBase);
7974
+ if (directMatch) {
7975
+ return {
7976
+ apiBase,
7977
+ displayBase: directMatch.displayBase,
7978
+ relativePath: directMatch.relativePath,
7979
+ score: directMatch.score
7980
+ };
7981
+ }
7982
+ const resolvedBase = resolveBaseUrlTemplateFromEnv(apiBase);
7983
+ if (resolvedBase !== null && resolvedBase !== apiBase) {
7984
+ const resolvedMatch = matchFirewallBaseUrl(url, resolvedBase);
7985
+ if (resolvedMatch) {
7986
+ return {
7987
+ apiBase,
7988
+ displayBase: resolvedMatch.displayBase,
7989
+ relativePath: resolvedMatch.relativePath,
7990
+ score: resolvedMatch.score
7991
+ };
7992
+ }
7993
+ return null;
7994
+ }
7995
+ const patternBase = baseUrlTemplateToPattern(apiBase);
7996
+ if (patternBase === null) return null;
7997
+ const patternMatch = matchFirewallBaseUrl(url, patternBase);
7998
+ if (!patternMatch) return null;
7999
+ return {
8000
+ apiBase,
8001
+ displayBase: apiBase,
8002
+ relativePath: patternMatch.relativePath,
8003
+ score: patternMatch.score
8004
+ };
8005
+ }
8006
+ function findBestBaseMatch(url, deniedUrl, connectorRef, apis) {
8007
+ let bestMatch = null;
8008
+ for (const api2 of apis) {
8009
+ const match = matchApiBaseUrl(url, api2.base);
8010
+ if (match && (!bestMatch || match.score > bestMatch.score)) {
8011
+ bestMatch = match;
8012
+ }
8013
+ }
8014
+ if (bestMatch !== null) return bestMatch;
8015
+ const unresolvedWholeBaseApis = apis.filter((api2) => {
8016
+ const name = wholeBaseUrlTemplateVarName(api2.base);
8017
+ return name !== null && !process.env[name];
8018
+ });
8019
+ if (unresolvedWholeBaseApis.length !== 1) return null;
8020
+ if (!hostnameMatchesConnectorRef(deniedUrl, connectorRef)) return null;
8021
+ const api = unresolvedWholeBaseApis[0];
8022
+ return {
8023
+ apiBase: api.base,
8024
+ displayBase: api.base,
8025
+ relativePath: rawPathFromDeniedUrl(url),
8026
+ score: 0
8027
+ };
8028
+ }
8029
+ function printPermissionChangeGuidance(connectorRef, permissions) {
8030
+ const sortedPermissions = [...permissions].sort();
8031
+ if (sortedPermissions.length === 1) {
8032
+ const permission = sortedPermissions[0];
8033
+ console.log(`This is covered by the "${permission}" permission.`);
8034
+ console.log(
8035
+ `To allow this permission, run: zero doctor permission-change ${connectorRef} --permission ${permission} --enable --duration 1h`
8036
+ );
8037
+ return;
8038
+ }
8039
+ console.log(
8040
+ `This is covered by these permissions: ${sortedPermissions.join(", ")}.`
8041
+ );
8042
+ for (const permission of sortedPermissions) {
8043
+ console.log(
8044
+ `To allow ${permission}, run: zero doctor permission-change ${connectorRef} --permission ${permission} --enable --duration 1h`
8045
+ );
8046
+ }
8047
+ }
7826
8048
  var permissionDenyCommand = new Command().name("permission-deny").description(
7827
8049
  "Diagnose a permission denial and find the permission that covers it"
7828
8050
  ).argument("<connector-ref>", "The connector type (e.g. github)").addOption(
@@ -7831,23 +8053,44 @@ var permissionDenyCommand = new Command().name("permission-deny").description(
7831
8053
  "The denied HTTP method"
7832
8054
  ).makeOptionMandatory()
7833
8055
  ).addOption(
7834
- new Option("--path <path>", "The denied path").makeOptionMandatory()
7835
- ).addHelpText(
8056
+ new Option(
8057
+ "--url <url>",
8058
+ "The denied request URL; query strings are ignored (required)"
8059
+ )
8060
+ ).addOption(new Option("--path <path>", "Deprecated: use --url").hideHelp()).addHelpText(
7836
8061
  "after",
7837
8062
  `
7838
8063
  Examples:
7839
- zero doctor permission-deny github --method GET --path /repos/owner/repo/pulls
7840
- zero doctor permission-deny slack --method POST --path /chat.postMessage
7841
- zero doctor permission-deny computer-use --method POST --path /computer-use/list-apps
8064
+ zero doctor permission-deny github --method GET --url https://api.github.com/repos/owner/repo/pulls
8065
+ zero doctor permission-deny slack --method POST --url https://slack.com/api/chat.postMessage
8066
+ zero doctor permission-deny youtube --method PUT --url https://youtube.googleapis.com/upload/youtube/v3/videos
7842
8067
 
7843
8068
  Notes:
7844
8069
  - Identifies which named permission covers a denied request
8070
+ - If the firewall denial response includes a url field, pass that value to --url
8071
+ - Requires the denied URL origin and path because method/path alone can match the wrong API base
8072
+ - Query strings and fragments are ignored for matching; omit them when they may contain secrets
7845
8073
  - Use permission-change to request or enable the permission
7846
8074
  - Permission-change enable requests default to --duration 1h; pick 24h, 7d, or always only when appropriate`
7847
8075
  ).action(
7848
8076
  withErrorHandler(
7849
8077
  async (connectorRef, opts) => {
7850
- if (isComputerUsePermissionTarget({ connectorRef, path: opts.path })) {
8078
+ if (opts.path !== void 0) {
8079
+ throw pathOnlyError();
8080
+ }
8081
+ if (!opts.url) {
8082
+ throw pathOnlyError();
8083
+ }
8084
+ const method = parseDeniedMethod(opts.method);
8085
+ const deniedUrl = parseDeniedUrl(opts.url);
8086
+ const deniedPath = rawPathFromDeniedUrl(opts.url);
8087
+ if (hasUnsafeFirewallPath(deniedPath)) {
8088
+ throw unsafePathError();
8089
+ }
8090
+ if (isComputerUsePermissionTarget({
8091
+ connectorRef,
8092
+ path: deniedPath
8093
+ })) {
7851
8094
  printComputerUsePermissionGuidance();
7852
8095
  return;
7853
8096
  }
@@ -7856,14 +8099,25 @@ Notes:
7856
8099
  throw new Error(`Unknown connector type: ${connectorRef}`);
7857
8100
  }
7858
8101
  const label = getFirewallPermissionSummary(connectorRef)?.label ?? connectorRef;
8102
+ const match = findBestBaseMatch(
8103
+ opts.url,
8104
+ deniedUrl,
8105
+ connectorRef,
8106
+ metadata.apis
8107
+ );
8108
+ if (!match) {
8109
+ throw new Error(
8110
+ `No registered ${label} base URL matches the provided URL.`
8111
+ );
8112
+ }
7859
8113
  const permissions = findMatchingRoutingPermissions(
7860
- opts.method,
7861
- opts.path,
8114
+ method,
8115
+ match.relativePath,
7862
8116
  metadata.apis,
7863
- { serviceName: connectorRef }
8117
+ { apiBase: match.apiBase, serviceName: connectorRef }
7864
8118
  );
7865
8119
  console.log(
7866
- `The ${label} permission filtered ${opts.method} ${opts.path}.`
8120
+ `The ${label} permission filtered ${method} ${match.relativePath} relative to base URL ${match.displayBase}.`
7867
8121
  );
7868
8122
  if (permissions.length === 0) {
7869
8123
  console.log("No named permission was found covering this request.");
@@ -7875,22 +8129,7 @@ Notes:
7875
8129
  );
7876
8130
  return;
7877
8131
  }
7878
- const ruleCount = /* @__PURE__ */ new Map();
7879
- for (const api of metadata.apis) {
7880
- for (const route of api.routes) {
7881
- ruleCount.set(
7882
- route.permissionName,
7883
- (ruleCount.get(route.permissionName) ?? 0) + 1
7884
- );
7885
- }
7886
- }
7887
- const permission = permissions.reduce((narrowest, current) => {
7888
- return (ruleCount.get(current) ?? Infinity) < (ruleCount.get(narrowest) ?? Infinity) ? current : narrowest;
7889
- });
7890
- console.log(`This is covered by the "${permission}" permission.`);
7891
- console.log(
7892
- `To allow this permission, run: zero doctor permission-change ${connectorRef} --permission ${permission} --enable --duration 1h`
7893
- );
8132
+ printPermissionChangeGuidance(connectorRef, permissions);
7894
8133
  }
7895
8134
  )
7896
8135
  );
@@ -8161,7 +8400,7 @@ Examples:
8161
8400
  Check a URL? zero doctor check-connector --url https://api.github.com/repos/owner/repo
8162
8401
  Check credits? zero doctor credit
8163
8402
  Check with permission? zero doctor check-connector --env-name SLACK_TOKEN --check-permission chat:write
8164
- Permission denied? zero doctor permission-deny github --method GET --path /repos/owner/repo
8403
+ Permission denied? zero doctor permission-deny github --method GET --url https://api.github.com/repos/owner/repo
8165
8404
  Change a permission? zero doctor permission-change github --permission contents:read --enable --duration 1h
8166
8405
  Disable unknown URLs? zero doctor permission-change cloudflare --permission __unknown__ --disable
8167
8406
 
@@ -8174,4 +8413,4 @@ Notes:
8174
8413
  export {
8175
8414
  zeroDoctorCommand
8176
8415
  };
8177
- //# sourceMappingURL=doctor-NL5HUJ6F.js.map
8416
+ //# sourceMappingURL=doctor-A7V3ZJEY.js.map