@tokenoftrust/cli 1.4.0-rc.0 → 1.4.0-rc.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/README.md +19 -13
- package/bin/tot.mjs +51 -11
- package/package.json +2 -2
- package/src/candidate-state.mjs +97 -0
- package/src/commands/{checkout.mjs → clone.mjs} +129 -28
- package/src/commands/dev.mjs +110 -15
- package/src/commands/doctor.mjs +4 -3
- package/src/commands/grants.mjs +8 -3
- package/src/commands/link.mjs +225 -0
- package/src/commands/login.mjs +19 -12
- package/src/commands/pr.mjs +200 -0
- package/src/commands/preview.mjs +71 -0
- package/src/commands/ship.mjs +53 -0
- package/src/commands/start.mjs +34 -14
- package/src/commands/submit.mjs +239 -23
- package/src/commands/validate.mjs +2 -2
- package/src/commands/whoami.mjs +6 -2
- package/src/context.mjs +2 -2
- package/src/oauth.mjs +92 -42
- package/src/obstacle-beacon.cjs +1 -1
- package/src/token-store.mjs +38 -15
package/src/token-store.mjs
CHANGED
|
@@ -30,36 +30,59 @@
|
|
|
30
30
|
*
|
|
31
31
|
* `TOT_HOME` overrides the home dir (used by tests to point at a temp dir).
|
|
32
32
|
*
|
|
33
|
-
* PROFILES (`TOT_PROFILE`)
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* (the renderer cache, last-tenant, etc.
|
|
39
|
-
*
|
|
33
|
+
* PROFILES (`TOT_PROFILE`) — OPTIONAL, for parallel work. Almost every developer
|
|
34
|
+
* leaves this UNSET and uses the single default `credentials.json` — that path is
|
|
35
|
+
* unchanged and is the norm. It exists only when you want MORE THAN ONE identity
|
|
36
|
+
* live at once (a staff `@tokenoftrust.com` sign-in and a plain developer one, or
|
|
37
|
+
* many parallel test identities): export a profile per shell and each gets its OWN
|
|
38
|
+
* credential file under the same `~/.tot` (the renderer cache, last-tenant, etc.
|
|
39
|
+
* stay shared — only the identity splits). The value is an OPAQUE label — any
|
|
40
|
+
* string works, so `export TOT_PROFILE=$(uuidgen)` per terminal/test is fine:
|
|
41
|
+
* - a clean short token (`staff`, `dev`, `test-7`) is used verbatim for a
|
|
42
|
+
* readable `credentials.<profile>.json`;
|
|
43
|
+
* - any other value (symbols, uppercase, long) is HASHED to a stable, safe
|
|
44
|
+
* `credentials.h<hash>.json` — so an arbitrary opaque id can never collide
|
|
45
|
+
* with another or escape `~/.tot`, while `tot whoami` still shows what you set.
|
|
40
46
|
*/
|
|
41
47
|
import {
|
|
42
48
|
readFileSync, writeFileSync, mkdirSync, renameSync, chmodSync, existsSync, rmSync,
|
|
43
49
|
} from "node:fs";
|
|
44
50
|
import { homedir } from "node:os";
|
|
51
|
+
import { createHash } from "node:crypto";
|
|
45
52
|
import { join, dirname } from "node:path";
|
|
46
53
|
|
|
54
|
+
/** A short token safe to drop straight into a filename (readable profiles). */
|
|
55
|
+
const CLEAN_PROFILE_RE = /^[a-z0-9_-]{1,64}$/;
|
|
56
|
+
|
|
47
57
|
/**
|
|
48
|
-
* The active
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* stray `/` or `..` from ever escaping the `~/.tot` dir.
|
|
58
|
+
* The active profile's DISPLAY label — the raw `TOT_PROFILE`, trimmed — or null
|
|
59
|
+
* when unset. This is what `tot whoami` shows; it is NOT the filename (see
|
|
60
|
+
* profileSlug, which makes any value filesystem-safe).
|
|
52
61
|
*/
|
|
53
62
|
export function activeProfile(env = process.env) {
|
|
54
|
-
|
|
55
|
-
|
|
63
|
+
return String(env.TOT_PROFILE || "").trim() || null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The active profile's safe filename token, or null for the default session. A
|
|
68
|
+
* clean short label passes through verbatim (readable files); ANY other opaque
|
|
69
|
+
* value is hashed — collision-resistant and incapable of a `/` or `..` path
|
|
70
|
+
* escape, so `TOT_PROFILE` can be a literally arbitrary identifier. Hashing the
|
|
71
|
+
* RAW value (not a stripped form) keeps distinct tokens distinct.
|
|
72
|
+
*/
|
|
73
|
+
export function profileSlug(env = process.env) {
|
|
74
|
+
const raw = String(env.TOT_PROFILE || "").trim();
|
|
75
|
+
if (!raw) return null;
|
|
76
|
+
const lower = raw.toLowerCase();
|
|
77
|
+
if (CLEAN_PROFILE_RE.test(lower)) return lower;
|
|
78
|
+
return `h${createHash("sha256").update(raw).digest("hex").slice(0, 16)}`;
|
|
56
79
|
}
|
|
57
80
|
|
|
58
81
|
/** Absolute path to the credential file for this environment (+ TOT_PROFILE). */
|
|
59
82
|
export function defaultCredentialsPath(env = process.env) {
|
|
60
83
|
const home = env.TOT_HOME || homedir();
|
|
61
|
-
const
|
|
62
|
-
return join(home, ".tot",
|
|
84
|
+
const slug = profileSlug(env);
|
|
85
|
+
return join(home, ".tot", slug ? `credentials.${slug}.json` : "credentials.json");
|
|
63
86
|
}
|
|
64
87
|
|
|
65
88
|
/**
|