securewithtrace 0.14.1 → 0.16.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.
Files changed (3) hide show
  1. package/README.md +9 -4
  2. package/dist/index.js +60 -13
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -66,12 +66,17 @@ tracecli vulnerabilities list --severity HIGH
66
66
  tracecli auth login
67
67
  tracecli auth status
68
68
  tracecli auth logout
69
- tracecli auth org list
70
- tracecli auth org current
71
- tracecli auth org switch <organization-id-or-slug>
72
69
  ```
73
70
 
74
- When your account belongs to multiple organizations, use `tracecli auth org switch` to set the active organization context used by repository, vulnerability, and pentest commands.
71
+ ### Organization context
72
+
73
+ ```bash
74
+ tracecli org list
75
+ tracecli org current
76
+ tracecli org switch <organization-id-or-slug>
77
+ ```
78
+
79
+ When your account belongs to multiple organizations, use `tracecli org switch` to set the active organization context used by repository, vulnerability, and pentest commands.
75
80
 
76
81
  ### Repositories
77
82
 
package/dist/index.js CHANGED
@@ -22645,6 +22645,7 @@ var PatchCapabilitiesResponseSchema = external_exports.object({
22645
22645
  });
22646
22646
  var OrganizationResponseSchema = external_exports.object({
22647
22647
  organizationId: external_exports.uuid(),
22648
+ workosOrganizationId: external_exports.string().optional(),
22648
22649
  name: external_exports.string(),
22649
22650
  slug: external_exports.string(),
22650
22651
  logoUrl: external_exports.string().nullable(),
@@ -22671,6 +22672,15 @@ var organizationContract = c9.router({
22671
22672
  500: ErrorResponseSchema
22672
22673
  }
22673
22674
  },
22675
+ listMyOrganizations: {
22676
+ method: "GET",
22677
+ path: "/users/me/organizations",
22678
+ responses: {
22679
+ 200: ListOrganizationsResponseSchema,
22680
+ 401: ErrorResponseSchema,
22681
+ 500: ErrorResponseSchema
22682
+ }
22683
+ },
22674
22684
  getOrganization: {
22675
22685
  method: "GET",
22676
22686
  path: "/organizations/:organizationId",
@@ -24692,17 +24702,21 @@ async function pollForToken(clientId, deviceCode, options = {}) {
24692
24702
  }
24693
24703
  throw new Error("Authorization timed out. Please try again.");
24694
24704
  }
24695
- async function refreshAccessToken(clientId, refreshToken) {
24705
+ async function refreshAccessToken(clientId, refreshToken, organizationId) {
24706
+ const body = new URLSearchParams({
24707
+ grant_type: "refresh_token",
24708
+ client_id: clientId,
24709
+ refresh_token: refreshToken
24710
+ });
24711
+ if (organizationId && organizationId.trim().length > 0) {
24712
+ body.set("organization_id", organizationId);
24713
+ }
24696
24714
  const response = await fetch(WORKOS_TOKEN_URL, {
24697
24715
  method: "POST",
24698
24716
  headers: {
24699
24717
  "Content-Type": "application/x-www-form-urlencoded"
24700
24718
  },
24701
- body: new URLSearchParams({
24702
- grant_type: "refresh_token",
24703
- client_id: clientId,
24704
- refresh_token: refreshToken
24705
- })
24719
+ body
24706
24720
  });
24707
24721
  if (!response.ok) {
24708
24722
  const text = await response.text();
@@ -24890,6 +24904,24 @@ async function refreshStoredAccessToken() {
24890
24904
  return null;
24891
24905
  }
24892
24906
  }
24907
+ async function refreshStoredAccessTokenForOrganization(workosOrganizationId) {
24908
+ const clientId = getWorkosClientId();
24909
+ const refreshToken = readRefreshToken();
24910
+ if (!clientId || !refreshToken) {
24911
+ return false;
24912
+ }
24913
+ try {
24914
+ const tokenResponse = await refreshAccessToken(clientId, refreshToken, workosOrganizationId);
24915
+ const nextRefreshToken = tokenResponse.refresh_token ?? refreshToken;
24916
+ writeTokens(tokenResponse.access_token, nextRefreshToken);
24917
+ return true;
24918
+ } catch (error48) {
24919
+ if (error48 instanceof Error && (error48.message.includes(" 400 ") || error48.message.includes(" 401 "))) {
24920
+ removeToken();
24921
+ }
24922
+ return false;
24923
+ }
24924
+ }
24893
24925
  async function authenticatedRequest(request) {
24894
24926
  const token = readToken();
24895
24927
  if (!token) {
@@ -24953,8 +24985,8 @@ function determineActiveOrganization(organizations, selectedOrganizationId) {
24953
24985
  };
24954
24986
  }
24955
24987
  async function resolveOrganizationId(client) {
24956
- const result = client ? await client.organization.listOrganizations() : await authenticatedRequest(
24957
- (authenticatedClient) => authenticatedClient.organization.listOrganizations()
24988
+ const result = client ? await client.organization.listMyOrganizations() : await authenticatedRequest(
24989
+ (authenticatedClient) => authenticatedClient.organization.listMyOrganizations()
24958
24990
  );
24959
24991
  if (result.status !== 200) {
24960
24992
  console.error(`Failed to resolve organization (status ${result.status}).`);
@@ -24987,8 +25019,8 @@ async function resolveOrganizationId(client) {
24987
25019
  }
24988
25020
  async function resolveOrganizationIdSafe(client) {
24989
25021
  try {
24990
- const result = client ? await client.organization.listOrganizations() : await authenticatedRequestSafe(
24991
- (authenticatedClient) => authenticatedClient.organization.listOrganizations()
25022
+ const result = client ? await client.organization.listMyOrganizations() : await authenticatedRequestSafe(
25023
+ (authenticatedClient) => authenticatedClient.organization.listMyOrganizations()
24992
25024
  );
24993
25025
  if (!result) {
24994
25026
  return null;
@@ -25083,7 +25115,7 @@ function isSafeOrganizationId(organizationId) {
25083
25115
  return SAFE_ORGANIZATION_ID_PATTERN.test(organizationId);
25084
25116
  }
25085
25117
  async function fetchOrganizationContext() {
25086
- const result = await authenticatedRequest((client) => client.organization.listOrganizations());
25118
+ const result = await authenticatedRequest((client) => client.organization.listMyOrganizations());
25087
25119
  if (result.status !== 200) {
25088
25120
  console.error(`Failed to list organizations (status ${result.status}).`);
25089
25121
  process.exit(1);
@@ -25163,9 +25195,15 @@ Use an organization ID or exact slug.`
25163
25195
  };
25164
25196
  }
25165
25197
  return {
25166
- error: `Organization '${input}' not found. Run \`tracecli auth org list\` to see available organizations.`
25198
+ error: `Organization '${input}' not found. Run \`tracecli org list\` to see available organizations.`
25167
25199
  };
25168
25200
  }
25201
+ async function refreshAfterOrganizationSwitch(workosOrganizationId, refreshForOrganization = (organizationId) => refreshStoredAccessTokenForOrganization(organizationId)) {
25202
+ if (!workosOrganizationId || workosOrganizationId.trim().length === 0) {
25203
+ return false;
25204
+ }
25205
+ return refreshForOrganization(workosOrganizationId);
25206
+ }
25169
25207
  function createLoginCommand() {
25170
25208
  return new Command("login").description("Authenticate with Trace").action(async () => {
25171
25209
  const existingToken = readToken();
@@ -25342,10 +25380,18 @@ function createOrgSwitchCommand() {
25342
25380
  process.exit(1);
25343
25381
  }
25344
25382
  writeSelectedOrganizationId(match.organization.organizationId);
25383
+ const refreshed = await refreshAfterOrganizationSwitch(
25384
+ match.organization.workosOrganizationId
25385
+ );
25345
25386
  console.log(
25346
25387
  `Active organization set to ${sanitizeForOutput(match.organization.name)} (${sanitizeForOutput(match.organization.slug)})`
25347
25388
  );
25348
25389
  console.log(` Org ID: ${match.organization.organizationId}`);
25390
+ if (!refreshed) {
25391
+ console.warn(
25392
+ "Token refresh for the selected organization was not completed. If repository commands fail, run `tracecli auth login` again."
25393
+ );
25394
+ }
25349
25395
  });
25350
25396
  }
25351
25397
  function createOrgCommand() {
@@ -25360,7 +25406,7 @@ function createAuthCommand() {
25360
25406
  auth.addCommand(createLoginCommand());
25361
25407
  auth.addCommand(createLogoutCommand());
25362
25408
  auth.addCommand(createStatusCommand());
25363
- auth.addCommand(createOrgCommand());
25409
+ auth.addCommand(createOrgCommand(), { hidden: true });
25364
25410
  return auth;
25365
25411
  }
25366
25412
 
@@ -26737,6 +26783,7 @@ program2.action(() => {
26737
26783
  program2.outputHelp();
26738
26784
  });
26739
26785
  program2.addCommand(createAuthCommand());
26786
+ program2.addCommand(createOrgCommand());
26740
26787
  program2.addCommand(createRepoCommand());
26741
26788
  program2.addCommand(createVulnerabilitiesCommand());
26742
26789
  program2.addCommand(createPentestCommand());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securewithtrace",
3
- "version": "0.14.1",
3
+ "version": "0.16.0",
4
4
  "description": "Official Trace CLI for vulnerability intelligence in your terminal",
5
5
  "type": "module",
6
6
  "bin": {