@tokenoftrust/cli 2.4.10 → 2.4.11
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokenoftrust/cli",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.11",
|
|
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/hotfix.mjs
CHANGED
|
@@ -36,6 +36,7 @@ import { fail } from "../errors.mjs";
|
|
|
36
36
|
import { planForAction, printPlanAndConfirm } from "../plan.mjs";
|
|
37
37
|
import { startProgress } from "../progress.mjs";
|
|
38
38
|
import { openBrowser } from "../open.mjs";
|
|
39
|
+
import { missingGrantsOf, refusalHint } from "../admission-hint.mjs";
|
|
39
40
|
// Reuse `tot ship`'s operator-secret precedence + live-url derivation verbatim so
|
|
40
41
|
// ship + hotfix speak ONE operator-auth contract.
|
|
41
42
|
import { resolveOperatorSecret, liveUrlFor } from "./ship.mjs";
|
|
@@ -245,18 +246,27 @@ export async function runHotfix(
|
|
|
245
246
|
return 1;
|
|
246
247
|
}
|
|
247
248
|
const planData = await readJsonSafe(planRes);
|
|
248
|
-
if (
|
|
249
|
+
if (planRes.status === 401 || planRes.status === 403) {
|
|
250
|
+
// The admission rule's own refusal (body shape `{ ok:false, error,
|
|
251
|
+
// admission:{ missing } }`) — name exactly what's missing instead of a
|
|
252
|
+
// generic "check the operator secret" when the server named one.
|
|
249
253
|
const msg = planData?.error || `HTTP ${planRes.status}`;
|
|
254
|
+
const missing = missingGrantsOf(planData);
|
|
250
255
|
console.error(
|
|
251
256
|
fail(
|
|
252
257
|
`the hotfix plan was refused: ${msg}`,
|
|
253
|
-
|
|
254
|
-
? "check the operator secret and that it's authorised for this tenant"
|
|
255
|
-
: "check --tenant / --url / --pr, then re-run",
|
|
258
|
+
missing.length > 0 ? refusalHint(planRes.status, missing) : "check the operator secret and that it's authorised for this tenant",
|
|
256
259
|
),
|
|
257
260
|
);
|
|
258
261
|
return 1;
|
|
259
262
|
}
|
|
263
|
+
if (!planRes.ok && planData?.ok !== false) {
|
|
264
|
+
// A transport-level refusal the endpoint didn't explain in its own shape
|
|
265
|
+
// (tenant-resolution/network) — surface it honestly.
|
|
266
|
+
const msg = planData?.error || `HTTP ${planRes.status}`;
|
|
267
|
+
console.error(fail(`the hotfix plan was refused: ${msg}`, "check --tenant / --url / --pr, then re-run"));
|
|
268
|
+
return 1;
|
|
269
|
+
}
|
|
260
270
|
const plan = normalizeHotfixPlan(planData);
|
|
261
271
|
if (!plan.ok) {
|
|
262
272
|
console.error(fail(plan.message, hotfixNextStep(plan.reason)));
|
package/src/commands/pr.mjs
CHANGED
|
@@ -41,6 +41,7 @@ import { repoNameFromRemote, currentBranch } from "./submit.mjs";
|
|
|
41
41
|
// `tot pr list` reuses `tot ship --pr`'s operator-secret transport helpers verbatim
|
|
42
42
|
// (same env precedence, same queue normalisation) so the two speak one wire, not two.
|
|
43
43
|
import { resolveOperatorSecret, normalizeChangesQueue } from "./ship.mjs";
|
|
44
|
+
import { missingGrantsOf, refusalHint } from "../admission-hint.mjs";
|
|
44
45
|
import {
|
|
45
46
|
defaultCandidateStatePath,
|
|
46
47
|
readActiveChangeId,
|
|
@@ -280,11 +281,14 @@ export async function runPrListOperator({ tenant, secret, storefrontUrl = null }
|
|
|
280
281
|
}
|
|
281
282
|
if (!res.ok) {
|
|
282
283
|
const msg = data?.error || `HTTP ${res.status}`;
|
|
284
|
+
const missing = missingGrantsOf(data);
|
|
283
285
|
console.error(
|
|
284
286
|
fail(
|
|
285
287
|
`the candidate queue refused the request: ${msg}`,
|
|
286
288
|
res.status === 401 || res.status === 403
|
|
287
|
-
?
|
|
289
|
+
? missing.length > 0
|
|
290
|
+
? refusalHint(res.status, missing)
|
|
291
|
+
: "check the operator secret and that it's authorised for this tenant"
|
|
288
292
|
: "check --tenant / --url, then re-run",
|
|
289
293
|
),
|
|
290
294
|
);
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* Treat the token like a password: anyone holding it sees the unpublished site.
|
|
15
15
|
*/
|
|
16
16
|
import { resolveViewerTransport } from "../viewer-session.mjs";
|
|
17
|
+
import { missingGrantsOf, refusalHint } from "../admission-hint.mjs";
|
|
17
18
|
|
|
18
19
|
const MAX_TTL_SECONDS = 24 * 3600;
|
|
19
20
|
|
|
@@ -107,19 +108,19 @@ export async function run(argv, ctx, deps = {}) {
|
|
|
107
108
|
return 1;
|
|
108
109
|
}
|
|
109
110
|
|
|
111
|
+
let data = null;
|
|
112
|
+
try {
|
|
113
|
+
data = await res.json();
|
|
114
|
+
} catch {
|
|
115
|
+
/* non-JSON error body — this endpoint answers 401/403 as plain text */
|
|
116
|
+
}
|
|
110
117
|
if (res.status === 401 || res.status === 403) {
|
|
111
118
|
err(
|
|
112
119
|
`✗ your account can't view ${tenant}'s preview.\n\n` +
|
|
113
|
-
|
|
120
|
+
` → next: ${refusalHint(res.status, missingGrantsOf(data))}.`,
|
|
114
121
|
);
|
|
115
122
|
return 1;
|
|
116
123
|
}
|
|
117
|
-
let data = null;
|
|
118
|
-
try {
|
|
119
|
-
data = await res.json();
|
|
120
|
-
} catch {
|
|
121
|
-
/* non-JSON error body */
|
|
122
|
-
}
|
|
123
124
|
if (!res.ok || typeof data?.token !== "string") {
|
|
124
125
|
err(`✗ the store didn't mint a token (HTTP ${res.status}).\n\n → next: retry shortly; if it persists, report it with \`tot feedback\`.`);
|
|
125
126
|
return 1;
|