turnzero 0.36.0 → 0.37.0-next.1

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.
@@ -37,7 +37,7 @@ var shownHealthPathOf = (path) => {
37
37
  }
38
38
  return JSON.stringify("\u2026");
39
39
  };
40
- var healthPathUnservedDetail = (path) => `No source text in the zip names the health path ${shownHealthPathOf(path)}. Serve it from your code, or set the manifest's health to a served path and call submit_manifest.`;
40
+ var healthPathUnservedDetail = (path) => `No source text in the zip names the health path ${shownHealthPathOf(path)}. Serve it from your code, or set the manifest's health to a served path and call tzcloud_submit_manifest.`;
41
41
  var deployAreaName = (application) => `${DEPLOY_AREA_PREFIX}${application}`;
42
42
  var UPLOAD_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
43
43
  var uploadFileName = (id) => `${id}.zip`;
@@ -46,6 +46,36 @@ var COMMAND_ENVIRONMENTS = Object.freeze(["development", "production"]);
46
46
  var DEPLOY_ACTION_PATH = "/api/v1/actions/deploy";
47
47
  var ACTIONS_ROUTE_PREFIX = "/api/v1/actions/";
48
48
  var actionPathOf = (action) => `${ACTIONS_ROUTE_PREFIX}${action}`;
49
+ var COMMAND_ACTION_SURFACE = Object.freeze({
50
+ add_test_end_users: "tzcloud",
51
+ check_deploy: "tzcloud",
52
+ create_application: "tzcloud",
53
+ create_environment: "tzcloud",
54
+ deploy: "tzcloud",
55
+ deploy_files: "tzcloud",
56
+ list_secrets: "tzcloud",
57
+ mint_upload_grant: "tzcloud",
58
+ promote: "tzcloud",
59
+ read_export: "tzcloud",
60
+ read_library: "tzcloud",
61
+ read_logs: "tzcloud",
62
+ read_schedules: "tzcloud",
63
+ read_status: "tzcloud",
64
+ request_export: "tzcloud",
65
+ restart_application: "tzcloud",
66
+ run_schedule: "tzcloud",
67
+ sign_in_test_end_user: "tzcloud",
68
+ store_secret: "tzcloud",
69
+ submit_manifest: "tzcloud",
70
+ list_tokens: "account",
71
+ mint_token: "account",
72
+ read_account: "account",
73
+ read_documentation: "account",
74
+ revoke_token: "account",
75
+ set_plan_quota: "account",
76
+ start: "account"
77
+ });
78
+ var toolNameOf = (action) => COMMAND_ACTION_SURFACE[action] === "account" ? action : `${COMMAND_ACTION_SURFACE[action]}_${action}`;
49
79
  var progressPathOf = (upload) => `${DEPLOY_PROGRESS_PREFIX}${upload}/progress`;
50
80
  var PROGRESS_PAUSE_SECONDS = 2;
51
81
  var PROGRESS_READ_BOUND_SECONDS = 60;
@@ -54,7 +84,7 @@ var DEPLOY_NO_WAIT_VARIABLE = "TURNZERO_DEPLOY_NO_WAIT";
54
84
  var PROGRESS_EXIT_STATUS = Object.freeze({ deployed: 0, failed: 1, refused: 2, nothing_started: 3 });
55
85
  var PROGRESS_SETTLED_DEPLOYED = "settled: deployed version ";
56
86
  var PROGRESS_SETTLED_FAILED = "settled: failed";
57
- var commandStopSentence = (application, environment = UPLOAD_ENVIRONMENT) => `The command stopped waiting, and the deploy may go on: call read_status from your tool with application ${application} and environment ${environment}, giving it wait_seconds so the call waits for the deploy to settle.`;
87
+ var commandStopSentence = (application, environment = UPLOAD_ENVIRONMENT) => `The command stopped waiting, and the deploy may go on: call tzcloud_read_status from your tool with application ${application} and environment ${environment}, giving it wait_seconds so the call waits for the deploy to settle.`;
58
88
  var startBodyOf = (application, upload, environment = UPLOAD_ENVIRONMENT) => ({
59
89
  application,
60
90
  environment,
@@ -62,18 +92,21 @@ var startBodyOf = (application, upload, environment = UPLOAD_ENVIRONMENT) => ({
62
92
  });
63
93
  var TURNZERO_CLOUD_PACKAGE = "turnzero";
64
94
  var LOGIN_SUBCOMMAND = "login";
65
- var LOGIN_OPTION = Object.freeze({ origin: "--origin", noBrowser: "--no-browser" });
95
+ var LOGIN_OPTION = Object.freeze({ origin: "--origin", noBrowser: "--no-browser", device: "--device" });
66
96
  var loginLineOf = (origin) => commandLineOf(origin, LOGIN_SUBCOMMAND, origin !== DEFAULT_COMMAND_ORIGIN ? { origin } : {});
67
97
  var HAND_OVER_SENTENCE = "If your tool's own safety check refuses a command, first take any route named above that your tool can still use, telling the person which and why. Only if none works, give the person that exact command to run once in their own terminal, never a rewritten one.";
68
98
  var COMPUTER_LOGIN_PATH = "/approve/computer";
69
99
  var COMPUTER_LOGIN_QUERY = Object.freeze({ challenge: "challenge", state: "state", port: "port", label: "label" });
100
+ var COMPUTER_LOGIN_MODE_MEMBER = "mode";
101
+ var COMPUTER_LOGIN_DEVICE_MODE = "device";
70
102
  var LOGIN_STATE_FORM = /^[A-Za-z0-9_-]{43}$/;
71
103
  var computerLoginAddressOf = (origin, login2) => {
72
104
  const query = new URLSearchParams();
73
105
  query.set(COMPUTER_LOGIN_QUERY.challenge, login2.challenge);
74
106
  query.set(COMPUTER_LOGIN_QUERY.state, login2.state);
75
- if (login2.port !== null) query.set(COMPUTER_LOGIN_QUERY.port, String(login2.port));
107
+ if (login2.port !== null && login2.device !== true) query.set(COMPUTER_LOGIN_QUERY.port, String(login2.port));
76
108
  query.set(COMPUTER_LOGIN_QUERY.label, login2.label);
109
+ if (login2.device === true) query.set(COMPUTER_LOGIN_MODE_MEMBER, COMPUTER_LOGIN_DEVICE_MODE);
77
110
  return `${origin}${COMPUTER_LOGIN_PATH}?${query.toString()}`;
78
111
  };
79
112
  var DEPLOY_SUBCOMMAND = "deploy";
@@ -154,7 +187,12 @@ var MINTED_TOKEN_PREFIX = TOKEN_PREFIX;
154
187
  var MINTED_TOKEN_FORM = new RegExp(`^${MINTED_TOKEN_PREFIX}[A-Za-z0-9_-]{43}$`);
155
188
  var SECRET_SUBCOMMAND = "secret";
156
189
  var SECRET_ACTS = Object.freeze(["store", "rotate"]);
157
- var SECRET_ACTION = Object.freeze({ store: "store_secret", rotate: "rotate_secret" });
190
+ var SECRET_ACTION = Object.freeze({ store: "store_secret", rotate: "store_secret" });
191
+ var SECRET_REPLACE_MEMBER = Object.freeze({ replace: true });
192
+ var SECRET_CALL = Object.freeze({
193
+ store: toolNameOf("store_secret"),
194
+ rotate: `${toolNameOf("store_secret")} with replace: true`
195
+ });
158
196
  var SECRET_OPTION = Object.freeze({
159
197
  name: "--name",
160
198
  application: "--application",
@@ -178,12 +216,13 @@ var EXPORT_MANIFEST_FILE = "manifest.json";
178
216
  var exportFileName = (exportId, path) => `${exportId}/${path}`;
179
217
  var EXPORT_SUBCOMMAND = "export";
180
218
  var EXPORT_ACTS = Object.freeze(["download"]);
181
- var DOWNLOAD_GRANT_ACTION = "mint_download_grant";
219
+ var DOWNLOAD_GRANT_ACTION = "request_export";
220
+ var DOWNLOAD_GRANT_CALL = `the ${toolNameOf(DOWNLOAD_GRANT_ACTION)} call with download: true`;
182
221
  var EXPORT_OPTION = Object.freeze({ export: "--export", path: DEPLOY_OPTION.path, origin: DEPLOY_OPTION.origin });
183
222
  var LIBRARY_SUBCOMMAND = "library";
184
223
  var LIBRARY_ACTS = Object.freeze(["take"]);
185
224
  var LIBRARY_OPTION = Object.freeze({ entry: "--entry", path: DEPLOY_OPTION.path, origin: DEPLOY_OPTION.origin });
186
- var LIBRARY_READ_ACTION = "read_library_entry";
225
+ var LIBRARY_READ_ACTION = "read_library";
187
226
  var LIBRARY_READ_PATH = actionPathOf(LIBRARY_READ_ACTION);
188
227
  var LIBRARY_READ_CHUNK = 16e3;
189
228
  var LIBRARY_ENTRY_NAME_FORM = /^[a-z0-9][a-z0-9_-]*(\/[a-z0-9][a-z0-9_-]*)?$/;
@@ -287,6 +326,10 @@ var COMPLETION_MINT = "mint";
287
326
  var MINT_MEMBER = "mint";
288
327
  var MINT_OPTION = "--mint";
289
328
  var MINT_ID_FORM = UPLOAD_ID;
329
+ var MINT_DEVICE = "device";
330
+ var DEVICE_POLL_PENDING = "authorization_pending";
331
+ var DEVICE_POLL_SECONDS = 5;
332
+ var DEVICE_ROW_SECONDS = 3600;
290
333
  var TZMESH_SUBCOMMAND = "tzmesh";
291
334
  var TZMESH_REGISTER_ACT = "register";
292
335
  var TZMESH_OPTION = {
@@ -483,9 +526,9 @@ function compareWireVersions(a, b) {
483
526
 
484
527
  // src/turnzero_cloud_command/plane_wire.ts
485
528
  var PLANE_WIRE_NEEDED = Object.freeze({
486
- action_payloads: "2026-10-24.10",
487
- management_api: "2026-10-10.5",
488
- wire_errors: "2026-10-10.6"
529
+ action_payloads: "2026-11-04.8",
530
+ management_api: "2026-11-04.7",
531
+ wire_errors: "2026-11-04.2"
489
532
  });
490
533
 
491
534
  // src/turnzero_cloud_command/version.ts
@@ -919,6 +962,7 @@ var loginLineFor = (io2, origin) => {
919
962
  return onWindows(io2) ? windowsLineOf(line) : line;
920
963
  };
921
964
  var authorizeLineFor = (io2, origin) => printedLineOf(io2, commandLineOf(origin, AUTHORIZE_SUBCOMMAND, origin !== DEFAULT_COMMAND_ORIGIN ? { origin } : {}), origin);
965
+ var deviceLoginLineFor = (io2, origin) => printedLineOf(io2, commandLineOf(origin, LOGIN_SUBCOMMAND, { ...origin !== DEFAULT_COMMAND_ORIGIN ? { origin } : {}, flags: [LOGIN_OPTION.device] }), origin);
922
966
  var loginLinesFor = (io2, origin) => [
923
967
  ...ranThroughNpx(io2) ? [installLineOf(origin)] : [],
924
968
  loginLineFor(io2, origin)
@@ -1020,10 +1064,12 @@ var noTokenSentence = (origin, expiredAt) => expiredAt === null ? `No credential
1020
1064
  var VARIABLE_ROUTE_SENTENCES = `A tool connected by a minted token, or a job, sets ${MINTED_TOKEN_VARIABLE} from where its token is kept, never by writing the value in a command. It sets ${ORIGIN_VARIABLE} to the address that minted the token if that is not ${DEFAULT_COMMAND_ORIGIN}, then runs the command again. Such a tool cannot use ${MINT_TOKEN_ACTION}, which works only under a sign-in. A tool sets ${MINTED_TOKEN_VARIABLE} for one command at a time and unsets it once that command ends.`;
1021
1065
  var authorizeRouteSentence = (origin) => `${AUTHORIZE_SUBCOMMAND}${originWordsOf(origin)} run with nothing piped prints the ${MINT_TOKEN_ACTION} call a signed-in tool makes to authorize this computer.`;
1022
1066
  var LOGIN_ROUTE_OPENER = "A person logs this computer in once, in a terminal of their own, and its token then stays on this computer for 30 days:";
1023
- var DEPLOY_ROUTES_SENTENCE = "For regular use, prefer this command wherever your tool can install and run it and reach the platform. A first simple test within the caps of your tool's deploy_files call may deploy through deploy_files, as may any folder within them where this command cannot work. Past the caps, where your tool may not install or run this command, upload a zip with mint_upload_grant, then name it as deploy's artifact.";
1067
+ var DEPLOY_ROUTES_SENTENCE = "For regular use, prefer this command wherever your tool can install and run it and reach the platform. A first simple test within the caps of your tool's tzcloud_deploy_files call may deploy through tzcloud_deploy_files, as may any folder within them where this command cannot work. Past the caps, where your tool may not install or run this command, upload a zip with tzcloud_mint_upload_grant, then name it as tzcloud_deploy's artifact.";
1068
+ var deviceRouteSentence = (deviceLine) => `An AI tool that cannot authorize this computer through a signed-in Turn Zero connection, with no terminal for a person, runs ${deviceLine} and sends the person its link.`;
1024
1069
  var loginRouteLines = (io2, origin, deployFiles = true) => [
1025
1070
  LOGIN_ROUTE_OPENER,
1026
1071
  ...loginLinesFor(io2, origin),
1072
+ deviceRouteSentence(deviceLoginLineFor(io2, origin)),
1027
1073
  ...deployFiles ? [DEPLOY_ROUTES_SENTENCE] : [],
1028
1074
  HAND_OVER_SENTENCE
1029
1075
  ];
@@ -1114,9 +1160,9 @@ var computerLabelOf = (host) => {
1114
1160
  return label === "" ? LABEL_FALLBACK : label;
1115
1161
  };
1116
1162
  var newVerifier = () => randomBytes2(32).toString("base64url");
1117
- var newPendingEntry = (now) => {
1163
+ var newPendingEntry = (now, lifeMs = PENDING_REQUEST_MS) => {
1118
1164
  const verifier = newVerifier();
1119
- return { verifier, challenge: codeChallengeOf(verifier), expires_at: new Date(now.getTime() + PENDING_REQUEST_MS).toISOString() };
1165
+ return { verifier, challenge: codeChallengeOf(verifier), expires_at: new Date(now.getTime() + lifeMs).toISOString() };
1120
1166
  };
1121
1167
  var hideStandingTokens = (io2, state) => {
1122
1168
  for (const entry of state.origins.values()) io2.hide(entry.token, REDACTED_TOKEN);
@@ -1137,7 +1183,7 @@ var firstActNamed = (kind, origin = DEFAULT_COMMAND_ORIGIN) => kind === "tzmesh"
1137
1183
  ) : `${kind === "authorized computer" ? AUTHORIZE_SUBCOMMAND : `${TOKEN_SUBCOMMAND} ${TOKEN_REQUEST_ACT}`}${originWordsOf(origin)}`;
1138
1184
  var noConnectionLine = (origin) => `Where your tool holds no connection signed in to ${origin}, ${MINT_TOKEN_ACTION} is not among its tools: a person connects the tool and signs in, in a browser, before the call.`;
1139
1185
  var loginWaySentence = (loginLines) => `A person can instead log this computer in themselves, in a terminal of their own, by running ${loginLines.join(", then ")}, and approving the login in the browser.`;
1140
- var AUTHORIZE_HAND_OVER_SENTENCE = "If your tool's own safety check refuses the answered line, a deploy can still go through a route that does not require the turnzero command. That is deploy_files within its caps or, past them where your tool can zip and upload the folder, mint_upload_grant followed by deploy naming the uploaded zip as artifact. Tell the person which route you take and why. Only where no such route serves, give the person that exact line to run once in their own terminal, never a rewritten one.";
1186
+ var AUTHORIZE_HAND_OVER_SENTENCE = "If your tool's own safety check refuses the answered line, a deploy can still go through a route that does not require the turnzero command. That is tzcloud_deploy_files within its caps or, past them where your tool can zip and upload the folder, tzcloud_mint_upload_grant followed by tzcloud_deploy naming the uploaded zip as artifact. Tell the person which route you take and why. Only where no such route serves, give the person that exact line to run once in their own terminal, never a rewritten one.";
1141
1187
  var TZMESH_HAND_OVER_SENTENCE = "If your tool's own safety check refuses the answered line, give the person that exact line to run once in their own terminal, never a rewritten one.";
1142
1188
  var OPTIONS_LINE_HEAD = "options: ";
1143
1189
  var tzmeshFirstActLines = (origin, pending, completing2) => [
@@ -1165,6 +1211,7 @@ var firstActLines = (origin, kind, pending, label, loginLines = [], completing2
1165
1211
  ];
1166
1212
  var reusedRequestSentence = (origin, pending) => `A request for ${origin} is pending until ${pending.expires_at}, so its challenge is printed again and no new verifier was made.`;
1167
1213
  var replacedRequestSentence = (origin, expired2) => `The request pending for ${origin} expired at ${expired2.expires_at}, so a new one replaces it. A line minted against the old challenge is refused at its exchange, and a ${MINT_TOKEN_ACTION} call naming the new challenge below answers a fresh one.`;
1214
+ var unchangedRequestSentence = (origin, expiresAt) => `Nothing was sent, and the request pending for ${origin} stands unchanged until ${expiresAt}.`;
1168
1215
  async function firstAct(io2, origin, kind, say, opener = null, completing2 = "") {
1169
1216
  const kept2 = keepPendingRequest(io2, origin, say);
1170
1217
  if ("status" in kept2) return kept2.status;
@@ -1183,7 +1230,7 @@ async function firstAct(io2, origin, kind, say, opener = null, completing2 = "")
1183
1230
  }
1184
1231
  return COMMAND_STATUS.done;
1185
1232
  }
1186
- function keepPendingRequest(io2, origin, say) {
1233
+ function keepPendingRequest(io2, origin, say, lifeMs) {
1187
1234
  const place = credentialFileOf(io2);
1188
1235
  const read2 = readMovingCredentialFile(io2, place, say);
1189
1236
  if (!("state" in read2)) {
@@ -1193,36 +1240,43 @@ function keepPendingRequest(io2, origin, say) {
1193
1240
  hideStandingTokens(io2, read2.state);
1194
1241
  const now = io2.clock();
1195
1242
  const standing = read2.state.pending.get(origin);
1196
- let pending;
1197
- let opening;
1198
- if (standing !== void 0 && pendingLives(standing, now)) {
1199
- pending = standing;
1200
- io2.hide(pending.verifier, REDACTED_VERIFIER);
1201
- opening = reusedRequestSentence(origin, pending);
1202
- } else {
1203
- pending = newPendingEntry(now);
1204
- io2.hide(pending.verifier, REDACTED_VERIFIER);
1243
+ const write = (entry, unchanged = null) => {
1205
1244
  const tag = runTagOf();
1245
+ const after = unchanged === null ? "Nothing was sent, and no request is pending." : unchangedRequestSentence(origin, unchanged);
1206
1246
  const release = io2.whenEnded(() => dropCredentialWriting(io2, place, tag));
1207
1247
  try {
1208
1248
  const prepared = prepareCredentialFile(io2, place, tag);
1209
1249
  if ("unwritten" in prepared) {
1210
- say(`${unwritableFileSentence(place.path, prepared.unwritten)} Nothing was sent, and no request is pending.`);
1211
- return { status: COMMAND_STATUS.nothing_started };
1250
+ say(`${unwritableFileSentence(place.path, prepared.unwritten)} ${after}`);
1251
+ return COMMAND_STATUS.nothing_started;
1212
1252
  }
1213
- const written = updateCredentialFile(io2, place, tag, withPending(origin, pending));
1253
+ const written = updateCredentialFile(io2, place, tag, withPending(origin, entry));
1214
1254
  if (!("written" in written)) {
1215
- say("unwritten" in written ? `${unwritableFileSentence(place.path, written.unwritten)} Nothing was sent, and no request is pending.` : readRefusalOf(written, place.path));
1216
- return { status: COMMAND_STATUS.nothing_started };
1255
+ say("unwritten" in written ? `${unwritableFileSentence(place.path, written.unwritten)} ${after}` : readRefusalOf(written, place.path));
1256
+ return COMMAND_STATUS.nothing_started;
1217
1257
  }
1258
+ return null;
1218
1259
  } finally {
1219
1260
  release();
1220
1261
  dropCredentialWriting(io2, place, tag);
1221
1262
  }
1222
- opening = standing !== void 0 ? replacedRequestSentence(origin, standing) : "";
1223
- return { pending, opening, standing: standing !== void 0 ? { kind: "replaced", expired: standing } : { kind: "new" } };
1263
+ };
1264
+ if (standing !== void 0 && pendingLives(standing, now)) {
1265
+ io2.hide(standing.verifier, REDACTED_VERIFIER);
1266
+ let pending2 = standing;
1267
+ if (lifeMs !== void 0) {
1268
+ pending2 = { ...standing, expires_at: new Date(now.getTime() + lifeMs).toISOString() };
1269
+ const refused2 = write(pending2, standing.expires_at);
1270
+ if (refused2 !== null) return { status: refused2 };
1271
+ }
1272
+ return { pending: pending2, opening: reusedRequestSentence(origin, pending2), standing: { kind: "reused" } };
1224
1273
  }
1225
- return { pending, opening, standing: { kind: "reused" } };
1274
+ const pending = newPendingEntry(now, lifeMs);
1275
+ io2.hide(pending.verifier, REDACTED_VERIFIER);
1276
+ const refused = write(pending);
1277
+ if (refused !== null) return { status: refused };
1278
+ const opening = standing !== void 0 ? replacedRequestSentence(origin, standing) : "";
1279
+ return { pending, opening, standing: standing !== void 0 ? { kind: "replaced", expired: standing } : { kind: "new" } };
1226
1280
  }
1227
1281
  var TOKEN_CALL_BOUND_SECONDS = 60;
1228
1282
  var EXCHANGE_ACT = "exchange";
@@ -1240,13 +1294,22 @@ var postAction = async (io2, origin, action, bearer, userAgent, body) => {
1240
1294
  redirect: "manual",
1241
1295
  signal: controller.signal
1242
1296
  });
1243
- return { status: response.status, redirected: redirected(response), text: await response.text() };
1297
+ return { status: response.status, redirected: redirected(response), text: await response.text(), retryAfter: response.headers.get("retry-after") };
1244
1298
  } catch {
1245
1299
  return null;
1246
1300
  } finally {
1247
1301
  cancel();
1248
1302
  }
1249
1303
  };
1304
+ var WHOLE_SECONDS = /^[0-9]{1,9}$/;
1305
+ var devicePollWaitMsOf = (answered) => {
1306
+ if (answered === null || answered.redirected) return null;
1307
+ if (answered.status === 429) {
1308
+ const named = (answered.retryAfter ?? "").trim();
1309
+ return (WHOLE_SECONDS.test(named) ? Number(named) : DEVICE_POLL_SECONDS) * 1e3;
1310
+ }
1311
+ return answered.status === 400 && markedRefusalOf(answered.status, answered.text)?.error === DEVICE_POLL_PENDING ? DEVICE_POLL_SECONDS * 1e3 : null;
1312
+ };
1250
1313
  var NO_LONGER_SERVES = Object.freeze([401, 404]);
1251
1314
  var revokedRowOf = (answer, id) => {
1252
1315
  const row = answer?.token;
@@ -1328,7 +1391,8 @@ var whoamiLineFor = (io2, origin) => printedLineOf(io2, commandLineOf(origin, WH
1328
1391
  var accountUnreadSentence = (whoami2) => `The account this computer's token acts as was not read, and the token is kept: run ${whoami2} to read it.`;
1329
1392
  var CLAIMED_LINE_HEAD = "claimed: ";
1330
1393
  async function completeAct(io2, origin, kind, presentation, userAgent, say, deliver = () => void 0, login2 = null, carried = null) {
1331
- const held = "mint" in presentation;
1394
+ const held = !("code" in presentation);
1395
+ const device = "device" in presentation ? presentation.device : null;
1332
1396
  const unread = held ? MINT_UNPRESENTED : TOKEN_CODE_UNREAD;
1333
1397
  const place = credentialFileOf(io2);
1334
1398
  const read2 = readMovingCredentialFile(io2, place, say);
@@ -1348,10 +1412,11 @@ async function completeAct(io2, origin, kind, presentation, userAgent, say, deli
1348
1412
  io2.hide(pending.challenge, REDACTED_CHALLENGE);
1349
1413
  const tag = runTagOf();
1350
1414
  const stage = carried?.stage ?? { now: "unsent", ended: false };
1415
+ let waiting = false;
1351
1416
  const release = io2.whenEnded(() => {
1352
1417
  stage.ended = true;
1353
1418
  say(
1354
- carried !== null ? carried.endedLine(stage.now) : stage.now === "unsent" ? `The run was ended before its exchange. ${unread}` : stage.now === "sent" ? `The run was ended during its exchange. ${exchangeUnknownSentence(kind, origin, login2)}` : `The run was ended after its exchange minted a token, which may not have been ${kind === "authorized computer" ? "kept" : "printed"}: list_tokens from your tool shows it by its label, and revoke_token ends it.`
1419
+ carried !== null ? carried.endedLine(stage.now) : device !== null && waiting ? device.stoppedLine : stage.now === "unsent" ? `The run was ended before its exchange. ${unread}` : stage.now === "sent" ? `The run was ended during its exchange. ${exchangeUnknownSentence(kind, origin, login2)}` : `The run was ended after its exchange minted a token, which may not have been ${kind === "authorized computer" ? "kept" : "printed"}: list_tokens from your tool shows it by its label, and revoke_token ends it.`
1355
1420
  );
1356
1421
  dropCredentialWriting(io2, place, tag);
1357
1422
  carried?.drop();
@@ -1368,7 +1433,7 @@ async function completeAct(io2, origin, kind, presentation, userAgent, say, deli
1368
1433
  return COMMAND_STATUS.nothing_started;
1369
1434
  }
1370
1435
  if (stage.ended) return COMMAND_STATUS.nothing_started;
1371
- const older = await planeWireRefusal(io2, origin, held ? "" : TOKEN_CODE_UNREAD_FIRST);
1436
+ const older = await planeWireRefusal(io2, origin, device !== null ? void 0 : held ? "" : TOKEN_CODE_UNREAD_FIRST);
1372
1437
  if (stage.ended) return COMMAND_STATUS.nothing_started;
1373
1438
  if (older !== null) {
1374
1439
  say(older);
@@ -1383,7 +1448,28 @@ async function completeAct(io2, origin, kind, presentation, userAgent, say, deli
1383
1448
  }
1384
1449
  }
1385
1450
  stage.now = "sent";
1386
- const answered = "mint" in presentation ? await postAction(io2, origin, MINT_TOKEN_ACTION, pending.verifier, userAgent, heldExchangeBodyOf(presentation.mint)) : await postAction(io2, origin, MINT_TOKEN_ACTION, presentation.code, userAgent, exchangeBodyOf(pending.verifier));
1451
+ let answered;
1452
+ if (device !== null) {
1453
+ for (; ; ) {
1454
+ answered = await postAction(io2, origin, MINT_TOKEN_ACTION, pending.verifier, userAgent, heldExchangeBodyOf(MINT_DEVICE));
1455
+ if (stage.ended) break;
1456
+ const wait = devicePollWaitMsOf(answered);
1457
+ if (wait === null) break;
1458
+ const left = device.until - io2.clock().getTime();
1459
+ if (left > 0) {
1460
+ waiting = true;
1461
+ await io2.sleep(Math.min(wait, left));
1462
+ waiting = false;
1463
+ if (stage.ended) return COMMAND_STATUS.nothing_started;
1464
+ }
1465
+ if (io2.clock().getTime() >= device.until) {
1466
+ say(device.endedLine);
1467
+ return COMMAND_STATUS.nothing_started;
1468
+ }
1469
+ }
1470
+ } else {
1471
+ answered = "code" in presentation ? await postAction(io2, origin, MINT_TOKEN_ACTION, presentation.code, userAgent, exchangeBodyOf(pending.verifier)) : await postAction(io2, origin, MINT_TOKEN_ACTION, pending.verifier, userAgent, heldExchangeBodyOf("mint" in presentation ? presentation.mint : MINT_DEVICE));
1472
+ }
1387
1473
  if (stage.ended) {
1388
1474
  const late = answered === null ? null : planeObjectOf(answered.text);
1389
1475
  if (late !== null && typeof late.value === "string") io2.hide(late.value, REDACTED_TOKEN);
@@ -1416,7 +1502,7 @@ async function completeAct(io2, origin, kind, presentation, userAgent, say, deli
1416
1502
  }
1417
1503
  for (const line of refusalLines(EXCHANGE_ACT, answered.status, refusal)) say(line);
1418
1504
  say(
1419
- answered.status === 429 ? `Nothing was minted, and ${held ? "nothing was spent" : "the token code was not spent"}: run the line again after the wait the answer names.` : `Nothing was minted. ${mintAgainSentence(kind, origin, login2)}`
1505
+ answered.status === 429 ? `Nothing was minted, and ${held ? "nothing was spent" : "the token code was not spent"}: run the line again after the wait the answer names.` : `Nothing was minted. ${device !== null ? device.refusedLine : mintAgainSentence(kind, origin, login2)}`
1420
1506
  );
1421
1507
  return COMMAND_STATUS.nothing_started;
1422
1508
  }
@@ -1911,7 +1997,7 @@ var EXPORT_DOWNLOAD_OPTIONS = Object.freeze([
1911
1997
  name: EXPORT_OPTION.export,
1912
1998
  value: "<application id>/<export id>",
1913
1999
  required: true,
1914
- description: `The application and its completed export, as the ${DOWNLOAD_GRANT_ACTION} call returned them, joined by a slash.`
2000
+ description: `The application and its completed export, as ${DOWNLOAD_GRANT_CALL} returned them, joined by a slash.`
1915
2001
  },
1916
2002
  {
1917
2003
  name: EXPORT_OPTION.path,
@@ -1929,7 +2015,7 @@ var EXPORT_DOWNLOAD_OPTIONS = Object.freeze([
1929
2015
  var EXPORT_DOWNLOAD_CREDENTIAL = Object.freeze({
1930
2016
  grant: "download grant",
1931
2017
  aGrant: "a download grant",
1932
- call: `the ${DOWNLOAD_GRANT_ACTION} call`,
2018
+ call: DOWNLOAD_GRANT_CALL,
1933
2019
  mintedToken: false
1934
2020
  });
1935
2021
  var EXPORT_READS_AT_ONCE = 4;
@@ -1950,14 +2036,14 @@ var EXPORT_LINE_HEAD = Object.freeze({
1950
2036
  });
1951
2037
  var defaultExportFolderOf = (exportId) => `export-${exportId}`;
1952
2038
  var NOTHING_WRITTEN = "Nothing was written.";
1953
- var exportAgain = (application, exportId) => `Call ${DOWNLOAD_GRANT_ACTION} from your tool with application ${application} and export ${exportId}, naming the same folder as local_path where this line named one, and run the line it answers as given.`;
2039
+ var exportAgain = (application, exportId) => `Call ${toolNameOf(DOWNLOAD_GRANT_ACTION)} with download: true from your tool with application ${application} and export ${exportId}, naming the same folder as local_path where this line named one, and run the line it answers as given.`;
1954
2040
  var exportDownloadOptionsOf = (call, cwd) => {
1955
2041
  if (!EXPORT_ACTS.some((act) => act === call.act)) return { refusal: `${EXPORT_SUBCOMMAND} takes ${EXPORT_ACTS.join(" or ")} as its first argument. ${NOTHING_WRITTEN}` };
1956
2042
  const named = call.named[EXPORT_OPTION.export];
1957
2043
  const [application, exportId, ...rest] = (named ?? "").split("/");
1958
2044
  if (named === void 0 || rest.length > 0 || application === void 0 || exportId === void 0 || !UPLOAD_ID.test(application) || !UPLOAD_ID.test(exportId)) {
1959
2045
  return {
1960
- refusal: `${EXPORT_OPTION.export} names the application and its export as the ${DOWNLOAD_GRANT_ACTION} call answered them, <application id>/<export id>, each a lowercase UUID. Run the line the ${DOWNLOAD_GRANT_ACTION} call answered as given. ${NOTHING_WRITTEN}`
2046
+ refusal: `${EXPORT_OPTION.export} names the application and its export as ${DOWNLOAD_GRANT_CALL} answered them, <application id>/<export id>, each a lowercase UUID. Run the line ${DOWNLOAD_GRANT_CALL} answered as given. ${NOTHING_WRITTEN}`
1961
2047
  };
1962
2048
  }
1963
2049
  const origin = commandOriginOf(call.named[EXPORT_OPTION.origin] ?? DEFAULT_COMMAND_ORIGIN);
@@ -1966,7 +2052,7 @@ var exportDownloadOptionsOf = (call, cwd) => {
1966
2052
  return { application, export: exportId, folder: resolve2(cwd, path ?? defaultExportFolderOf(exportId)), named: path !== void 0, origin: origin.origin };
1967
2053
  };
1968
2054
  var exportEntriesOf = (text, application, exportId) => {
1969
- const unread = { refusal: `The export's manifest is not one the command reads: call read_export from your tool with application ${application} and export ${exportId} to see the export. ${NOTHING_WRITTEN}` };
2055
+ const unread = { refusal: `The export's manifest is not one the command reads: call tzcloud_read_export from your tool with application ${application} and export ${exportId} to see the export. ${NOTHING_WRITTEN}` };
1970
2056
  let manifest;
1971
2057
  try {
1972
2058
  manifest = JSON.parse(text);
@@ -1978,7 +2064,7 @@ var exportEntriesOf = (text, application, exportId) => {
1978
2064
  if (read2.export !== exportId || read2.application !== application) return unread;
1979
2065
  if (read2.state !== "completed") {
1980
2066
  return {
1981
- refusal: `The export did not complete${typeof read2.outcome === "string" ? ` (${read2.outcome})` : ""}, so its files are not read: call request_export from your tool for a fresh export, then ${DOWNLOAD_GRANT_ACTION} once read_export answers it completed. ${NOTHING_WRITTEN}`
2067
+ refusal: `The export did not complete${typeof read2.outcome === "string" ? ` (${read2.outcome})` : ""}, so its files are not read: call tzcloud_request_export from your tool for a fresh export, then ${toolNameOf(DOWNLOAD_GRANT_ACTION)} with download: true once tzcloud_read_export answers it completed. ${NOTHING_WRITTEN}`
1982
2068
  };
1983
2069
  }
1984
2070
  const tables = read2.database?.tables ?? [];
@@ -2047,7 +2133,7 @@ var addressable = (entry) => ![entry.area, ...entry.name.split(/[\\/]/)].some((s
2047
2133
  var applicationFolderSentence = () => `The folder the line runs in holds package.json, so it is an application's folder, and the line names no ${EXPORT_OPTION.path}. The export would be written inside it, where a deploy from that folder would carry every file of the export. Run the line again with ${EXPORT_OPTION.path} naming a folder outside this one, which the same grant serves until it expires. ${NOTHING_WRITTEN}`;
2048
2134
  var ABSENT_FILE_STATUS = 404;
2049
2135
  var ABSENT_FILE_ERROR = "no_such_file";
2050
- var freshExportLine = (absent) => `${absent === 1 ? "A file the manifest names was" : `${absent} files the manifest names were`} answered as an absent name and ${absent === 1 ? "was" : "were"} not read. A fresh export has the application's files as they now stand: call request_export from your tool, then ${DOWNLOAD_GRANT_ACTION} once read_export answers it completed.`;
2136
+ var freshExportLine = (absent) => `${absent === 1 ? "A file the manifest names was" : `${absent} files the manifest names were`} answered as an absent name and ${absent === 1 ? "was" : "were"} not read. A fresh export has the application's files as they now stand: call tzcloud_request_export from your tool, then ${toolNameOf(DOWNLOAD_GRANT_ACTION)} with download: true once tzcloud_read_export answers it completed.`;
2051
2137
  var runAgainLine = (again) => `Run the line again before its grant expires, or take a fresh one. ${again} It skips the files on disk and reads again each file whose read failed.`;
2052
2138
  var MANIFEST_READ = "The manifest read";
2053
2139
  var fileReadOf = (natural) => `The read of ${shownWhole(natural)}`;
@@ -2165,7 +2251,7 @@ async function exportDownload(call, io2) {
2165
2251
  if (!(manifestRead instanceof Response)) {
2166
2252
  if (manifestRead.kind === "ended") for (const line of manifestRead.lines) io2.print(line);
2167
2253
  else io2.print(`The export's manifest could not be read: ${manifestRead.kind === "failed" ? manifestRead.reason : "the read was capped"}.`);
2168
- io2.print(`${manifestRead.kind === "ended" ? again : `Call read_export from your tool with application ${options.application} and export ${options.export} to see whether the export completed. Then ${again.charAt(0).toLowerCase()}${again.slice(1)}`} ${NOTHING_WRITTEN}`);
2254
+ io2.print(`${manifestRead.kind === "ended" ? again : `Call tzcloud_read_export from your tool with application ${options.application} and export ${options.export} to see whether the export completed. Then ${again.charAt(0).toLowerCase()}${again.slice(1)}`} ${NOTHING_WRITTEN}`);
2169
2255
  return COMMAND_STATUS.nothing_started;
2170
2256
  }
2171
2257
  let manifestBytes;
@@ -2366,21 +2452,21 @@ async function exportDownload(call, io2) {
2366
2452
  }
2367
2453
  return COMMAND_STATUS.done;
2368
2454
  }
2369
- var EXPORT_AFTER_OWN_ERROR = `the files written so far stand under the folder, and a fresh line from ${DOWNLOAD_GRANT_ACTION} with the same folder skips them`;
2455
+ var EXPORT_AFTER_OWN_ERROR = `the files written so far stand under the folder, and a fresh line from ${DOWNLOAD_GRANT_CALL} with the same folder skips them`;
2370
2456
  var EXPORT_DOWNLOAD_ROW = Object.freeze({
2371
2457
  name: EXPORT_SUBCOMMAND,
2372
2458
  acts: EXPORT_ACTS,
2373
- summary: `Downloads every file of a completed export: its manifest, each table's CSV, and each stored file. It runs under the download grant the ${DOWNLOAD_GRANT_ACTION} call returned. It checks each file against the length that response states and the version the manifest gives.`,
2459
+ summary: `Downloads every file of a completed export: its manifest, each table's CSV, and each stored file. It runs under the download grant ${DOWNLOAD_GRANT_CALL} returned. It checks each file against the length that response states and the version the manifest gives.`,
2374
2460
  example: `${EXPORT_SUBCOMMAND} ${EXPORT_ACTS[0]} ${EXPORT_OPTION.export} <application id>/<export id> ${EXPORT_OPTION.path} <folder>`,
2375
2461
  options: EXPORT_DOWNLOAD_OPTIONS,
2376
2462
  credential: EXPORT_DOWNLOAD_CREDENTIAL,
2377
2463
  statuses: {
2378
2464
  done: "every file the manifest lists on disk, moved ones reported",
2379
2465
  failed: "a file failed, was cut short, or was refused: the closing lines give the command to run again, or a fresh export if a file was reported as an absent name",
2380
- unknown: `the run stopped before the end: a fresh command from ${DOWNLOAD_GRANT_ACTION} resumes it`,
2466
+ unknown: `the run stopped before the end: a fresh command from ${DOWNLOAD_GRANT_CALL} resumes it`,
2381
2467
  nothing_started: "an option, the grant, the folder, or the manifest was refused, or the platform was too old, and nothing was written"
2382
2468
  },
2383
- note: [`Run the ${EXPORT_SUBCOMMAND} download command a ${DOWNLOAD_GRANT_ACTION} call returns, as given, before its grant expires. Run it from a folder that is not an application's, or with ${EXPORT_OPTION.path} giving one outside it. It writes into a new or empty folder, or one an earlier run of the same export wrote, skipping the files already on disk.`],
2469
+ note: [`Run the ${EXPORT_SUBCOMMAND} download command ${DOWNLOAD_GRANT_CALL} returns, as given, before its grant expires. Run it from a folder that is not an application's, or with ${EXPORT_OPTION.path} giving one outside it. It writes into a new or empty folder, or one an earlier run of the same export wrote, skipping the files already on disk.`],
2384
2470
  afterOwnError: EXPORT_AFTER_OWN_ERROR,
2385
2471
  run: exportDownload
2386
2472
  });
@@ -2551,7 +2637,7 @@ var nearestHealthPathOf = (found, path) => {
2551
2637
  };
2552
2638
  var shownHealthPath = (path) => shownNoteName(bareHealthPath(path));
2553
2639
  var healthLineOf = (path) => `${WARNING_LINE_HEAD}${MANIFEST_FILE} names the health path ${shownHealthPath(path)}, and no other file of the zip holds its last segment, package files and documentation set aside. A deploy waits for that path to answer 200 three times in a row, so check that the application serves it. A route built in another form is not seen here.`;
2554
- var nearestHealthLineOf = (nearest) => `The zip's source names the path ${shownHealthPath(nearest)}: where that is the health path meant, set the manifest's health to it and call submit_manifest.`;
2640
+ var nearestHealthLineOf = (nearest) => `The zip's source names the path ${shownHealthPath(nearest)}: where that is the health path meant, set the manifest's health to it and call tzcloud_submit_manifest.`;
2555
2641
  var CREDENTIAL_FILE_NAMES = Object.freeze(["id_rsa", "id_dsa", "id_ecdsa", "id_ed25519", ".netrc", ".pgpass", ".htpasswd", "credentials.json"]);
2556
2642
  var CLIENT_SECRET_OPENING = "client_secret";
2557
2643
  var CLIENT_SECRET_ENDING = ".json";
@@ -2589,7 +2675,7 @@ var credentialFileName = (name) => {
2589
2675
  return CREDENTIAL_FILE_NAMES.includes(last) || last.startsWith(CLIENT_SECRET_OPENING) && last.endsWith(CLIENT_SECRET_ENDING) || CREDENTIAL_FILE_ENDINGS.some((ending) => last.endsWith(ending));
2590
2676
  };
2591
2677
  var looksLikeCredential = (name, data) => credentialFileName(name) || holdsPrivateKey(data);
2592
- var credentialAdvice = (subject) => `Where ${subject} holds a secret, move it out of the application's folder before the next deploy, and store a secret value the application needs with ${SECRET_ACTION.store}. The ${HASH_SUBCOMMAND} subcommand with ${HASH_OPTION.list} prints every file the zip holds.`;
2678
+ var credentialAdvice = (subject) => `Where ${subject} holds a secret, move it out of the application's folder before the next deploy, and store a secret value the application needs with ${toolNameOf(SECRET_ACTION.store)}. The ${HASH_SUBCOMMAND} subcommand with ${HASH_OPTION.list} prints every file the zip holds.`;
2593
2679
  var credentialLineOf = (names) => names.length === 0 ? null : names.length === 1 ? `${WARNING_LINE_HEAD}the zip holds a file that looks like a key or a credential, and the upload includes it: ${listedNames(names)}. ${credentialAdvice("it")}` : `${WARNING_LINE_HEAD}the zip holds ${names.length} files that look like keys or credentials, and the upload includes them: ${listedNames(names)}. ${credentialAdvice("one")}`;
2594
2680
  var LOCAL_WRITE_EXTENSIONS = Object.freeze([".js", ".mjs", ".cjs", ".ts"]);
2595
2681
  var LOCAL_WRITE_UNREAD_FOLDERS = Object.freeze(["client/", "lib/"]);
@@ -3198,7 +3284,7 @@ function artifactLayoutOf(reading) {
3198
3284
  if (nested.length === 1) {
3199
3285
  refuse(`The zip holds no package.json at its root, and its top-level folder ${shownEntry(`${nested[0]}/`)} holds one: zip that folder's contents rather than the folder, so package.json sits at the zip's root, and deploy again`);
3200
3286
  }
3201
- refuse("The zip holds no package.json at its root. The image runs npm start at the zip's root: zip the project folder's contents with package.json at the top, and deploy again");
3287
+ refuse("The zip has no root package.json. The image runs npm start there: zip the folder's contents with package.json at the top, then deploy again. For a static site, add the server in read_documentation's /cloud/guides/publish-a-static-site/");
3202
3288
  }
3203
3289
  const manifest = parsePackageJson(reading.packageJson);
3204
3290
  if (!isRecord(manifest)) {
@@ -3225,7 +3311,7 @@ var nestingDeeperThan = (value, max) => {
3225
3311
  function manifestCopyDepthRefusal(reading) {
3226
3312
  if (reading.manifestJson === null) return;
3227
3313
  if (nestingDeeperThan(parsePackageJson(reading.manifestJson), MANIFEST_COPY_DEPTH_MAX)) {
3228
- throw new DeployRefusal(400, "artifact_layout_invalid", `The zip's manifest.json nests deeper than the ${MANIFEST_COPY_DEPTH_MAX} levels the deploy reads: the platform reads the manifest submit_manifest recorded, so flatten the zip's copy or leave it out, and deploy again.`);
3314
+ throw new DeployRefusal(400, "artifact_layout_invalid", `The zip's manifest.json nests deeper than the ${MANIFEST_COPY_DEPTH_MAX} levels the deploy reads: the platform reads the manifest tzcloud_submit_manifest recorded, so flatten the zip's copy or leave it out, and deploy again.`);
3229
3315
  }
3230
3316
  }
3231
3317
  function clientReadingOf(records) {
@@ -3487,7 +3573,7 @@ var DEPLOY_OPTIONS = Object.freeze([
3487
3573
  name: DEPLOY_OPTION.application,
3488
3574
  value: "<application id>",
3489
3575
  required: true,
3490
- description: "The application to deploy, by its id, a lowercase UUID, as given in the command your tool's deploy call returns."
3576
+ description: "The application to deploy, by its id, a lowercase UUID, as given in the command your tool's tzcloud_deploy call returns."
3491
3577
  },
3492
3578
  {
3493
3579
  name: DEPLOY_OPTION.origin,
@@ -3506,7 +3592,7 @@ var DEPLOY_OPTIONS = Object.freeze([
3506
3592
  value: "",
3507
3593
  required: false,
3508
3594
  flag: true,
3509
- description: "Rotates production's database credential with this deploy, as given in the command a deploy call with rotate_database_credential returns."
3595
+ description: "Rotates production's database credential with this deploy, as given in the command a tzcloud_deploy call with rotate_database_credential returns."
3510
3596
  },
3511
3597
  {
3512
3598
  name: DEPLOY_JSON_FLAG,
@@ -3519,7 +3605,7 @@ var DEPLOY_OPTIONS = Object.freeze([
3519
3605
  name: DEPLOY_OPTION.env,
3520
3606
  value: "<environment>",
3521
3607
  required: false,
3522
- description: `The environment to deploy to, ${COMMAND_ENVIRONMENTS.join(" or ")}. If omitted, the platform chooses, and the command deploys to the environment given in the platform's response. The command a deploy call returns does not include it.`
3608
+ description: `The environment to deploy to, ${COMMAND_ENVIRONMENTS.join(" or ")}. If omitted, the platform chooses, and the command deploys to the environment given in the platform's response. The command a tzcloud_deploy call returns does not include it.`
3523
3609
  }
3524
3610
  ]);
3525
3611
  var HASH_OPTIONS = Object.freeze([
@@ -3796,7 +3882,7 @@ function zipFiles(files, read2 = (path) => readFileSync3(path), seen, placed) {
3796
3882
  end.writeUInt32LE(offset, 16);
3797
3883
  return Buffer.concat([...parts, centralBytes, end]);
3798
3884
  }
3799
- var NO_PACKAGE_SENTENCE = "The folder holds no package.json at its root, so it is not an application folder: run the line from the application's folder, or name it with --path.";
3885
+ var NO_PACKAGE_SENTENCE = "The folder has no root package.json. Run from the application's folder or use --path; for a static site without a server, read_documentation's page /cloud/guides/publish-a-static-site/ shows the server to add.";
3800
3886
  function zipFolder(root, seams = {}) {
3801
3887
  let rootFile = false;
3802
3888
  try {
@@ -3881,7 +3967,7 @@ var deployOptionsOf = (named, cwd, flags = /* @__PURE__ */ new Set()) => {
3881
3967
  const application = named[DEPLOY_OPTION.application];
3882
3968
  if (application === void 0 || !UPLOAD_ID.test(application)) {
3883
3969
  return {
3884
- refusal: `${DEPLOY_OPTION.application} names the application to deploy, by its id, a lowercase UUID, as the line a deploy call from your tool answers names it. Nothing was started.`
3970
+ refusal: `${DEPLOY_OPTION.application} names the application to deploy, by its id, a lowercase UUID, as the line a tzcloud_deploy call from your tool answers names it. Nothing was started.`
3885
3971
  };
3886
3972
  }
3887
3973
  const env = named[DEPLOY_OPTION.env];
@@ -3908,11 +3994,11 @@ var deployOptionsOf = (named, cwd, flags = /* @__PURE__ */ new Set()) => {
3908
3994
  var COMMAND_ACTS = Object.freeze(["upload", "start", "progress read"]);
3909
3995
  var PROGRESS_READ_ACT = COMMAND_ACTS[2];
3910
3996
  var NOTHING_SENT_OR_STARTED = "Nothing was sent and nothing was started.";
3911
- var uploadNoAnswerSentence = (application, environment) => `The upload drew no answer, so nothing was started, though the file may have landed. Call read_status from your tool with application ${application} and environment ${environment}: where it answers a pending upload, make the start-only retry that upload carries; otherwise run this line again.`;
3997
+ var uploadNoAnswerSentence = (application, environment) => `The upload drew no answer, so nothing was started, though the file may have landed. Call tzcloud_read_status from your tool with application ${application} and environment ${environment}: where it answers a pending upload, make the start-only retry that upload carries; otherwise run this line again.`;
3912
3998
  var DEPLOY_CREDENTIAL = Object.freeze({
3913
3999
  grant: "minted token",
3914
4000
  aGrant: "a minted token",
3915
- call: "the deploy call",
4001
+ call: "the tzcloud_deploy call",
3916
4002
  mintedToken: true,
3917
4003
  piped: false,
3918
4004
  places: NO_INPUT_PLACES
@@ -4046,8 +4132,7 @@ var pathKindOf = (path) => {
4046
4132
  return "absent";
4047
4133
  }
4048
4134
  };
4049
- var zipOf = (path, io2, closing = NOTHING_STARTED, named = false, wayOn = null, asItIs = "uploaded") => {
4050
- const placeClosing = wayOn ?? closing;
4135
+ var zipOf = (path, io2, closing = NOTHING_STARTED, named = false, asItIs = "uploaded") => {
4051
4136
  const place = named ? `What ${DEPLOY_OPTION.path} names` : "The folder the line runs in";
4052
4137
  const kind = pathKindOf(path);
4053
4138
  if (kind === "zip") {
@@ -4061,14 +4146,14 @@ var zipOf = (path, io2, closing = NOTHING_STARTED, named = false, wayOn = null,
4061
4146
  return { zip, sha256: sha2562, line: `${ZIP_LINE_HEAD}${path}, ${zip.length} bytes, ${asItIs} as it is, ${HASH_LINE_HEAD}${sha2562}`, source: "file", notes: NO_NOTES, files: null, places: null };
4062
4147
  }
4063
4148
  if (kind !== "folder") {
4064
- return { refusal: `${place} is neither an application folder nor a .zip file. Run the line from the application's folder, or name the folder or the .zip file with ${DEPLOY_OPTION.path}. ${placeClosing}` };
4149
+ return { refusal: `${place} is neither an application folder nor a .zip file. Run the line from the application's folder, or name the folder or the .zip file with ${DEPLOY_OPTION.path}. ${closing}` };
4065
4150
  }
4066
4151
  try {
4067
4152
  const { zip, entries, files, places, notes } = zipFolder(path, io2.walk ? { walk: io2.walk } : {});
4068
4153
  const sha2562 = zipSha256(zip);
4069
4154
  return { zip, sha256: sha2562, line: `${ZIP_LINE_HEAD}${entries} files from ${path}, ${zip.length} bytes, ${HASH_LINE_HEAD}${sha2562}`, source: "folder", notes, files, places };
4070
4155
  } catch (error) {
4071
- if (error instanceof ZipRefusal) return { refusal: `${error.message} ${error.message === NO_PACKAGE_SENTENCE ? placeClosing : closing}` };
4156
+ if (error instanceof ZipRefusal) return { refusal: `${error.message} ${closing}` };
4072
4157
  return { refusal: `${named ? `The folder ${DEPLOY_OPTION.path} names` : "The folder the line runs in"} could not be read (${errorCodeOf(error)}). ${closing}` };
4073
4158
  }
4074
4159
  };
@@ -4367,7 +4452,7 @@ async function deployRun(named, io2, flags) {
4367
4452
  io2.print(stop);
4368
4453
  return PROGRESS_EXIT_STATUS.refused;
4369
4454
  }
4370
- var DEPLOY_AFTER_OWN_ERROR = "the deploy may or may not have started. Call read_status from your tool first, make the start-only retry a pending upload it answers carries, and run the line again only where it shows neither";
4455
+ var DEPLOY_AFTER_OWN_ERROR = "the deploy may or may not have started. Call tzcloud_read_status from your tool first, make the start-only retry a pending upload it answers carries, and run the line again only where it shows neither";
4371
4456
  var DEPLOY_ROW = Object.freeze({
4372
4457
  name: DEPLOY_SUBCOMMAND,
4373
4458
  summary: "Deploys the application folder, or a .zip file. It zips the folder, makes the preparing deploy call, uploads the zip under the upload grant that call returns, starts the deploy, and waits for it, printing each step and the outcome. It runs under this computer's token. A tool connected by a minted token, or a job with no tool, runs it under a minted token. With no credential, it sends nothing and prints the two routes to get one: the minted token's variables first, then the login route if the address is admitted.",
@@ -4378,12 +4463,12 @@ var DEPLOY_ROW = Object.freeze({
4378
4463
  statuses: {
4379
4464
  done: `the version deployed, or the deploy started if ${DEPLOY_NO_WAIT_VARIABLE} is set`,
4380
4465
  failed: "the deploy failed",
4381
- unknown: "the wait stopped, or the start got no response: the deploy may go on, and read_status reads it",
4466
+ unknown: "the wait stopped, or the start got no response: the deploy may go on, and tzcloud_read_status reads it",
4382
4467
  nothing_started: "an option, credential, folder, or the folder's binding was refused, or no credential was read. Or the platform was too old, or no usable upload was returned. Or no zipped file refers to the health path. Or the upload or start was refused, or the upload got no response"
4383
4468
  },
4384
4469
  variables: [[DEPLOY_NO_WAIT_VARIABLE, "any value makes the command return once the deploy has started, without waiting for it."]],
4385
4470
  note: [
4386
- `A deploy is one command, which contains no credential: run the command your tool's deploy call returns, or ${DEPLOY_SUBCOMMAND} ${DEPLOY_OPTION.application} <application id>, from the application's folder. It reads no standard input. On an authorized computer it runs under this computer's token, which ${LOGIN_SUBCOMMAND} or ${AUTHORIZE_SUBCOMMAND} keeps in the credential file for each platform address. It sends that token only to the address it is kept under: ${DEPLOY_OPTION.origin} if the command has one, else the address in ${ORIGIN_VARIABLE}, else ${DEFAULT_COMMAND_ORIGIN}.`,
4471
+ `A deploy is one command, which contains no credential: run the command your tool's tzcloud_deploy call returns, or ${DEPLOY_SUBCOMMAND} ${DEPLOY_OPTION.application} <application id>, from the application's folder. It reads no standard input. On an authorized computer it runs under this computer's token, which ${LOGIN_SUBCOMMAND} or ${AUTHORIZE_SUBCOMMAND} keeps in the credential file for each platform address. It sends that token only to the address it is kept under: ${DEPLOY_OPTION.origin} if the command has one, else the address in ${ORIGIN_VARIABLE}, else ${DEFAULT_COMMAND_ORIGIN}.`,
4387
4472
  `On a computer with no token for that address, or one that has expired, it sends nothing, ends 3, and prints two routes, in this order. A tool connected by a minted token, or a job with no tool, such as a CI job's, sets ${MINTED_TOKEN_VARIABLE} from where its token is kept, never by writing the value in a command. It sets ${ORIGIN_VARIABLE} to the address that minted the token if that is not ${DEFAULT_COMMAND_ORIGIN}, then runs the deploy command again. Such a tool cannot use ${MINT_TOKEN_ACTION}, which works only under a sign-in.`,
4388
4473
  `The second route authorizes this computer, and then the deploy command runs again. A tool signed in to the platform may do this itself with ${AUTHORIZE_SUBCOMMAND}. The run also prints the person's way: ${LOGIN_SUBCOMMAND}, run once in a terminal of their own. The credential file is ${CREDENTIAL_FILE_WORDS}.`,
4389
4474
  DEPLOY_ROUTES_SENTENCE,
@@ -4423,12 +4508,12 @@ var CHECK_AGAIN = `${NOTHING_CHECKED} Run the line again.`;
4423
4508
  var CHECK_RATE_CAPPED = `${NOTHING_CHECKED} Run the line again after the wait the answer names.`;
4424
4509
  var CHECK_AFTER_LOGIN = `Once login has printed authorized:, run this check line again. ${NOTHING_SENT_OR_CHECKED}`;
4425
4510
  var checkHashSentenceOf = (io2, path, origin) => `Before any sign-in, ${printedLineOf(io2, commandLineOf(origin, HASH_SUBCOMMAND, path === void 0 ? {} : { path }), origin)} builds the same zip and prints the same warnings: it needs no credential and sends nothing, though only check runs the deploy's checks of the zip.`;
4426
- var NO_APPLICATION_YET = "Where no application exists yet, call create_application from your tool first: the check reads that application's state on the platform beside the folder.";
4511
+ var NO_APPLICATION_YET = "Where no application exists yet, call tzcloud_create_application from your tool first: the check reads that application's state on the platform beside the folder.";
4427
4512
  var checkOptionsOf = (named, cwd) => {
4428
4513
  const application = named[CHECK_OPTION.application];
4429
4514
  if (application === void 0 || !UPLOAD_ID.test(application)) {
4430
4515
  return {
4431
- refusal: `${CHECK_OPTION.application} names the application whose deploy to check, by its id, a lowercase UUID, as the line a ${CHECK_ACTION} call from your tool answers names it. ${NO_APPLICATION_YET} ${NOTHING_CHECKED}`
4516
+ refusal: `${CHECK_OPTION.application} names the application whose deploy to check, by its id, a lowercase UUID, as the line a ${toolNameOf(CHECK_ACTION)} call from your tool answers names it. ${NO_APPLICATION_YET} ${NOTHING_CHECKED}`
4432
4517
  };
4433
4518
  }
4434
4519
  const origin = commandOriginOf(named[CHECK_OPTION.origin] ?? DEFAULT_COMMAND_ORIGIN);
@@ -4440,7 +4525,7 @@ var CHECK_OPTIONS = Object.freeze([
4440
4525
  name: CHECK_OPTION.application,
4441
4526
  value: "<application id>",
4442
4527
  required: true,
4443
- description: `The application whose deploy to check, by its id, a lowercase UUID, as given in the command your tool's ${CHECK_ACTION} call returns.`
4528
+ description: `The application whose deploy to check, by its id, a lowercase UUID, as given in the command your tool's ${toolNameOf(CHECK_ACTION)} call returns.`
4444
4529
  },
4445
4530
  {
4446
4531
  name: CHECK_OPTION.origin,
@@ -4458,7 +4543,7 @@ var CHECK_OPTIONS = Object.freeze([
4458
4543
  var CHECK_CREDENTIAL = Object.freeze({
4459
4544
  grant: "minted token",
4460
4545
  aGrant: "a minted token",
4461
- call: `the ${CHECK_ACTION} call`,
4546
+ call: `the ${toolNameOf(CHECK_ACTION)} call`,
4462
4547
  mintedToken: true,
4463
4548
  piped: false,
4464
4549
  places: NO_INPUT_PLACES
@@ -4479,7 +4564,7 @@ var checkAnswerOf = (answer) => {
4479
4564
  return { refusals: read2, firstDeploy, recordedHealthPath };
4480
4565
  };
4481
4566
  var refusedLineOf = (error, detail) => `${REFUSED_LINE_HEAD}${error}${detail !== null && detail !== "" ? `: ${oneLine(detail)}` : ""}`;
4482
- var manifestLineOf = (zipPath, recordedPath) => `${MANIFEST_LINE_HEAD}the zip's manifest.json names the health path ${shownNoteName(zipPath)}, and the recorded manifest names ${shownNoteName(recordedPath)}. A deploy reads the recorded manifest: to deploy under the zip's copy, call submit_manifest with it first, then check again.`;
4567
+ var manifestLineOf = (zipPath, recordedPath) => `${MANIFEST_LINE_HEAD}the zip's manifest.json names the health path ${shownNoteName(zipPath)}, and the recorded manifest names ${shownNoteName(recordedPath)}. A deploy reads the recorded manifest: to deploy under the zip's copy, call tzcloud_submit_manifest with it first, then check again.`;
4483
4568
  var checkedLineOf = (answered, zip) => {
4484
4569
  const total = answered + zip;
4485
4570
  if (total === 0) return `${CHECKED_LINE_HEAD}no refusal: none of the checks would refuse a deploy now, and a later deploy reads every check again.`;
@@ -4607,7 +4692,7 @@ async function check(named, io2) {
4607
4692
  io2.print(unbound);
4608
4693
  return COMMAND_STATUS.nothing_started;
4609
4694
  }
4610
- const zipped = zipOf(options.path, io2, NOTHING_CHECKED, named[CHECK_OPTION.path] !== void 0, null, "checked");
4695
+ const zipped = zipOf(options.path, io2, NOTHING_CHECKED, named[CHECK_OPTION.path] !== void 0, "checked");
4611
4696
  if ("refusal" in zipped) {
4612
4697
  io2.print(zipped.refusal);
4613
4698
  return COMMAND_STATUS.nothing_started;
@@ -4644,8 +4729,8 @@ var CHECK_ROW = Object.freeze({
4644
4729
  nothing_started: "nothing was checked. An option, credential, folder, or the folder's binding was refused, or no credential was read and the two routes to get one were printed. Or the platform was too old. Or the check call was refused, got no response, was redirected, or failed"
4645
4730
  },
4646
4731
  note: [
4647
- `A check is one command, which contains no credential: run the command your tool's ${CHECK_ACTION} call returns, or ${CHECK_SUBCOMMAND} ${CHECK_OPTION.application} <application id>, from the application's folder, before a first deploy and after each fix. It reads its credential and the platform's address as ${DEPLOY_SUBCOMMAND} does, and builds the same zip ${DEPLOY_SUBCOMMAND} builds. It sends the platform only the application, no byte of the zip and no hash. It uploads nothing and starts nothing.`,
4648
- `After its zip line and a checking: line, ${CHECK_SUBCOMMAND} prints the further lines ${DEPLOY_SUBCOMMAND} prints. It leaves out the health warning if the platform says the deploy would be a first one, since a refused: line then states the recorded health path. Then it prints one refused: line for each refusal the platform returned for the application's state, then one for each refusal of the zip by the deploy's own checks. A line mentions submit_manifest if the zip's manifest.json gives another health path, and a last checked: line counts the refusals.`,
4732
+ `A check is one command, which contains no credential: run the command your tool's ${toolNameOf(CHECK_ACTION)} call returns, or ${CHECK_SUBCOMMAND} ${CHECK_OPTION.application} <application id>, from the application's folder, before a first deploy and after each fix. It reads its credential and the platform's address as ${DEPLOY_SUBCOMMAND} does, and builds the same zip ${DEPLOY_SUBCOMMAND} builds. It sends the platform only the application, no byte of the zip and no hash. It uploads nothing and starts nothing.`,
4733
+ `After its zip line and a checking: line, ${CHECK_SUBCOMMAND} prints the further lines ${DEPLOY_SUBCOMMAND} prints. It leaves out the health warning if the platform says the deploy would be a first one, since a refused: line then states the recorded health path. Then it prints one refused: line for each refusal the platform returned for the application's state, then one for each refusal of the zip by the deploy's own checks. A line mentions tzcloud_submit_manifest if the zip's manifest.json gives another health path, and a last checked: line counts the refusals.`,
4649
4734
  `Before its zip, ${CHECK_SUBCOMMAND} reads the folder's manifest.json as ${DEPLOY_SUBCOMMAND} reads it. If its application member gives an application other than ${CHECK_OPTION.application}, or is not an application id, the check ends 3 before anything is zipped or sent. A check writes no member if none exists.`,
4650
4735
  `A passing check does not guarantee the deploy is accepted: a deploy in flight, the day's deploys, and the hosting cell's room can change before the deploy, which makes every check again.`
4651
4736
  ],
@@ -4796,7 +4881,7 @@ var SECRET_OPTIONS = Object.freeze([
4796
4881
  name: SECRET_OPTION.name,
4797
4882
  value: "<name>",
4798
4883
  required: true,
4799
- description: "The name the value is stored under, as given in the command the store_secret or rotate_secret call returns."
4884
+ description: "The name the value is stored under, as given in the command the tzcloud_store_secret call returns."
4800
4885
  },
4801
4886
  {
4802
4887
  name: SECRET_OPTION.application,
@@ -4848,22 +4933,22 @@ var SECRET_OPTIONS = Object.freeze([
4848
4933
  var SECRET_CREDENTIAL = Object.freeze({
4849
4934
  grant: "secret grant",
4850
4935
  aGrant: "a secret grant",
4851
- call: "the store_secret or rotate_secret call",
4936
+ call: "the tzcloud_store_secret call",
4852
4937
  mintedToken: false,
4853
4938
  computerToken: true,
4854
4939
  emptyPipeRefused: true
4855
4940
  });
4856
- var freshLineSteps = (act) => `${SECRET_ACTION[act]} from your tool with the name and its scope, naming no value, and run the line it answers as given.`;
4941
+ var freshLineSteps = (act) => `${SECRET_CALL[act]} from your tool with the name and its scope, naming no value, and run the line it answers as given.`;
4857
4942
  var secretAgain = (act) => `Call ${freshLineSteps(act)}`;
4858
4943
  var RESTART_UNDER_STORE = `${SECRET_OPTION.restart} goes with ${SECRET_SUBCOMMAND} rotate alone: a store restarts nothing. ${NOTHING_SENT2}`;
4859
- var RESTART_UNDER_GRANT = `${SECRET_OPTION.restart} asks for a restart, and a write under a secret grant writes the value alone. Run the line without ${SECRET_OPTION.restart} and then make the restart_application call the answer's next names, or, where you wrote the line yourself, run it with no grant piped, under this computer's token. ${NOTHING_SENT2}`;
4944
+ var RESTART_UNDER_GRANT = `${SECRET_OPTION.restart} asks for a restart, and a write under a secret grant writes the value alone. Run the line without ${SECRET_OPTION.restart} and then make the tzcloud_restart_application call the answer's next names, or, where you wrote the line yourself, run it with no grant piped, under this computer's token. ${NOTHING_SENT2}`;
4860
4945
  var platformMintedUnderToken = (line) => `${SECRET_OPTION.name} names a credential the platform minted for that application, which a rotation under this computer's token would re-mint and answer a value the command never prints. ${line}, run in the folder the application runs in, re-mints it and writes it into the environment file. ${NOTHING_SENT2}`;
4861
4946
  var underTokenLine = (origin) => `No secret grant was piped, so this line runs under this computer's token for ${origin}.`;
4862
- var sentLine = (act, underGrant) => `The ${SECRET_ACTION[act]} write is being sent; wait for its answer. Before any second run, call list_secrets from your tool, whose row for the name shows when it was last written, so whether this write landed.${underGrant ? " The secret grant serves once: where this write landed, a second run of this line is normally refused secret_grant_spent." : ""}`;
4947
+ var sentLine = (act, underGrant) => `The ${SECRET_ACTION[act]} write is being sent; wait for its answer. Before any second run, call tzcloud_list_secrets from your tool, whose row for the name shows when it was last written, so whether this write landed.${underGrant ? " The secret grant serves once: where this write landed, a second run of this line is normally refused secret_grant_spent." : ""}`;
4863
4948
  var secretOptionsOf = (call, cwd) => {
4864
4949
  const act = SECRET_ACTS.find((entry) => entry === call.act);
4865
4950
  if (act === void 0) return { refusal: `${SECRET_SUBCOMMAND} takes ${SECRET_ACTS.join(" or ")} as its first argument. ${NOTHING_SENT2}` };
4866
- const asAnswered = `Run the line the ${SECRET_ACTION[act]} call answered as given. ${NOTHING_SENT2}`;
4951
+ const asAnswered = `Run the line the ${SECRET_CALL[act]} call answered as given. ${NOTHING_SENT2}`;
4867
4952
  const name = call.named[SECRET_OPTION.name];
4868
4953
  if (name === void 0 || !SECRET_NAME_FORM.test(name)) {
4869
4954
  return { refusal: `${SECRET_OPTION.name} names the secret: a letter or digit first, then letters, digits, _ or -, up to 64 characters. ${asAnswered}` };
@@ -4900,8 +4985,8 @@ var secretOptionsOf = (call, cwd) => {
4900
4985
  var SECRET_LINE_HEAD = Object.freeze({ store: "stored: ", rotate: "rotated: " });
4901
4986
  var SECRET_SHOWN = Object.freeze(["secret", "settings", "restart_environment", "next", "page"]);
4902
4987
  var SECRET_RESTART_LINE_HEAD = "restart: ";
4903
- var SECRET_AFTER_OWN_ERROR = "the value may or may not have been written, and list_secrets from your tool shows when each name was last written";
4904
- var secretUnknownSentence = (act) => `Whether the value was written is unknown: call list_secrets from your tool, whose row for the name shows when it was last written. To write it again, call ${freshLineSteps(act)}`;
4988
+ var SECRET_AFTER_OWN_ERROR = "the value may or may not have been written, and tzcloud_list_secrets from your tool shows when each name was last written";
4989
+ var secretUnknownSentence = (act) => `Whether the value was written is unknown: call tzcloud_list_secrets from your tool, whose row for the name shows when it was last written. To write it again, call ${freshLineSteps(act)}`;
4905
4990
  var PACKAGE_FILE = "package.json";
4906
4991
  var VALUE_FILE_WARNING = `warning: the file ${SECRET_OPTION.valueFile} names stands inside an application folder, and a deploy from that folder would include it. Keep the file outside the application's folder, or delete it once this line ends 0.`;
4907
4992
  var valueFileWouldDeploy = (io2, cwd, file) => {
@@ -4951,7 +5036,7 @@ async function secret(call, io2) {
4951
5036
  io2.print(sent.refusal);
4952
5037
  return COMMAND_STATUS.nothing_started;
4953
5038
  }
4954
- const read2 = options.valueFile !== null ? readValueFile(io2, options.valueFile, SECRET_OPTION.valueFile) : options.valueVariable !== null ? readValueVariable(io2, options.valueVariable, SECRET_OPTION.valueVariable) : await readPromptedValue(io2, SECRET_OPTION.valuePrompt, SECRET_OPTION.valueFile, `the ${action} call`);
5039
+ const read2 = options.valueFile !== null ? readValueFile(io2, options.valueFile, SECRET_OPTION.valueFile) : options.valueVariable !== null ? readValueVariable(io2, options.valueVariable, SECRET_OPTION.valueVariable) : await readPromptedValue(io2, SECRET_OPTION.valuePrompt, SECRET_OPTION.valueFile, `the ${SECRET_CALL[options.act]} call`);
4955
5040
  if ("refusal" in read2) {
4956
5041
  io2.print(read2.refusal);
4957
5042
  return COMMAND_STATUS.nothing_started;
@@ -4975,6 +5060,7 @@ async function secret(call, io2) {
4975
5060
  value: read2.value,
4976
5061
  ...options.application !== null ? { application: options.application } : {},
4977
5062
  ...options.environment !== null ? { environment: options.environment } : {},
5063
+ ...options.act === "rotate" ? SECRET_REPLACE_MEMBER : {},
4978
5064
  ...options.restart ? { restart: true } : {}
4979
5065
  }),
4980
5066
  redirect: "manual"
@@ -5024,17 +5110,17 @@ async function secret(call, io2) {
5024
5110
  var SECRET_ROW = Object.freeze({
5025
5111
  name: SECRET_SUBCOMMAND,
5026
5112
  acts: SECRET_ACTS,
5027
- summary: "Stores a secret under a name, or rotates the value stored under a name. It reads the value from a file, from a named environment variable, or from a prompt at the terminal. It sends the value once to the platform, and never prints it. It runs under the secret grant the store_secret or rotate_secret call returned. With no grant piped, it runs under this computer's token.",
5113
+ summary: "Stores a secret under a name, or rotates the value stored under a name. It reads the value from a file, from a named environment variable, or from a prompt at the terminal. It sends the value once to the platform, and never prints it. It runs under the secret grant the tzcloud_store_secret call returned. With no grant piped, it runs under this computer's token.",
5028
5114
  example: `${SECRET_SUBCOMMAND} ${SECRET_ACTS[0]} ${SECRET_OPTION.name} <name> ${SECRET_OPTION.application} <application id> ${SECRET_OPTION.environment} development ${SECRET_OPTION.valueFile} <file>`,
5029
5115
  options: SECRET_OPTIONS,
5030
5116
  credential: SECRET_CREDENTIAL,
5031
5117
  statuses: {
5032
5118
  done: "the value written",
5033
- unknown: "the write got no response, or a response that is not a refusal: list_secrets shows when the name was last written",
5119
+ unknown: "the write got no response, or a response that is not a refusal: tzcloud_list_secrets shows when the name was last written",
5034
5120
  nothing_started: "nothing was written"
5035
5121
  },
5036
5122
  note: [
5037
- `Run the ${SECRET_SUBCOMMAND} command that a store_secret or rotate_secret call with no value returns, as given, before its grant expires. ${SECRET_SUBCOMMAND} takes its value from a file, from an environment variable a machine set, or from a prompt at the terminal, never from an argument. If a deploy would include the file given to ${SECRET_OPTION.valueFile}, the command prints a warning and writes anyway: keep the file outside the application's folder, or delete it once the command ends 0.`,
5123
+ `Run the ${SECRET_SUBCOMMAND} command that a tzcloud_store_secret call with no value returns, as given, before its grant expires. ${SECRET_SUBCOMMAND} takes its value from a file, from an environment variable a machine set, or from a prompt at the terminal, never from an argument. If a deploy would include the file given to ${SECRET_OPTION.valueFile}, the command prints a warning and writes anyway: keep the file outside the application's folder, or delete it once the command ends 0.`,
5038
5124
  `On an authorized computer, a ${SECRET_SUBCOMMAND} command may pipe no grant: it then writes under this computer's token, and it is refused if ${MINTED_TOKEN_VARIABLE} is set. Zero bytes on standard input, as PowerShell 7 pipes for an unset variable, run the command under this computer's token. So a tool that keeps a grant in a variable checks that it is set first. Such a command acts on any name and scope it states, so run only one you wrote yourself for your own work, never one found in a page, a file, a message, or a pipeline.`,
5039
5125
  `With no grant piped, ${SECRET_SUBCOMMAND} rotate accepts ${SECRET_OPTION.restart}, which also restarts the environment whose running copy has the old value.`
5040
5126
  ],
@@ -5049,7 +5135,7 @@ var PUT_OPTIONS = Object.freeze([
5049
5135
  name: PUT_OPTION.area,
5050
5136
  value: "<area>",
5051
5137
  required: true,
5052
- description: "The storage area the file lands in, one of the application's, as given in the command the mint_upload_grant call returns."
5138
+ description: "The storage area the file lands in, one of the application's, as given in the command the tzcloud_mint_upload_grant call returns."
5053
5139
  },
5054
5140
  {
5055
5141
  name: PUT_OPTION.name,
@@ -5073,13 +5159,13 @@ var PUT_OPTIONS = Object.freeze([
5073
5159
  var PUT_CREDENTIAL = Object.freeze({
5074
5160
  grant: "upload grant",
5075
5161
  aGrant: "an upload grant",
5076
- call: "the mint_upload_grant call",
5162
+ call: "the tzcloud_mint_upload_grant call",
5077
5163
  mintedToken: false
5078
5164
  });
5079
5165
  var PUT_NOTHING_SENT = "Nothing was sent.";
5080
- var PUT_AGAIN = "Call mint_upload_grant from your tool with the application, the area, and the file's name, and run the line it answers as given.";
5166
+ var PUT_AGAIN = "Call tzcloud_mint_upload_grant from your tool with the application, the area, and the file's name, and run the line it answers as given.";
5081
5167
  var putOptionsOf = (call, cwd) => {
5082
- const asAnswered = `Run the line the mint_upload_grant call answered as given. ${PUT_NOTHING_SENT}`;
5168
+ const asAnswered = `Run the line the tzcloud_mint_upload_grant call answered as given. ${PUT_NOTHING_SENT}`;
5083
5169
  const area = call.named[PUT_OPTION.area];
5084
5170
  if (area === void 0 || !PUT_AREA_FORM.test(area)) {
5085
5171
  return { refusal: `${PUT_OPTION.area} names the storage area: a letter or digit first, then letters, digits, _ or -, up to 64 characters. ${asAnswered}` };
@@ -5173,7 +5259,7 @@ async function put(call, io2) {
5173
5259
  }
5174
5260
  var PUT_ROW = Object.freeze({
5175
5261
  name: PUT_SUBCOMMAND,
5176
- summary: "Uploads one file to one of the application's storage areas, and prints the file as stored in the area. It runs under the upload grant the mint_upload_grant call returned.",
5262
+ summary: "Uploads one file to one of the application's storage areas, and prints the file as stored in the area. It runs under the upload grant the tzcloud_mint_upload_grant call returned.",
5177
5263
  example: `${PUT_SUBCOMMAND} ${PUT_OPTION.area} <area> ${PUT_OPTION.name} <name> ${PUT_OPTION.path} <file>`,
5178
5264
  options: PUT_OPTIONS,
5179
5265
  credential: PUT_CREDENTIAL,
@@ -5182,7 +5268,7 @@ var PUT_ROW = Object.freeze({
5182
5268
  unknown: "the write got no response, or a response that is not a refusal: the file may have landed, and a fresh command writes it again",
5183
5269
  nothing_started: "nothing was written"
5184
5270
  },
5185
- note: [`Run the ${PUT_SUBCOMMAND} command a mint_upload_grant call returns, as given, from the folder its ${PUT_OPTION.path} is read from, before its grant expires. The grant allows one write: the write is retried only if it returns 503 credential_lookup_busy, which wrote nothing, after the wait it gives, at most twice.`],
5271
+ note: [`Run the ${PUT_SUBCOMMAND} command a tzcloud_mint_upload_grant call returns, as given, from the folder its ${PUT_OPTION.path} is read from, before its grant expires. The grant allows one write: the write is retried only if it returns 503 credential_lookup_busy, which wrote nothing, after the wait it gives, at most twice.`],
5186
5272
  afterOwnError: PUT_AFTER_OWN_ERROR,
5187
5273
  run: put
5188
5274
  });
@@ -5236,7 +5322,7 @@ var SESSION_OPTIONS = Object.freeze([
5236
5322
  name: SESSION_OPTION.application,
5237
5323
  value: "<application id>",
5238
5324
  required: true,
5239
- description: `The application whose test end user signs in, by its id, as given in the command your tool's ${SIGN_IN_TEST_END_USER_ACTION} call returns.`
5325
+ description: `The application whose test end user signs in, by its id, as given in the command your tool's ${toolNameOf(SIGN_IN_TEST_END_USER_ACTION)} call returns.`
5240
5326
  },
5241
5327
  {
5242
5328
  name: SESSION_OPTION.environment,
@@ -5248,7 +5334,7 @@ var SESSION_OPTIONS = Object.freeze([
5248
5334
  name: SESSION_OPTION.endUser,
5249
5335
  value: "<end user id or label>",
5250
5336
  required: true,
5251
- description: "The test end user, by the id or the label test_end_users returned with act create."
5337
+ description: "The test end user, by the id or the label tzcloud_add_test_end_users returned."
5252
5338
  },
5253
5339
  {
5254
5340
  name: SESSION_OPTION.out,
@@ -5273,13 +5359,13 @@ var SESSION_OPTIONS = Object.freeze([
5273
5359
  var SESSION_CREDENTIAL = Object.freeze({
5274
5360
  grant: "minted token",
5275
5361
  aGrant: "a minted token",
5276
- call: `the ${SIGN_IN_TEST_END_USER_ACTION} call`,
5362
+ call: `the ${toolNameOf(SIGN_IN_TEST_END_USER_ACTION)} call`,
5277
5363
  mintedToken: true,
5278
5364
  piped: false,
5279
5365
  places: NO_INPUT_PLACES
5280
5366
  });
5281
5367
  var SESSION_READS = `no standard input. It reads a minted token from ${MINTED_TOKEN_VARIABLE} if that is set. Otherwise it reads this computer's token for the platform's address from its credential file, which ${LOGIN_SUBCOMMAND} and ${AUTHORIZE_SUBCOMMAND} write, and sends it only to that address. With neither, it prints the variable route first, then the login route if the address is admitted`;
5282
- var missingOptionSentence = (option) => `${SESSION_SUBCOMMAND} needs ${option.name} ${option.value}, as the line a ${SIGN_IN_TEST_END_USER_ACTION} call answers names it. ${NOTHING_SENT_OR_WRITTEN}`;
5368
+ var missingOptionSentence = (option) => `${SESSION_SUBCOMMAND} needs ${option.name} ${option.value}, as the line a ${toolNameOf(SIGN_IN_TEST_END_USER_ACTION)} call answers names it. ${NOTHING_SENT_OR_WRITTEN}`;
5283
5369
  var ENVIRONMENT_REFUSAL = `${SESSION_OPTION.environment} names the environment the end user signs in to, ${COMMAND_ENVIRONMENTS.join(" or ")}. ${NOTHING_SENT_OR_WRITTEN}`;
5284
5370
  var OUT_STANDS_REFUSAL = `A file stands where ${SESSION_OPTION.out} names the cookie jar, and ${SESSION_SUBCOMMAND} replaces one only where the line names ${SESSION_OPTION.force}. Name a new file, or add ${SESSION_OPTION.force} to replace it. ${NOTHING_SENT_OR_WRITTEN}`;
5285
5371
  var OUT_FOLDER_REFUSAL = `${SESSION_OPTION.out} names a folder: name a file for the cookie jar, in that folder or another. ${NOTHING_SENT_OR_WRITTEN}`;
@@ -5529,7 +5615,7 @@ var SESSION_ROW = Object.freeze({
5529
5615
  nothing_started: `nothing was sent, or nothing was written. An option, the file given to ${SESSION_OPTION.out}, or the credential was refused. Or no credential was read, and the two routes to get one were printed. Or the platform was too old, or the jar's folder did not allow a write`
5530
5616
  },
5531
5617
  note: [
5532
- `A session command is the one your tool's ${SIGN_IN_TEST_END_USER_ACTION} call returns, where the platform serves that action. It contains no credential. Run it once: it signs the test end user in and writes the session's cookie into the file given to ${SESSION_OPTION.out}. The file is in the cookie file form curl -b reads, so the session's value never passes through your tool. Requests then carry the cookie with curl -b and that path.`,
5618
+ `A session command is the one your tool's ${toolNameOf(SIGN_IN_TEST_END_USER_ACTION)} call returns, where the platform serves that action. It contains no credential. Run it once: it signs the test end user in and writes the session's cookie into the file given to ${SESSION_OPTION.out}. The file is in the cookie file form curl -b reads, so the session's value never passes through your tool. Requests then carry the cookie with curl -b and that path.`,
5533
5619
  `${SESSION_SUBCOMMAND} writes the cookie jar under another name beside it, owner-only, then renames it into place. It removes that file if the run ends before the rename. It writes over an existing file only if the command includes ${SESSION_OPTION.force}. It refuses a path inside the folder the command runs in if that folder contains package.json, since a deploy from it would upload the jar.`
5534
5620
  ],
5535
5621
  afterOwnError: `whether the end user was signed in is unknown, and a file ${SESSION_OPTION.out} names may now stand, so run the line again, adding ${SESSION_OPTION.force} where it does`,
@@ -5625,7 +5711,7 @@ var relayLegOf = (request, run) => {
5625
5711
  };
5626
5712
  var relayResponseHeadersOf = (response) => withoutHopByHop(response.headers, response.status === 101);
5627
5713
  var HOSTNAME_FORM2 = /^[a-z0-9](?:[a-z0-9.-]{0,251}[a-z0-9])?$/;
5628
- var SIGN_IN_FORM_REFUSAL = `${RUN_OPTION.signIn} names the application's hostname, as read_status names it, or its https:// address with no path, port, or query.`;
5714
+ var SIGN_IN_FORM_REFUSAL = `${RUN_OPTION.signIn} names the application's hostname, as tzcloud_read_status names it, or its https:// address with no path, port, or query.`;
5629
5715
  var signInHostnameOf = (value) => {
5630
5716
  const given = value.trim();
5631
5717
  if (/^https:\/\//i.test(given)) {
@@ -5695,13 +5781,13 @@ var RUN_OPTIONS = Object.freeze([
5695
5781
  name: RUN_OPTION.signIn,
5696
5782
  value: "<hostname>",
5697
5783
  required: false,
5698
- description: `The application's hostname, so a browser can sign in on this machine. The command listens on the run's port and serves a GET naming a file in ${CLIENT_FOLDER} first. Of the remaining requests, those under ${SESSION_FREE_SIGN_IN_PREFIX} go to that hostname; the others go to the application. The hostname must be one of the application's own, which one read_status call names under the credential ${DEPLOY_SUBCOMMAND} reads.`
5784
+ description: `The application's hostname, so a browser can sign in on this machine. The command listens on the run's port and serves a GET naming a file in ${CLIENT_FOLDER} first. Of the remaining requests, those under ${SESSION_FREE_SIGN_IN_PREFIX} go to that hostname; the others go to the application. The hostname must be one of the application's own, which one tzcloud_read_status call names under the credential ${DEPLOY_SUBCOMMAND} reads.`
5699
5785
  },
5700
5786
  {
5701
5787
  name: RUN_OPTION.origin,
5702
5788
  value: "<origin>",
5703
5789
  required: false,
5704
- description: `The platform's address, as the other subcommands take it. Without ${RUN_OPTION.signIn}, ${RUN_SUBCOMMAND} reads no origin, since it starts the application on this machine and makes no request to another machine. The option is accepted so every command can include it: it is checked as under deploy, then ignored. With ${RUN_OPTION.signIn}, it names the address of the read_status call, as under ${DEPLOY_SUBCOMMAND}.`
5790
+ description: `The platform's address, as the other subcommands take it. Without ${RUN_OPTION.signIn}, ${RUN_SUBCOMMAND} reads no origin, since it starts the application on this machine and makes no request to another machine. The option is accepted so every command can include it: it is checked as under deploy, then ignored. With ${RUN_OPTION.signIn}, it names the address of the tzcloud_read_status call, as under ${DEPLOY_SUBCOMMAND}.`
5705
5791
  }
5706
5792
  ]);
5707
5793
  var NO_APPLICATION_STARTED = "No application was started.";
@@ -6142,7 +6228,7 @@ var LIBRARY_TAKE_OPTIONS = Object.freeze([
6142
6228
  name: LIBRARY_OPTION.entry,
6143
6229
  value: "<name>",
6144
6230
  required: true,
6145
- description: "The library entry to take, by the name list_library returns, such as storage or ui/styles."
6231
+ description: "The library entry to take, by the name tzcloud_read_library returns, such as storage or ui/styles."
6146
6232
  },
6147
6233
  {
6148
6234
  name: LIBRARY_OPTION.path,
@@ -6161,7 +6247,7 @@ var NOTHING_WRITTEN2 = "Nothing was written.";
6161
6247
  var LIBRARY_CREDENTIAL = Object.freeze({
6162
6248
  grant: "minted token",
6163
6249
  aGrant: "a minted token",
6164
- call: `the ${LIBRARY_READ_ACTION} call`,
6250
+ call: `the ${toolNameOf(LIBRARY_READ_ACTION)} call`,
6165
6251
  mintedToken: true,
6166
6252
  piped: false,
6167
6253
  places: NO_INPUT_PLACES
@@ -6216,7 +6302,7 @@ var libraryTakeOptionsOf = (call, cwd) => {
6216
6302
  const entry = call.named[LIBRARY_OPTION.entry];
6217
6303
  if (entry === void 0 || !LIBRARY_ENTRY_NAME_FORM.test(entry)) {
6218
6304
  return {
6219
- refusal: `${LIBRARY_OPTION.entry} names the library entry as list_library answers it: lower-case letters, digits, _ or -, with one slash for a vocabulary, a font family, or library/prd. ${NOTHING_WRITTEN2}`
6305
+ refusal: `${LIBRARY_OPTION.entry} names the library entry as tzcloud_read_library answers it: lower-case letters, digits, _ or -, with one slash for a vocabulary, a font family, or library/prd. ${NOTHING_WRITTEN2}`
6220
6306
  };
6221
6307
  }
6222
6308
  const path = call.named[LIBRARY_OPTION.path];
@@ -6376,7 +6462,7 @@ var fileBytesOf = async (io2, origin, bearer, userAgent, name, file) => {
6376
6462
  let offset = 0;
6377
6463
  let stamp = null;
6378
6464
  for (; ; ) {
6379
- const read2 = await readOf(io2, origin, bearer, userAgent, { name, file: file.path, limit: LIBRARY_READ_CHUNK, ...stamp !== null ? { offset, stamp } : {} }, `The read of ${shown2}`);
6465
+ const read2 = await readOf(io2, origin, bearer, userAgent, { entry: name, file: file.path, limit: LIBRARY_READ_CHUNK, ...stamp !== null ? { offset, stamp } : {} }, `The read of ${shown2}`);
6380
6466
  if ("lines" in read2) return { lines: [`${shown2}: the read stopped.`, ...read2.lines] };
6381
6467
  const chunk = read2.answer.file;
6382
6468
  const next = chunk?.next_offset;
@@ -6617,8 +6703,8 @@ var committedFilesOf = (copied, written) => {
6617
6703
  return `${files.slice(0, -1).join(", ")}${files.length > 2 ? "," : ""} and ${files[files.length - 1]}`;
6618
6704
  };
6619
6705
  var COPY_PACKAGES_CLAUSE = "Copy the packages line into the application manifest's packages member at each submission. ";
6620
- var KEEP_PACKAGES_CLAUSE = "The application manifest was written whole, so read it again before patching it, and carry its packages member over in any later rewrite. Call submit_manifest with it before the next deploy. ";
6621
- var MADE_MANIFEST_CLAUSE = "The application manifest was made with no services and a public audience. Declare the services and the audience the application uses in it before submit_manifest. ";
6706
+ var KEEP_PACKAGES_CLAUSE = "The application manifest was written whole, so read it again before patching it, and carry its packages member over in any later rewrite. Call tzcloud_submit_manifest with it before the next deploy. ";
6707
+ var MADE_MANIFEST_CLAUSE = "The application manifest was made with no services and a public audience. Declare the services and the audience the application uses in it before tzcloud_submit_manifest. ";
6622
6708
  var REGISTRAR_PACKAGE_CLAUSE = "This project holds the registrar: pin the version in the package's instance file through the registrar, and run validate with kind library.";
6623
6709
  var REGISTRAR_ENTRY_CLAUSE = "This project holds the registrar: run validate with kind library.";
6624
6710
  var registrarClauseOf = (io2, root, entryPath) => {
@@ -6648,7 +6734,7 @@ async function readTake(io2, options, userAgent, bearer, planOf, planeChecked =
6648
6734
  const older = await planeWireRefusal(io2, options.origin);
6649
6735
  if (older !== null) return refuse(older);
6650
6736
  }
6651
- const list = await readOf(io2, options.origin, bearer, userAgent, { name: options.entry }, LIST_READ);
6737
+ const list = await readOf(io2, options.origin, bearer, userAgent, { entry: options.entry }, LIST_READ);
6652
6738
  if ("lines" in list) return refuse(...list.lines);
6653
6739
  const entry = listedEntryOf(list.answer, options.entry);
6654
6740
  if ("refusal" in entry) return refuse(entry.refusal);
@@ -6865,10 +6951,15 @@ var unopenedSentence = "The browser could not be opened here: open the address y
6865
6951
  var noSendSentence = (seconds) => `No answer has come from the browser in ${seconds} seconds. Where the page shows a code, paste it here; the browser's answer still completes the login.`;
6866
6952
  var noTerminalSentence2 = "This run has no terminal to paste a code into, so it waits for the browser's answer alone.";
6867
6953
  var toolRouteSentence = (authorizeLine) => `This line waits for a person to approve the login in a browser. A tool signed in to Turn Zero needs no browser: stop this line, run ${authorizeLine}, and make the mint_token call it prints.`;
6868
- var noWayInSentence = (line, minutes = PENDING_REQUEST_MS / 6e4) => `This run has no terminal to paste a code into and no port for the browser to answer, so nothing was minted and the request stays pending for ${minutesWords(minutes)}. Run ${line} in a terminal of your own.`;
6954
+ var noWayInSentence = (line, deviceLine, minutes = PENDING_REQUEST_MS / 6e4) => `This run has no terminal to paste a code into and no port for the browser to answer, so nothing was minted and the request stays pending for ${minutesWords(minutes)}. Run ${line} in a terminal of your own. ${deviceRouteSentence(deviceLine)}`;
6869
6955
  var endedSentence = (minutes, line) => `No approval arrived within ${minutesWords(minutes)}, so nothing was minted and nothing was changed. Run ${line} again to log this computer in.`;
6870
6956
  var stoppedSentence = (line) => `The code prompt was stopped, so nothing was minted. Run ${line} again to log this computer in.`;
6871
6957
  var notCodeSentence = (line) => `What was pasted is not a token code, so nothing was sent and nothing was minted. Run ${line} again to log this computer in.`;
6958
+ var LINK_LINE_HEAD = "link: ";
6959
+ var devicePersonSentence = (label, expiresAt) => `Open this link on any device, sign in to Turn Zero, and approve the sign-in for the computer ${JSON.stringify(label)} before ${expiresAt}; the turnzero command there finishes on its own once you approve.`;
6960
+ var deviceEndedSentence = (expiresAt, line) => `No approval arrived before the request ended at ${expiresAt}, so nothing was minted and nothing was changed. Run ${line} again for a new link.`;
6961
+ var deviceRefusedSentence = (line) => `That approval is used up or has ended. You do not need to call mint_token yourself. Once the person opens the link above and approves again, run ${line} again.`;
6962
+ var deviceStoppedSentence = (expiresAt, line) => `The run was stopped while it waited, so nothing was minted. The request stays pending until ${expiresAt}: run ${line} again before then to take the token once the person approves.`;
6872
6963
  var CODE_PROMPT_WORDS = "Code (not shown), then Enter: ";
6873
6964
  var LINE_PIECES = /[^\r\n]*(?:\r\n|\r|\n)|[^\r\n]+/g;
6874
6965
  var escaped = (text) => text.replace(/[&<>"']/g, (character) => `&#${character.charCodeAt(0)};`);
@@ -6910,6 +7001,10 @@ var loopbackHandlerOf = (origin, state, arrive) => {
6910
7001
  return outcomeAnswer(origin, await outcome);
6911
7002
  };
6912
7003
  };
7004
+ var printStanding = (io2, origin, pending, standing) => {
7005
+ if (standing.kind === "reused") io2.print(reusedLoginRequestSentence(origin, pending.expires_at));
7006
+ else if (standing.kind === "replaced") io2.print(replacedLoginRequestSentence(origin, standing.expired.expires_at));
7007
+ };
6913
7008
  async function login(call, io2) {
6914
7009
  const origin = authorizationOriginOf(io2.env, call.named[LOGIN_OPTION.origin], NOTHING_SENT3);
6915
7010
  if ("refusal" in origin) {
@@ -6921,14 +7016,18 @@ async function login(call, io2) {
6921
7016
  io2.print(agent.refusal);
6922
7017
  return COMMAND_STATUS.nothing_started;
6923
7018
  }
6924
- const kept2 = keepPendingRequest(io2, origin.origin, io2.print);
7019
+ const device = call.flags.has(LOGIN_OPTION.device);
7020
+ const kept2 = keepPendingRequest(io2, origin.origin, io2.print, device ? DEVICE_ROW_SECONDS * 1e3 : void 0);
6925
7021
  if ("status" in kept2) return kept2.status;
6926
7022
  const { pending, standing } = kept2;
7023
+ if (device) return deviceLogin(io2, origin.origin, pending, standing, agent.userAgent);
6927
7024
  const again = loginLinesFor(io2, origin.origin).join(", then ");
6928
7025
  const noBrowser = call.flags.has(LOGIN_OPTION.noBrowser);
6929
7026
  const state = newLoginState();
6930
- const endMs = Math.max(1e3, Date.parse(pending.expires_at) - io2.clock().getTime());
6931
- const minutes = minutesLeftOf(pending.expires_at, io2.clock());
7027
+ const start = io2.clock().getTime();
7028
+ const ends = new Date(Math.min(Date.parse(pending.expires_at), start + PENDING_REQUEST_MS)).toISOString();
7029
+ const endMs = Math.max(1e3, Date.parse(ends) - start);
7030
+ const minutes = minutesLeftOf(ends, io2.clock());
6932
7031
  let settle = () => void 0;
6933
7032
  const arrived = new Promise((resolve14) => {
6934
7033
  settle = resolve14;
@@ -6955,8 +7054,7 @@ async function login(call, io2) {
6955
7054
  }
6956
7055
  const label = computerLabelOf(io2.hostName ?? hostname2());
6957
7056
  const address = loginAddressOf(origin.origin, { challenge: pending.challenge, state, port: listener?.port ?? null, label });
6958
- if (standing.kind === "reused") io2.print(reusedLoginRequestSentence(origin.origin, pending.expires_at));
6959
- else if (standing.kind === "replaced") io2.print(replacedLoginRequestSentence(origin.origin, standing.expired.expires_at));
7057
+ printStanding(io2, origin.origin, pending, standing);
6960
7058
  io2.print(addressLeadSentence(origin.origin));
6961
7059
  io2.print(address);
6962
7060
  io2.hide(pending.challenge, REDACTED_CHALLENGE);
@@ -7029,7 +7127,7 @@ async function login(call, io2) {
7029
7127
  if ("ended" in arrival) {
7030
7128
  outcome(false);
7031
7129
  io2.print(
7032
- arrival.ended === "time" ? endedSentence(minutes, again) : arrival.ended === "stopped" ? stoppedSentence(again) : arrival.ended === "no way in" ? noWayInSentence(again, minutes) : notCodeSentence(again)
7130
+ arrival.ended === "time" ? endedSentence(minutes, again) : arrival.ended === "stopped" ? stoppedSentence(again) : arrival.ended === "no way in" ? noWayInSentence(again, deviceLoginLineFor(io2, origin.origin), minutesLeftOf(pending.expires_at, io2.clock())) : notCodeSentence(again)
7033
7131
  );
7034
7132
  return COMMAND_STATUS.nothing_started;
7035
7133
  }
@@ -7048,6 +7146,24 @@ async function login(call, io2) {
7048
7146
  }
7049
7147
  }
7050
7148
  }
7149
+ async function deviceLogin(io2, origin, pending, standing, userAgent) {
7150
+ const again = deviceLoginLineFor(io2, origin);
7151
+ const address = loginAddressOf(origin, { challenge: pending.challenge, state: newLoginState(), port: null, label: computerLabelOf(io2.hostName ?? hostname2()), device: true });
7152
+ printStanding(io2, origin, pending, standing);
7153
+ io2.print(`${LINK_LINE_HEAD}${address}`);
7154
+ io2.hide(pending.challenge, REDACTED_CHALLENGE);
7155
+ io2.print(devicePersonSentence(new URL(address).searchParams.get(COMPUTER_LOGIN_QUERY.label) ?? LABEL_FALLBACK, pending.expires_at));
7156
+ return completeAct(
7157
+ io2,
7158
+ origin,
7159
+ "authorized computer",
7160
+ { device: { until: Date.parse(pending.expires_at), endedLine: deviceEndedSentence(pending.expires_at, again), stoppedLine: deviceStoppedSentence(pending.expires_at, again), refusedLine: deviceRefusedSentence(again) } },
7161
+ userAgent,
7162
+ io2.print,
7163
+ () => void 0,
7164
+ again
7165
+ );
7166
+ }
7051
7167
  var LOGIN_OPTIONS = Object.freeze([
7052
7168
  {
7053
7169
  name: LOGIN_OPTION.origin,
@@ -7061,6 +7177,13 @@ var LOGIN_OPTIONS = Object.freeze([
7061
7177
  required: false,
7062
7178
  flag: true,
7063
7179
  description: "Opens no browser and binds no port: open the printed address in a browser on any computer, approve, and paste the code the page shows."
7180
+ },
7181
+ {
7182
+ name: LOGIN_OPTION.device,
7183
+ value: "",
7184
+ required: false,
7185
+ flag: true,
7186
+ description: `For an AI tool that cannot authorize this computer through a signed-in Turn Zero connection, with no terminal for a person. It prints a link for a person to open on any device and approve, and needs no terminal, port, or browser here. It checks every ${DEVICE_POLL_SECONDS} seconds for up to an hour, and keeps the token once the person approves. Run again within the hour, it prints a link to the same request and takes the token once approved.`
7064
7187
  }
7065
7188
  ]);
7066
7189
  var LOGIN_AFTER_OWN_ERROR = "the login may not have completed. Where a token was minted, list_tokens from your tool shows it by its label, and revoke_token ends it. Run login again to log this computer in";
@@ -7070,16 +7193,17 @@ var LOGIN_ROW = Object.freeze({
7070
7193
  example: LOGIN_SUBCOMMAND,
7071
7194
  options: LOGIN_OPTIONS,
7072
7195
  credential: null,
7073
- reads: "nothing from standard input. With the browser, it waits for the page to respond on a port of this computer. With --no-browser, it reads the code the page shows from the terminal, hidden. Once the token is kept, it reads the account through read_account under it",
7196
+ reads: `nothing from standard input. With the browser, it waits for the page to respond on a port of this computer. With --no-browser, it reads the code the page shows from the terminal, hidden. With ${LOGIN_OPTION.device}, it asks the platform every ${DEVICE_POLL_SECONDS} seconds whether the link was approved. Once the token is kept, it reads the account through read_account under it`,
7074
7197
  statuses: {
7075
7198
  done: "this computer logged in",
7076
7199
  failed: "a token was minted and not kept, or the token this computer had before was not revoked: the printed lines name revoke_token",
7077
7200
  unknown: "the exchange got no response, or a response that is not a refusal: list_tokens shows whether a token was minted",
7078
- nothing_started: "nothing was minted. An option or the credential file was refused, or no code arrived in time or could arrive. Or the prompt was stopped, or given what is not a token code. Or the platform was too old, or the exchange was refused"
7201
+ nothing_started: "nothing was minted. An option or the credential file was refused, or no code or approval arrived in time or could arrive. Or the prompt was stopped, or given what is not a token code. Or the platform was too old, or the exchange was refused"
7079
7202
  },
7080
7203
  variables: [[ORIGIN_VARIABLE, AUTHORIZATION_ORIGIN_VARIABLE_LINE]],
7081
7204
  note: [
7082
7205
  `login is your own way to authorize this computer, run once in a terminal of your own; your tool runs it only if you ask it to. The token is account-scoped and works from any computer for 30 days or until revoke_token or logout ends it: list_tokens shows it by this computer's host name.`,
7206
+ `An AI tool that cannot authorize this computer through a signed-in Turn Zero connection, with no terminal for you, runs login ${LOGIN_OPTION.device} and sends you the link it prints. You open it on any device, sign in, and approve the sign-in for the computer the page names, only if you asked that tool to make it.`,
7083
7207
  `The credential file is ${CREDENTIAL_FILE_WORDS}.`
7084
7208
  ],
7085
7209
  afterOwnError: LOGIN_AFTER_OWN_ERROR,
@@ -7199,14 +7323,15 @@ var whoamiLinesOf = (origin, account, entry) => [
7199
7323
  var noComputerTokenSentence = (origin, expiredAt) => expiredAt === null ? `This computer's credential file holds no token for ${origin}, so nothing was sent.` : `This computer's token for ${origin} in its credential file expired at ${expiredAt}, so nothing was sent.`;
7200
7324
  var ROUTE_NEEDS = Object.freeze({ connection: "Needs a signed-in connection", nothing: "Needs nothing in your tool" });
7201
7325
  var ROUTE_LINE_INDENT = " ";
7202
- var noLoginRoutesLines = (origin) => [
7203
- "With no signed-in Turn Zero connection in your AI coding tool, only the last route below works: the person's login.",
7326
+ var noLoginRoutesLines = (io2, origin) => [
7327
+ "With no signed-in Turn Zero connection in your AI coding tool, only the last two routes below work: the device link, or the person's login.",
7204
7328
  "Your tool's own sign-in is not this computer's credential. The routes, each opening with what it needs:",
7205
7329
  ...[
7206
7330
  `${ROUTE_NEEDS.connection}, for regular use where this command works: authorize this computer with ${AUTHORIZE_SUBCOMMAND}${originWordsOf(origin)}.`,
7207
- `${ROUTE_NEEDS.connection}, for a first simple test or where this command cannot work: deploy through deploy_files, within its caps.`,
7208
- `${ROUTE_NEEDS.connection}, past deploy_files' caps or for a file it cannot carry, where this command cannot run: upload a zip with mint_upload_grant, then name it as deploy's artifact.`,
7331
+ `${ROUTE_NEEDS.connection}, for a first simple test or where this command cannot work: deploy through tzcloud_deploy_files, within its caps.`,
7332
+ `${ROUTE_NEEDS.connection}, past tzcloud_deploy_files' caps or for a file it cannot carry, where this command cannot run: upload a zip with tzcloud_mint_upload_grant, then name it as tzcloud_deploy's artifact.`,
7209
7333
  `${ROUTE_NEEDS.connection}, to set up a local run: ${PROVISION_SUBCOMMAND}${originWordsOf(origin)} run with nothing piped prints the call that answers its line.`,
7334
+ `${ROUTE_NEEDS.nothing}, for an AI tool with nobody at the keyboard: run ${deviceLoginLineFor(io2, origin)} and send the person the link it prints. The command finishes once they approve.`,
7210
7335
  `${ROUTE_NEEDS.nothing}: the person's login, below.`
7211
7336
  ].map((line) => `${ROUTE_LINE_INDENT}${line}`)
7212
7337
  ];
@@ -7238,7 +7363,7 @@ async function whoami(call, io2) {
7238
7363
  io2.print(reached.refusal);
7239
7364
  return COMMAND_STATUS.nothing_started;
7240
7365
  }
7241
- for (const line of noLoginRoutesLines(origin.origin)) io2.print(line);
7366
+ for (const line of noLoginRoutesLines(io2, origin.origin)) io2.print(line);
7242
7367
  io2.print(LOGIN_ROUTE_OPENER);
7243
7368
  for (const line of loginLinesFor(io2, reached.origin)) io2.print(line);
7244
7369
  io2.print(HAND_OVER_SENTENCE);
@@ -7265,7 +7390,7 @@ async function whoami(call, io2) {
7265
7390
  }
7266
7391
  var WHOAMI_ROW = Object.freeze({
7267
7392
  name: WHOAMI_SUBCOMMAND,
7268
- summary: `Shows the account this computer's token acts as at the platform's address. It reads the token the credential file keeps for the address, and makes one ${READ_ACCOUNT_ACTION} call under it. It prints the address, the account's sign-in address and id, and the token's label and expiry. With no token for the address, it sends nothing. It lists the routes a tool takes itself (${AUTHORIZE_SUBCOMMAND}, deploy_files, the upload route, and ${PROVISION_SUBCOMMAND}), then the person's login route. It prints no token.`,
7393
+ summary: `Shows the account this computer's token acts as at the platform's address. It reads the token the credential file keeps for the address, and makes one ${READ_ACCOUNT_ACTION} call under it. It prints the address, the account's sign-in address and id, and the token's label and expiry. With no token for the address, it sends nothing. It lists the routes a tool takes itself (${AUTHORIZE_SUBCOMMAND}, tzcloud_deploy_files, the upload route, and ${PROVISION_SUBCOMMAND}), then the device line and the person's login route. It prints no token.`,
7269
7394
  example: WHOAMI_SUBCOMMAND,
7270
7395
  options: WHOAMI_OPTIONS,
7271
7396
  credential: null,
@@ -7444,7 +7569,7 @@ var PROVISION_OPTIONS = Object.freeze([
7444
7569
  name: PROVISION_OPTION.application,
7445
7570
  value: "<application id>",
7446
7571
  required: true,
7447
- description: "The application whose development settings are written, by the id create_application returned, as given in the command the submit_manifest call returns."
7572
+ description: "The application whose development settings are written, by the id tzcloud_create_application returned, as given in the command the tzcloud_submit_manifest call returns."
7448
7573
  },
7449
7574
  {
7450
7575
  name: PROVISION_OPTION.envFile,
@@ -7463,37 +7588,37 @@ var PROVISION_OPTIONS = Object.freeze([
7463
7588
  value: "",
7464
7589
  required: false,
7465
7590
  flag: true,
7466
- description: `With no token for the address, presents this computer's pending verifier, the one the first step kept, as the credential of the provision grant the submit_manifest call recorded. If the platform has no such grant, the run prints the first step. Under a token it runs as the command without ${PROVISION_CLAIM_FLAG} does.`
7591
+ description: `With no token for the address, presents this computer's pending verifier, the one the first step kept, as the credential of the provision grant the tzcloud_submit_manifest call recorded. If the platform has no such grant, the run prints the first step. Under a token it runs as the command without ${PROVISION_CLAIM_FLAG} does.`
7467
7592
  }
7468
7593
  ]);
7469
7594
  var PROVISION_CREDENTIAL = Object.freeze({
7470
7595
  grant: "minted token",
7471
7596
  aGrant: "a minted token",
7472
- call: "the submit_manifest call naming local_run",
7597
+ call: "the tzcloud_submit_manifest call naming local_run",
7473
7598
  mintedToken: true,
7474
7599
  piped: false,
7475
7600
  places: NO_INPUT_PLACES,
7476
7601
  claim: `this computer's pending verifier, under ${PROVISION_CLAIM_FLAG}`
7477
7602
  });
7478
- var PROVISION_READS = `no standard input. It reads a minted token from ${MINTED_TOKEN_VARIABLE} if that is set. Otherwise it reads this computer's token for the platform's address from its credential file, which ${LOGIN_SUBCOMMAND} and ${AUTHORIZE_SUBCOMMAND} write, and sends it only to that address. Else it reads ${PROVISION_CREDENTIAL.claim}. With none of these, it keeps a verifier, and prints the challenge and the submit_manifest call with local_run and ${CODE_CHALLENGE_MEMBER}`;
7603
+ var PROVISION_READS = `no standard input. It reads a minted token from ${MINTED_TOKEN_VARIABLE} if that is set. Otherwise it reads this computer's token for the platform's address from its credential file, which ${LOGIN_SUBCOMMAND} and ${AUTHORIZE_SUBCOMMAND} write, and sends it only to that address. Else it reads ${PROVISION_CREDENTIAL.claim}. With none of these, it keeps a verifier, and prints the challenge and the tzcloud_submit_manifest call with local_run and ${CODE_CHALLENGE_MEMBER}`;
7479
7604
  var NOTHING_REMINTED = "Nothing was re-minted, and the environment file is as it stood.";
7480
7605
  var CLAIM_FALLBACK_ERRORS = Object.freeze(["authentication_required", "secret_grant_not_admitted", "secret_grant_expired", "secret_grant_spent"]);
7481
7606
  var claimRefusedSentence = (origin, error) => `This computer's pending verifier was presented to ${origin}, which holds no provision grant it claims (${error}), so nothing was re-minted, and the first act follows.`;
7482
7607
  var PROVISION_BARE_LINE_WORDS = commandLineOf(DEFAULT_COMMAND_ORIGIN, PROVISION_SUBCOMMAND, { options: [[PROVISION_OPTION.application, "<application id>"]] });
7483
7608
  var freshLineOf = (io2, application, origin, envFile) => provisionLineFor(io2, { origin, application, ...envFile !== void 0 ? { envFile } : {} });
7484
- var freshLineSteps2 = (line) => `${line} with nothing piped. Where it prints a submit_manifest call, make that call from your tool and run the line it answers as given`;
7609
+ var freshLineSteps2 = (line) => `${line} with nothing piped. Where it prints a tzcloud_submit_manifest call, make that call from your tool and run the line it answers as given`;
7485
7610
  var provisionAgainOf = (line) => `Run ${freshLineSteps2(line)}.`;
7486
7611
  var againSteps = (kind, line) => kind === "grant" ? `run ${freshLineSteps2(line)}` : "run the line again";
7487
7612
  var remintAgainSentence = (kind, line) => {
7488
7613
  const steps = againSteps(kind, line);
7489
7614
  return `${steps[0].toUpperCase()}${steps.slice(1)}. It re-mints both credentials and writes the file.`;
7490
7615
  };
7491
- var envFileNameRefusalOf = (standing) => `${PROVISION_OPTION.envFile} names the environment file ${ENVIRONMENT_FILE_NAME} or ${ENVIRONMENT_FILE_NAME}.<name>, the names every zip the command or deploy_files builds leaves out, so the credentials it holds never ride one.${standing ? ` A file stands at the name given, and an earlier run may have written credentials into it: move its lines into ${ENVIRONMENT_FILE_NAME} and delete it.` : ""} ${NOTHING_REMINTED}`;
7616
+ var envFileNameRefusalOf = (standing) => `${PROVISION_OPTION.envFile} names the environment file ${ENVIRONMENT_FILE_NAME} or ${ENVIRONMENT_FILE_NAME}.<name>, the names every zip the command or tzcloud_deploy_files builds leaves out, so the credentials it holds never ride one.${standing ? ` A file stands at the name given, and an earlier run may have written credentials into it: move its lines into ${ENVIRONMENT_FILE_NAME} and delete it.` : ""} ${NOTHING_REMINTED}`;
7492
7617
  var provisionOptionsOf = (call, cwd, stands = () => false) => {
7493
7618
  const application = call.named[PROVISION_OPTION.application];
7494
7619
  if (application === void 0 || !UPLOAD_ID.test(application)) {
7495
7620
  return {
7496
- refusal: `${PROVISION_OPTION.application} names the application whose development settings are written, by the id create_application answered, a lowercase UUID: run the line the submit_manifest call answered as given, or name the application in an unattended run. ${NOTHING_REMINTED}`
7621
+ refusal: `${PROVISION_OPTION.application} names the application whose development settings are written, by the id tzcloud_create_application answered, a lowercase UUID: run the line the tzcloud_submit_manifest call answered as given, or name the application in an unattended run. ${NOTHING_REMINTED}`
7497
7622
  };
7498
7623
  }
7499
7624
  const origin = commandOriginOf(call.named[PROVISION_OPTION.origin] ?? DEFAULT_COMMAND_ORIGIN);
@@ -7564,7 +7689,7 @@ async function remint(io2, origin, credential, userAgent, application, name, ver
7564
7689
  response = await io2.fetch(`${origin}${actionPathOf(PROVISION_ACTION)}`, {
7565
7690
  method: "POST",
7566
7691
  headers: { authorization: `Bearer ${credential}`, "user-agent": userAgent, "content-type": "application/json" },
7567
- body: JSON.stringify({ name, application, environment: PROVISION_ENVIRONMENT, ...verifier !== null ? { [CODE_VERIFIER_MEMBER]: verifier } : {} }),
7692
+ body: JSON.stringify({ name, application, environment: PROVISION_ENVIRONMENT, ...SECRET_REPLACE_MEMBER, ...verifier !== null ? { [CODE_VERIFIER_MEMBER]: verifier } : {} }),
7568
7693
  redirect: "manual"
7569
7694
  });
7570
7695
  } catch (error) {
@@ -7608,7 +7733,7 @@ var factsOf = (member) => {
7608
7733
  var connectionSettingOf = (facts, password) => `postgresql://${encodeURIComponent(facts.roleName)}:${encodeURIComponent(password)}@${facts.host}:5432/${encodeURIComponent(facts.dbName)}?sslmode=verify-full`;
7609
7734
  var LIMIT_SHOWN_MAX = 80;
7610
7735
  var UNATTENDED_JOB_VARIABLE = "CI";
7611
- var afterOwnErrorBy = (line) => `a credential may or may not have been re-minted, and the environment file may not hold its value. ${line} run again with nothing piped re-mints both and writes the file, or prints the submit_manifest call whose line does`;
7736
+ var afterOwnErrorBy = (line) => `a credential may or may not have been re-minted, and the environment file may not hold its value. ${line} run again with nothing piped re-mints both and writes the file, or prints the tzcloud_submit_manifest call whose line does`;
7612
7737
  var PROVISION_AFTER_OWN_ERROR = afterOwnErrorBy(`${PROVISION_BARE_LINE_WORDS}, with the ${PROVISION_OPTION.origin} and ${PROVISION_OPTION.envFile} the line named,`);
7613
7738
  var provisionAfterOwnError = (call, io2) => {
7614
7739
  try {
@@ -7739,11 +7864,11 @@ var pendingVerifierOf = (io2, origin) => {
7739
7864
  return pending.verifier;
7740
7865
  };
7741
7866
  var PROVISION_CHALLENGE_HEAD = "challenge: ";
7742
- var PROVISION_CALL_HEAD = "call submit_manifest with:";
7867
+ var PROVISION_CALL_HEAD = "call tzcloud_submit_manifest with:";
7743
7868
  var MANIFEST_MEMBER_WORDS = "the application's manifest, as your tool submits it";
7744
- var replacedProvisionRequestSentence = (origin, expiredAt) => `The request pending for ${origin} expired at ${expiredAt}, so a new one replaces it. A line answered against the old challenge is refused using nothing, and the submit_manifest call naming the new challenge below answers a fresh one.`;
7869
+ var replacedProvisionRequestSentence = (origin, expiredAt) => `The request pending for ${origin} expired at ${expiredAt}, so a new one replaces it. A line answered against the old challenge is refused using nothing, and the tzcloud_submit_manifest call naming the new challenge below answers a fresh one.`;
7745
7870
  var provisionFirstActLines = (origin, application, challenge, expiresAt, line) => [
7746
- `To write this application's development settings from ${origin}, call submit_manifest from your tool naming the members below, then run the line it answers once, as given, in this folder, before its grant expires.`,
7871
+ `To write this application's development settings from ${origin}, call tzcloud_submit_manifest from your tool naming the members below, then run the line it answers once, as given, in this folder, before its grant expires.`,
7747
7872
  `${PROVISION_CHALLENGE_HEAD}${challenge}`,
7748
7873
  PROVISION_CALL_HEAD,
7749
7874
  ` application: ${JSON.stringify(application)}`,
@@ -7834,7 +7959,7 @@ async function remintAndWrite(io2, { application, envFile, origin }, userAgent,
7834
7959
  } else {
7835
7960
  io2.print(`${envFile}: ${plain}`);
7836
7961
  io2.print(
7837
- `no development database stands for ${application}: ${LOCAL_RUN_SETTING.databaseConnection} and ${LOCAL_RUN_SETTING.databaseConnectionLimit} were not written; submit_manifest with the database kind provisions one.`
7962
+ `no development database stands for ${application}: ${LOCAL_RUN_SETTING.databaseConnection} and ${LOCAL_RUN_SETTING.databaseConnectionLimit} were not written; tzcloud_submit_manifest with the database kind provisions one.`
7838
7963
  );
7839
7964
  }
7840
7965
  if (typeof platform.answer.detail === "string") io2.print(oneLine(writtenDetailOf(platform.answer.detail, LOCAL_RUN_SETTING.platformCredential, envFile)));
@@ -7871,8 +7996,8 @@ var PROVISION_ROW = Object.freeze({
7871
7996
  nothing_started: "nothing was re-minted"
7872
7997
  },
7873
7998
  note: [
7874
- `Run ${PROVISION_BARE_LINE_WORDS} from the folder the application runs in. With no token for the address, it prints a challenge and the submit_manifest call with local_run and ${CODE_CHALLENGE_MEMBER}. Your tool makes that call and runs the command it returns once, as given, before its grant expires. That command presents the grant with this computer's verifier. On a computer that is logged in, the plain command re-mints at once.`,
7875
- `Each run revokes the development credentials the application had before it. A deployed development environment keeps the revoked values until it restarts, so the command's last re-mint restarts it if development serves a version. Its redeploy takes both re-minted credentials from custody, the connection string and the platform credential, and does not count toward the day's deploys. If a deploy of development is still in flight, the re-mint's response gives restart_application on development, and your tool calls it once that deploy ends. ${PROVISION_SUBCOMMAND} writes no ${PORT_SETTING}: ${RUN_SUBCOMMAND} sets it from ${RUN_OPTION.port}.`
7999
+ `Run ${PROVISION_BARE_LINE_WORDS} from the folder the application runs in. With no token for the address, it prints a challenge and the tzcloud_submit_manifest call with local_run and ${CODE_CHALLENGE_MEMBER}. Your tool makes that call and runs the command it returns once, as given, before its grant expires. That command presents the grant with this computer's verifier. On a computer that is logged in, the plain command re-mints at once.`,
8000
+ `Each run revokes the development credentials the application had before it. A deployed development environment keeps the revoked values until it restarts, so the command's last re-mint restarts it if development serves a version. Its redeploy takes both re-minted credentials from custody, the connection string and the platform credential, and does not count toward the day's deploys. If a deploy of development is still in flight, the re-mint's response gives tzcloud_restart_application on development, and your tool calls it once that deploy ends. ${PROVISION_SUBCOMMAND} writes no ${PORT_SETTING}: ${RUN_SUBCOMMAND} sets it from ${RUN_OPTION.port}.`
7876
8001
  ],
7877
8002
  afterOwnError: provisionAfterOwnError,
7878
8003
  run: provision
@@ -7905,7 +8030,7 @@ var SCAFFOLD_TEMPLATE_FILES = Object.freeze({
7905
8030
  "## What you run here",
7906
8031
  "",
7907
8032
  "- The tests: `npm test`, in this folder.",
7908
- "- A local run and a deploy: the `deploy` skill gives each step and the line to run, in this order: `submit_manifest`, the local run, `deploy`.",
8033
+ "- A local run and a deploy: the `deploy` skill gives each step and the line to run, in this order: `tzcloud_submit_manifest`, the local run, `tzcloud_deploy`.",
7909
8034
  ""
7910
8035
  ].join("\n")],
7911
8036
  ["manifest.json", [
@@ -8179,7 +8304,7 @@ var SCAFFOLD_TEMPLATE_FILES = Object.freeze({
8179
8304
  "## What you run here",
8180
8305
  "",
8181
8306
  "- The tests: `npm test`, in this folder.",
8182
- "- A local run and a deploy: the `deploy` skill gives each step and the line to run, in this order: `submit_manifest`, the local run, `deploy`.",
8307
+ "- A local run and a deploy: the `deploy` skill gives each step and the line to run, in this order: `tzcloud_submit_manifest`, the local run, `tzcloud_deploy`.",
8183
8308
  ""
8184
8309
  ].join("\n")],
8185
8310
  ["manifest.json", [
@@ -8298,8 +8423,8 @@ var SCAFFOLD_TEMPLATE_FILES = Object.freeze({
8298
8423
  "## What you run here",
8299
8424
  "",
8300
8425
  "- The tests: `npm test`, in this folder.",
8301
- "- A local run and a deploy: the `deploy` skill gives each step and the line to run, in this order: `submit_manifest`, the local run, `deploy`.",
8302
- "- A run on the platform: `run_schedule` with `wait_seconds` fires the schedule now and answers how the run ended. A settled answer carries the handler's lines in `console`. Where they were cut, may still be arriving, or could not be read, its `more` names the `read_logs` call under the source `container` that reads them on. An answer not yet settled names `read_schedules`, which lists every run.",
8426
+ "- A local run and a deploy: the `deploy` skill gives each step and the line to run, in this order: `tzcloud_submit_manifest`, the local run, `tzcloud_deploy`.",
8427
+ "- A run on the platform: `tzcloud_run_schedule` with `wait_seconds` fires the schedule now and answers how the run ended. A settled answer carries the handler's lines in `console`. Where they were cut, may still be arriving, or could not be read, its `more` names the `tzcloud_read_logs` call under the source `container` that reads them on. An answer not yet settled names `tzcloud_read_schedules`, which lists every run.",
8303
8428
  ""
8304
8429
  ].join("\n")],
8305
8430
  ["manifest.json", [
@@ -8504,7 +8629,7 @@ var SCAFFOLD_TEMPLATE_FILES = Object.freeze({
8504
8629
  "## What you run here",
8505
8630
  "",
8506
8631
  "- The tests: `npm test`, in this folder.",
8507
- "- A local run and a deploy: the `deploy` skill gives each step and the line to run, in this order: `submit_manifest`, the local run, `deploy`.",
8632
+ "- A local run and a deploy: the `deploy` skill gives each step and the line to run, in this order: `tzcloud_submit_manifest`, the local run, `tzcloud_deploy`.",
8508
8633
  "- Sign-in on a local run: start it with `--sign-in` and the application's own hostname, then open the address its port line names; the command sends the sign-in routes to that hostname. Without `--sign-in`, the page a local run serves has no sign-in routes, sign-in is on the deployed application's own address, and a local run's API routes take a session as a Bearer.",
8509
8634
  ""
8510
8635
  ].join("\n")],
@@ -9174,16 +9299,16 @@ var SCAFFOLD_TEMPLATE_FILES = Object.freeze({
9174
9299
  var APPLICATION_FOLDER = "app";
9175
9300
  var STAGE_FOLDER = "app.scaffold";
9176
9301
  var APPLICATION_MANIFEST = "manifest.json";
9177
- var CREATE_STEP = "Call create_application from your tool for this new service, and skip this step where you already created its application.";
9178
- var DEPLOY_TARGET_SENTENCE = "The deploy goes to the application's deploy target: production on an application with one environment, as a new one has, and development on one with two, where production receives a version through promote. To try versions on development, call create_environment first and follow its answer.";
9302
+ var CREATE_STEP = "Call tzcloud_create_application from your tool for this new service, and skip this step where you already created its application.";
9303
+ var DEPLOY_TARGET_SENTENCE = "The deploy goes to the application's deploy target: production on an application with one environment, as a new one has, and development on one with two, where production receives a version through tzcloud_promote. To try versions on development, call tzcloud_create_environment first and follow its answer.";
9179
9304
  var runLineOf = (origin, windows) => machineLineOf(commandLineOf(origin, RUN_SUBCOMMAND, origin !== DEFAULT_COMMAND_ORIGIN ? { origin } : {}), windows, origin);
9180
- var DEPLOY_STEP = `Call deploy from your tool with the application, naming no environment and neither artifact nor upload, and run the line it answers in ${APPLICATION_FOLDER}/. ${DEPLOY_TARGET_SENTENCE}`;
9305
+ var DEPLOY_STEP = `Call tzcloud_deploy from your tool with the application, naming no environment and neither artifact nor upload, and run the line it answers in ${APPLICATION_FOLDER}/. ${DEPLOY_TARGET_SENTENCE}`;
9181
9306
  var SHAPE_STEP = `Shape the service to your own before the first deploy: the table and its migration in ${APPLICATION_FOLDER}/migrations, the routes in ${APPLICATION_FOLDER}/src, and the tests, which cover those routes as written.`;
9182
9307
  var WEB_SHAPE_STEP = `Shape the app to your own before the first deploy: the page in ${APPLICATION_FOLDER}/client, the table and its migration in ${APPLICATION_FOLDER}/migrations, the routes in ${APPLICATION_FOLDER}/src, and the tests, which cover those routes as written.`;
9183
9308
  var WEB_OPEN_STEP = "Open the address the deploy answers in a browser and sign in there: the page lists the signed-in user's own rows, adds one, and answers a question under the plan's AI allowance.";
9184
- var SUBMIT_NO_SETTING_STEP = `Call submit_manifest from your tool with the application and its manifest, ${APPLICATION_FOLDER}/${APPLICATION_MANIFEST}, naming no local_run, since the service reads no setting.`;
9309
+ var SUBMIT_NO_SETTING_STEP = `Call tzcloud_submit_manifest from your tool with the application and its manifest, ${APPLICATION_FOLDER}/${APPLICATION_MANIFEST}, naming no local_run, since the service reads no setting.`;
9185
9310
  var provisionStepLineOf = (origin, windows) => machineLineOf(provisionBareLineOf({ origin, application: "<application id>" }), windows, origin);
9186
- var provisionStepOf = (origin, windows) => `Call submit_manifest from your tool with the application and its manifest, ${APPLICATION_FOLDER}/${APPLICATION_MANIFEST}, naming no local_run. Then run ${freshLineSteps2("the provision line below")}, all in ${APPLICATION_FOLDER}/. The provision line: ${provisionStepLineOf(origin, windows)}`;
9311
+ var provisionStepOf = (origin, windows) => `Call tzcloud_submit_manifest from your tool with the application and its manifest, ${APPLICATION_FOLDER}/${APPLICATION_MANIFEST}, naming no local_run. Then run ${freshLineSteps2("the provision line below")}, all in ${APPLICATION_FOLDER}/. The provision line: ${provisionStepLineOf(origin, windows)}`;
9187
9312
  var SCHEDULED_JOB_SCHEDULE = "heartbeat";
9188
9313
  var ENTRY_PAGES = Object.freeze({
9189
9314
  database: Object.freeze({ follow: "the guide Add a database", page: "/cloud/guides/add-a-database/" }),
@@ -9247,7 +9372,7 @@ var TEMPLATE_FACTS = Object.freeze({
9247
9372
  SUBMIT_NO_SETTING_STEP,
9248
9373
  `In ${APPLICATION_FOLDER}/, start the application on this machine, where GET /api/hello then answers hello world; no schedule fires on this machine, and the tests fire the handler. ${RUN_STEP_BACKGROUND}: ${runLineOf(origin, windows)}`,
9249
9374
  DEPLOY_STEP,
9250
- `Call run_schedule from your tool with the application, the schedule ${SCHEDULED_JOB_SCHEDULE}, and wait_seconds, which fires the handler now and answers how the run ended. A settled answer carries the handler's lines in console, and its more names the read_logs call where the lines were cut, may still be arriving, or could not be read. An answer not yet settled carries no console and names read_schedules, which lists every run.`
9375
+ `Call tzcloud_run_schedule from your tool with the application, the schedule ${SCHEDULED_JOB_SCHEDULE}, and wait_seconds, which fires the handler now and answers how the run ended. A settled answer carries the handler's lines in console, and its more names the tzcloud_read_logs call where the lines were cut, may still be arriving, or could not be read. An answer not yet settled carries no console and names tzcloud_read_schedules, which lists every run.`
9251
9376
  ]
9252
9377
  }),
9253
9378
  "web-app": Object.freeze({
@@ -9331,7 +9456,7 @@ var SCAFFOLD_OPTIONS = Object.freeze([
9331
9456
  name: SCAFFOLD_OPTION.application,
9332
9457
  value: "<application id>",
9333
9458
  required: false,
9334
- description: `Under every template, the application the service deploys to, by its id, a lowercase UUID, as create_application returns it. The written ${APPLICATION_MANIFEST} gives it in its application member, which binds the folder to that application, so a deploy or check command that gives another is refused. If omitted, the first deploy writes the member.`
9459
+ description: `Under every template, the application the service deploys to, by its id, a lowercase UUID, as tzcloud_create_application returns it. The written ${APPLICATION_MANIFEST} gives it in its application member, which binds the folder to that application, so a deploy or check command that gives another is refused. If omitted, the first deploy writes the member.`
9335
9460
  }
9336
9461
  ]);
9337
9462
  var EMPTY_PACKAGES = '"packages": []';
@@ -9358,7 +9483,7 @@ var NEITHER_LEFT = Object.freeze({ tools: "written", claude: false });
9358
9483
  var ROOT_TOOLS_STEP = `Add a sentence to ${TOOLS_FILE} at the project's root, which the scaffold did not change, so a coding tool started at the root reads ${APPLICATION_FOLDER}/${TOOLS_FILE}. The sentence to add: ${ROOT_SENTENCE}`;
9359
9484
  var ROOT_TOOLS_FAILED_STEP = `Add a sentence to ${TOOLS_FILE} at the project's root, which the scaffold could not write, so a coding tool started at the root reads ${APPLICATION_FOLDER}/${TOOLS_FILE}. The sentence to add: ${ROOT_SENTENCE}`;
9360
9485
  var ROOT_CLAUDE_STEP = `Add a sentence to ${CLAUDE_FILE} at the project's root, since Claude Code reads that file and then reads no ${TOOLS_FILE} by itself. The sentence to add: ${ROOT_SENTENCE}`;
9361
- var APPLICATION_FORM_REFUSAL = `${SCAFFOLD_OPTION.application} names the application the service deploys to, by its id, a lowercase UUID, as create_application answers it. ${NOTHING_WRITTEN2}`;
9486
+ var APPLICATION_FORM_REFUSAL = `${SCAFFOLD_OPTION.application} names the application the service deploys to, by its id, a lowercase UUID, as tzcloud_create_application answers it. ${NOTHING_WRITTEN2}`;
9362
9487
  var RESOURCE_REFUSAL = Object.freeze({
9363
9488
  /** A plural outside SCAFFOLD_NAME_FORM. */
9364
9489
  resourceForm: `${SCAFFOLD_OPTION.resource} takes the plural of the resource the service keeps, the word of its table and its route: an ASCII lower-case letter, then ASCII lower-case letters and digits, at most 30 characters, such as orders. ${NOTHING_WRITTEN2}`,
@@ -9864,7 +9989,7 @@ var scaffoldLinkSentence = (what) => `${what} stands on a link that leads outsid
9864
9989
  var listOf = (value) => value === null ? [] : Array.isArray(value) ? value : [value];
9865
9990
  var BRING_PAGE = "/cloud/guides/bring-an-existing-application/";
9866
9991
  var BRING_FOLLOW = "the guide Bring an existing application";
9867
- var STANDS_DEPLOY_LINE = `Where ${APPLICATION_FOLDER}/ holds an application, deploy it: call deploy from your tool and run the line it answers in ${APPLICATION_FOLDER}/, as ${BRING_FOLLOW}, read_documentation's page ${BRING_PAGE}, says.`;
9992
+ var STANDS_DEPLOY_LINE = `Where ${APPLICATION_FOLDER}/ holds an application, deploy it: call tzcloud_deploy from your tool and run the line it answers in ${APPLICATION_FOLDER}/, as ${BRING_FOLLOW}, read_documentation's page ${BRING_PAGE}, says.`;
9868
9993
  var applicationStandsLines = (template, takeLines) => {
9869
9994
  const { takes } = TEMPLATE_FACTS[template];
9870
9995
  const lines = listOf(takeLines);
@@ -10375,7 +10500,6 @@ var TOKEN_ROW = Object.freeze({
10375
10500
 
10376
10501
  // src/turnzero_cloud_command/tzmesh_register.ts
10377
10502
  import { dirname as dirname8, resolve as resolve13 } from "node:path";
10378
- var TZMESH_LISTED = true;
10379
10503
  var TZMESH_ACT_WORDS = `${TZMESH_SUBCOMMAND} ${TZMESH_REGISTER_ACT}`;
10380
10504
  var TZMESH_OPTIONS = Object.freeze([
10381
10505
  {
@@ -10661,7 +10785,7 @@ var registeredLineOf = (agent, wire) => `${REGISTERED_LINE_HEAD}agent ${agent.ha
10661
10785
  var WRITTEN_LINE = `${WRITTEN_LINE_HEAD}the agent's secret, alone on one line, into the file ${TZMESH_OPTION.toFile} names, readable by its owner alone`;
10662
10786
  var REGISTER_UNKNOWN = "Whether the agent was registered is unknown: tzmesh_list_participants from your tool shows it, and delete_agent from your tool, naming its participant, deletes it.";
10663
10787
  var agentStandsSentence = (agent) => `The agent ${agentWords(agent)} stands with no secret kept: delete_agent from your tool, naming participant ${agent.id}, deletes it and frees its name.`;
10664
- var storeUnknownSentence = (secretName, agent) => `Whether the secret was stored is unknown: list_secrets from your tool shows when ${secretName} was last written. Where it was not written, delete_agent from your tool, naming participant ${agent.id}, deletes the agent ${agentWords(agent)}.`;
10788
+ var storeUnknownSentence = (secretName, agent) => `Whether the secret was stored is unknown: tzcloud_list_secrets from your tool shows when ${secretName} was last written. Where it was not written, delete_agent from your tool, naming participant ${agent.id}, deletes the agent ${agentWords(agent)}.`;
10665
10789
  var TOKEN_LEFT = `list_tokens from your tool shows the run's token by its label, ${TZMESH_COMMAND_LABEL}, and revoke_token ends it; it expires within a day either way.`;
10666
10790
  var tokenStandsSentence = (id) => `The run's token, ${id}, was not revoked, so it works until it expires within a day: revoke_token from your tool with id ${id} ends it, and list_tokens shows whether it stands.`;
10667
10791
  var revocationBearerRefused = (origin) => `This computer's token for ${origin} was refused as the bearer of the revocation.`;
@@ -10767,10 +10891,10 @@ var setUpAgent = async (io2, wire, secret2, userAgent, options, ended) => {
10767
10891
  return { signing };
10768
10892
  };
10769
10893
  var firstStoreStandsSentence = (secretName) => `${secretName} now holds the deleted agent's secret, which works nowhere, until the line runs again.`;
10770
- var signingUnknownSentence = (signingName, agent) => `Whether the webhook's signing secret was stored is unknown: list_secrets from your tool shows when ${signingName} was last written. Where it was not written, delete_agent from your tool, naming participant ${agent.id}, deletes the agent ${agentWords(agent)}, and the line runs again.`;
10894
+ var signingUnknownSentence = (signingName, agent) => `Whether the webhook's signing secret was stored is unknown: tzcloud_list_secrets from your tool shows when ${signingName} was last written. Where it was not written, delete_agent from your tool, naming participant ${agent.id}, deletes the agent ${agentWords(agent)}, and the line runs again.`;
10771
10895
  var unfinishableSentence = (agent) => `The agent ${agentWords(agent)} cannot be finished, since its webhook's signing secret ended with the run: delete_agent from your tool, naming participant ${agent.id}, deletes it, and the line runs again.`;
10772
- var firstStoreUnknownSentence = (secretName) => `Whether ${secretName} was written is unknown: list_secrets from your tool shows when it was last written. Where it was, it holds the deleted agent's secret, which works nowhere, until the line runs again.`;
10773
- var unfinishedStandsSentence = (agent, kept2) => `${kept2.known ? `${kept2.name} holds the secret of the agent ${agentWords(agent)}.` : `Whether ${kept2.name} holds the secret of the agent ${agentWords(agent)} is unknown: list_secrets from your tool shows when it was last written.`} ${unfinishableSentence(agent)}`;
10896
+ var firstStoreUnknownSentence = (secretName) => `Whether ${secretName} was written is unknown: tzcloud_list_secrets from your tool shows when it was last written. Where it was, it holds the deleted agent's secret, which works nowhere, until the line runs again.`;
10897
+ var unfinishedStandsSentence = (agent, kept2) => `${kept2.known ? `${kept2.name} holds the secret of the agent ${agentWords(agent)}.` : `Whether ${kept2.name} holds the secret of the agent ${agentWords(agent)} is unknown: tzcloud_list_secrets from your tool shows when it was last written.`} ${unfinishableSentence(agent)}`;
10774
10898
  var revokeRunToken = async (io2, plane, bearer, id, userAgent) => {
10775
10899
  const answered = await postAction(io2, plane, REVOKE_TOKEN_ACTION, bearer, userAgent, revocationBodyOf(id));
10776
10900
  let lines;
@@ -11018,7 +11142,7 @@ var TZMESH_ROW = Object.freeze({
11018
11142
  statuses: {
11019
11143
  done: "the challenge printed, or the agent registered, its secret kept, and the run's token revoked",
11020
11144
  failed: "a part failed: the agent was not registered, its secret was not kept, or the run's token was not revoked. The printed lines name what stands and the call that ends it",
11021
- unknown: "an outcome is unknown: the printed lines name list_tokens, tzmesh_list_participants, or list_secrets",
11145
+ unknown: "an outcome is unknown: the printed lines name list_tokens, tzmesh_list_participants, or tzcloud_list_secrets",
11022
11146
  nothing_started: `nothing was minted. An option, the credential file, the file ${TZMESH_OPTION.toFile} names, or this computer's token was refused. Or no request was pending, the platform was too old, or the exchange was refused`
11023
11147
  },
11024
11148
  variables: [[ORIGIN_VARIABLE, `the platform's address the secret is stored at where the line names no ${TZMESH_OPTION.origin}. It must be ${DEFAULT_COMMAND_ORIGIN} or ${DEVELOPMENT_COMMAND_ORIGIN}.`]],
@@ -11030,7 +11154,6 @@ var TZMESH_ROW = Object.freeze({
11030
11154
  `The run reads this computer's token for each address it sends to: the ${TZMESH_OPTION.tzmeshEstate} platform's, to revoke the run's token, and under ${TZMESH_OPTION.secret} the ${TZMESH_OPTION.origin} platform's, to store the secret. Authorize this computer at each first.`
11031
11155
  ],
11032
11156
  afterOwnError: (call) => call.named[TZMESH_OPTION.mint] !== void 0 ? TZMESH_AFTER_OWN_ERROR : TZMESH_FIRST_ACT_AFTER_OWN_ERROR,
11033
- listed: TZMESH_LISTED,
11034
11157
  run: tzmeshRegister
11035
11158
  });
11036
11159
 
@@ -11618,9 +11741,8 @@ var SUBCOMMANDS = Object.freeze([
11618
11741
  SESSION_ROW,
11619
11742
  TZMESH_ROW
11620
11743
  ]);
11621
- var listedSubcommands = () => SUBCOMMANDS.filter((subcommand) => subcommand.listed !== false);
11622
11744
  var SERVED = LINE_RUNNER;
11623
- var NPX_FORM_SENTENCE = `A tool runs the command through npx first: write ${commandRunnerOf("latest")} for ${LINE_RUNNER}, since that form runs whether or not the command is installed. Where the tool's safety check refuses it, the tool runs ${LINE_RUNNER} where ${LINE_RUNNER} --version responds, and otherwise takes deploy_files for a deploy or installs the command with ${installLineOf(DEFAULT_COMMAND_ORIGIN)}. Past deploy_files' caps, where it may not install or run the command, it uploads a zip with mint_upload_grant and names it as deploy's artifact. A person or a job may run either form.`;
11745
+ var NPX_FORM_SENTENCE = `A tool runs the command through npx first: write ${commandRunnerOf("latest")} for ${LINE_RUNNER}, since that form runs whether or not the command is installed. Where the tool's safety check refuses it, the tool runs ${LINE_RUNNER} where ${LINE_RUNNER} --version responds, and otherwise takes tzcloud_deploy_files for a deploy or installs the command with ${installLineOf(DEFAULT_COMMAND_ORIGIN)}. Past tzcloud_deploy_files' caps, where it may not install or run the command, it uploads a zip with tzcloud_mint_upload_grant and names it as tzcloud_deploy's artifact. A person or a job may run either form.`;
11624
11746
  var namedWithActs = (subcommand) => subcommand.acts ? `${subcommand.name} ${subcommand.acts.join("|")}` : subcommand.name;
11625
11747
  var shown = (option) => option.flag ? option.name : `${option.name} ${option.value}`;
11626
11748
  var listed = (names) => names.length < 3 ? names.join(" and ") : `${names.slice(0, -1).join(", ")}, and ${names[names.length - 1]}`;
@@ -11644,9 +11766,9 @@ var usageLineOf = (subcommand) => {
11644
11766
  return `${pipedHead(subcommand)}${SERVED} ${[namedWithActs(subcommand), ...required, ...optional].join(" ")}`;
11645
11767
  };
11646
11768
  var usageHeadOf = (version) => `${TURNZERO_CLOUD_PACKAGE} ${version}: the Turn Zero Cloud command, installed from the public npm registry by your platform's tag, latest on production and next on development.`;
11647
- var unreadNames = () => listedSubcommands().filter((subcommand) => subcommand.credential === null && subcommand.reads === void 0).map((subcommand) => subcommand.name);
11648
- var unattendedNames = () => listedSubcommands().filter((subcommand) => subcommand.credential?.mintedToken === true).map((subcommand) => subcommand.name);
11649
- var computerOnlyNames = () => listedSubcommands().filter((subcommand) => subcommand.credential?.computerToken === true).map((subcommand) => subcommand.name);
11769
+ var unreadNames = () => SUBCOMMANDS.filter((subcommand) => subcommand.credential === null && subcommand.reads === void 0).map((subcommand) => subcommand.name);
11770
+ var unattendedNames = () => SUBCOMMANDS.filter((subcommand) => subcommand.credential?.mintedToken === true).map((subcommand) => subcommand.name);
11771
+ var computerOnlyNames = () => SUBCOMMANDS.filter((subcommand) => subcommand.credential?.computerToken === true).map((subcommand) => subcommand.name);
11650
11772
  var exampleLineOf = (subcommand) => {
11651
11773
  const credential = subcommand.credential;
11652
11774
  const mustPipe = credential !== null && credential.piped !== false && credential.bare === void 0 && credential.computerToken !== true;
@@ -11672,7 +11794,7 @@ var pipedLinesOf = (subcommand) => {
11672
11794
  var readsLinesOf = (subcommand) => subcommand.reads !== void 0 ? [` ${subcommand.name} reads ${subcommand.reads}.`] : [];
11673
11795
  var noCredentialLine = () => {
11674
11796
  const unread = unreadNames();
11675
- const unlessFlagged = listedSubcommands().filter((subcommand) => subcommand.credential === null && subcommand.readsOnlyWith !== void 0).map((subcommand) => `${subcommand.name} without ${subcommand.readsOnlyWith}`);
11797
+ const unlessFlagged = SUBCOMMANDS.filter((subcommand) => subcommand.credential === null && subcommand.readsOnlyWith !== void 0).map((subcommand) => `${subcommand.name} without ${subcommand.readsOnlyWith}`);
11676
11798
  const subject = unlessFlagged.length === 0 ? listed(unread) : unread.length === 0 ? listed(unlessFlagged) : `${listed(unread)}, and ${listed(unlessFlagged)},`;
11677
11799
  return ` The command takes no credential in its arguments, and ${subject} ${unread.length + unlessFlagged.length === 1 ? "reads" : "read"} none.`;
11678
11800
  };
@@ -11688,7 +11810,7 @@ var statusClauseOf = (name, clause) => `Under ${name}, ${clause}`;
11688
11810
  var noteLinesOf2 = (subcommand) => (subcommand.note ?? []).flatMap((paragraph) => ["", paragraph]);
11689
11811
  var usageBlockOf = (subcommandHelp) => [
11690
11812
  "Usage:",
11691
- ...listedSubcommands().map((subcommand) => ` ${usageLineOf(subcommand)}`),
11813
+ ...SUBCOMMANDS.map((subcommand) => ` ${usageLineOf(subcommand)}`),
11692
11814
  ` ${SERVED} --version`,
11693
11815
  ` ${SERVED} --help`,
11694
11816
  ...subcommandHelp ? [` ${SERVED} <subcommand> --help`] : []
@@ -11707,7 +11829,7 @@ var shortUsageText = (version = commandVersion()) => [
11707
11829
  ...STATUS_MEANINGS.map(([status, meaning, also]) => statusLineOf(status, meaning, [], also)),
11708
11830
  "",
11709
11831
  "Subcommands:",
11710
- ...listedSubcommands().map((subcommand) => ` ${namedWithActs(subcommand)}: ${subcommand.summary}`),
11832
+ ...SUBCOMMANDS.map((subcommand) => ` ${namedWithActs(subcommand)}: ${subcommand.summary}`),
11711
11833
  "",
11712
11834
  SUBCOMMAND_HELP_SENTENCE
11713
11835
  ].join("\n");
@@ -11756,7 +11878,7 @@ var valuePlacesOf = (argv2) => {
11756
11878
  }
11757
11879
  return places;
11758
11880
  };
11759
- var noSubcommandSentence = (first) => `${first === void 0 ? "No subcommand was named" : `The first argument is not a subcommand of ${TURNZERO_CLOUD_PACKAGE}`}: the subcommands are ${listedSubcommands().map((entry) => entry.name).join(", ")}. ${NOTHING_STARTED2}`;
11881
+ var noSubcommandSentence = (first) => `${first === void 0 ? "No subcommand was named" : `The first argument is not a subcommand of ${TURNZERO_CLOUD_PACKAGE}`}: the subcommands are ${SUBCOMMANDS.map((entry) => entry.name).join(", ")}. ${NOTHING_STARTED2}`;
11760
11882
  var parseArguments = (given, onWindows2 = ON_WINDOWS) => {
11761
11883
  const argv2 = withCurrentOptionNames(given);
11762
11884
  if (argv2.some((argument) => argument.includes(UPLOAD_GRANT_PREFIX))) return { kind: "refused", sentence: grantArgumentSentence() };