Skip to content

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

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.

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.

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
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.

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.

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.

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.

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 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, and npx wawesome login starts a new session.

Whether we revoked it or you did, do these three things:

  1. Replace it. Mint a new credential and set it wherever the old one lived, such as a CI secret or a .env file. For a connector, add it again in your AI client. For the CLI, run npx wawesome login.
  2. Check what was deployed while the secret was public. Revoking stops new deploys. It does not undo the ones already made. Run npx wawesome versions for each Function, and npx wawesome switch <version> puts back a version you trust.
  3. 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.

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.