Skip to content

Keys & authorizations ​

This page explains the keys that can write data under your wallet, where those grants live, and how to review or revoke them. It also covers agent keys: the keys you create so an agent, a script or a server can publish, redeploy, roll back and manage your projects without your browser.

Prerequisite: signed in. Background: Your data on-chain.

Prompt for your agent

Copy this into Claude Code, Cursor or any agent that can run shell commands. Creating a key is yours alone; the agent tells you exactly which key to create, then proves it works.

text
Read https://docs.stasho.xyz/guides/keys-and-authorizations.md. I want you to manage my
Stasho projects. Tell me exactly which agent key to create: in Settings → Authorizations for an
All sites key, or in one project's Settings → Agent access for a key tied to it. Say which
scopes you need and why, that I must untick every other, the shortest expiry that fits, and
whether to pick "My agent signs". If so, tell me it covers every site record in my wallet,
generate your own signing keypair, keep the private key in STASHO_SIGNING_KEY, give me the
public key to paste, and never show me the private key. If I need an App VM app rolled back,
say that only a key that signs for itself can do it. I will put the key in the
STASHO_AGENT_KEY environment variable: never ask me to paste it in chat. Then verify the key
works with a read call and tell me what it lists. Never ask for my wallet key, my seed phrase
or my session token.

Why other keys write under your wallet ​

Your project data lives on-chain under your wallet address — but you wouldn't want to approve a wallet popup for every status change of every deploy. So the network supports delegation: your wallet signs, once, a security record listing other keys allowed to write specific kinds of messages on your behalf. Everything in that record is public and auditable.

Three keys are always involved; two more appear once you work with an agent.

Your wallet key authorizes two things: the Stasho delegate, which writes deployment progress and pins artifacts, and a browser session key that signs your writes and rotates every 24 hours. Both can write project and deployment records, but only the Stasho delegate can also write custom-domain records. Neither can touch your wallet's security settings.Your wallet key authorizes two things: the Stasho delegate, which writes deployment progress and pins artifacts, and a browser session key that signs your writes and rotates every 24 hours. Both can write project and deployment records, but only the Stasho delegate can also write custom-domain records. Neither can touch your wallet's security settings.
What each of the three everyday keys is allowed to write. Revoking a grant removes exactly one arrow. Agent keys (below) ride on the delegate's arrow or add one of their own.
KeyHeld byWhat it's for
Your walletYouThe owner. Signs the grants below; the only key that can change them.
Browser session keyYour browserSigns your own writes (creating projects, saving settings) without a wallet popup each time. Rotates on a 24-hour cycle; a new one is created and the old one revoked automatically as you use the app.
Stasho delegateOur backendWrites deployment progress (queued → building → live) and pins artifacts as your builds run — the writes that happen while your browser is closed.
Agent keyYour agent, script or serverA bearer token (stasho_ak_…), not an on-chain key. Acts as you on your projects, within the scopes you gave it, over the agent API. Stasho stores only its hash.
Agent signing keyYour agentOptional. A public key you paste when creating an agent key with My agent signs. It can create, change and remove every site record of this wallet directly on the network, whatever the key's scopes, until its row is revoked or expires: scopes limit only the API. It is listed here as an Agent signer row.

The grants are scoped: the session key can write project and deployment records only; the Stasho delegate can write those, plus your custom-domain records, on a separate channel. Neither can touch the security record itself — so a leaked session key can forge deploy statuses for a day at worst, never lock you out or grant itself more power. An agent key that can create, change or remove sites needs one of two things on-chain, chosen when you create it: with Stasho signs for me, your signature lets the delegate write site records on the agent's behalf (the delegate row then wears an Agent keys badge); with My agent signs, the agent's signing key gets a row of its own, covering every site record of the wallet, and the delegate gains nothing.

The Authorizations section ​

Settings → Authorizations lists every key currently (or previously) authorized under your wallet, labelled by what it is:

RowWhat it is
Stasho (current)The Stasho delegate. Wears an Agent keys badge, with a Withdraw button, while it may create, change and remove sites for your agent keys.
Stasho (retired)A previous delegate key, kept so its old writes stay verifiable.
This browserYour active session key. This browser (expired) is one of this browser's that has rotated out.
Another browser or sessionA session key registered by a different browser or device of yours — or not.
Agent signer · key namesAn agent's signing key, naming the agent keys that use it; Agent signer (key revoked) when none is left.
OtherA grant Stasho did not create, for instance from another tool.

Each row shows its status and the channels it writes to, and offers Revoke; the delegate row offers Re-authorize or Enable fast path when a grant is missing. What a row may write is in the audit endpoint (see Verification). Below the list, the Agent keys section holds every agent key of your account with Create key.

Agent keys ​

An agent key is created in one of two places, and both lists show the same keys:

  • Settings → Authorizations → Agent keys, for a key that works on all your sites. The dialog there has no project choice.
  • A project's Settings page → Agent access, for a key tied to that one project. Every kind of project has this card: an uploaded site, a repo project and an App VM app.

What an agent can do with a key is the whole agent API. What a key can hold depends on what the project is:

ProjectScopes its key can hold
Uploaded sitepublish, domains, delete, read, rollback
Repo project (static site built from GitHub)read, deploy, rollback, domains
App VM appread, deploy

The Agent access card offers exactly the scopes in its row. A key for all projects offers every scope. Each key in the list shows its name, which projects it reaches, its scopes, its expiry and when it was last used, with Rotate (a new key with the same settings, shown once; the old one stops at once) and Revoke. Each build a key publishes reads "Published with key" in the site's deployment list.

Creating a key ​

Create key opens a dialog with:

  • Name — the attribution: it shows on every build, domain and site the key touches, so name it after what holds it ("Worker prod", "Claude chat").

  • On the Agent access card only, which projects: This project (This site on an uploaded site) or All sites. A key for one project cannot create sites.

  • Scopes: what the key may do:

    • read lists projects, reads one and lists its deployments. It is not implied by the others, so a publish key reads nothing under /projects unless it also has read.
    • deploy redeploys a repo project or an App VM app, like Redeploy in the dashboard.
    • rollback rolls a project back to an earlier live build and undoes it, like Roll back to this and Undo rollback.
    • publish, create and delete publish a new version of an uploaded site, create one and delete one.
    • domains attaches, checks and detaches custom domains, on uploaded sites and on repo static sites.

    A new All sites key opens with publish, create, domains and read ticked. A key on an uploaded site opens with publish, domains and read, and one on a repo project or an App VM app with read alone. Untick anything you did not mean to grant.

    delete needs an expiry (90 days at most) and an email on file for your account, so you can be told when a key deletes a site or detaches a domain.

  • Expires — 1, 7, 30 or 90 days, or Never. For a chat agent, 1 or 7 days; Never only for a server you control.

  • Who signs the site records: shown when a scope writes project records (create, domains, delete, rollback):

    • Stasho signs for me: Stasho's delegate creates, changes and removes site records for this key. If that grant isn't there yet, the next step, Allow Stasho to manage your sites, ends in Sign and create key, one signature.
    • My agent signs: paste the agent's public signing key (an uncompressed secp256k1 key, 0x04 followed by 128 hex characters). The signing key can then create, change and remove every site record of this wallet directly on the network, whatever this key's scopes, until its row is revoked or expires. It is listed as an Agent signer row. Only on an All sites key with at least one of those scopes.

The key is shown once, on the Key created view, together with a ready-made prompt to hand your agent. Copy it then: anyone who has it can act on your sites within its scopes until it expires, including anyone who can read the chat you paste it into. A key with only publish, read and deploy needs no signature at all: a redeploy is a build dispatch, not a record write. A rollback key does need it, because a rollback writes the project's record.

Rolling back an App VM app ​

An App VM reads a rollback only from your own wallet or from a key that signs for itself, not from Stasho's delegate. So a rollback of an App VM app needs an All sites key created with My agent signs and the rollback scope. A key tied to one App VM app cannot hold rollback, because a project key cannot carry a signing key, and any other key answers app_rollback_needs_signer and changes nothing. That signing key covers every site record of the wallet, not only this app, so weigh it against rolling back in the dashboard. Without such a key, you roll back in the dashboard (see Manage deployments). When you create an All sites key with rollback and leave Stasho signing, the dialog says an App VM will need the My agent signs option.

Revoking ​

Revoke a session key any time, for instance one from a device you've lost. One signature removes it.

Revoke an agent key from either list: anything using it stops working at once. When it is the last key that needed Stasho's permission to manage sites, the dialog offers Also withdraw (one signature) so the delegate's grant goes with it. When a signer key is revoked, its signing key stays authorized while another key still uses it; with the last one the dialog also revokes the Agent signer row, one signature.

Withdraw, on the delegate row, removes the delegate's permission to create, change and remove sites and revokes every key that relied on it; keys under My agent signs and keys with only publish, read or deploy keep working.

Revoke an Agent signer row directly, and the agent keys that use it can no longer create, change or remove sites; publishing with them keeps working, and existing deployments are unaffected.

Revoke all other sessions first revokes every agent key at once, with no signature and no undo, even if you then decline the wallet prompt. One signature then removes other browsers' session keys and agent signing keys (50 per signature; run it again for the rest) and withdraws the delegate's grant. It does not touch Other rows or this browser's keys, and it is disabled when there are no other sessions or signer rows; revoke those rows and keys one by one.

Revoke the Stasho delegate and deploys stop working: builds can't report status and artifacts can't be pinned. The deployment that hits the wall shows Re-authorization required (awaiting_resign), and the Redeploy button becomes Re-authorize. This is reversible — re-authorizing is one wallet signature, and the next deploy proceeds.

The same Re-authorization required state can appear without you revoking anything — e.g. when the app needs a grant that didn't exist when you first signed up (this happened to alpha users when custom domains shipped). The fix is the same single signature in Settings → Authorizations.

Verification ​

  • The Authorizations section shows the delegate and your current browser, both marked authorized; every agent key you created is in the Agent keys list, and a key under My agent signs has its Agent signer row
  • The same list, from outside the app: https://api.stasho.xyz/api/audit/<your-address> — or on-chain via any public explorer
  • After a revoke + re-authorize cycle, a Redeploy completes normally
  • After revoking an agent key, a call with it answers 401 key_invalid

What can go wrong ​

SymptomCauseFix
Deployment stuck at "Re-authorization required"The delegate lacks a grant (revoked, or a newer feature needs more scope)Settings → Authorizations → sign the re-authorize prompt → Redeploy
Authorizations section shows a browser you don't recognizeA session key from another device or browser profile of yours — or notRevoke it; sessions elsewhere will just re-prompt to sign in
An agent key or an Agent signer row you don't recognizeA key you forgot, a key someone created in a session of yours, or a signing key you never pastedRevoke it. A signer row's revoke stops those keys from changing site records at once; the keys themselves are in the Agent keys list
Creating a key, or Re-authorize, is refused on a wallet with a hand-written delegate rowA row for the Stasho delegate, written outside the app, names the security record among what the delegate may write. Stasho never widens such a row, so the signature is refused (409 delegate_row_forbidden)Rewrite that row with the tool that wrote it so it no longer names security, then retry. Or, if the Stasho (current) row shows Revoke, revoke it and Re-authorize, then retry: that takes two signatures and stops deploys in between. A row showing Enable fast path: click it, then Revoke appears. A row showing Re-authorize has no in-app fix

Working with an agent ​

Key management is yours alone: an agent cannot create, rotate or revoke a key, and it should never see the dashboard. Its part is to tell you which key to create and to prove it works afterwards.

What the agent hands you, in these words:

text
In the Stasho dashboard open Settings → Authorizations, scroll to Agent keys and click
Create key (for a key tied to one project, open that project's Settings → Agent access instead
and pick This project, or This site on an uploaded site). Name: "<name>". Tick exactly these
scopes and untick every other: <read, deploy, rollback, domains>. Expires: <7 days>. Who signs
the site records: <Stasho signs for me, then Sign and create key if it asks / My agent signs,
paste this public key: 0x04…; it can then change every site record in your wallet>. On the Key created view, copy
the key and set it as the STASHO_AGENT_KEY environment variable where I run; do not paste it
here. Tell me when it is set.

How the agent verifies it afterwards. The key itself is the proof, with one read call:

bash
curl -s -w '\n%{http_code}\n' -H "Authorization: Bearer $STASHO_AGENT_KEY" \
     https://api.stasho.xyz/api/agent/sites

200 means an All sites key with publish; a key for one site with publish answers 403 with wallet_key_required there and 200 on GET /api/agent/sites/<projectId> instead, and a key without publish answers 403 with scope_missing. A key with read verifies with GET /api/agent/projects (or GET /api/agent/projects/<projectId> for one project) the same way; 401 key_invalid means the key was mistyped, has expired or is revoked. A write scope is checked only by a write: a 403 scope_missing names the scope the key lacks. A key under My agent signs also has a public trace: the signing key's address (shown on the Key created view) appears in the audit endpoint's authorized senders, currently authorized, with projects among its aggregate keys:

Set SIGNER to the signing address from the Key created view:

bash
SIGNER=0x…
curl -s https://api.stasho.xyz/api/audit/$ADDRESS \
  | jq --arg a "$(echo "$SIGNER" | tr A-Z a-z)" \
       '.authorizedSenders.sessionKeys[] | select(.address | ascii_downcase == $a)'