litmus-cli 1.4.22 → 1.4.25
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/README.md +30 -0
- package/dist/commands/connect.d.ts +231 -2
- package/dist/commands/connect.d.ts.map +1 -1
- package/dist/commands/connect.js +311 -12
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +16 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/pause.d.ts +36 -0
- package/dist/commands/pause.d.ts.map +1 -0
- package/dist/commands/pause.js +110 -0
- package/dist/commands/pause.js.map +1 -0
- package/dist/commands/push.d.ts +7 -1
- package/dist/commands/push.d.ts.map +1 -1
- package/dist/commands/push.js +40 -1
- package/dist/commands/push.js.map +1 -1
- package/dist/commands/setup-check.d.ts +19 -0
- package/dist/commands/setup-check.d.ts.map +1 -0
- package/dist/commands/setup-check.js +48 -0
- package/dist/commands/setup-check.js.map +1 -0
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +6 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/submit.d.ts.map +1 -1
- package/dist/commands/submit.js +18 -0
- package/dist/commands/submit.js.map +1 -1
- package/dist/index.js +38 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/api.d.ts +27 -0
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +45 -0
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/environment-checks.d.ts +123 -0
- package/dist/lib/environment-checks.d.ts.map +1 -0
- package/dist/lib/environment-checks.js +324 -0
- package/dist/lib/environment-checks.js.map +1 -0
- package/dist/lib/git-bundle.d.ts +19 -0
- package/dist/lib/git-bundle.d.ts.map +1 -0
- package/dist/lib/git-bundle.js +71 -0
- package/dist/lib/git-bundle.js.map +1 -0
- package/dist/lib/session-end.d.ts +111 -0
- package/dist/lib/session-end.d.ts.map +1 -0
- package/dist/lib/session-end.js +126 -0
- package/dist/lib/session-end.js.map +1 -0
- package/dist/lib/submit-route.d.ts +68 -0
- package/dist/lib/submit-route.d.ts.map +1 -0
- package/dist/lib/submit-route.js +73 -0
- package/dist/lib/submit-route.js.map +1 -0
- package/dist/lib/watcher.js +23 -2
- package/dist/lib/watcher.js.map +1 -1
- package/dist/lib/workspace-token.d.ts +69 -0
- package/dist/lib/workspace-token.d.ts.map +1 -0
- package/dist/lib/workspace-token.js +93 -0
- package/dist/lib/workspace-token.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where `litmus push` gets its assessment token (ENG-2064).
|
|
3
|
+
*
|
|
4
|
+
* The command has two callers and they hold the credential differently:
|
|
5
|
+
*
|
|
6
|
+
* * ON A LAPTOP the candidate types it, `litmus push <token>`, copied from their
|
|
7
|
+
* assessment page. That is unchanged and stays the first branch here, so an
|
|
8
|
+
* explicit argument always wins.
|
|
9
|
+
* * INSIDE A CODESPACES v2 WORKSPACE nobody should type anything. The container
|
|
10
|
+
* was created for exactly one candidate, so the host already knows who they
|
|
11
|
+
* are and injects their own token at container start, the same way it injects
|
|
12
|
+
* the AI gateway pre-auth. See litmus-firstboot 3c in
|
|
13
|
+
* `infra/codespaces-v2-image/entrypoint/litmus-firstboot.sh` and hostd's
|
|
14
|
+
* `sanitize_workspace_env`.
|
|
15
|
+
*
|
|
16
|
+
* WHY AN ENV VAR AND NOT A FILE. The container's one persistent surface is the
|
|
17
|
+
* candidate home, and everything in it rides the submission zip and the R2
|
|
18
|
+
* durability tar. A bearer token must be at rest in neither, which is exactly why
|
|
19
|
+
* `hostd._stage_litmus_config` declines to put one in `.litmus/config.json`. The
|
|
20
|
+
* env is staged per boot into a root-owned file that firstboot CONSUMES, so
|
|
21
|
+
* nothing survives the boot on disk.
|
|
22
|
+
*
|
|
23
|
+
* The name is NOT a routing input and never has been (ENG-1025): it carries the
|
|
24
|
+
* credential only. `LITMUS_API_URL` still decides which deployment we talk to, and
|
|
25
|
+
* the workspace injects that separately.
|
|
26
|
+
*/
|
|
27
|
+
/** The env name the workspace injects the candidate's own token under. */
|
|
28
|
+
export declare const WORKSPACE_TOKEN_ENV = "LITMUS_ASSESSMENT_TOKEN";
|
|
29
|
+
/**
|
|
30
|
+
* Where the Codespaces v2 image installs this CLI.
|
|
31
|
+
*
|
|
32
|
+
* MUST match `DEST` in `infra/codespaces-v2-image/scripts/install-litmus-cli.sh`;
|
|
33
|
+
* `backend/tests/test_workspace_cli_install.py` holds the two together.
|
|
34
|
+
*/
|
|
35
|
+
export declare const WORKSPACE_INSTALL_PREFIX = "/opt/litmus/cli/";
|
|
36
|
+
/**
|
|
37
|
+
* The token to authenticate with, or `null` when we have none.
|
|
38
|
+
*
|
|
39
|
+
* `null` rather than a throw so the caller owns the wording: what to tell a
|
|
40
|
+
* candidate depends on whether they are sitting in a terminal we pre-authed
|
|
41
|
+
* (something is wrong with their container) or on their own machine (they simply
|
|
42
|
+
* left the argument off).
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveAssessmentToken(argToken: string | undefined, env?: NodeJS.ProcessEnv): string | null;
|
|
45
|
+
/**
|
|
46
|
+
* Is this the copy of the CLI baked into a Litmus workspace image?
|
|
47
|
+
*
|
|
48
|
+
* Read from our OWN module path rather than from an environment variable, and
|
|
49
|
+
* that choice is load-bearing. sshd builds a session environment from scratch, so
|
|
50
|
+
* a marker baked as a Docker `ENV` is simply absent in the candidate's shell
|
|
51
|
+
* unless it is also on the sshd allowlist, and a marker we inject alongside the
|
|
52
|
+
* token disappears in precisely the case this predicate exists to describe: the
|
|
53
|
+
* injection did not happen. The install prefix is a property of the artifact, is
|
|
54
|
+
* root-owned on a read-only rootfs, and is true whether or not staging worked.
|
|
55
|
+
*
|
|
56
|
+
* COMPARED ON THE URL's OWN PATHNAME, never on a host filesystem path, and that
|
|
57
|
+
* is the cross-platform rule AGENTS.md states for anything in `cli/src` reasoning
|
|
58
|
+
* about a path belonging to some OTHER platform. `WORKSPACE_INSTALL_PREFIX` is a
|
|
59
|
+
* LINUX container path; `fileURLToPath` renders for the HOST, so on Windows it
|
|
60
|
+
* answers `\opt\litmus\cli\...` and the prefix can never match. A file URL's
|
|
61
|
+
* pathname is always slash-separated by definition, so this is the one comparison
|
|
62
|
+
* that is correct on every host — which matters because the Windows CLI gate runs
|
|
63
|
+
* these tests and their expectations are literal paths.
|
|
64
|
+
*
|
|
65
|
+
* Used only to choose which sentence a candidate reads. Nothing security-relevant
|
|
66
|
+
* hangs off it.
|
|
67
|
+
*/
|
|
68
|
+
export declare function isWorkspaceInstall(moduleUrl: string): boolean;
|
|
69
|
+
//# sourceMappingURL=workspace-token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-token.d.ts","sourceRoot":"","sources":["../../src/lib/workspace-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,0EAA0E;AAC1E,eAAO,MAAM,mBAAmB,4BAA4B,CAAA;AAE5D;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,qBAAqB,CAAA;AAE1D;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,GAAG,IAAI,CAMf;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAc7D"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where `litmus push` gets its assessment token (ENG-2064).
|
|
3
|
+
*
|
|
4
|
+
* The command has two callers and they hold the credential differently:
|
|
5
|
+
*
|
|
6
|
+
* * ON A LAPTOP the candidate types it, `litmus push <token>`, copied from their
|
|
7
|
+
* assessment page. That is unchanged and stays the first branch here, so an
|
|
8
|
+
* explicit argument always wins.
|
|
9
|
+
* * INSIDE A CODESPACES v2 WORKSPACE nobody should type anything. The container
|
|
10
|
+
* was created for exactly one candidate, so the host already knows who they
|
|
11
|
+
* are and injects their own token at container start, the same way it injects
|
|
12
|
+
* the AI gateway pre-auth. See litmus-firstboot 3c in
|
|
13
|
+
* `infra/codespaces-v2-image/entrypoint/litmus-firstboot.sh` and hostd's
|
|
14
|
+
* `sanitize_workspace_env`.
|
|
15
|
+
*
|
|
16
|
+
* WHY AN ENV VAR AND NOT A FILE. The container's one persistent surface is the
|
|
17
|
+
* candidate home, and everything in it rides the submission zip and the R2
|
|
18
|
+
* durability tar. A bearer token must be at rest in neither, which is exactly why
|
|
19
|
+
* `hostd._stage_litmus_config` declines to put one in `.litmus/config.json`. The
|
|
20
|
+
* env is staged per boot into a root-owned file that firstboot CONSUMES, so
|
|
21
|
+
* nothing survives the boot on disk.
|
|
22
|
+
*
|
|
23
|
+
* The name is NOT a routing input and never has been (ENG-1025): it carries the
|
|
24
|
+
* credential only. `LITMUS_API_URL` still decides which deployment we talk to, and
|
|
25
|
+
* the workspace injects that separately.
|
|
26
|
+
*/
|
|
27
|
+
/** The env name the workspace injects the candidate's own token under. */
|
|
28
|
+
export const WORKSPACE_TOKEN_ENV = "LITMUS_ASSESSMENT_TOKEN";
|
|
29
|
+
/**
|
|
30
|
+
* Where the Codespaces v2 image installs this CLI.
|
|
31
|
+
*
|
|
32
|
+
* MUST match `DEST` in `infra/codespaces-v2-image/scripts/install-litmus-cli.sh`;
|
|
33
|
+
* `backend/tests/test_workspace_cli_install.py` holds the two together.
|
|
34
|
+
*/
|
|
35
|
+
export const WORKSPACE_INSTALL_PREFIX = "/opt/litmus/cli/";
|
|
36
|
+
/**
|
|
37
|
+
* The token to authenticate with, or `null` when we have none.
|
|
38
|
+
*
|
|
39
|
+
* `null` rather than a throw so the caller owns the wording: what to tell a
|
|
40
|
+
* candidate depends on whether they are sitting in a terminal we pre-authed
|
|
41
|
+
* (something is wrong with their container) or on their own machine (they simply
|
|
42
|
+
* left the argument off).
|
|
43
|
+
*/
|
|
44
|
+
export function resolveAssessmentToken(argToken, env = process.env) {
|
|
45
|
+
const explicit = argToken?.trim();
|
|
46
|
+
if (explicit)
|
|
47
|
+
return explicit;
|
|
48
|
+
const injected = env[WORKSPACE_TOKEN_ENV]?.trim();
|
|
49
|
+
if (injected)
|
|
50
|
+
return injected;
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Is this the copy of the CLI baked into a Litmus workspace image?
|
|
55
|
+
*
|
|
56
|
+
* Read from our OWN module path rather than from an environment variable, and
|
|
57
|
+
* that choice is load-bearing. sshd builds a session environment from scratch, so
|
|
58
|
+
* a marker baked as a Docker `ENV` is simply absent in the candidate's shell
|
|
59
|
+
* unless it is also on the sshd allowlist, and a marker we inject alongside the
|
|
60
|
+
* token disappears in precisely the case this predicate exists to describe: the
|
|
61
|
+
* injection did not happen. The install prefix is a property of the artifact, is
|
|
62
|
+
* root-owned on a read-only rootfs, and is true whether or not staging worked.
|
|
63
|
+
*
|
|
64
|
+
* COMPARED ON THE URL's OWN PATHNAME, never on a host filesystem path, and that
|
|
65
|
+
* is the cross-platform rule AGENTS.md states for anything in `cli/src` reasoning
|
|
66
|
+
* about a path belonging to some OTHER platform. `WORKSPACE_INSTALL_PREFIX` is a
|
|
67
|
+
* LINUX container path; `fileURLToPath` renders for the HOST, so on Windows it
|
|
68
|
+
* answers `\opt\litmus\cli\...` and the prefix can never match. A file URL's
|
|
69
|
+
* pathname is always slash-separated by definition, so this is the one comparison
|
|
70
|
+
* that is correct on every host — which matters because the Windows CLI gate runs
|
|
71
|
+
* these tests and their expectations are literal paths.
|
|
72
|
+
*
|
|
73
|
+
* Used only to choose which sentence a candidate reads. Nothing security-relevant
|
|
74
|
+
* hangs off it.
|
|
75
|
+
*/
|
|
76
|
+
export function isWorkspaceInstall(moduleUrl) {
|
|
77
|
+
let pathname;
|
|
78
|
+
try {
|
|
79
|
+
const url = new URL(moduleUrl);
|
|
80
|
+
// A non-file URL is not an install location. Checked rather than assumed so an
|
|
81
|
+
// `https:` module URL cannot match by having a same-looking path.
|
|
82
|
+
if (url.protocol !== "file:")
|
|
83
|
+
return false;
|
|
84
|
+
pathname = decodeURIComponent(url.pathname);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// Only decides which sentence a candidate reads, so an exotic or malformed
|
|
88
|
+
// module URL must degrade to the laptop wording rather than crash the command.
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
return pathname.startsWith(WORKSPACE_INSTALL_PREFIX);
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=workspace-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-token.js","sourceRoot":"","sources":["../../src/lib/workspace-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,0EAA0E;AAC1E,MAAM,CAAC,MAAM,mBAAmB,GAAG,yBAAyB,CAAA;AAE5D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,kBAAkB,CAAA;AAE1D;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CACpC,QAA4B,EAC5B,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,QAAQ,GAAG,QAAQ,EAAE,IAAI,EAAE,CAAA;IACjC,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAA;IAC7B,MAAM,QAAQ,GAAG,GAAG,CAAC,mBAAmB,CAAC,EAAE,IAAI,EAAE,CAAA;IACjD,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAA;IAC7B,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,IAAI,QAAgB,CAAA;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAA;QAC9B,+EAA+E;QAC/E,kEAAkE;QAClE,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO;YAAE,OAAO,KAAK,CAAA;QAC1C,QAAQ,GAAG,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,2EAA2E;QAC3E,+EAA+E;QAC/E,OAAO,KAAK,CAAA;IACd,CAAC;IACD,OAAO,QAAQ,CAAC,UAAU,CAAC,wBAAwB,CAAC,CAAA;AACtD,CAAC"}
|