| 1 | # Members and service credentials |
| 2 | |
| 3 | Two kinds of thing act on your apps. A person is a Keymail address with a |
| 4 | role in the account. A credential is something a server holds — a CI runner, |
| 5 | a job, a router — with its reach decided when it was minted and no human |
| 6 | attached to it. They are administered in different places, and the mistakes |
| 7 | they invite are different too. |
| 8 | |
| 9 | ## People |
| 10 | |
| 11 | Invites go out from the Team page in the console, addressed to a Keymail |
| 12 | address. The invitation lands in that person's Keymail Apps inbox — the same |
| 13 | sealed path a sign-in confirmation takes — so inviting somebody sends them no |
| 14 | email. It works once and expires after seven days, and an owner can revoke a |
| 15 | pending one before it is used. If the delivery itself fails the console hands |
| 16 | you the link to pass on yourself; the invitation is real by then either way. |
| 17 | |
| 18 | There are two roles. A member does the day-to-day work on the account's apps |
| 19 | — deploy, promote, roll back, config, domains, logs. An owner does all of |
| 20 | that plus everything that changes who can act or ends something permanently: |
| 21 | inviting, removing a member, handing ownership over, deleting an app or the |
| 22 | account, and every credential in the next section. Handing over ownership is |
| 23 | a single transaction that steps you down to member as it lifts them up, so |
| 24 | there is no moment with two owners or none. |
| 25 | |
| 26 | Some of those actions ask for your passkey again even though you are already |
| 27 | signed in — removing a member, transferring ownership, deleting the account, |
| 28 | approving a terminal or revoking one, minting or rotating a credential. The |
| 29 | gesture has to be within the last five minutes. A session cookie proves who |
| 30 | you are and not that you are still at the keyboard, which is the whole |
| 31 | question when the action is irreversible. |
| 32 | |
| 33 | None of this has a `carlos` verb. Membership is console work, deliberately: |
| 34 | the passkey prompt is the point of it, and a terminal has nowhere to put one. |
| 35 | |
| 36 | ## Credentials a server holds |
| 37 | |
| 38 | ```sh |
| 39 | carlos services create -role publish -app hello ci-runner |
| 40 | ``` |
| 41 | |
| 42 | The secret prints once, right there in your terminal, and only its hash is |
| 43 | stored. There is no page and no command that will show it to you again — a |
| 44 | lost secret means rotating, not re-running. Get it into the app the way you |
| 45 | get any credential in: |
| 46 | |
| 47 | ```sh |
| 48 | carlos secrets set -app hello CARLOS_SERVICE_TOKEN=<the secret> |
| 49 | ``` |
| 50 | |
| 51 | Pick the narrowest role that does the job. `publish` is the deploy loop: |
| 52 | claim an app, ship, promote, roll back, manage hostnames, retire. `operate` |
| 53 | is runtime work with no release authority — restart, config, logs. `instance` |
| 54 | is the older app-token shape, kept for what already depends on it. `admin` is |
| 55 | the union of those plus ledgers, storage and placement. It also grants |
| 56 | object-store access, and that mints a real IAM user — hand one out only when |
| 57 | you mean to hand over. |
| 58 | |
| 59 | `-app hello` binds the credential to one app; it cannot claim new ones. |
| 60 | Leave it off for an account-wide credential. Either way the reach is fixed at |
| 61 | mint: if you join another account next month, the credential you minted does |
| 62 | not follow you there. Its rate budgets are its own, separate from yours — see |
| 63 | [Limits](/docs/limits/) — and it never expires, so revoking is the control. |
| 64 | |
| 65 | ## Rotate replaces, revoke stops |
| 66 | |
| 67 | This is the distinction to have straight before you need it. |
| 68 | |
| 69 | ```sh |
| 70 | carlos services rotate ci-runner |
| 71 | ``` |
| 72 | |
| 73 | Rotation mints a fresh secret and prints it once, keeping the name, the role, |
| 74 | the scope and the history. The old secret is refused on the credential's |
| 75 | *next* call — work already in flight is unaffected. That makes rotation a |
| 76 | hygiene move: something you schedule. |
| 77 | |
| 78 | ```sh |
| 79 | carlos services revoke ci-runner |
| 80 | ``` |
| 81 | |
| 82 | Revocation is the hard stop: the credential's next call fails whatever secret |
| 83 | it is holding. It is idempotent, so revoking a name twice, or one that never |
| 84 | existed, answers the same way. And unlike minting and rotating, it does not |
| 85 | ask for your passkey — one step, at whatever hour you find out. |
| 86 | |
| 87 | If you suspect a secret has leaked, revoke. Then mint a replacement under a |
| 88 | new name if the work still needs doing. |
| 89 | |
| 90 | To see what exists: |
| 91 | |
| 92 | ```sh |
| 93 | carlos services ls |
| 94 | ``` |
| 95 | |
| 96 | Live credentials only — name, role, scope, when it was minted, when its |
| 97 | current secret began, when it was last used, and who minted it. A revoked one |
| 98 | disappears from the list entirely, so this is inventory, not history. |
| 99 | |
| 100 | Every verb here is owner-only, and closed to service credentials themselves: |
| 101 | no credential can mint, rotate or revoke any credential, not even its own. |
| 102 | A leaked one therefore cannot quietly issue itself a quieter sibling. The |
| 103 | console's Account settings page carries the same list, the same mint form, |
| 104 | and rotate and revoke controls per row. |
| 105 | |
| 106 | Each verb takes `-account` when you belong to more than one; with a single |
| 107 | account you can leave it off. |
| 108 | [carlos services](https://carlosframework.com/docs/cli/#carlos-services) has |
| 109 | the rest of the flags. |
| 110 | |