turnzero 0.36.0-next.1 → 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.
- package/dist/turnzero-cloud.mjs +291 -169
- package/package.json +4 -4
package/dist/turnzero-cloud.mjs
CHANGED
|
@@ -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
|
|
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
|
|
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: "
|
|
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 = "
|
|
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 = "
|
|
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-
|
|
487
|
-
management_api: "2026-
|
|
488
|
-
wire_errors: "2026-
|
|
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
|
|
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() +
|
|
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
|
|
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
|
-
|
|
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)}
|
|
1211
|
-
return
|
|
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,
|
|
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)}
|
|
1216
|
-
return
|
|
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
|
-
|
|
1223
|
-
|
|
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
|
-
|
|
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 = "
|
|
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
|
-
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 ${
|
|
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
|
|
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 ${
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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}. ${
|
|
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} ${
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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) => `${
|
|
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
|
|
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
|
|
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 ${
|
|
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
|
|
4904
|
-
var secretUnknownSentence = (act) => `Whether the value was written is unknown: call
|
|
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 ${
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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, {
|
|
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
|
|
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
|
|
6931
|
-
const
|
|
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
|
-
|
|
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,
|
|
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:
|
|
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
|
|
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
|
|
7208
|
-
`${ROUTE_NEEDS.connection}, past
|
|
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},
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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;
|
|
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
|
|
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
|
|
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: `
|
|
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: `
|
|
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: `
|
|
8302
|
-
"- A run on the platform: `
|
|
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: `
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
|
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
|
|
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 = () =>
|
|
11648
|
-
var unattendedNames = () =>
|
|
11649
|
-
var computerOnlyNames = () =>
|
|
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 =
|
|
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
|
-
...
|
|
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
|
-
...
|
|
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 ${
|
|
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() };
|