@levr-one/cli 0.12.5 → 0.12.7

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 (22) hide show
  1. package/dist/{addHandler-CAmLxnsF.js → addHandler-ybX54_3f.js} +6 -6
  2. package/dist/{appendHandler-CUmlIX6q.js → appendHandler-CKkl9ymw.js} +7 -7
  3. package/dist/{artifact-upload-BvBSevIx.js → artifact-upload-Ba801tb6.js} +1 -1
  4. package/dist/{attachHandler-DXZi2ILT.js → attachHandler-CfNvVAV2.js} +7 -7
  5. package/dist/cli.js +18 -18
  6. package/dist/{connect-DVjgyfls.js → connect-yq3fGXkW.js} +9 -8
  7. package/dist/{find-workspace-Bl4rfr73.js → find-workspace-4Us2vEb7.js} +1 -1
  8. package/dist/{importHandler-BhOznIQW.js → importHandler-bYBWYC_0.js} +8 -8
  9. package/dist/{listHandler-DjWj1D3H.js → listHandler-Du_YGzre.js} +4 -4
  10. package/dist/{loginHandler-C9Oi92IY.js → loginHandler-PbKmDAGo.js} +4 -4
  11. package/dist/{logoutHandler-Cf5aI1wq.js → logoutHandler-DxnzGPYx.js} +1 -1
  12. package/dist/{pushHandler-NvZYBz-H.js → pushHandler-BulraEwP.js} +15 -13
  13. package/dist/{refsHandler-DtcceTRP.js → refsHandler--ySvLjmX.js} +6 -4
  14. package/dist/{resolve-token-ByZq05Us.js → resolve-token-DKEXT7SA.js} +8 -5
  15. package/dist/{resolve-workspace-BbK3uYQc.js → resolve-workspace-D8y7twod.js} +37 -5
  16. package/dist/{runHandler-CTfUyBNW.js → runHandler-B-u-0eRk.js} +25 -13
  17. package/dist/{sdk-client-B4FMd_Fa.js → sdk-client-BgzKzVIR.js} +1 -1
  18. package/dist/{selectHandler-CrLuGY3d.js → selectHandler-C0gs-Q70.js} +9 -4
  19. package/dist/{statusHandler-BQXn93-r.js → statusHandler-Dnnh80ZN.js} +7 -5
  20. package/dist/{token-refresh-CJB7Qlxy.js → token-refresh-BpFuU4Ij.js} +26 -2
  21. package/package.json +1 -1
  22. /package/dist/{env-CvjMSRd7.js → env-DjeRwmZ7.js} +0 -0
@@ -1,10 +1,10 @@
1
- import { configureClient } from "./sdk-client-B4FMd_Fa.js";
2
- import { getApiUrl } from "./env-CvjMSRd7.js";
3
- import "./token-refresh-CJB7Qlxy.js";
4
- import { resolveToken } from "./resolve-token-ByZq05Us.js";
1
+ import { configureClient } from "./sdk-client-BgzKzVIR.js";
2
+ import "./token-refresh-BpFuU4Ij.js";
3
+ import { getApiUrl } from "./env-DjeRwmZ7.js";
4
+ import { resolveToken } from "./resolve-token-DKEXT7SA.js";
5
5
  import "./workspace-store-Bmw104Qa.js";
6
- import { fetchSites } from "./resolve-workspace-BbK3uYQc.js";
7
- import { describeWorkspaces, findWorkspaceByKeyOrName, isScopedMcpUrl, resolveMcpUrl, scopedMcpUrl, servedBySessionApi } from "./find-workspace-Bl4rfr73.js";
6
+ import { fetchSites } from "./resolve-workspace-D8y7twod.js";
7
+ import { describeWorkspaces, findWorkspaceByKeyOrName, isScopedMcpUrl, resolveMcpUrl, scopedMcpUrl, servedBySessionApi } from "./find-workspace-4Us2vEb7.js";
8
8
  import { chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
9
9
  import { basename, delimiter, dirname, join, resolve } from "node:path";
10
10
  import { homedir } from "node:os";
@@ -1,12 +1,12 @@
1
- import { appendActualResult } from "./sdk-client-B4FMd_Fa.js";
2
- import "./env-CvjMSRd7.js";
3
- import "./token-refresh-CJB7Qlxy.js";
4
- import "./resolve-token-ByZq05Us.js";
1
+ import { appendActualResult } from "./sdk-client-BgzKzVIR.js";
2
+ import "./token-refresh-BpFuU4Ij.js";
3
+ import "./env-DjeRwmZ7.js";
4
+ import "./resolve-token-DKEXT7SA.js";
5
5
  import "./workspace-store-Bmw104Qa.js";
6
- import "./resolve-workspace-BbK3uYQc.js";
7
- import { connect } from "./connect-DVjgyfls.js";
6
+ import "./resolve-workspace-D8y7twod.js";
7
+ import { connect } from "./connect-yq3fGXkW.js";
8
8
  import "./sleep-CGBHjsj5.js";
9
- import { embedMarkdown, parseTarget, uploadArtifactFile } from "./artifact-upload-BvBSevIx.js";
9
+ import { embedMarkdown, parseTarget, uploadArtifactFile } from "./artifact-upload-Ba801tb6.js";
10
10
  import { readFileSync } from "node:fs";
11
11
  import { basename } from "node:path";
12
12
 
@@ -1,4 +1,4 @@
1
- import { uploadAttachment } from "./sdk-client-B4FMd_Fa.js";
1
+ import { uploadAttachment } from "./sdk-client-BgzKzVIR.js";
2
2
  import { sleep } from "./sleep-CGBHjsj5.js";
3
3
  import { constants, promises, readlinkSync, realpathSync, statSync } from "node:fs";
4
4
  import path from "node:path";
@@ -1,12 +1,12 @@
1
- import { appendActualResult, createComment } from "./sdk-client-B4FMd_Fa.js";
2
- import "./env-CvjMSRd7.js";
3
- import "./token-refresh-CJB7Qlxy.js";
4
- import "./resolve-token-ByZq05Us.js";
1
+ import { appendActualResult, createComment } from "./sdk-client-BgzKzVIR.js";
2
+ import "./token-refresh-BpFuU4Ij.js";
3
+ import "./env-DjeRwmZ7.js";
4
+ import "./resolve-token-DKEXT7SA.js";
5
5
  import "./workspace-store-Bmw104Qa.js";
6
- import "./resolve-workspace-BbK3uYQc.js";
7
- import { connect } from "./connect-DVjgyfls.js";
6
+ import "./resolve-workspace-D8y7twod.js";
7
+ import { connect } from "./connect-yq3fGXkW.js";
8
8
  import "./sleep-CGBHjsj5.js";
9
- import { TargetParseError, embedMarkdown, parseTarget, uploadArtifactFile } from "./artifact-upload-BvBSevIx.js";
9
+ import { TargetParseError, embedMarkdown, parseTarget, uploadArtifactFile } from "./artifact-upload-Ba801tb6.js";
10
10
  import { readFileSync } from "node:fs";
11
11
  import { basename } from "node:path";
12
12
 
package/dist/cli.js CHANGED
@@ -224,7 +224,7 @@ Examples:
224
224
  aliases: { y: "yes" }
225
225
  },
226
226
  loader: async () => {
227
- const { mcpAddHandler } = await import("./addHandler-CAmLxnsF.js");
227
+ const { mcpAddHandler } = await import("./addHandler-ybX54_3f.js");
228
228
  return mcpAddHandler;
229
229
  }
230
230
  });
@@ -273,7 +273,7 @@ Examples:
273
273
  aliases: { d: "device-code" }
274
274
  },
275
275
  loader: async () => {
276
- const { loginHandler } = await import("./loginHandler-C9Oi92IY.js");
276
+ const { loginHandler } = await import("./loginHandler-PbKmDAGo.js");
277
277
  return loginHandler;
278
278
  }
279
279
  });
@@ -292,7 +292,7 @@ Examples:
292
292
  },
293
293
  parameters: {},
294
294
  loader: async () => {
295
- const { logoutHandler } = await import("./logoutHandler-Cf5aI1wq.js");
295
+ const { logoutHandler } = await import("./logoutHandler-DxnzGPYx.js");
296
296
  return logoutHandler;
297
297
  }
298
298
  });
@@ -312,7 +312,7 @@ Examples:
312
312
  },
313
313
  parameters: {},
314
314
  loader: async () => {
315
- const { statusHandler } = await import("./statusHandler-BQXn93-r.js");
315
+ const { statusHandler } = await import("./statusHandler-Dnnh80ZN.js");
316
316
  return statusHandler;
317
317
  }
318
318
  });
@@ -367,7 +367,7 @@ levr attach --manifest or later uploads.`
367
367
  "workspace-id": {
368
368
  kind: "parsed",
369
369
  parse: String,
370
- brief: "Workspace ID (required for multi-workspace JWT auth)",
370
+ brief: "Workspace ID: needed with a login token and several workspaces; a personal access token is bound to its own",
371
371
  placeholder: "uuid",
372
372
  optional: true
373
373
  },
@@ -441,7 +441,7 @@ levr attach --manifest or later uploads.`
441
441
  }
442
442
  },
443
443
  loader: async () => {
444
- const { pushHandler } = await import("./pushHandler-NvZYBz-H.js");
444
+ const { pushHandler } = await import("./pushHandler-BulraEwP.js");
445
445
  return pushHandler;
446
446
  }
447
447
  });
@@ -482,7 +482,7 @@ Examples:
482
482
  "workspace-id": {
483
483
  kind: "parsed",
484
484
  parse: String,
485
- brief: "Workspace ID (required for multi-workspace JWT auth)",
485
+ brief: "Workspace ID: needed with a login token and several workspaces; a personal access token is bound to its own",
486
486
  placeholder: "uuid",
487
487
  optional: true
488
488
  },
@@ -561,7 +561,7 @@ Examples:
561
561
  }
562
562
  },
563
563
  loader: async () => {
564
- const { importHandler } = await import("./importHandler-BhOznIQW.js");
564
+ const { importHandler } = await import("./importHandler-bYBWYC_0.js");
565
565
  return importHandler;
566
566
  }
567
567
  });
@@ -582,7 +582,7 @@ Examples:
582
582
  },
583
583
  parameters: {},
584
584
  loader: async () => {
585
- const { listHandler } = await import("./listHandler-DjWj1D3H.js");
585
+ const { listHandler } = await import("./listHandler-Du_YGzre.js");
586
586
  return listHandler;
587
587
  }
588
588
  });
@@ -620,7 +620,7 @@ Examples:
620
620
  flags: {}
621
621
  },
622
622
  loader: async () => {
623
- const { selectHandler } = await import("./selectHandler-CrLuGY3d.js");
623
+ const { selectHandler } = await import("./selectHandler-C0gs-Q70.js");
624
624
  return selectHandler;
625
625
  }
626
626
  });
@@ -695,7 +695,7 @@ Examples:
695
695
  }
696
696
  } },
697
697
  loader: async () => {
698
- const { gatesRefsHandler } = await import("./refsHandler-DtcceTRP.js");
698
+ const { gatesRefsHandler } = await import("./refsHandler--ySvLjmX.js");
699
699
  return gatesRefsHandler;
700
700
  }
701
701
  });
@@ -745,7 +745,7 @@ Examples:
745
745
  "workspace-id": {
746
746
  kind: "parsed",
747
747
  parse: String,
748
- brief: "Workspace ID (required for multi-workspace JWT auth)",
748
+ brief: "Workspace ID: needed with a login token and several workspaces; a personal access token is bound to its own",
749
749
  placeholder: "uuid",
750
750
  optional: true
751
751
  },
@@ -776,7 +776,7 @@ Examples:
776
776
  }
777
777
  },
778
778
  loader: async () => {
779
- const { gatesRunHandler } = await import("./runHandler-CTfUyBNW.js");
779
+ const { gatesRunHandler } = await import("./runHandler-B-u-0eRk.js");
780
780
  return gatesRunHandler;
781
781
  }
782
782
  });
@@ -842,7 +842,7 @@ Examples:
842
842
  "workspace-id": {
843
843
  kind: "parsed",
844
844
  parse: String,
845
- brief: "Workspace ID (required for multi-workspace JWT auth)",
845
+ brief: "Workspace ID: needed with a login token and several workspaces; a personal access token is bound to its own",
846
846
  placeholder: "uuid",
847
847
  optional: true
848
848
  },
@@ -889,7 +889,7 @@ Examples:
889
889
  }
890
890
  },
891
891
  loader: async () => {
892
- const { attachHandler } = await import("./attachHandler-DXZi2ILT.js");
892
+ const { attachHandler } = await import("./attachHandler-CfNvVAV2.js");
893
893
  return attachHandler;
894
894
  }
895
895
  });
@@ -924,7 +924,7 @@ Examples:
924
924
  "workspace-id": {
925
925
  kind: "parsed",
926
926
  parse: String,
927
- brief: "Workspace ID (required for multi-workspace JWT auth)",
927
+ brief: "Workspace ID: needed with a login token and several workspaces; a personal access token is bound to its own",
928
928
  placeholder: "uuid",
929
929
  optional: true
930
930
  },
@@ -965,14 +965,14 @@ Examples:
965
965
  }
966
966
  },
967
967
  loader: async () => {
968
- const { resultAppendHandler } = await import("./appendHandler-CUmlIX6q.js");
968
+ const { resultAppendHandler } = await import("./appendHandler-CKkl9ymw.js");
969
969
  return resultAppendHandler;
970
970
  }
971
971
  });
972
972
 
973
973
  //#endregion
974
974
  //#region package.json
975
- var version = "0.12.5";
975
+ var version = "0.12.7";
976
976
 
977
977
  //#endregion
978
978
  //#region src/app.ts
@@ -1,12 +1,13 @@
1
- import { client, configureClient } from "./sdk-client-B4FMd_Fa.js";
2
- import { resolveToken } from "./resolve-token-ByZq05Us.js";
3
- import { resolveWorkspace } from "./resolve-workspace-BbK3uYQc.js";
1
+ import { client, configureClient } from "./sdk-client-BgzKzVIR.js";
2
+ import { resolveToken } from "./resolve-token-DKEXT7SA.js";
3
+ import { resolveWorkspaceFor } from "./resolve-workspace-D8y7twod.js";
4
4
 
5
5
  //#region src/utils/connect.ts
6
6
  /**
7
7
  * Authenticate the SDK client for a command (ENG-6164): resolve the token,
8
- * and for a JWT the workspace. Reports the failure and sets exit code 1;
9
- * returns false when the command must stop.
8
+ * then the workspace — looked up for a JWT, taken from an explicit flag or
9
+ * `LEVR_WORKSPACE_ID` for a PAT (ENG-6068). Reports the failure and sets exit
10
+ * code 1; returns false when the command must stop.
10
11
  */
11
12
  async function connect(ctx, workspaceIdFlag) {
12
13
  let auth;
@@ -18,9 +19,9 @@ async function connect(ctx, workspaceIdFlag) {
18
19
  return false;
19
20
  }
20
21
  configureClient(auth);
21
- if (auth.type === "jwt") try {
22
- const ws = await resolveWorkspace(workspaceIdFlag);
23
- client.setConfig({
22
+ try {
23
+ const ws = await resolveWorkspaceFor(auth, workspaceIdFlag);
24
+ if (ws) client.setConfig({
24
25
  ...client.getConfig(),
25
26
  workspaceId: ws.workspaceId
26
27
  });
@@ -1,4 +1,4 @@
1
- import { getApiUrl } from "./env-CvjMSRd7.js";
1
+ import { getApiUrl } from "./env-DjeRwmZ7.js";
2
2
 
3
3
  //#region src/mcp/url.ts
4
4
  const KNOWN_MCP_URLS = {
@@ -1,9 +1,9 @@
1
- import { authGetProfileV1, client, configureClient } from "./sdk-client-B4FMd_Fa.js";
2
- import { getApiUrl, getTeamId } from "./env-CvjMSRd7.js";
3
- import "./token-refresh-CJB7Qlxy.js";
4
- import { resolveToken } from "./resolve-token-ByZq05Us.js";
1
+ import { authGetProfileV1, client, configureClient } from "./sdk-client-BgzKzVIR.js";
2
+ import "./token-refresh-BpFuU4Ij.js";
3
+ import { getApiUrl, getTeamId } from "./env-DjeRwmZ7.js";
4
+ import { resolveToken } from "./resolve-token-DKEXT7SA.js";
5
5
  import "./workspace-store-Bmw104Qa.js";
6
- import { resolveWorkspace } from "./resolve-workspace-BbK3uYQc.js";
6
+ import { resolveWorkspaceFor } from "./resolve-workspace-D8y7twod.js";
7
7
  import chalk from "chalk";
8
8
  import { createReadStream } from "node:fs";
9
9
  import { basename } from "node:path";
@@ -373,16 +373,16 @@ async function importHandler(flags, file) {
373
373
  this.logger.debug(`Auth: ${auth.type.toUpperCase()}`);
374
374
  this.logger.debug(`API: ${getApiUrl()}`);
375
375
  }
376
- if (auth.type === "jwt") {
376
+ {
377
377
  let workspace;
378
378
  try {
379
- workspace = await resolveWorkspace.call(this, flags["workspace-id"]);
379
+ workspace = await resolveWorkspaceFor(auth, flags["workspace-id"]);
380
380
  } catch (err) {
381
381
  this.logger.error(err instanceof Error ? err.message : "Could not resolve the workspace.");
382
382
  this.process.exitCode = 1;
383
383
  return;
384
384
  }
385
- configureClient(auth, workspace.workspaceId);
385
+ if (workspace) configureClient(auth, workspace.workspaceId);
386
386
  }
387
387
  let teamId;
388
388
  try {
@@ -1,7 +1,7 @@
1
- import { authGetSitesV1, configureClient } from "./sdk-client-B4FMd_Fa.js";
2
- import "./env-CvjMSRd7.js";
3
- import "./token-refresh-CJB7Qlxy.js";
4
- import { resolveToken } from "./resolve-token-ByZq05Us.js";
1
+ import { authGetSitesV1, configureClient } from "./sdk-client-BgzKzVIR.js";
2
+ import "./token-refresh-BpFuU4Ij.js";
3
+ import "./env-DjeRwmZ7.js";
4
+ import { resolveToken } from "./resolve-token-DKEXT7SA.js";
5
5
  import { loadWorkspace } from "./workspace-store-Bmw104Qa.js";
6
6
 
7
7
  //#region src/commands/workspace/listHandler.ts
@@ -1,9 +1,9 @@
1
- import { configureClient } from "./sdk-client-B4FMd_Fa.js";
2
- import { CLI_CLIENT_ID, getApiUrl, getAuthUrl, setSessionApiUrl, writeCredentials } from "./env-CvjMSRd7.js";
1
+ import { configureClient } from "./sdk-client-BgzKzVIR.js";
2
+ import { CLI_CLIENT_ID, getApiUrl, getAuthUrl, setSessionApiUrl, writeCredentials } from "./env-DjeRwmZ7.js";
3
3
  import { saveWorkspace } from "./workspace-store-Bmw104Qa.js";
4
- import { autoSelectWorkspace, fetchSites } from "./resolve-workspace-BbK3uYQc.js";
4
+ import { autoSelectWorkspace, fetchSites } from "./resolve-workspace-D8y7twod.js";
5
5
  import { sleep } from "./sleep-CGBHjsj5.js";
6
- import { findWorkspaceByKeyOrName, looksLikeUrlKey, resolveMcpUrl, scopedMcpUrl } from "./find-workspace-Bl4rfr73.js";
6
+ import { findWorkspaceByKeyOrName, looksLikeUrlKey, resolveMcpUrl, scopedMcpUrl } from "./find-workspace-4Us2vEb7.js";
7
7
  import chalk from "chalk";
8
8
  import { createHash, randomBytes } from "node:crypto";
9
9
  import { createServer } from "node:http";
@@ -1,4 +1,4 @@
1
- import { deleteCredentials, getPatToken } from "./env-CvjMSRd7.js";
1
+ import { deleteCredentials, getPatToken } from "./env-DjeRwmZ7.js";
2
2
  import { clearWorkspace } from "./workspace-store-Bmw104Qa.js";
3
3
 
4
4
  //#region src/commands/auth/logoutHandler.ts
@@ -1,11 +1,11 @@
1
- import { client, configureClient, uploadImport } from "./sdk-client-B4FMd_Fa.js";
2
- import { getApiUrl, getAutomationSourceIdOverride, getSourceOverride, getTeamId } from "./env-CvjMSRd7.js";
3
- import "./token-refresh-CJB7Qlxy.js";
4
- import { resolveToken } from "./resolve-token-ByZq05Us.js";
1
+ import { client, configureClient, uploadImport } from "./sdk-client-BgzKzVIR.js";
2
+ import "./token-refresh-BpFuU4Ij.js";
3
+ import { getApiUrl, getAutomationSourceIdOverride, getSourceOverride, getTeamId } from "./env-DjeRwmZ7.js";
4
+ import { resolveToken } from "./resolve-token-DKEXT7SA.js";
5
5
  import "./workspace-store-Bmw104Qa.js";
6
- import { resolveWorkspace } from "./resolve-workspace-BbK3uYQc.js";
6
+ import { resolveWorkspaceFor } from "./resolve-workspace-D8y7twod.js";
7
7
  import "./sleep-CGBHjsj5.js";
8
- import { resolveArtifactPath, uploadArtifactFile } from "./artifact-upload-BvBSevIx.js";
8
+ import { resolveArtifactPath, uploadArtifactFile } from "./artifact-upload-Ba801tb6.js";
9
9
  import { readFileSync, statSync, writeFileSync } from "node:fs";
10
10
  import { basename, dirname, resolve } from "node:path";
11
11
  import { execSync } from "node:child_process";
@@ -474,13 +474,15 @@ async function pushHandler(flags, file) {
474
474
  this.logger.debug(`Auth: ${auth.type.toUpperCase()}`);
475
475
  this.logger.debug(`API: ${getApiUrl()}`);
476
476
  }
477
- if (auth.type === "jwt") try {
478
- const ws = await resolveWorkspace(flags["workspace-id"]);
479
- client.setConfig({
480
- ...client.getConfig(),
481
- workspaceId: ws.workspaceId
482
- });
483
- if (flags.verbose) this.logger.debug(`Workspace: ${ws.workspaceId} (${ws.source})`);
477
+ try {
478
+ const ws = await resolveWorkspaceFor(auth, flags["workspace-id"]);
479
+ if (ws) {
480
+ client.setConfig({
481
+ ...client.getConfig(),
482
+ workspaceId: ws.workspaceId
483
+ });
484
+ if (flags.verbose) this.logger.debug(`Workspace: ${ws.workspaceId} (${ws.source})`);
485
+ } else if (flags.verbose) this.logger.debug("Workspace: the token's own");
484
486
  } catch (err) {
485
487
  this.logger.error(err instanceof Error ? err.message : "Workspace resolution failed.");
486
488
  this.process.exitCode = 1;
@@ -156,9 +156,11 @@ function notFound(filesScanned, tsConfigPath) {
156
156
  * interpret. The gate framework exists to make "verified" and "not verified"
157
157
  * distinguishable, and an OOM is neither.
158
158
  *
159
- * 8000 sits above the largest legitimate single scope in this repo
160
- * (`apps/backender` at 6,314, which resolves comfortably) and below the
161
- * whole-repo set that does not. Override deliberately with `--max-files` if a
159
+ * 10,000 sits above the largest legitimate single scope in this repo and below
160
+ * the whole-repo set that does not. `apps/backender/src` was 6,314 files when
161
+ * the cap was 8000, and reached 8,016 with ENG-6802, which made every gate
162
+ * scoped to it refuse. It counts test files even when `includeTests` is off
163
+ * (about 1,100 of them); excluding those is a separate follow-up. Override deliberately with `--max-files` if a
162
164
  * genuinely larger scope is ever needed — and expect to raise Node's heap with
163
165
  * `NODE_OPTIONS=--max-old-space-size=...` at the same time.
164
166
  *
@@ -168,7 +170,7 @@ function notFound(filesScanned, tsConfigPath) {
168
170
  * would change verdicts for reasons that have nothing to do with the code.
169
171
  * (Moved from `scripts/gates/symbol-referenced.lib.ts`, ENG-7284 D5.)
170
172
  */
171
- const DEFAULT_MAX_FILES = 8e3;
173
+ const DEFAULT_MAX_FILES = 1e4;
172
174
  /** Thrown when the requested scope holds more files than the resolver will load. */
173
175
  var ScopeTooBroadError = class extends Error {
174
176
  fileCount;
@@ -1,5 +1,5 @@
1
- import { getApiUrl, getPatToken, readCredentials } from "./env-CvjMSRd7.js";
2
- import { isTokenExpired, refreshToken } from "./token-refresh-CJB7Qlxy.js";
1
+ import { classifyToken, isTokenExpired, refreshToken } from "./token-refresh-BpFuU4Ij.js";
2
+ import { getApiUrl, getPatToken, readCredentials } from "./env-DjeRwmZ7.js";
3
3
 
4
4
  //#region src/auth/resolve-token.ts
5
5
  /**
@@ -16,7 +16,8 @@ var CredentialsMismatchError = class extends Error {
16
16
  };
17
17
  /**
18
18
  * Resolve auth token in priority order:
19
- * 1. LEVR_TOKEN env var (PAT) — long-lived, no refresh
19
+ * 1. LEVR_TOKEN env var — a PAT or an OAuth access token, told apart by
20
+ * shape (ENG-6068); never refreshed
20
21
  * 2. Stored credentials (JWT) — auto-refresh if expired
21
22
  * 3. Error — not authenticated
22
23
  */
@@ -24,7 +25,8 @@ async function resolveToken() {
24
25
  const pat = getPatToken();
25
26
  if (pat) return {
26
27
  token: pat,
27
- type: "pat"
28
+ type: classifyToken(pat),
29
+ source: "env"
28
30
  };
29
31
  let creds = readCredentials();
30
32
  if (creds) {
@@ -38,7 +40,8 @@ async function resolveToken() {
38
40
  }
39
41
  return {
40
42
  token: creds.access_token,
41
- type: "jwt"
43
+ type: "jwt",
44
+ source: "stored"
42
45
  };
43
46
  }
44
47
  throw new Error("Not authenticated. Run 'levr auth login' or set LEVR_TOKEN environment variable.");
@@ -1,4 +1,4 @@
1
- import { authGetSitesV1 } from "./sdk-client-B4FMd_Fa.js";
1
+ import { authGetSitesV1 } from "./sdk-client-BgzKzVIR.js";
2
2
  import { clearWorkspace, loadWorkspace, saveWorkspace } from "./workspace-store-Bmw104Qa.js";
3
3
 
4
4
  //#region src/workspace/resolve-workspace.ts
@@ -40,7 +40,8 @@ async function autoSelectWorkspace() {
40
40
  };
41
41
  return { kind: "none" };
42
42
  }
43
- async function resolveWorkspace(flagValue) {
43
+ async function resolveWorkspace(flagValue, options = {}) {
44
+ const persist = options.persist ?? true;
44
45
  let sites = null;
45
46
  const getSites = async () => {
46
47
  if (!sites) sites = await fetchSites();
@@ -61,7 +62,7 @@ async function resolveWorkspace(flagValue) {
61
62
  source: "env"
62
63
  };
63
64
  }
64
- const cached = loadWorkspace();
65
+ const cached = persist ? loadWorkspace() : null;
65
66
  if (cached) {
66
67
  if ((await getSites()).some((site) => site.workspace_id === cached)) return {
67
68
  workspaceId: cached,
@@ -73,7 +74,7 @@ async function resolveWorkspace(flagValue) {
73
74
  if (s.length === 0) throw new Error("No workspaces available.");
74
75
  if (s.length === 1) {
75
76
  const single = s[0];
76
- saveWorkspace(single.workspace_id);
77
+ if (persist) saveWorkspace(single.workspace_id);
77
78
  return {
78
79
  workspaceId: single.workspace_id,
79
80
  source: "auto"
@@ -84,6 +85,37 @@ async function resolveWorkspace(flagValue) {
84
85
  const overflow = s.length > maxList ? `\n ... and ${s.length - maxList} more` : "";
85
86
  throw new Error(`Multiple workspaces. Select one:\n${list}${overflow}\n\nRun: levr workspace select <id>`);
86
87
  }
88
+ /**
89
+ * The workspace a command runs in, for whichever credential it holds —
90
+ * [issue:ENG-6068].
91
+ *
92
+ * A JWT is not bound to a workspace, so one is resolved the usual way: the
93
+ * flag, `LEVR_WORKSPACE_ID`, the cached selection, then auto-select, each
94
+ * validated against the sites the account can see.
95
+ *
96
+ * A personal access token IS bound to one workspace, and the server scopes
97
+ * every request by it. An explicit `--workspace-id` or `LEVR_WORKSPACE_ID` is
98
+ * still sent as `Workspace-Id` — the server refuses one that is not the
99
+ * token's — but nothing is looked up or cached, and with neither set the
100
+ * answer is null: the token's own workspace applies. Until ENG-6068 both were
101
+ * silently dropped for every `LEVR_TOKEN`, including an OAuth access token,
102
+ * which was classified as a PAT by where it came from and has no workspace to
103
+ * fall back to. An OAuth token from LEVR_TOKEN is not the login session, so
104
+ * the saved workspace choice is left alone for it (`persist: false`).
105
+ */
106
+ async function resolveWorkspaceFor(auth, flagValue) {
107
+ if (auth.type === "jwt") return resolveWorkspace(flagValue, { persist: auth.source !== "env" });
108
+ if (flagValue) return {
109
+ workspaceId: flagValue,
110
+ source: "flag"
111
+ };
112
+ const envWs = process.env["LEVR_WORKSPACE_ID"];
113
+ if (envWs) return {
114
+ workspaceId: envWs,
115
+ source: "env"
116
+ };
117
+ return null;
118
+ }
87
119
 
88
120
  //#endregion
89
- export { autoSelectWorkspace, fetchSites, resolveWorkspace };
121
+ export { autoSelectWorkspace, fetchSites, resolveWorkspaceFor };
@@ -1,10 +1,10 @@
1
1
  import { executeInspect } from "./inspect-BbL7kDe-.js";
2
- import { client, configureClient } from "./sdk-client-B4FMd_Fa.js";
3
- import "./env-CvjMSRd7.js";
4
- import "./token-refresh-CJB7Qlxy.js";
5
- import { resolveToken } from "./resolve-token-ByZq05Us.js";
2
+ import { client, configureClient } from "./sdk-client-BgzKzVIR.js";
3
+ import "./token-refresh-BpFuU4Ij.js";
4
+ import "./env-DjeRwmZ7.js";
5
+ import { resolveToken } from "./resolve-token-DKEXT7SA.js";
6
6
  import "./workspace-store-Bmw104Qa.js";
7
- import { resolveWorkspace } from "./resolve-workspace-BbK3uYQc.js";
7
+ import { resolveWorkspaceFor } from "./resolve-workspace-D8y7twod.js";
8
8
  import { existsSync } from "node:fs";
9
9
  import { constants as constants$1 } from "node:os";
10
10
  import { spawnSync } from "node:child_process";
@@ -365,6 +365,15 @@ function delay(ms) {
365
365
 
366
366
  //#endregion
367
367
  //#region src/commands/gates/runHandler.ts
368
+ /** The server's own words for a failed SDK call, for an error line. */
369
+ function describeSdkError(error) {
370
+ if (typeof error === "string") return error.length > 200 ? `${error.slice(0, 200)}…` : error;
371
+ if (!error || typeof error !== "object") return "request failed";
372
+ const e = error;
373
+ const message = Array.isArray(e.message) ? e.message.map(String).join("; ") : typeof e.message === "string" ? e.message : typeof e.error === "string" ? e.error : "";
374
+ const text = [typeof e.statusCode === "number" ? `HTTP ${e.statusCode}` : "", message].filter(Boolean).join(": ") || "request failed";
375
+ return text.length > 200 ? `${text.slice(0, 200)}…` : text;
376
+ }
368
377
  /** ENG-6070 review R5 M3 — dead gates are named, with their remedy. */
369
378
  function printDeadGates(out, dead) {
370
379
  for (const d of dead ?? []) out(` DEAD ${d.test_name ? `"${d.test_name}"` : d.link_id}${d.required === false ? " (advisory)" : ""}: ${d.reason === "test_deleted" ? "its test was deleted" : "the gate was removed"}${d.remedy ? ` — ${d.remedy}` : ""}`);
@@ -431,13 +440,15 @@ async function gatesRunHandler(flags, issue) {
431
440
  };
432
441
  if (flags.ci) setCiHeaders(null);
433
442
  let workspaceId;
434
- if (auth.type === "jwt") try {
435
- const ws = await resolveWorkspace(flags["workspace-id"]);
436
- workspaceId = ws.workspaceId;
437
- client.setConfig({
438
- ...client.getConfig(),
439
- workspaceId: ws.workspaceId
440
- });
443
+ try {
444
+ const ws = await resolveWorkspaceFor(auth, flags["workspace-id"]);
445
+ if (ws) {
446
+ workspaceId = ws.workspaceId;
447
+ client.setConfig({
448
+ ...client.getConfig(),
449
+ workspaceId: ws.workspaceId
450
+ });
451
+ }
441
452
  } catch (err) {
442
453
  this.logger.error(err instanceof Error ? err.message : "Workspace resolution failed.");
443
454
  this.process.exitCode = 1;
@@ -451,7 +462,8 @@ async function gatesRunHandler(flags, issue) {
451
462
  } });
452
463
  const row = found.data?.data?.[0];
453
464
  if (found.error || !row) {
454
- this.logger.error(`Issue ${issue} not found in this workspace.`);
465
+ const where = workspaceId ? `workspace ${workspaceId}` : "the token's workspace";
466
+ this.logger.error(found.error ? `Could not look up issue ${issue} in ${where} (${describeSdkError(found.error)}).` : `Issue ${issue} not found in ${where}.`);
455
467
  this.process.exitCode = 1;
456
468
  return;
457
469
  }
@@ -1,4 +1,4 @@
1
- import { getApiUrl } from "./env-CvjMSRd7.js";
1
+ import { getApiUrl } from "./env-DjeRwmZ7.js";
2
2
 
3
3
  //#region ../sdk-public/dist/runtime/client.js
4
4
  function createInterceptorManager() {
@@ -1,7 +1,7 @@
1
- import { authGetSitesV1, configureClient } from "./sdk-client-B4FMd_Fa.js";
2
- import "./env-CvjMSRd7.js";
3
- import "./token-refresh-CJB7Qlxy.js";
4
- import { resolveToken } from "./resolve-token-ByZq05Us.js";
1
+ import { authGetSitesV1, configureClient } from "./sdk-client-BgzKzVIR.js";
2
+ import "./token-refresh-BpFuU4Ij.js";
3
+ import "./env-DjeRwmZ7.js";
4
+ import { resolveToken } from "./resolve-token-DKEXT7SA.js";
5
5
  import { saveWorkspace } from "./workspace-store-Bmw104Qa.js";
6
6
 
7
7
  //#region src/commands/workspace/selectHandler.ts
@@ -19,6 +19,11 @@ async function selectHandler(_flags, workspaceId) {
19
19
  this.process.exitCode = 1;
20
20
  return;
21
21
  }
22
+ if (auth.source === "env") {
23
+ this.logger.error("LEVR_TOKEN is set: a workspace selected here would be saved for your login session, not for that token. Pass --workspace-id or set LEVR_WORKSPACE_ID instead.");
24
+ this.process.exitCode = 1;
25
+ return;
26
+ }
22
27
  configureClient(auth);
23
28
  const result = await authGetSitesV1();
24
29
  if (result.error) {
@@ -1,6 +1,6 @@
1
- import { authGetProfileV1, configureClient } from "./sdk-client-B4FMd_Fa.js";
2
- import { getApiUrl, getPatToken, readCredentials } from "./env-CvjMSRd7.js";
3
- import { isTokenExpired } from "./token-refresh-CJB7Qlxy.js";
1
+ import { authGetProfileV1, configureClient } from "./sdk-client-BgzKzVIR.js";
2
+ import { classifyToken, isTokenExpired } from "./token-refresh-BpFuU4Ij.js";
3
+ import { getApiUrl, getPatToken, readCredentials } from "./env-DjeRwmZ7.js";
4
4
  import chalk from "chalk";
5
5
 
6
6
  //#region src/commands/auth/statusHandler.ts
@@ -8,8 +8,10 @@ async function statusHandler() {
8
8
  const apiUrl = getApiUrl();
9
9
  const pat = getPatToken();
10
10
  if (pat) {
11
- if (await checkApiReachable(pat, "pat")) {
12
- this.process.stdout.write(`${chalk.green("ok")} Authenticated via LEVR_TOKEN (PAT)\n`);
11
+ const type = classifyToken(pat);
12
+ const kind = type === "pat" ? "personal access token" : "OAuth access token";
13
+ if (await checkApiReachable(pat, type)) {
14
+ this.process.stdout.write(`${chalk.green("ok")} Authenticated via LEVR_TOKEN (${kind})\n`);
13
15
  this.process.stdout.write(` API: ${apiUrl} (reachable)\n`);
14
16
  } else {
15
17
  this.process.stdout.write(`${chalk.yellow("warn")} LEVR_TOKEN is set but API is unreachable\n`);
@@ -1,5 +1,29 @@
1
- import { CLI_CLIENT_ID, deleteCredentials, getApiUrl, writeCredentials } from "./env-CvjMSRd7.js";
1
+ import { CLI_CLIENT_ID, deleteCredentials, getApiUrl, writeCredentials } from "./env-DjeRwmZ7.js";
2
2
 
3
+ //#region src/auth/token-shape.ts
4
+ /**
5
+ * Classify a bearer token by its SHAPE — [issue:ENG-6068].
6
+ *
7
+ * The server decides how to verify a token by looking at the token, not at
8
+ * where it came from (`isPersonalAccessToken` in the backend's auth
9
+ * middleware): a Levr personal access token starts with `tq_`, and anything
10
+ * else is handed to the JWT verifier. `LEVR_TOKEN` carries either kind — a
11
+ * PAT minted in Settings, or an OAuth access token a device-code login
12
+ * printed for CI — so the CLI must apply the same rule. Until ENG-6068 every
13
+ * `LEVR_TOKEN` was called a PAT, and the JWT-only steps (resolving
14
+ * `--workspace-id` / `LEVR_WORKSPACE_ID`, `levr workspace list|select`) were
15
+ * silently skipped for an OAuth token, which has no workspace of its own.
16
+ *
17
+ * Leaf module on purpose: no imports, so `resolve-token`, the handlers and
18
+ * their tests can all read it without pulling in credentials or the SDK.
19
+ */
20
+ const PAT_PREFIX = "tq_";
21
+ /** `tq_…` is a personal access token; everything else is treated as a JWT. */
22
+ function classifyToken(token) {
23
+ return token.startsWith(PAT_PREFIX) ? "pat" : "jwt";
24
+ }
25
+
26
+ //#endregion
3
27
  //#region src/auth/token-refresh.ts
4
28
  const REFRESH_BUFFER_MS = 300 * 1e3;
5
29
  /**
@@ -45,4 +69,4 @@ async function refreshToken(creds) {
45
69
  }
46
70
 
47
71
  //#endregion
48
- export { isTokenExpired, refreshToken };
72
+ export { classifyToken, isTokenExpired, refreshToken };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@levr-one/cli",
3
- "version": "0.12.5",
3
+ "version": "0.12.7",
4
4
  "description": "The command-line interface for Levr",
5
5
  "type": "module",
6
6
  "license": "MIT",
File without changes