Deploy credentials
Put a deploy credential in WAWESOME_DEPLOY_CREDENTIAL and every CLI command authenticates with it.
Your CI job deploys with no browser step and no npx wawesome login.
export WAWESOME_DEPLOY_CREDENTIAL=wawe_ab3k9xqmr7t2vhd4npy8scf3kjw9zeu5
npx wawesome deploy
The variable wins over the session in ~/.wawesome/credentials.json, so a runner with a stale
cached home directory still deploys as itself. npx wawesome whoami says which of the two is in
use:
[wawesome] Acting as a deploy credential:
Credential: wawe_ab3k9x (from WAWESOME_DEPLOY_CREDENTIAL)
Workspace: Hello Co
Address: k7ptn3wq9d
Gateway: https://api.wawesome.io
It belongs to the workspace, not to you
Section titled “It belongs to the workspace, not to you”Minting records who did it. Nothing reads that record again. When a request arrives, we read the words the credential itself carries and nothing else. Your role at that moment does not come into it.
A credential still cannot keep more than the role of the person who minted it. When somebody moves to a narrower role, every credential they minted and every connector they approved loses the words the new role does not carry, in that same moment. It keeps every word the two share, so the pipeline they set up goes on working for everything they can still do themselves. A credential left with no word at all is revoked. Moving them back up gives nothing back: mint again for that.
Leaving is different. When somebody’s membership ends, every credential they minted is revoked in that same moment, and so is every connector they approved. The person walking out is holding the secret: their session here stops on their very next request, and a token sitting in a config file would not. The removal shows what it revoked and every owner is emailed the list, so a pipeline that has stopped is one somebody already knows about. See people.
Nothing un-revokes a credential. If a pipeline needed one of them, mint a replacement and set it wherever the old one lived.
What a credential may do
Section titled “What a credential may do”A credential carries capability words. Each one is a verb and a resource: read:apps,
write:functions, write:env. A write carries its own read, so write:functions also reads
Functions and you do not list both.
Three presets carry the words one job needs:
| Preset | What it carries |
|---|---|
viewer |
Reads the workspace, Apps, Functions, environment variables, domains, invocations, runs, schedules, previews and the egress allowlist. It writes nothing |
deployer |
The viewer reads, plus creating Apps, deploying Functions, setting environment variables and running Functions |
member |
The deployer words, plus pausing and resuming schedules and creating previews |
deployer is the one built for CI. It ships code and reads back what happened, and it does not
attach a domain, pause a schedule or create a preview.
npx wawesome credentials --help prints the words each preset carries, so you see the list before
you hand it out. To pick words yourself instead, pass --capability and skip the preset.
--app restricts a credential to the Apps you name, repeated or comma-separated. Without it, the
credential reaches every App in the workspace.
A credential that can deploy can reach every secret in the Apps it reaches. It can’t read one back, but it can ship code that puts the value in a response. Leaving log reads off doesn’t close that path, because the Function’s URL is public. Only give deploy rights to someone, or an agent, you’d trust with the key.
Minting cannot hand out what you do not hold
Section titled “Minting cannot hand out what you do not hold”Your own role limits what you can mint. Ask for a word your role does not carry and the mint is turned down, and it names every word you are short of:
[wawesome] Error: Your role in this workspace is 'viewer', which does not carry 'write:functions'. A deploy credential cannot be minted carrying a capability its minter does not hold: mint it without it, or ask somebody whose role carries it.
That check runs at the mint. After that, your role is not read on any request the credential makes. It is read again only when your role changes or you leave, as described above.
The credentials commands are themselves closed to credentials, whatever they carry. Minting, listing, regenerating, revoking and deleting all need a signed-in session, so a leaked credential cannot mint a second one or renew its own expiry:
[wawesome] Error: This route is closed to deploy credentials, whatever they carry. Use a signed-in session for it.
The secret is shown once
Section titled “The secret is shown once”A secret is printed at the moment it is made and never again. We keep a digest of it, so no later command can print it back, and no flag reveals it. Lose one and you regenerate the credential or mint another.
The secret starts with wawe_, always. That prefix is fixed so a secret scanner can spot one in a
pushed commit and tell us before somebody else reads it.
mint and regenerate print the secret on stdout on a line of its own, and everything a person
reads on stderr. So a redirect catches the secret and not one character besides:
npx wawesome credentials mint ci --preset deployer > ci.secret
Mint one
Section titled “Mint one”npx wawesome credentials mint ci --preset deployer --app shop
[wawesome] ✔ Minted deploy credential 'ci'.
Prefix: wawe_ab3k9x
Capabilities: read:tenant, read:apps, read:functions, read:env, read:domains, read:invocations, read:runs, read:schedules, read:previews, read:egress, write:apps, write:functions, write:env, write:runs
Apps: shop
Expires: 2026-12-07 12:00 UTC
Copy it now. This is the only time it will be shown. If you lose it, revoke this credential and mint another.
wawe_ab3k9xqmr7t2vhd4npy8scf3kjw9zeu5
The name is yours to choose and it is what tells the CI one from the agent one a year from now. It has to be unique in the workspace.
Prefix is the first eleven characters of the secret. It is what every later listing shows instead
of the secret, and what you match against the value in your CI settings page.
A credential expires in 90 days unless you say otherwise. --expires 30 and --expires never both
work. A credential that never expires is a fine choice, and it is a choice, so the CLI makes you type
the word.
List them
Section titled “List them”npx wawesome credentials list
🔑 Deploy credentials
NAME | PREFIX | KIND | CAPABILITIES | APPS | LAST USED | EXPIRES | STATUS
-------|-------------|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|----------------------|----------------------|-------
ci | wawe_ab3k9x | minted | read:tenant, read:apps, read:functions, read:env, read:domains, read:invocations, read:runs, read:schedules, read:previews, read:egress, write:apps, write:functions, write:env, write:runs | shop | 2026-09-08 09:12 UTC | 2026-12-07 12:00 UTC | active
claude | wawe_zz1122 | connector (https://claude.ai) | read:apps, read:functions, write:functions | every App | 2026-09-08 12:05 UTC | 2026-09-08 13:00 UTC | active
npx wawesome credentials on its own prints the same listing.
KIND says where the row came from. minted is one somebody here typed a command for. connector
is one an MCP client was issued when a person approved it, and the product it went to is
named beside the word.
LAST USED is the column to revoke on. A credential nothing has presented in three months is a
better reason to revoke than any date on a calendar. It reads never for one nothing has ever
used.
STATUS is active, revoked or expired.
regenerate, revoke and delete each take a name or a prefix. A partial prefix works, so you can
paste what your CI settings page shows you. One that matches two credentials is turned down rather
than guessed at.
Regenerate one
Section titled “Regenerate one”Regenerating replaces the secret where it stands. The name, the capabilities and the App restriction all survive. The pipeline whose settings already name this credential goes on working, once you paste the new value in.
npx wawesome credentials regenerate ci
? Regenerate 'ci' (wawe_ab3k9x)? Anything holding the old secret stops working at once and has to be given the new one. (y/N)
[wawesome] ✔ Regenerated 'ci'. Anything still presenting the old secret is refused from its very next request.
Prefix: wawe_m4t7pq
Capabilities: read:tenant, read:apps, read:functions, read:env, read:domains, read:invocations, read:runs, read:schedules, read:previews, read:egress, write:apps, write:functions, write:env, write:runs
Apps: shop
Expires: 2026-12-07 12:00 UTC
Copy it now. This is the only time it will be shown. If you lose it, regenerate this credential again.
wawe_m4t7pqe5vscd9k2jrn8ythzwbf46q3xs
The prefix changed, because a prefix names a secret rather than a credential. The old one is gone and nothing answers to it any more, not even to say it was revoked.
Regenerating resets the expiry the same way minting sets it: 90 days unless you pass --expires. Pass
--yes where there is nobody to answer the question.
Revoke one
Section titled “Revoke one”npx wawesome credentials revoke ci
? Revoke 'ci' (wawe_ab3k9x)? Nothing un-revokes it. (y/N)
[wawesome] ✔ Revoked 'ci' (wawe_ab3k9x).
[wawesome] Anything still presenting it is refused from its very next request.
Revoking is the one act on this platform that nothing reverses. A leaked secret does not become un-leaked, so there is no undo and no regenerate afterwards. What you do instead is mint a replacement.
The row stays in the listing as revoked, holding its name. Anything that presents the secret is
told the credential was revoked, which is what sends whoever reads the pipeline output to the right
place.
Delete one
Section titled “Delete one”Deleting forgets a credential. The row goes and its name comes free.
Only a credential that has already stopped working can be deleted. A live one is turned down, and the answer names the step that comes first:
[wawesome] Error: 'ci' (wawe_ab3k9x) still works, and only a credential that has stopped working is deleted.
[wawesome] Revoke it first: wawesome credentials revoke ci
npx wawesome credentials delete ci
[wawesome] Deleting 'ci' (wawe_ab3k9x) forgets it.
[wawesome] It leaves the listing, and the name 'ci' comes free.
[wawesome] Anything still presenting its secret is told the secret is unknown, rather
[wawesome] than that somebody here revoked it.
? Delete 'ci' (wawe_ab3k9x)? (y/N)
[wawesome] ✔ Deleted 'ci' (wawe_ab3k9x). The name 'ci' is free again.
[wawesome] Anything still presenting its secret is told the secret is unknown.
That last line is what deleting costs. A revoked credential tells the holder somebody here ended it. A deleted one tells them the secret is unknown, which sends them to their own CI settings looking for a typo. Revoke and leave it if anyone might still be presenting it.
Deleting a credential also discards the drafts it opened, and their preview links stop working.
If a secret leaks
Section titled “If a secret leaks”If a secret of ours ends up somewhere public, revoke it now. Do not wait to find out whether anyone used it.
GitHub scans public repositories for our secrets. When it finds one, it tells us and we revoke it straight away, without asking you first. What happens next depends on the secret:
- A deploy credential (
wawe_) is revoked. Every owner of the workspace gets an email that names the credential and links to where GitHub found it. - A connector’s token (
wawr_) ends the connector’s grant. The owners get the same email. - A CLI session token (
waws_) ends that session. Nobody gets an email. The next CLI command fails, andnpx wawesome loginstarts a new session.
Whether we revoked it or you did, do these three things:
- Replace it. Mint a new credential and set it wherever the old one lived, such as a
CI secret or a
.envfile. For a connector, add it again in your AI client. For the CLI, runnpx wawesome login. - Check what was deployed while the secret was public. Revoking stops new deploys. It does not
undo the ones already made. Run
npx wawesome versionsfor each Function, andnpx wawesome switch <version>puts back a version you trust. - If you find a version you did not deploy, change your environment variables too. Code in that version can read them.
You do not need to rewrite your git history for our sake. A revoked secret works nowhere.
Deploy from GitHub Actions
Section titled “Deploy from GitHub Actions”Mint a deployer credential, store the secret in your repository’s settings, and read it into the
step that deploys.
npx wawesome credentials mint github-actions --preset deployer --app shop
Copy the last line of that output. In your repository, go to Settings, then Secrets and variables,
then Actions, and add a new repository secret named WAWESOME_DEPLOY_CREDENTIAL with that value.
Then add .github/workflows/deploy.yml:
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- name: Deploy to wawesome
run: npx wawesome deploy
env:
WAWESOME_DEPLOY_CREDENTIAL: ${{ secrets.WAWESOME_DEPLOY_CREDENTIAL }}
The App and the Function come from wawesome-function.json in the repository, so the workflow names
neither. npm ci installs your own dependencies. npx fetches the CLI itself.
Every merge to main now builds, uploads and promotes a version. The step’s output ends with the
address the Function answers on and the version number it made. version switch takes you back to the one before it.
If the pipeline starts failing on authentication, read the reason the CLI prints. It says whether the credential was revoked, has expired, is one we never issued, or is short of a word for what the step asked to do. Each of those takes a different next step, and minting a new credential fixes only one of them.