Service accounts
A service account is a principal that belongs to an organization rather than to a person. Use one for automation that should outlive whoever set it up: a hub, a pipeline, a long-running agent. Its tokens keep working when the owner or admin who minted them leaves the org or is demoted.
A service account is written {org}/{name}, for example acme/hub-x. Its name
follows the repository name rules and is unique among the org’s service
accounts. A service account and a repository may share a name; every command
that takes a service account says so.
What a service account is
Section titled “What a service account is”- It can’t sign in. It has no login and no email anyone can use. It acts only through the personal access tokens minted for it.
- It takes no seat.
- It holds a role in its org,
vieweroreditor, never owner or admin. That role is the live ceiling for every token minted for it: demote the account and its tokens narrow at their next request. - It belongs to one org. It can’t be invited into another org, added as a member, or listed among members.
- Two permissions govern it, both on its org and both granted by
org:configure:org:service-accounts-manageto create, list, view, re-role, disable, enable and delete it, andorg:service-accounts-mintto mint, list, view and revoke its tokens. Owners and admins holdorg:configurethrough their role; a member whose scope override grantsorg:configureon the org holds both too. A personal access token needsorg:configureon that org as well, since a token never exceeds the member it acts for.
Create one
Section titled “Create one”wh org service-account create acme hub-x --role viewer -d "Hub X reader"wh org service-account list acmewh org service-account view acme hub-xThe role is required; nothing defaults to editor. In the TypeScript SDK the
same operations are client.org.serviceAccounts.create|list|get|setRole|disable|enable|delete,
each taking a plain object such as { orgName: 'acme', name: 'hub-x' }.
Mint its tokens
Section titled “Mint its tokens”Add --service-account to the usual wh token verbs:
wh token create --service-account acme/hub-x --name hub-x-toolset \ --scope acme/markets=repo:read --expires 90dwh token list --service-account acme/hub-xwh token get --service-account acme/hub-x --name hub-x-toolsetwh token revoke --service-account acme/hub-x --name hub-x-toolset--scope(or--scopes-json) is required, and every scope names a resource: the org (acme=repo:read) or a repository (acme/markets=repo:read). A service account’s token never silently gets the account’s whole role.- The scopes you request must be within both the service account’s access and your own. An admin whose access is narrowed can’t mint past it; if your access to any repository in the org is narrowed, scope the token per repository rather than org-wide.
- Expiry limits are the same as for any token: 30 days by default, 365 at most.
--committer-identityfollows the usual identity-use rules, with the service account as the owner, so it can bind the account’s own Identity.getandlistshow who minted each token. Listing and revoking work while the account is disabled, so you can clean up.
In the TypeScript SDK, pass serviceAccount: 'acme/hub-x' to
client.token.create, { serviceAccount } as the second argument to
client.token.get and client.token.revoke, and list with
client.token.listForServiceAccount('acme/hub-x').
A token minted for a service account can mint shorter-lived child tokens with
the plain wh token create, as any token can. A child is bounded by its
parent and is revoked with it.
Its Identity
Section titled “Its Identity”Creating a service account provisions its Identity in warmhub/users, as
signing in does for a person. The Identity’s display name is the account’s
external id; its org and name are not published there.
- Writes made with its tokens are attributed to that Identity by default.
wh doctorandclient.auth.whoami()report it asidentityWref.- Disabling or deleting the account leaves the Identity in place.
Lifecycle
Section titled “Lifecycle”| Action | Effect on its tokens |
|---|---|
wh org service-account set-role acme hub-x --role editor | Widen or narrow at the next request |
wh org service-account disable acme hub-x | Rejected until the account is enabled |
wh org service-account enable acme hub-x | Work again |
wh org service-account delete acme hub-x | Revoked |
| Archive the org | Every service account in it is disabled |
| Unarchive the org | Accounts stay disabled until someone with org:service-accounts-manage enables each one |
Deleting a service account keeps its history: commits and token records still point at it. The name becomes free for a new service account, which gets a new external id and inherits nothing from the old one, including its tokens.
In an archived org you can still list, view and delete service accounts, and list or revoke their tokens. Creating, enabling, disabling, changing a role and minting are refused.
Follow changes with webhooks
Section titled “Follow changes with webhooks”Owners and admins can subscribe an org webhook to service-account changes:
wh sub create sa-audit --org acme --event org.service_account_created \ --webhook-url https://example.com/hooks/warmhubThe events are org.service_account_created, org.service_account_role_changed,
org.service_account_disabled (also sent once per account when the org is
archived), org.service_account_enabled and org.service_account_deleted.
Creating a service account does not send org.member_added. See
organization activity subscriptions
for the payload.