@tokenoftrust/cli 2.0.14 → 2.0.16

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 CHANGED
@@ -15,9 +15,7 @@ tot ship # promote a reconciled preview live (diff + one con
15
15
 
16
16
  **Prerequisites: Node.js and an invite. Nothing else.** `tot dev` downloads the
17
17
  moat-free storefront runner and runs it as a plain host process — no Docker
18
- install, no hand-provisioned AWS credentials. (Docker remains available as a
19
- fallback — `tot dev --docker` — or automatically if the native artifact can't
20
- be fetched.)
18
+ install or hand-provisioned AWS credentials.
21
19
 
22
20
  For Storefront Private App contracts, examples, and LLM-ready developer material, start at
23
21
  [Storefront Devkit — Apps / Private](https://github.com/tokenoftrust/storefront-devkit/tree/main/apps/private).
@@ -30,7 +28,7 @@ published npm SDK.
30
28
  | --- | --- | --- |
31
29
  | `tot clone [<tenant>] [<dir>]` | **built** | Clone a store you're entitled to build on (mirrors `git clone`), with an authenticated remote configured. Dir defaults to `<tenant>`. No arg → list your stores. |
32
30
  | `tot validate` | next | Lint your store before you preview. |
33
- | `tot dev` | **built** | Run your store locally with save→reload — NATIVELY (no Docker; falls back to it with `--docker` or automatically if the native artifact isn't available). |
31
+ | `tot dev` | **built** | Run your store locally with save→reload — natively. |
34
32
  | `tot preview` | **built** | Bundle your edits into a compliance-reviewed preview (validates, auto-commits the known content trees, pushes the preview ref, opens/updates a candidate PR, reports the reconcile/compliance verdict + preview URL). `tot submit` / `tot deploy` still work as teaching aliases for this same flow. |
35
33
  | `tot ship` | **built** | Promote a reconciled preview live: always shows a diff-vs-live and asks for one `[y/N]` confirm (no `--yes`, refuses outside a terminal); records an approval request if you're not authorised to ship yourself. |
36
34
  | `tot pr [list\|view\|close]` | **built** | See and manage the candidate PRs `tot preview` opens (`gh pr`-shaped). |
@@ -75,4 +73,4 @@ A clean short name (`staff`, `dev`, `test-7`) becomes a readable `credentials.<n
75
73
 
76
74
  ## Design notes
77
75
 
78
- Dependency-free by design (global `fetch` + `git` + the system `tar`), so `npm i -g @tokenoftrust/cli` stays light. `tot dev` is the only command that pulls in the storefront runner: for a standalone checkout it downloads the moat-free runner artifact (`dev_renderer_artifact`, entitlement-gated, same shape as the Docker pull-token path) once per version to `~/.tot/cache/renderer/<version>/`, `pnpm install`s it there (via corepack — no separate pnpm install needed), and reuses that cache on every later run. See `src/` for the small modules: `context.mjs` (detection), `mcp.mjs` (transport), `auth.mjs` (the identity seam), `commands/`.
76
+ Dependency-free by design (global `fetch` + `git` + the system `tar`), so `npm i -g @tokenoftrust/cli` stays light. `tot dev` is the only command that pulls in the storefront runner: for a standalone checkout it downloads the moat-free runner artifact (`dev_renderer_artifact`, entitlement-gated) once per version to `~/.tot/cache/renderer/<version>/`, `pnpm install`s it there (via corepack — no separate pnpm install needed), and reuses that cache on every later run. See `src/` for the small modules: `context.mjs` (detection), `mcp.mjs` (transport), `auth.mjs` (the identity seam), `commands/`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tokenoftrust/cli",
3
- "version": "2.0.14",
3
+ "version": "2.0.16",
4
4
  "description": "Token of Trust developer CLI — clone a tenant store, run it locally with save→reload, and submit it for preview. Installs the `tot` command.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Token of Trust",
@@ -117,7 +117,7 @@ const USAGE = `tot clone — clone a tenant store you can build on (mirrors \`gi
117
117
  <tenant>-pr<N>)
118
118
 
119
119
  Options:
120
- --tag <tag> which repo (repo = "<tenant>-<tag>"). Default: main.
120
+ --tag <tag> deprecated compatibility input; tenant repos use the bare domain.
121
121
  --pr <N> clone PR #<N>'s head instead of the default branch — a
122
122
  READ-ONLY cross-tenant credential, not a push checkout.
123
123
  --remote-only don't clone; just mint + print the clone URL for <tenant>.
@@ -9,16 +9,14 @@
9
9
  *
10
10
  * checkout — a standalone tenant checkout has no runner. `tot dev` DOWNLOADS the
11
11
  * published, RUNNER ARTIFACT (a plain tarball — the exact
12
- * same tree Docker used to bake into the image, see
12
+ * same renderer tree used by the platform, see
13
13
  * scripts/build/build-runner.mjs) and runs it NATIVELY: no Docker, no
14
14
  * container. Cached once per version under ~/.tot/cache/renderer/, so
15
15
  * only the first run pays the download+install cost. The runner's own
16
16
  * scripts/tot-dev.mjs grafts the checkout in and boots astro dev
17
17
  * --host at http://localhost:<port>/<appDomain>/, with real (not
18
18
  * polled) file-watch HMR. Nothing is published; product data renders
19
- * from local fixtures. Docker remains available as a fallback
20
- * (--docker, or automatically if the native artifact can't be
21
- * fetched) — see runContainer below.
19
+ * from local fixtures.
22
20
  *
23
21
  * --sample — the ZERO-LOGIN, NO-MCP free taste. Scaffolds a bundled sample store
24
22
  * onto disk and runs it natively WITHOUT any authenticated
@@ -28,8 +26,7 @@
28
26
  *
29
27
  * IP note: the artifact is the pruned runner (control plane physically absent),
30
28
  * vended by a short-lived signed URL (`dev_renderer_artifact`) gated on the same
31
- * developer entitlement as the Docker pull token — no hand-provisioned AWS creds
32
- * either way.
29
+ * developer entitlement — no hand-provisioned AWS credentials.
33
30
  */
34
31
  import { spawn, spawnSync, execFileSync } from "node:child_process";
35
32
  import { existsSync, readFileSync, writeFileSync, mkdirSync, renameSync, rmSync, readdirSync, createWriteStream, openSync, closeSync, writeSync } from "node:fs";
@@ -55,7 +52,7 @@ import { streamDevLogs } from "../dev-logs.mjs";
55
52
  import { cockpitUrlFrom } from "../banner.mjs";
56
53
  import { recordDiagnostic } from "../diagnostics.mjs";
57
54
 
58
- /** The published runner image (--docker fallback). Override with --image / TOT_DEV_IMAGE. */
55
+ // Kept for the internal `tot start` migration path. `tot dev` itself is native-only.
59
56
  const DEFAULT_DEV_IMAGE =
60
57
  "242086487598.dkr.ecr.us-east-1.amazonaws.com/tot-dev:latest";
61
58
  const DEFAULT_MCP_URL = "https://mcp.tokenoftrust.com";
@@ -67,19 +64,17 @@ const DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org";
67
64
 
68
65
  export function parseArgs(argv) {
69
66
  const a = {
70
- workspace: null, port: "4321", image: null, mcp: null,
71
- noLogin: false, noOpen: false, docker: false, sample: false, help: false,
67
+ workspace: null, port: "4321", mcp: null,
68
+ noLogin: false, noOpen: false, sample: false, help: false,
72
69
  rendererVersion: null,
73
70
  };
74
71
  for (let i = 0; i < argv.length; i++) {
75
72
  const t = argv[i];
76
73
  if (t === "--workspace") a.workspace = argv[++i];
77
74
  else if (t === "--port") a.port = argv[++i];
78
- else if (t === "--image") a.image = argv[++i];
79
75
  else if (t === "--mcp") a.mcp = argv[++i];
80
76
  else if (t === "--no-login") a.noLogin = true;
81
77
  else if (t === "--no-open") a.noOpen = true;
82
- else if (t === "--docker") a.docker = true;
83
78
  else if (t === "--sample") a.sample = true;
84
79
  else if (t === "--renderer-version") a.rendererVersion = argv[++i];
85
80
  else if (t === "--help" || t === "-h") a.help = true;
@@ -95,8 +90,6 @@ const USAGE = `tot dev — run your store locally with save→reload
95
90
  no MCP, no account (the free first taste)
96
91
  tot dev --workspace <dir> run a specific checkout directory
97
92
  tot dev --port <n> host port (default 4321)
98
- tot dev --docker use the Docker runner image instead of the native path
99
- tot dev --image <ref> runner image ref, only with --docker (default: the published image)
100
93
  tot dev --no-open don't auto-open the browser when the server is up
101
94
 
102
95
  Edit content/*.html or the theme + save → the browser reloads. Private local
@@ -128,8 +121,7 @@ export async function run(argv, ctx) {
128
121
  return runMonorepo(ctx, argv);
129
122
  }
130
123
 
131
- // Standalone checkout (or an explicit --workspace anywhere): native by default,
132
- // Docker on request (--docker) or as an automatic fallback (see runStandalone).
124
+ // Standalone checkout (or an explicit --workspace anywhere): native runtime.
133
125
  const workspace = args.workspace
134
126
  ? resolve(args.workspace)
135
127
  : ctx.mode === "checkout"
@@ -148,31 +140,20 @@ export async function run(argv, ctx) {
148
140
  }
149
141
 
150
142
  /**
151
- * Standalone-checkout entrypoint: native runtime by default (no Docker
152
- * prerequisite), Docker on explicit request, and Docker as an automatic
153
- * fallback when the native artifact can't be fetched (e.g. the MCP's
154
- * dev_renderer_artifact isn't configured on this deployment yet) — so `tot dev`
155
- * keeps working instead of hard-failing.
143
+ * Standalone-checkout entrypoint: run the native renderer. When the entitled
144
+ * artifact is unavailable, use the public runner package on the same release line.
156
145
  */
157
146
  async function runStandalone(workspace, args, ctx) {
158
- if (args.docker) return runContainer(workspace, args, ctx);
159
147
  try {
160
148
  return await runNative(workspace, args, ctx);
161
149
  } catch (e) {
162
150
  if (e instanceof NativeArtifactUnavailableError) {
163
151
  // Entitled artifact unavailable — stay NATIVE on the public npm runner
164
152
  // (@tokenoftrust/storefront-runner, the SAME renderer bits), so
165
- // `tot dev` never needs Docker just because dev_renderer_artifact isn't
166
- // configured. Docker is the last resort only if the public runner is also
167
- // unreachable (offline).
168
153
  try {
169
- console.error(`~ couldn't set up your store preview the usual way (${e.message}) — using the fallback preview engine instead (no Docker needed).`);
154
+ console.error(`~ couldn't set up your store preview the usual way (${e.message}) — using the public preview engine instead.`);
170
155
  return await runNativePublic(workspace, args, ctx);
171
156
  } catch (e2) {
172
- if (e2 instanceof NativeArtifactUnavailableError) {
173
- console.error(`~ couldn't reach the fallback preview engine either (${e2.message}) — switching to the Docker runner.`);
174
- return runContainer(workspace, args, ctx);
175
- }
176
157
  console.error(formatError(e2));
177
158
  return e2 instanceof CliError ? (e2.exitCode ?? 2) : 2;
178
159
  }
@@ -189,7 +170,7 @@ async function runStandalone(workspace, args, ctx) {
189
170
  * ensureSampleRenderer (env override → in-tree monorepo → version-pinned public
190
171
  * npm, reusing the matching `public-<version>` cache), which throws
191
172
  * NativeArtifactUnavailableError when even the public runner can't be fetched
192
- * (offline) so the caller can drop to Docker.
173
+ * (offline) so the caller can report the unavailable local preview.
193
174
  */
194
175
  async function runNativePublic(workspace, args, ctx) {
195
176
  const cfg = readWorkspaceConfig(workspace);
@@ -769,9 +769,9 @@ export function parseNameStatus(text) {
769
769
  }
770
770
 
771
771
  /**
772
- * Derive the g1b forge repo name (`"<tenant>-<tag>"`, e.g. `"acme.com-main"`)
772
+ * Derive the g1b forge repo name (the bare tenant domain, e.g. `"acme.com"`)
773
773
  * from the checkout's authenticated origin remote — the SAME name
774
- * `tenant_checkout` minted it as, so no separate lookup or stored tag is
774
+ * `tenant_checkout` resolved, so no separate lookup or stored tag is
775
775
  * needed. Returns null when the remote URL can't be parsed (candidate_open is
776
776
  * then skipped, reported, never crashed). Pure — unit-tested.
777
777
  * @param {string} remoteUrl
@@ -812,11 +812,10 @@ export function isForgeAuthError(text) {
812
812
  }
813
813
 
814
814
  /**
815
- * Derive the checkout's forge tag from its repo name (`"<tenant>-<tag>"`), so a
816
- * re-mint targets the SAME repo the checkout points at. Defaults to "main" when the
817
- * repo is bare (`"<tenant>"`, post-8425) or the `<tenant>-` prefix doesn't match, so
818
- * the mint degrades to the clone default rather than a wrong tag. Pure —
819
- * unit-tested.
815
+ * Retain compatibility with historical `"<tenant>-<tag>"` repos when re-minting a
816
+ * checkout credential. Current repos use the bare tenant domain and therefore
817
+ * resolve to the compatibility default `main`; the server ignores that tag for
818
+ * current repo naming. Pure — unit-tested.
820
819
  * @param {string|null} repoName
821
820
  * @param {string} tenant
822
821
  * @returns {string}
package/src/validate.mjs CHANGED
@@ -212,7 +212,6 @@ export const KNOWN_EMBEDS = [
212
212
  },
213
213
  ];
214
214
  const KNOWN_EMBED_SLUGS = new Set(KNOWN_EMBEDS.map((p) => p.slug));
215
- const EMBED_ALWAYS_ALLOWED = new Set(["static.cloudflareinsights.com", "cloudflareinsights.com"]);
216
215
  const EMBED_SRC_RE = /<(?:script|iframe)\b[^>]*\bsrc\s*=\s*["']([^"']+)["']/gi;
217
216
 
218
217
  /** Classify one HTML doc: which known providers + unknown external src origins. */
@@ -229,8 +228,7 @@ function scanHtmlForEmbeds(html) {
229
228
  } catch {
230
229
  continue;
231
230
  }
232
- const host = new URL(origin).hostname;
233
- if (EMBED_ALWAYS_ALLOWED.has(host) || catalogOrigins.has(origin)) continue;
231
+ if (catalogOrigins.has(origin)) continue;
234
232
  unknown.add(origin);
235
233
  }
236
234
  return { knownSlugs, unknownOrigins: [...unknown] };