turnzero 0.16.1-next.1 → 0.17.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.
@@ -201,6 +201,11 @@ var LOCAL_RUN_SETTING = Object.freeze({
201
201
  var LOCAL_RUN_ENVIRONMENT = "local";
202
202
  var LOCAL_RUN_CREDENTIAL_SETTINGS = Object.freeze([LOCAL_RUN_SETTING.platformCredential, LOCAL_RUN_SETTING.databaseConnection]);
203
203
  var ENVIRONMENT_FILE_NAME = ".env";
204
+ var provisionBareLineOf = (call) => commandLineOf(call.origin, PROVISION_SUBCOMMAND, {
205
+ options: [[PROVISION_OPTION.application, call.application]],
206
+ ...call.origin !== DEFAULT_COMMAND_ORIGIN ? { origin: call.origin } : {},
207
+ ...call.envFile !== void 0 ? { quoted: [[PROVISION_OPTION.envFile, call.envFile]] } : {}
208
+ });
204
209
  var DEPLOY_ROTATE_FLAG = "--rotate-database-credential";
205
210
  var DEPLOY_PREPARED_LINE_HEAD = "prepared: ";
206
211
  var CREDENTIAL_LOOKUP_BUSY = "credential_lookup_busy";
@@ -368,7 +373,7 @@ function compareWireVersions(a, b) {
368
373
 
369
374
  // src/turnzero_cloud_command/plane_wire.ts
370
375
  var PLANE_WIRE_NEEDED = Object.freeze({
371
- action_payloads: "2026-10-13.10",
376
+ action_payloads: "2026-10-14.2",
372
377
  management_api: "2026-10-10.5",
373
378
  wire_errors: "2026-10-10.6"
374
379
  });
@@ -777,6 +782,11 @@ var pipeWholeWayOn = (aWhat, call, nothingPiped = false) => `Pipe ${aWhat} whole
777
782
  // src/turnzero_cloud_command/line_form.ts
778
783
  var onWindows = (io2) => io2.windows ?? process.platform === "win32";
779
784
  var ranThroughNpx = (io2) => io2.ranThroughNpx ?? false;
785
+ var printedLineOf = (io2, line, origin) => {
786
+ const run = ranThroughNpx(io2) ? npxFormOf(line, origin) : line;
787
+ return onWindows(io2) ? windowsLineOf(run) : run;
788
+ };
789
+ var provisionLineFor = (io2, call) => printedLineOf(io2, provisionBareLineOf(call), call.origin);
780
790
  var loginLineFor = (io2, origin) => {
781
791
  const line = loginLineOf(origin);
782
792
  return onWindows(io2) ? windowsLineOf(line) : line;
@@ -801,6 +811,7 @@ var unendedReadRefusal = (declared, reading, nothingArrived = false) => unendedR
801
811
  declared.computerToken === true ? grantWaysOn(declared) : pipeWholeWayOn(declared.aGrant, declared.call, declared.mintedToken && nothingArrived)
802
812
  );
803
813
  var emptyTokenVariableRefusal = () => `${MINTED_TOKEN_VARIABLE} is set but empty, so nothing was sent and nothing was started: the read that set it for this line found no token. Set it to your minted token from where your tool keeps it, or unset it to use this computer's token.`;
814
+ var noCredentialRefusal = (declared, origin, expiredAt, again) => `No ${declared.grant} was read, so nothing was started: ${credentialPlaces(declared)} ${expiredAt === null ? `This computer's credential file holds no token for ${origin}.` : `This computer's token for ${origin} in its credential file expired at ${expiredAt}.`} ${again}`.trimEnd();
804
815
  var expired = (expiresAt, now) => expiresAt !== null && Date.parse(expiresAt) <= now.getTime();
805
816
  async function readCredential(io2, declared, again, line = { named: void 0, closing: "" }) {
806
817
  if (declared.piped !== false) {
@@ -841,7 +852,7 @@ async function readCredential(io2, declared, again, line = { named: void 0, clos
841
852
  if (!("state" in read2)) return { refusal: readRefusalOf(read2, place.path) };
842
853
  const entry = read2.state.origins.get(origin.origin);
843
854
  const unauthorized = (expiredAt) => ({
844
- refusal: `No ${declared.grant} was read, so nothing was started: ${credentialPlaces(declared)} ${expiredAt === null ? `This computer's credential file holds no token for ${origin.origin}.` : `This computer's token for ${origin.origin} in its credential file expired at ${expiredAt}.`} ${again}`.trimEnd(),
855
+ refusal: noCredentialRefusal(declared, origin.origin, expiredAt, again),
845
856
  unauthorized: { origin: origin.origin, expiredAt }
846
857
  });
847
858
  if (entry === void 0) return unauthorized(null);
@@ -1048,8 +1059,9 @@ function keepPendingRequest(io2, origin, say) {
1048
1059
  dropCredentialWriting(io2, place, tag);
1049
1060
  }
1050
1061
  opening = standing !== void 0 ? replacedRequestSentence(origin, standing) : "";
1062
+ return { pending, opening, standing: standing !== void 0 ? { kind: "replaced", expired: standing } : { kind: "new" } };
1051
1063
  }
1052
- return { pending, opening };
1064
+ return { pending, opening, standing: { kind: "reused" } };
1053
1065
  }
1054
1066
  var TOKEN_CALL_BOUND_SECONDS = 60;
1055
1067
  var EXCHANGE_ACT = "exchange";
@@ -2848,6 +2860,7 @@ var headCommitOf = (folder, reads = FILE_SYSTEM_READS) => {
2848
2860
  };
2849
2861
 
2850
2862
  // src/turnzero_cloud_command/options.ts
2863
+ var afterOwnErrorOf = (row, call, io2) => typeof row.afterOwnError === "function" ? row.afterOwnError(call, io2) : row.afterOwnError;
2851
2864
  var PATH_OPTION_NAMES = Object.freeze([DEPLOY_OPTION.path, SECRET_OPTION.valueFile, PROVISION_OPTION.envFile]);
2852
2865
  var DEPLOY_OPTIONS = Object.freeze([
2853
2866
  {
@@ -3252,7 +3265,6 @@ async function prepareDeploy(io2, options, zipSha256Value, bearer, userAgent, re
3252
3265
  io2.print(PREPARE_AGAIN);
3253
3266
  return nothingStarted;
3254
3267
  }
3255
- io2.print(preparedLineOf(prepared));
3256
3268
  return prepared;
3257
3269
  }
3258
3270
  var NOTHING_STARTED = "Nothing was started.";
@@ -3372,6 +3384,7 @@ async function deploy(named, io2, flags = /* @__PURE__ */ new Set()) {
3372
3384
  for (const line of unserved) io2.print(line);
3373
3385
  return PROGRESS_EXIT_STATUS.nothing_started;
3374
3386
  }
3387
+ io2.print(preparedLineOf(prepared));
3375
3388
  const { upload, grant, environment } = prepared;
3376
3389
  const headers = { authorization: `Bearer ${grant}`, "user-agent": agent.userAgent };
3377
3390
  const stop = commandStopSentence(options.application, environment);
@@ -3529,7 +3542,7 @@ var DEPLOY_ROW = Object.freeze({
3529
3542
  `A progress read answered 502, 503, or 504, which is often temporary, is made again, at most three more times, and an upload answered 503 credential_lookup_busy, which wrote nothing, is made again after the wait it names, at most twice.`,
3530
3543
  `After its zip line, ${DEPLOY_SUBCOMMAND} prints the folder's top-level entries the zip holds on one line, at most ten and then the count of the rest, and ${HASH_SUBCOMMAND} ${HASH_OPTION.list} names every file; no such line prints for a .zip file.`,
3531
3544
  `Then it prints the paths the zip left out, a warning for a .zip file at the folder's root, a warning for a file that looks like a key or a credential, and a warning for a health path that no file names, package files and documentation set aside, each on a line of its own and only where there is something to name. The health warning refuses nothing.`,
3532
- `After the ${PREPARED_LINE_HEAD.trimEnd()} line, where the platform's answer names the recorded manifest's health path and says the environment serves no version, and no file of the folder's zip names that path, ${DEPLOY_SUBCOMMAND} prints the platform's own refusal, then that nothing was uploaded and nothing was started, and ends 3, as the start would refuse it. A .zip file the line names is not read for it, and the start's own refusal stands.`
3545
+ `After the preparing call, where the platform's answer names the recorded manifest's health path and says the environment serves no version, and no file of the folder's zip names that path, ${DEPLOY_SUBCOMMAND} prints the platform's own refusal, then that nothing was uploaded and nothing was started, and ends 3 with no ${PREPARED_LINE_HEAD.trimEnd()} line, as the start would refuse it. A .zip file the line names is not read for it, and the start's own refusal stands.`
3533
3546
  ],
3534
3547
  afterOwnError: DEPLOY_AFTER_OWN_ERROR,
3535
3548
  run: (call, io2) => deploy(call.named, io2, call.flags)
@@ -3970,7 +3983,7 @@ var freshLineSteps = (act) => `${SECRET_ACTION[act]} from your tool with the nam
3970
3983
  var secretAgain = (act) => `Call ${freshLineSteps(act)}`;
3971
3984
  var RESTART_UNDER_STORE = `${SECRET_OPTION.restart} goes with ${SECRET_SUBCOMMAND} rotate alone: a store restarts nothing. ${NOTHING_SENT2}`;
3972
3985
  var RESTART_UNDER_GRANT = `${SECRET_OPTION.restart} asks for a restart, and a write under a secret grant writes the value alone. Run the line without ${SECRET_OPTION.restart} and then make the restart_application call the answer's next names, or, where you wrote the line yourself, run it with no grant piped, under this computer's token. ${NOTHING_SENT2}`;
3973
- var PLATFORM_MINTED_UNDER_TOKEN = `${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. The ${PROVISION_SUBCOMMAND} line a submit_manifest call naming local_run answers re-mints it and writes it into the environment file. ${NOTHING_SENT2}`;
3986
+ 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}`;
3974
3987
  var underTokenLine = (origin) => `No secret grant was piped, so this line runs under this computer's token for ${origin}.`;
3975
3988
  var sentLine = (act, underGrant) => `The ${SECRET_ACTION[act]} write is being sent; wait for its answer. Before any second run, call list_secrets from your tool, whose row for the name shows when it was last written, so whether this write landed.${underGrant ? " The secret grant serves once: where this write landed, a second run of this line is normally refused secret_grant_spent." : ""}`;
3976
3989
  var secretOptionsOf = (call, cwd) => {
@@ -4056,7 +4069,7 @@ async function secret(call, io2) {
4056
4069
  return COMMAND_STATUS.nothing_started;
4057
4070
  }
4058
4071
  if (credential.source === "credential_file" && options.act === "rotate" && options.application !== null && (options.name === databaseCredentialNameOf(options.application) || options.name === platformCredentialNameOf(options.application))) {
4059
- io2.print(PLATFORM_MINTED_UNDER_TOKEN);
4072
+ io2.print(platformMintedUnderToken(provisionLineFor(io2, { origin: credential.origin, application: options.application })));
4060
4073
  return COMMAND_STATUS.nothing_started;
4061
4074
  }
4062
4075
  const sent = credentialOriginOf(io2.env, credential, line);
@@ -5645,14 +5658,17 @@ var PROVISION_CREDENTIAL = Object.freeze({
5645
5658
  grant: "secret grant",
5646
5659
  aGrant: "a secret grant",
5647
5660
  call: "the submit_manifest call naming local_run",
5648
- mintedToken: true
5661
+ mintedToken: true,
5662
+ bare: `with nothing piped and neither token, it keeps a verifier and prints the challenge and the submit_manifest call naming local_run and ${CODE_CHALLENGE_MEMBER}, and a grant piped is presented with that verifier`
5649
5663
  });
5650
5664
  var NOTHING_REMINTED = "Nothing was re-minted, and the environment file is as it stood.";
5651
- var FRESH_LINE_STEPS = "submit_manifest from your tool with the application, its manifest, and local_run, and run the line it answers as given";
5652
- var PROVISION_AGAIN = `Call ${FRESH_LINE_STEPS}.`;
5653
- var againSteps = (kind) => kind === "grant" ? `call ${FRESH_LINE_STEPS}` : "run the line again";
5654
- var remintAgainSentence = (kind) => {
5655
- const steps = againSteps(kind);
5665
+ var PROVISION_BARE_LINE_WORDS = commandLineOf(DEFAULT_COMMAND_ORIGIN, PROVISION_SUBCOMMAND, { options: [[PROVISION_OPTION.application, "<application id>"]] });
5666
+ var freshLineOf = (io2, application, origin, envFile) => provisionLineFor(io2, { origin, application, ...envFile !== void 0 ? { envFile } : {} });
5667
+ var freshLineSteps2 = (line) => `${line} with nothing piped, and where it prints a submit_manifest call, make that call from your tool and run the line it answers as given`;
5668
+ var provisionAgainOf = (line) => `Run ${freshLineSteps2(line)}.`;
5669
+ var againSteps = (kind, line) => kind === "grant" ? `run ${freshLineSteps2(line)}` : "run the line again";
5670
+ var remintAgainSentence = (kind, line) => {
5671
+ const steps = againSteps(kind, line);
5656
5672
  return `${steps[0].toUpperCase()}${steps.slice(1)}: it re-mints both credentials and writes the file.`;
5657
5673
  };
5658
5674
  var envFileNameRefusalOf = (standing) => `${PROVISION_OPTION.envFile} names the environment file ${ENVIRONMENT_FILE_NAME} or ${ENVIRONMENT_FILE_NAME}.<name>, the names every zip the command or deploy_files builds leaves out, so the credentials it holds never ride one.${standing ? ` A file stands at the name given, and an earlier run may have written credentials into it: move its lines into ${ENVIRONMENT_FILE_NAME} and delete it.` : ""} ${NOTHING_REMINTED}`;
@@ -5704,13 +5720,13 @@ var unreachedLine = (origin, error) => {
5704
5720
  }
5705
5721
  return `${PROVISION_ACTION}: the platform could not be reached: ${said}`;
5706
5722
  };
5707
- async function remint(io2, origin, credential, userAgent, application, name) {
5723
+ async function remint(io2, origin, credential, userAgent, application, name, verifier = null) {
5708
5724
  let response;
5709
5725
  try {
5710
5726
  response = await io2.fetch(`${origin}${actionPathOf(PROVISION_ACTION)}`, {
5711
5727
  method: "POST",
5712
5728
  headers: { authorization: `Bearer ${credential}`, "user-agent": userAgent, "content-type": "application/json" },
5713
- body: JSON.stringify({ name, application, environment: PROVISION_ENVIRONMENT }),
5729
+ body: JSON.stringify({ name, application, environment: PROVISION_ENVIRONMENT, ...verifier !== null ? { [CODE_VERIFIER_MEMBER]: verifier } : {} }),
5714
5730
  redirect: "manual"
5715
5731
  });
5716
5732
  } catch (error) {
@@ -5753,7 +5769,20 @@ var factsOf = (member) => {
5753
5769
  };
5754
5770
  var connectionSettingOf = (facts, password) => `postgresql://${encodeURIComponent(facts.roleName)}:${encodeURIComponent(password)}@${facts.host}:5432/${encodeURIComponent(facts.dbName)}?sslmode=verify-full`;
5755
5771
  var LIMIT_SHOWN_MAX = 80;
5756
- var PROVISION_AFTER_OWN_ERROR = "a credential may or may not have been re-minted, and the environment file may not hold its value: a submit_manifest call naming local_run answers a fresh line, which re-mints both and writes the file";
5772
+ var UNATTENDED_JOB_VARIABLE = "CI";
5773
+ var afterOwnErrorBy = (line) => `a credential may or may not have been re-minted, and the environment file may not hold its value: ${line} run again with nothing piped re-mints both and writes the file, or prints the submit_manifest call whose line does`;
5774
+ var PROVISION_AFTER_OWN_ERROR = afterOwnErrorBy(`${PROVISION_BARE_LINE_WORDS}, with the ${PROVISION_OPTION.origin} and ${PROVISION_OPTION.envFile} the line named,`);
5775
+ var provisionAfterOwnError = (call, io2) => {
5776
+ try {
5777
+ const application = call.named[PROVISION_OPTION.application];
5778
+ if (application === void 0 || !UPLOAD_ID.test(application)) return PROVISION_AFTER_OWN_ERROR;
5779
+ const origin = commandOriginOf(call.named[PROVISION_OPTION.origin] ?? DEFAULT_COMMAND_ORIGIN);
5780
+ if ("refusal" in origin) return PROVISION_AFTER_OWN_ERROR;
5781
+ return afterOwnErrorBy(`${freshLineOf(io2, application, origin.origin, call.named[PROVISION_OPTION.envFile])},`);
5782
+ } catch {
5783
+ return PROVISION_AFTER_OWN_ERROR;
5784
+ }
5785
+ };
5757
5786
  var remintUnknownSentence = (which) => `Whether the development ${which} credential was re-minted is unknown, and no value was written.`;
5758
5787
  var DATABASE_VALUE_LOST = "The development database credential was re-minted and its value was not written, so a connection setting an earlier run wrote no longer connects.";
5759
5788
  var PLATFORM_VALUE_LOST = `The development platform credential was re-minted and its value was not written, so a ${LOCAL_RUN_SETTING.platformCredential} an earlier run wrote is revoked.`;
@@ -5781,7 +5810,18 @@ async function provision(call, io2) {
5781
5810
  );
5782
5811
  return COMMAND_STATUS.nothing_started;
5783
5812
  }
5784
- const read2 = await readCredential(io2, PROVISION_CREDENTIAL, PROVISION_AGAIN, { named: call.named[PROVISION_OPTION.origin], closing: NOTHING_REMINTED });
5813
+ const namedEnvFile = call.named[PROVISION_OPTION.envFile];
5814
+ const read2 = await readCredential(io2, PROVISION_CREDENTIAL, provisionAgainOf(freshLineOf(io2, options.application, options.origin, namedEnvFile)), {
5815
+ named: call.named[PROVISION_OPTION.origin],
5816
+ closing: NOTHING_REMINTED
5817
+ });
5818
+ if ("unauthorized" in read2) {
5819
+ if (io2.env[UNATTENDED_JOB_VARIABLE] !== void 0) {
5820
+ io2.print(noCredentialRefusal(PROVISION_CREDENTIAL, read2.unauthorized.origin, read2.unauthorized.expiredAt, ""));
5821
+ return COMMAND_STATUS.nothing_started;
5822
+ }
5823
+ return firstProvisionAct(io2, call, options.application, namedEnvFile, read2.unauthorized);
5824
+ }
5785
5825
  if ("refusal" in read2) {
5786
5826
  io2.print(read2.refusal);
5787
5827
  return COMMAND_STATUS.nothing_started;
@@ -5793,6 +5833,8 @@ async function provision(call, io2) {
5793
5833
  return COMMAND_STATUS.nothing_started;
5794
5834
  }
5795
5835
  const sent = { ...options, origin: where.origin };
5836
+ const again = freshLineOf(io2, options.application, sent.origin, namedEnvFile);
5837
+ const verifier = read2.kind === "grant" ? pendingVerifierOf(io2, sent.origin) : null;
5796
5838
  const tried = tryEnvironmentFile(io2, options.envFile);
5797
5839
  if ("unwritten" in tried) {
5798
5840
  io2.print(
@@ -5802,7 +5844,7 @@ async function provision(call, io2) {
5802
5844
  }
5803
5845
  const reminted = { database: "no", platform: "no" };
5804
5846
  const release = io2.whenEnded(() => {
5805
- for (const line of signalEndedLines(reminted, read2.kind)) io2.print(line);
5847
+ for (const line of signalEndedLines(reminted, read2.kind, again)) io2.print(line);
5806
5848
  dropWritingFile(io2, options.envFile);
5807
5849
  });
5808
5850
  try {
@@ -5811,29 +5853,72 @@ async function provision(call, io2) {
5811
5853
  io2.print(older);
5812
5854
  return COMMAND_STATUS.nothing_started;
5813
5855
  }
5814
- return await remintAndWrite(io2, sent, agent.userAgent, read2, standing.text, reminted);
5856
+ return await remintAndWrite(io2, sent, agent.userAgent, { ...read2, verifier, again }, standing.text, reminted);
5815
5857
  } finally {
5816
5858
  release();
5817
5859
  dropWritingFile(io2, options.envFile);
5818
5860
  }
5819
5861
  }
5820
- var signalEndedLines = (reminted, kind) => {
5862
+ var signalEndedLines = (reminted, kind, line) => {
5821
5863
  const lost = [
5822
5864
  ...reminted.database === "answered" ? [DATABASE_VALUE_LOST] : reminted.database === "unknown" ? [remintUnknownSentence("database")] : [],
5823
5865
  ...reminted.platform === "answered" ? [PLATFORM_VALUE_LOST] : reminted.platform === "unknown" ? [remintUnknownSentence("platform")] : []
5824
5866
  ];
5825
- return lost.length === 0 ? [NOTHING_REMINTED] : [...lost, remintAgainSentence(kind)];
5867
+ return lost.length === 0 ? [NOTHING_REMINTED] : [...lost, remintAgainSentence(kind, line)];
5826
5868
  };
5869
+ var pendingVerifierOf = (io2, origin) => {
5870
+ const read2 = readMovingCredentialFile(io2, credentialFileOf(io2), io2.print);
5871
+ if (!("state" in read2)) return null;
5872
+ hideStandingTokens(io2, read2.state);
5873
+ const pending = read2.state.pending.get(origin);
5874
+ if (pending === void 0) return null;
5875
+ io2.hide(pending.verifier, REDACTED_VERIFIER);
5876
+ return pending.verifier;
5877
+ };
5878
+ var PROVISION_CHALLENGE_HEAD = "challenge: ";
5879
+ var PROVISION_CALL_HEAD = "call submit_manifest with:";
5880
+ var MANIFEST_MEMBER_WORDS = "the application's manifest, as your tool submits it";
5881
+ var replacedProvisionRequestSentence = (origin, expiredAt) => `The request pending for ${origin} expired at ${expiredAt}, so a new one replaces it: a line answered against the old challenge is refused using nothing, and the submit_manifest call naming the new challenge below answers a fresh one.`;
5882
+ var provisionFirstActLines = (origin, application, challenge, expiresAt, line) => [
5883
+ `To write this application's development settings from ${origin}, call submit_manifest from your tool naming the members below, then run the line it answers once, as given, in this folder, before its grant expires.`,
5884
+ `${PROVISION_CHALLENGE_HEAD}${challenge}`,
5885
+ PROVISION_CALL_HEAD,
5886
+ ` application: ${JSON.stringify(application)}`,
5887
+ ` manifest: ${MANIFEST_MEMBER_WORDS}`,
5888
+ " local_run: true",
5889
+ ` ${CODE_CHALLENGE_MEMBER}: ${JSON.stringify(challenge)}`,
5890
+ `That line presents its grant with this computer's verifier, so a copy of it re-mints nothing elsewhere; it re-mints the development credentials and writes them into the environment file. The request is pending until ${expiresAt}: ${line} run again before then prints this challenge again.`
5891
+ ];
5892
+ async function firstProvisionAct(io2, call, application, envFile, unauthorized) {
5893
+ io2.print(noTokenSentence(unauthorized.origin, unauthorized.expiredAt));
5894
+ const origin = authorizationOriginOf(io2.env, call.named[PROVISION_OPTION.origin], NOTHING_REMINTED);
5895
+ if ("refusal" in origin) {
5896
+ io2.print(origin.refusal);
5897
+ return COMMAND_STATUS.nothing_started;
5898
+ }
5899
+ const kept2 = keepPendingRequest(io2, origin.origin, io2.print);
5900
+ if ("status" in kept2) return kept2.status;
5901
+ const { pending, standing } = kept2;
5902
+ const opening = standing.kind === "reused" ? kept2.opening : standing.kind === "replaced" ? replacedProvisionRequestSentence(origin.origin, standing.expired.expires_at) : null;
5903
+ const lines = [...opening !== null ? [opening] : [], ...provisionFirstActLines(origin.origin, application, pending.challenge, pending.expires_at, freshLineOf(io2, application, origin.origin, envFile))];
5904
+ let last = -1;
5905
+ for (const [index, line] of lines.entries()) if (line.includes(pending.challenge)) last = index;
5906
+ for (const [index, line] of lines.entries()) {
5907
+ io2.print(line);
5908
+ if (index === last) io2.hide(pending.challenge, REDACTED_CHALLENGE);
5909
+ }
5910
+ return COMMAND_STATUS.done;
5911
+ }
5827
5912
  async function remintAndWrite(io2, { application, envFile, origin }, userAgent, read2, standing, reminted = { database: "no", platform: "no" }) {
5828
5913
  const untouched = (lines2) => {
5829
5914
  for (const line of [...lines2, NOTHING_REMINTED]) io2.print(line);
5830
5915
  return COMMAND_STATUS.nothing_started;
5831
5916
  };
5832
5917
  const lost = (lines2) => {
5833
- for (const line of [...lines2, remintAgainSentence(read2.kind)]) io2.print(line);
5918
+ for (const line of [...lines2, remintAgainSentence(read2.kind, read2.again)]) io2.print(line);
5834
5919
  return COMMAND_STATUS.unknown;
5835
5920
  };
5836
- const database = await remint(io2, origin, read2.credential, userAgent, application, databaseCredentialNameOf(application));
5921
+ const database = await remint(io2, origin, read2.credential, userAgent, application, databaseCredentialNameOf(application), read2.verifier);
5837
5922
  reminted.database = database.kind === "answered" || database.kind === "unknown" ? database.kind : "no";
5838
5923
  if (database.kind === "unsent") return untouched(database.lines);
5839
5924
  if (database.kind === "unknown") return lost([...database.lines, remintUnknownSentence("database")]);
@@ -5850,7 +5935,7 @@ async function remintAndWrite(io2, { application, envFile, origin }, userAgent,
5850
5935
  io2.hide(password, settingMark(facts.setting));
5851
5936
  io2.hide(encodeURIComponent(password), settingMark(facts.setting));
5852
5937
  }
5853
- const platform = await remint(io2, origin, read2.credential, userAgent, application, platformCredentialNameOf(application));
5938
+ const platform = await remint(io2, origin, read2.credential, userAgent, application, platformCredentialNameOf(application), read2.verifier);
5854
5939
  reminted.platform = platform.kind === "answered" || platform.kind === "unknown" ? platform.kind : "no";
5855
5940
  const databaseLost = url !== null ? [DATABASE_VALUE_LOST] : [];
5856
5941
  if (platform.kind === "unsent" || platform.kind === "refused") return url !== null ? lost([...platform.lines, ...databaseLost]) : untouched(platform.lines);
@@ -5888,7 +5973,7 @@ async function remintAndWrite(io2, { application, envFile, origin }, userAgent,
5888
5973
  if (facts !== null && limitCarried !== null) {
5889
5974
  const cause = limitMember ? "the plan's database-connection-limit holds no usable quantity, which platform staff set with set_plan_quota" : "the platform that answered serves no such member yet";
5890
5975
  io2.print(
5891
- `${envFile} holds ${facts.setting} and the platform settings this run re-minted, and no ${LOCAL_RUN_SETTING.databaseConnectionLimit}: ${PROVISION_ACTION}'s development_database answer carried ${limitCarried}, where the pool's maximum is a positive integer, so ${cause}. Until that changes the application's pool holds one connection; once it has, ${againSteps(read2.kind)}.`
5976
+ `${envFile} holds ${facts.setting} and the platform settings this run re-minted, and no ${LOCAL_RUN_SETTING.databaseConnectionLimit}: ${PROVISION_ACTION}'s development_database answer carried ${limitCarried}, where the pool's maximum is a positive integer, so ${cause}. Until that changes the application's pool holds one connection; once it has, ${againSteps(read2.kind, read2.again)}.`
5892
5977
  );
5893
5978
  return COMMAND_STATUS.failed;
5894
5979
  }
@@ -5907,13 +5992,16 @@ var PROVISION_ROW = Object.freeze({
5907
5992
  options: PROVISION_OPTIONS,
5908
5993
  credential: PROVISION_CREDENTIAL,
5909
5994
  statuses: {
5910
- done: "the settings written",
5995
+ done: "the settings written, or the first act printed its challenge and call",
5911
5996
  failed: "the settings written without a connection limit, which the platform's answer did not carry",
5912
5997
  unknown: "a credential was re-minted, or may have been, and its value was not written: the printed sentence names the run that re-mints again",
5913
5998
  nothing_started: "nothing was re-minted"
5914
5999
  },
5915
- note: [`Run the ${PROVISION_SUBCOMMAND} line a submit_manifest call naming local_run answers as given, before its grant expires, from the folder the application runs in. Each run revokes the development credentials the application had before it. A deployed development environment holds the revoked values until it restarts, so call restart_application on development afterwards. Its redeploy takes both re-minted credentials from custody, the connection string and the platform credential, and spends no deploy of the day. ${PROVISION_SUBCOMMAND} writes no ${PORT_SETTING}: ${RUN_SUBCOMMAND} sets it from ${RUN_OPTION.port}.`],
5916
- afterOwnError: PROVISION_AFTER_OWN_ERROR,
6000
+ note: [
6001
+ `Run ${PROVISION_BARE_LINE_WORDS} from the folder the application runs in. With nothing piped and no token for the address, it prints a challenge and the submit_manifest call naming local_run and ${CODE_CHALLENGE_MEMBER}; your tool makes that call and runs the line it answers once, as given, before its grant expires, which presents the grant with this computer's verifier. On a computer logged in, the bare line re-mints at once.`,
6002
+ `Each run revokes the development credentials the application had before it. A deployed development environment holds the revoked values until it restarts, so call restart_application on development afterwards. Its redeploy takes both re-minted credentials from custody, the connection string and the platform credential, and spends no deploy of the day. ${PROVISION_SUBCOMMAND} writes no ${PORT_SETTING}: ${RUN_SUBCOMMAND} sets it from ${RUN_OPTION.port}.`
6003
+ ],
6004
+ afterOwnError: provisionAfterOwnError,
5917
6005
  run: provision
5918
6006
  });
5919
6007
 
@@ -7198,6 +7286,8 @@ var SHAPE_STEP = `Shape the service to your own before the first deploy: the tab
7198
7286
  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.`;
7199
7287
  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.";
7200
7288
  var SUBMIT_NO_SETTING_STEP = `Call submit_manifest from your tool with the application and its manifest, ${APPLICATION_FOLDER}/${APPLICATION_MANIFEST}, naming no local_run, since the service reads no setting.`;
7289
+ var provisionStepLineOf = (origin, windows) => machineLineOf(provisionBareLineOf({ origin, application: "<application id>" }), windows, origin);
7290
+ var provisionStepOf = (origin, windows) => `Call submit_manifest from your tool with the application and its manifest, ${APPLICATION_FOLDER}/${APPLICATION_MANIFEST}, naming no local_run. Then run ${freshLineSteps2("the provision line below")}, all in ${APPLICATION_FOLDER}/. The provision line: ${provisionStepLineOf(origin, windows)}`;
7201
7291
  var RUN_STEP_BACKGROUND = "The line runs until the application ends, so start it as a background process and read its lines";
7202
7292
  var SCHEDULED_JOB_SCHEDULE = "heartbeat";
7203
7293
  var ENTRY_PAGES = Object.freeze({
@@ -7237,13 +7327,14 @@ var TEMPLATE_FACTS = Object.freeze({
7237
7327
  routes: Object.freeze(["health"]),
7238
7328
  columns: SCAFFOLD_FIELD_RESERVED
7239
7329
  }),
7240
- // submit_manifest naming local_run, and the provision line that answer
7241
- // gives, in the words `provision` prints for a fresh line (provision.ts);
7242
- // the run line; the shaping step, so the first deploy ships the service
7330
+ // submit_manifest naming no local_run, then the bare provision line, the
7331
+ // call its first act prints and the line that call answers, in the
7332
+ // words `provision` prints for a fresh line (provisionStepOf); the run
7333
+ // line; the shaping step, so the first deploy ships the service
7243
7334
  // its author means and not the template (cloud:PLD-L0-103); and deploy.
7244
7335
  steps: (origin, windows) => [
7245
7336
  CREATE_STEP,
7246
- `${PROVISION_AGAIN} The manifest is ${APPLICATION_FOLDER}/${APPLICATION_MANIFEST}, and the line it answers is the provision line, which runs in ${APPLICATION_FOLDER}/.`,
7337
+ provisionStepOf(origin, windows),
7247
7338
  `In ${APPLICATION_FOLDER}/, start the application on this machine. ${RUN_STEP_BACKGROUND}: ${runLineOf(origin, windows)}`,
7248
7339
  SHAPE_STEP,
7249
7340
  DEPLOY_STEP
@@ -7279,7 +7370,7 @@ var TEMPLATE_FACTS = Object.freeze({
7279
7370
  // page first, and a sixth: the page opened on the deployed address.
7280
7371
  steps: (origin, windows) => [
7281
7372
  CREATE_STEP,
7282
- `${PROVISION_AGAIN} The manifest is ${APPLICATION_FOLDER}/${APPLICATION_MANIFEST}, and the line it answers is the provision line, which runs in ${APPLICATION_FOLDER}/.`,
7373
+ provisionStepOf(origin, windows),
7283
7374
  `In ${APPLICATION_FOLDER}/, start the application on this machine, where its page then answers at / and its API routes take a session as a Bearer; sign-in is on the deployed application's own address. ${RUN_STEP_BACKGROUND}: ${runLineOf(origin, windows)}`,
7284
7375
  WEB_SHAPE_STEP,
7285
7376
  DEPLOY_STEP,
@@ -8743,7 +8834,7 @@ var NOTHING_REACHED = "no subcommand was reached, so nothing was started";
8743
8834
  var ownErrorSentence = (error, afterOwnError = NOTHING_REACHED) => `The command stopped on an error of its own (${error instanceof Error ? error.message : String(error)}); ${afterOwnError}.`;
8744
8835
  var ownErrorLineOf = (argv2, io2, error) => {
8745
8836
  const parsed = parseArguments(argv2, io2.windows ?? ON_WINDOWS);
8746
- return ownErrorSentence(error, parsed.kind === "run" ? parsed.subcommand.afterOwnError : NOTHING_REACHED);
8837
+ return ownErrorSentence(error, parsed.kind === "run" ? afterOwnErrorOf(parsed.subcommand, parsed.call, io2) : NOTHING_REACHED);
8747
8838
  };
8748
8839
  async function runProcess(argv2, unguarded2, io2 = guarded(unguarded2)) {
8749
8840
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "turnzero",
3
- "version": "0.16.1-next.1",
3
+ "version": "0.17.0-next.1",
4
4
  "type": "module",
5
5
  "description": "The Turn Zero Cloud command, which an AI coding tool runs on your machine to deploy an application, store a secret, upload a file, download an export, take a library entry, write a local run's settings, start the application locally, and scaffold a new service from a template.",
6
6
  "license": "Apache-2.0",
@@ -8,7 +8,7 @@
8
8
  "node": ">=24"
9
9
  },
10
10
  "plane_wire": {
11
- "action_payloads": "2026-10-13.10",
11
+ "action_payloads": "2026-10-14.2",
12
12
  "management_api": "2026-10-10.5",
13
13
  "wire_errors": "2026-10-10.6"
14
14
  },