Appearance
Release checklist
One checklist per deliverable. A release is the contracts, the SDK, the dApp and relayer, and this documentation moving together: a contract address that is not in the SDK's deployment table, or an environment variable that is not in Vercel, is a release that is not finished.
The commands below are the ones the repositories' CI workflows run; a green local run is necessary, not sufficient — the CI run on the release commit is the record.
Contracts (smart-contracts)
- [ ] Toolchain pinned and matching the record: Rust
1.94.1(rust-toolchain.toml, anddtolnay/rust-toolchain@1.94.1in CI) and stellar-cli26.0.0(CI builds it withcargo +1.96.0 install --locked stellar-cli --version 26.0.0). The CLI version is stamped into every artifact'sclivermeta entry, so a different CLI changes the hash. - [ ]
cargo fmt --all -- --check,cargo clippy --workspace --all-targets -- -D warnings,cargo test --workspacegreen on the release commit. - [ ]
stellar contract build --optimize --out-dir wasmproduced the artifacts to deploy, and CI's fixture check passed (contracts/account_factory/src/wasm_fixtures/*.wasmbyte-identical to the fresh build — a stale fixture is a false green in the factory's tests). - [ ] Hashes reproduced:
scripts/verify_build.shcompares a rebuild against the table indocs/MAINNET_DEPLOYMENT.md§3 (--fixtures-onlyfor the six committed fixtures,--containerfor the reference linux/amd64 recipe). Until it is merged intomainthe script lives on branchverify-build; the reference environment is the CI runner, and only a Linux x86_64 build is expected to match all seven hashes byte for byte (see Mainnet deployment). - [ ] Deployment record updated: contract ids, WASM hashes, upload/deploy/initialize transaction hashes with explorer links, initialization parameters (owner, initial signers, guardian threshold, executor, policies), in
docs/MAINNET_DEPLOYMENT.md— the single source of truth for addresses. - [ ] Instance and persistent TTLs extended on every long-lived contract (
extend_instance_ttl/extend_ttl/extend_intent_ttlare permissionless), and a calendar reminder set before the next expiry. - [ ]
account_factoryadmin key handled: it alone can repointset_wasm_hashes, so it stays offline between releases; any key whose seed phrase was ever shared (the documented example treasury's owner is one) is treated as compromised and holds no value.
SDK (sdk, published as sta-sdk)
- [ ]
pnpm lint,pnpm typecheck,pnpm test,pnpm buildgreen. - [ ] Version bumped with
npm version <patch|minor|major>; the README's "Versioning against a deployment" table names the contract set this version targets (smart_accountandaccount_factoryids per network) and links the deployment record with ablob/main/URL. - [ ]
MAINNET_CONTRACTS,MAINNET_ASSETS, andTESTNETinsrc/config.tsequal the deployment records. - [ ] Examples run against the target network:
STA_NETWORK=mainnet STA_MAINNET_RPC_URL=<provider> npx tsx examples/read-treasury.tsreturns the recorded owner, policy version, and factory WASM hashes; the signing examples were run at least once on testnet. - [ ]
git push --follow-tags: thev*tag triggers.github/workflows/publish.yml, which reruns lint/typecheck/test/build, refuses a tag that does not equalpackage.json's version, and publishes through npm OIDC trusted publishing. NoNPM_TOKEN,registry-url, orNODE_AUTH_TOKENis added to that workflow — either one silently switches npm back to token auth and the publish fails. - [ ]
npm view sta-sdk versionshows the new version. The dApp pins the exact version ("sta-sdk": "0.2.1"in itspackage.json) so that an SDK release never changes the dApp's chain code silently: bump it there, runpnpm install, and rerun the dApp checks below.
dApp and relayer (dApp)
- [ ]
pnpm format:check,pnpm lint,pnpm typecheck,pnpm test,pnpm buildgreen locally and in CI (.github/workflows/ci.ymlruns them in that order, then pulls the environment from Vercel and builds). - [ ] Branches and environments:
mainis Production (mainnet),testnetis Preview. CI pulls the matching Vercel environment, which needs theVERCEL_TOKEN(team-scoped, "All projects"),VERCEL_ORG_ID, andVERCEL_PROJECT_IDrepository secrets. - [ ] Vercel environment set per environment, values from the deployment record:
NEXT_PUBLIC_STELLAR_RPC_URL,NEXT_PUBLIC_STELLAR_NETWORK_PASSPHRASE,NEXT_PUBLIC_STELLAR_EXPLORER_URLNEXT_PUBLIC_SMART_ACCOUNT_ID,NEXT_PUBLIC_POLICY_ENGINE_ID,NEXT_PUBLIC_INTENT_REGISTRY_ID,NEXT_PUBLIC_RECOVERY_MANAGER_ID,NEXT_PUBLIC_TRANSFER_ADAPTER_ID,NEXT_PUBLIC_SPLIT_ADAPTER_IDNEXT_PUBLIC_DEFAULT_ASSET_CONTRACT_ID(the XLM Stellar Asset Contract on mainnet),NEXT_PUBLIC_DEFAULT_DESTINATION(an existing, allowlisted account)NEXT_PUBLIC_ACCOUNT_FACTORY_ID,NEXT_PUBLIC_RELAYER_EXECUTOR_ADDRESS- server-only, never
NEXT_PUBLIC_:RELAYER_EXECUTOR_SECRET,RELAYER_ADMIN_TOKEN,RELAYER_APP_URL,DATABASE_URL, and for the scheduled triggerQSTASH_CURRENT_SIGNING_KEY,QSTASH_NEXT_SIGNING_KEY,QSTASH_RELAYER_RUN_URL
- [ ] The network is derived from the passphrase: the header of the deployed site reads
Stellar mainnet(orStellar testnet) and the contract list in the console matches the record. - [ ] Executor account (
NEXT_PUBLIC_RELAYER_EXECUTOR_ADDRESS, the public key ofRELAYER_EXECUTOR_SECRET) exists and is funded on the target network. A treasury deployed through the dApp registers this address as itsintent_registryexecutor; an unfunded executor only fails at execution time. - [ ]
pnpm db:migraterun against the environment'sDATABASE_URL(one Neon branch per environment; the migrations insrc/lib/db/migrationsare committed). - [ ] Smoke test on the deployed site with a disposable treasury: connect, read state, one Policy check rejection, one payment confirmed with an explorer link.
- [ ] Relayer: one scheduled payment created in the console, queued (the wallet signs the session challenge), executed — by the schedule, or by Execute on its card — to
executedwith a transaction hash, and its Execute button disabled afterwards. - [ ] Scheduled trigger: the QStash schedule is registered against the exact URL in
QSTASH_RELAYER_RUN_URL, the signing keys are set in the same Vercel environment (Production has them; a Preview has no schedule unless one is registered for it), a run shows{"trigger":"qstash",...}in the QStash logs, and the failure callback reaches an operator. - [ ]
pnpm auditreviewed; anything critical in a runtime dependency resolved or explicitly accepted in the release notes.
The schedule is per environment
POST /api/relayer/run accepts a QStash delivery only where the signing keys are configured, and only for the pinned URL. A new environment — a preview, a second deployment — has no schedule until one is registered for it; until then its due jobs run only through pnpm relayer:run or the console's Execute.
Documentation (docs, this site)
- [ ] Status says what is deployed today, with the "Last verified" date of this release.
- [ ] Mainnet deployment matches
docs/MAINNET_DEPLOYMENT.md(addresses, hashes, toolchain). - [ ] Every GitHub link resolves: no
blob/mainnet/(the branch does not exist; the record lives onmain) and no link to a branch that has since been merged or deleted. - [ ] Testing support guide expectations re-run against the release.
- [ ]
pnpm format:checkandpnpm buildgreen; the rendered pages checked, not only the build output.
Post-release
- [ ] Addresses announced from the deployment record, not retyped.
- [ ] Any key shared during the release (deploy scripts, chat, CI logs) rotated; the treasury it owned drained.
- [ ]
docs/MAINNET_DEPLOYMENT.mdstays the single source of truth: the SDK table, the dApp environment, and this site link to it rather than restating it. - [ ] Open a tracking issue for anything ticked as "accepted" rather than "done".
Feedback on this checklist and anything it missed goes through Reporting issues.