@tokenoftrust/cli 2.0.16 → 2.0.18
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/package.json +1 -1
- package/src/commands/clone.mjs +31 -1
- package/src/commands/dev.mjs +32 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokenoftrust/cli",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.18",
|
|
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",
|
package/src/commands/clone.mjs
CHANGED
|
@@ -287,7 +287,22 @@ export async function run(argv, ctx) {
|
|
|
287
287
|
* cloned: boolean, dir: string|null, head: string|null }>}
|
|
288
288
|
*/
|
|
289
289
|
export async function checkoutTenant(client, { tenant, tag = "main", cloneDir = null, redact = (s) => s }) {
|
|
290
|
-
|
|
290
|
+
// The switch is LOAD-BEARING, so its refusal is the error the developer must see. When
|
|
291
|
+
// the tenant is not one of this session's clients the server refuses here with the real
|
|
292
|
+
// cause (no grant / a grant issued to a client this identity is not bound to / a grant
|
|
293
|
+
// issued after sign-in that needs a re-auth) — far more specific than the tenant_checkout
|
|
294
|
+
// refusal that follows it. Surfacing the switch's own words, with the server's nextAction,
|
|
295
|
+
// stops a genuinely-unentitled tenant from being reported as a scope-selection slip.
|
|
296
|
+
try {
|
|
297
|
+
await client.callTool("client_switch", { tenant });
|
|
298
|
+
} catch (e) {
|
|
299
|
+
throw new CliError(redact(String(e?.message || e)), {
|
|
300
|
+
next:
|
|
301
|
+
"confirm you're entitled to this store — `tot grants` lists what your session can " +
|
|
302
|
+
"act on, and `tot login` refreshes a grant issued after you signed in",
|
|
303
|
+
cause: e,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
291
306
|
// vc-app-binding safety-net (08-18, §5): ensure THIS developer is bound to the
|
|
292
307
|
// storefront version-control app BEFORE checkout, so tenant_checkout can resolve
|
|
293
308
|
// `appForCaller` for them instead of 403-ing "No version-control app is bound." The
|
|
@@ -541,6 +556,21 @@ export function checkoutError(checkout) {
|
|
|
541
556
|
(c && (c.message || (typeof c.error === "string" ? c.error : c.error?.message))) ||
|
|
542
557
|
(c && typeof c.raw === "string" && c.raw.trim() ? c.raw.trim() : null) ||
|
|
543
558
|
null;
|
|
559
|
+
// Not entitled: the session resolved NO grant or client context for the asserted tenant.
|
|
560
|
+
// Distinct from both not-provisioned (the store is fine) and over-scope (you hold it but
|
|
561
|
+
// haven't switched) — and the one case where the remedy is upstream of this checkout.
|
|
562
|
+
if (
|
|
563
|
+
typeof msg === "string" &&
|
|
564
|
+
/not among the tenants your session holds|^Not entitled/i.test(msg)
|
|
565
|
+
) {
|
|
566
|
+
return {
|
|
567
|
+
message: msg,
|
|
568
|
+
next:
|
|
569
|
+
"`tot grants` lists what your session can actually act on — a grant whose grantee " +
|
|
570
|
+
"your identity doesn't resolve to never becomes visible here; if it was issued after " +
|
|
571
|
+
"you signed in, run `tot login` to refresh, then retry",
|
|
572
|
+
};
|
|
573
|
+
}
|
|
544
574
|
// The store's repo isn't provisioned yet — it isn't set up for this developer.
|
|
545
575
|
if (typeof msg === "string" && /not provisioned/i.test(msg)) {
|
|
546
576
|
return {
|
package/src/commands/dev.mjs
CHANGED
|
@@ -1039,6 +1039,36 @@ function sourceVersionKey(source) {
|
|
|
1039
1039
|
* @param {{ log?: (m: string) => void, cacheRoot?: string }} [opts]
|
|
1040
1040
|
* @returns {Promise<string>} the cached, installed runner tree's root directory.
|
|
1041
1041
|
*/
|
|
1042
|
+
/**
|
|
1043
|
+
* Rename the runner's shipped lockfile back to the name pnpm reads, so a pinned runner
|
|
1044
|
+
* version pins the graph it RUNS rather than just its own source.
|
|
1045
|
+
*
|
|
1046
|
+
* npm strips `pnpm-lock.yaml` from published tarballs unconditionally (the same
|
|
1047
|
+
* always-excluded list as package-lock.json / yarn.lock), so build-runner.mjs emits a
|
|
1048
|
+
* second copy as `pnpm-lock.runner.yaml`, which survives the publish. Verified both
|
|
1049
|
+
* directions: the published 2.0.33 tarball carries pnpm-workspace.yaml and no lock,
|
|
1050
|
+
* and a packed 2.0.34 tree delivers only the alias.
|
|
1051
|
+
*
|
|
1052
|
+
* Why it matters: without the restore, every developer resolves their own graph. Runner
|
|
1053
|
+
* 2.0.33 was built against vite 8.1.0 / rolldown 1.1.3 and installed as 8.2.2 / 1.2.8,
|
|
1054
|
+
* where an .astro parse regression failed the dependency scan — and Vite answers a
|
|
1055
|
+
* failed scan by skipping pre-bundling for the whole app rather than erroring, silently
|
|
1056
|
+
* disabling the SSR prebundle the renderer's own config depends on. Pages still
|
|
1057
|
+
* rendered, so nothing caught it.
|
|
1058
|
+
*
|
|
1059
|
+
* Never clobbers an existing `pnpm-lock.yaml`: the entitled .tar.gz path is a plain
|
|
1060
|
+
* tarball rather than an npm publish, so it already carries the real name.
|
|
1061
|
+
* @param {string} dir the extracted runner tree
|
|
1062
|
+
* @returns {boolean} whether a lock was restored
|
|
1063
|
+
*/
|
|
1064
|
+
export function restoreShippedLock(dir) {
|
|
1065
|
+
const alias = join(dir, "pnpm-lock.runner.yaml");
|
|
1066
|
+
const real = join(dir, "pnpm-lock.yaml");
|
|
1067
|
+
if (!existsSync(alias) || existsSync(real)) return false;
|
|
1068
|
+
renameSync(alias, real);
|
|
1069
|
+
return true;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1042
1072
|
export async function installRunnerTarball(
|
|
1043
1073
|
{ source, version, isUrl = true, strip = 0, integrity = null },
|
|
1044
1074
|
{ log = (m) => console.error(m), cacheRoot = RENDERER_CACHE_ROOT } = {},
|
|
@@ -1137,6 +1167,8 @@ export async function installRunnerTarball(
|
|
|
1137
1167
|
/** @type {any} */ (err).permanent = true;
|
|
1138
1168
|
throw err;
|
|
1139
1169
|
}
|
|
1170
|
+
// Must run BEFORE the install, or it has no effect at all.
|
|
1171
|
+
restoreShippedLock(stagingDir);
|
|
1140
1172
|
// Pin the runner install to PUBLIC npm. The moat-free runner has only public
|
|
1141
1173
|
// deps, but the HOST's global ~/.npmrc may point `registry` at a private
|
|
1142
1174
|
// mirror (an internal proxy that 502s, or one an invited developer can't
|