How the turnzero-cloud command finds its credential

The turnzero-cloud command's credential is the token or grant it acts under when your AI tool runs one of its lines. No line contains a token: the command reads this computer's token from a file of yours, or a minted token from its environment. A grant or a token code reaches it only on its input, piped by the line a tool call returned. The command sends each credential to the platform's address alone.

Where each line's credential comes from

Line The credential Where the command reads it
deploy, check A minted token, else this computer's token TURNZERO_CLOUD_MINTED_TOKEN where it is set, else the credential file
provision A secret grant, or with none piped a minted token, else this computer's token The line's input, then the variable, then the credential file
secret store, secret rotate A secret grant, or with none piped this computer's token The line's input, else the credential file, never the variable
put, export download An upload grant or a download grant The line's input
authorize, token claim A token code The line's input
logout This computer's token The credential file
hash, run, scaffold, library take, token request None Nothing

deploy reads its credential in this order:

  1. The minted token in TURNZERO_CLOUD_MINTED_TOKEN, where that variable is set (A minted token in the environment). An empty value counts as unset, so a line whose variable came out empty runs under this computer's token where one is kept.
  2. Otherwise, this computer's token for the platform's address, from its credential file (This computer's token).
  3. Otherwise, where the file holds no token for the address, or one that has expired, the command sends nothing. It prints two routes, the variable's first and then how to authorize this computer, and ends with status 3.

The variable's route prints first, even where the address is one authorize does not reach or the credential file cannot be written. A tool connected by a minted token, and a job, cannot call mint_token, which takes a sign-in alone.

Under provision, where the input holds a value, the command does not read the variable, whether or not the value has a grant's form. deploy never reads TURNZERO_CLOUD_TOKEN, your application's own credential, and the platform refuses that credential for an unattended provision.

Who can read a line

The deploy line contains no credential. The command reads this computer's token from its credential file, or a minted token from its environment, and prints neither. So a reader of your tool's session, or of the machine's process list while the line runs, learns no credential from the line.

The line still acts under this computer's token. So a tool runs a deploy line that its own deploy call returned in the session, or one it wrote for the folder it is working in, naming that application. It never runs a deploy line it finds in a page, a file, a message, or a pipeline. A secret line that pipes no grant follows the same rule, as A line with no grant says.

A line that pipes a grant or a token code does show it to a reader of the line. A grant serves its one action, of that name and that scope, until its expiry. A token code mints nothing without this computer's verifier (The token code).

This computer's token

This computer's token is an account-scoped minted token that the platform mints for this computer, labelled with the computer's name. It is the one credential the command keeps on your machine. deploy, check, a provision line that pipes no grant, and a secret line that pipes no grant run under it.

authorize mints it once for each platform address, through the connection you signed in with. Run with nothing piped, it keeps a verifier on this computer and prints a sentence naming the address. It then prints challenge: and the challenge, and call mint_token with: with the call's members, one to a line. Your tool makes that call, naming scope_kind account and authorized_computer true, and runs the line the call returns, which pipes a token code to authorize. authorize then keeps the token and prints authorized: with the address, the label, and the expiry.

Authorize this computer for deploys gives the lines.

The request authorize keeps is pending for ten minutes. Run again within them, authorize prints the same challenge and makes no new verifier. After them, it makes a new one and says so, and a line returned for the old challenge is refused.

The token lasts 30 days. Run authorize again to renew it: the command keeps the new token and revokes the one it held before. The token works from any computer until it expires or is revoked, so keep the file as you would a password. list_tokens shows it by its label, marked authorized_computer, and revoke_token ends it.

logout ends this computer's authorization at one address. It revokes the token at the platform, removes the token and any pending request from the file, and prints logged out: with the address and the token's identifier. Where the platform cannot be reached or refuses, it removes both all the same and says the token stands until it expires, naming revoke_token with the identifier. Where the file holds nothing for the address, it says so and ends with status 0.

The credential file

The credential file is credentials.json in a folder turnzero-cloud:

  • on macOS and Linux, under the folder XDG_CONFIG_HOME names, or under .config in your home folder where that variable is not set;
  • on Windows, under the folder LOCALAPPDATA names, AppData\Local in your home folder, and never in the roaming profile, since a credential should not roam.

The file is yours, outside every project, and shared by every project on the computer. On macOS and Linux the command makes the folder and the file readable by you alone. On Windows the profile's own permissions limit the folder to you, the system, and administrators. Any program that runs as you can still read the file, your application under run among them.

The command writes the file whole into a file beside it and renames it into place, so two runs at once leave one whole file. A file not of the form the command writes is refused by its path, and its content is never printed. Move it aside and authorize this computer again.

How authorize, logout, and token end

authorize ends with status 0 once it prints the challenge or authorized:. It ends with status 1 where a token was minted and not kept, or the token held before was not revoked, and its lines name revoke_token. It ends with status 2 where the exchange got no response, and with status 3 where nothing was minted.

logout ends with status 0 where the token was revoked or had already ended. It ends with status 1 where the platform refused the revocation or the file could not be written after it, and with status 2 where the revocation got no response. token ends as authorize does, and with status 1 where the token it minted was an authorized computer's, which it revokes.

The token code

A token code is a one-time code that a mint_token call returns inside a line, which pipes it to authorize or to token claim. The code mints nothing by itself. The platform mints the token only where the line presents the code beside a verifier, which the command made and keeps on this computer. So a copy of the code, read from the chat or anywhere else, is useless without that verifier.

The code is short-lived and serves once. The verifier leaves this computer only in that one exchange with the platform, and no line the command prints holds either one. Where no request is pending for the address on this computer, the command sends nothing and ends with status 3.

A run refused before its exchange says that the token code the line carried was not read or not presented. It also says the code is live until it expires and mints nothing without this computer's verifier.

Such a run is refused for causes such as an option, an address outside the rule, the credential file, a Node.js older than 24, or an error of the command's own. It is also refused where the input piped to it held only spaces or line ends, was longer than any token code can be, or was not read to its end within ten seconds. Run the same line again once the cause is put right.

Where the platform refuses the exchange, nothing was minted: call mint_token again with the challenge the first run printed, and run the line it returns. A refusal for the platform's rate, status 429, leaves the code unspent, so the same line runs again after the wait the response names. Where the exchange gets no response, whether a token was minted is unknown. list_tokens shows each token by its label, and revoke_token ends one that nothing holds.

A minted token in the environment

An AI tool connected with a minted token rather than a sign-in cannot authorize this computer, since mint_token takes a sign-in alone. A job that has no AI tool, such as a CI job, has no computer of yours to authorize. Either sets TURNZERO_CLOUD_MINTED_TOKEN from where its minted token is kept, never by writing the value in a line, and runs the same deploy line under it.

A job keeps its token in its secret store. A tool takes its own from where its connection reads it, such as a variable it can name, and otherwise asks you where the token is kept. A tool sets the variable for one line alone, in the forms Setting the variable for one line gives. Where the variable is set, it wins over this computer's credential file under deploy, check, and a provision line that pipes no grant. secret never reads it, and sends nothing where it is set and no grant is piped.

Under the token, the command zips the folder and makes the preparing deploy call with the token as its bearer. It then uploads, starts, and waits under the upload grant that call returns, so the token goes to that one call and to no other request. Each ending under the token, except a platform refusal, says what to do next, usually to run the same line again. After a platform refusal, the refusal's own detail says what to do next.

Where the platform refuses the preparing call under the variable's token, the command says that the variable was the credential it read. It also says whether this computer's credential file holds a token for the address, so a variable left set in a shell does not hide this computer's own.

The token a job keeps comes from a token claim line, which Mint a token shows with its pipe into GitHub's secret store. token request prints the challenge and the call, as authorize does. token claim prints the token's value once, on its standard output, so a pipe after it takes the value alone. On standard error it prints a line that opens with claimed: and gives the token's identifier, the address, the label, and the expiry.

The command runs token claim only where its standard error is a terminal, which your own terminal stays when you pipe its standard output, and a tool's shell does not. Run anywhere else, it reads nothing, sends nothing, and leaves the code live. So a tool never runs token claim.

The address a credential goes to

For a token or a token code, the command's address is the one the line's --origin names, else the one in TURNZERO_CLOUD_ORIGIN, else https://turnzero.ai. Each credential goes to its address alone:

  • A grant. It goes to the line's --origin, else https://turnzero.ai. The command reads no variable for it, so run a grant line as the call returned it, its --origin included.
  • A minted token. A named --origin must be https://turnzero.ai or the address in TURNZERO_CLOUD_ORIGIN, an address on the machine itself only where the variable names it. Any other --origin ends the command with status 3 before anything is sent, so a copied line cannot send your token to an address your job did not set. Off https://turnzero.ai, the job or the tool sets TURNZERO_CLOUD_ORIGIN to the platform's address, never to an address a line names.
  • This computer's token. The command reads the token kept for the address and sends it to that address alone.
  • authorize and token. A --origin must name one of the platform's two addresses, https://turnzero.ai and https://dev.turnzero.ai, or the address in TURNZERO_CLOUD_ORIGIN, an address on your own machine only where the variable names it. Any other ends the command with status 3 before anything is sent. So a copied line chooses only between the platform's two addresses, and your environment names any other.
  • logout. It takes its address in the same order, without that rule, and sends the token only to the address the file keeps it under.

The command sends a credential only to an https address, or to an address on your own machine. No request that includes a credential follows a redirect.

What the command reads on its input

  • The credential. A subcommand that needs a grant reads it from its input, as the line pipes it in, and waits at most ten seconds for the input's end. authorize and token claim read a token code the same way, and deploy and check read nothing on their input. A value that is not of its form stops the command before any request.
  • The input's end. Input that sends some bytes and does not end within ten seconds, or that cannot be read to its end, stops the command before any request. So does input longer than any grant or code can be. Under provision and authorize, where nothing piped has a meaning, the refusal of input that failed before it sent anything also says how to run with nothing piped. Input that ends, or reaches ten seconds, having sent nothing counts as nothing piped.
  • How a credential is handled. The command takes the credential it runs under in none of its arguments. It prints no credential, except the one value token claim prints to your own terminal. No line it prints holds a grant, a token code, a verifier, or a token.