Skip to content
Production

Production checklist

What to check before real users arrive, and how to check each one.

Work through these before you ship. Each one says what to set up and how to check it in the deployed app.

Every page is cross-origin isolated

Both headers are on every route that loads the SDK, in production as well as in development. Turn on cross-origin isolation has the config for each host.

How to check. Open the deployed app and run crossOriginIsolated in the console. It must print true. A CDN or proxy in front of your app can drop the headers, so check the live site.

The SDK's files are pinned and current

Your install runs nimbus-solana-web copy-assets, so the served files match the installed SDK. Your app refuses to run a build that does not check its files:

if (.. !== "pinned") {
  throw new ("Refusing to run unchecked WebAssembly.");
}

How to check. sdk.settings.assetPinning reads "pinned" in the deployed app. A payment then runs without a dependency-nonconforming error.

The Content Security Policy allows the SDK

A strict policy is your best defence for the user's signature, which the default store keeps readable by any script on your site. On top of your own rules, the SDK needs these:

script-src 'self' 'wasm-unsafe-eval';
worker-src 'self';
connect-src 'self' <every origin the SDK fetches from>;
  • 'wasm-unsafe-eval' lets the page and the workers compile WebAssembly. It does not allow JavaScript eval.
  • worker-src 'self' lets the SDK start its workers. The prover worker and the threads it starts are scripts on your own site, so blob: is not needed.
  • connect-src lists every origin the SDK fetches from. Build it from the loaded SDK, so it follows the preset and your own endpoints:
const { ,  } = .;
const  = [
  .,
  .,
  .,
  .,
  .,
  .,
  .....(() => .),
  .....(() => .),
  .....(() => .),
  .,
].(() =>  !== "");

const  = new (.(() => new (, .).));
.([...].(" "));

Send the policy with the SDK's files too. A worker follows the policy its own script was served with, not the page's.

How to check. Run a deposit and a withdrawal with the console open. No policy violation is reported.

The files are cached sensibly

The SDK's files keep the same names from one version to the next. Serve them with a short cache lifetime. Or copy them into a folder named for the version, such as /nimbus-0.1.0/, and cache that for as long as you like.

The SDK caches the larger circuit files itself, in IndexedDB. They need nothing from you.

How to check. Upgrade the SDK, deploy, and load the app in a browser that visited before. It loads without a dependency-nonconforming error.

The gateway token stays out of sight

Your app needs a gateway token for mainnet. To get one, email dev@umbraprivacy.com or reach out to any Umbra team member.

The SDK never logs the token or puts it in an error. Keep your own code the same:

  • Keep the token out of your repository. Load it from your configuration at build or run time. The mainnet gateway token shows how to pass it.
  • Never log request headers, or the options you pass to openNimbusSession.

How to check. Search your logs and your error reports for the token. It appears nowhere.

You chose where the sign-in is kept

The signature that unlocks a private account can be kept for the tab, for the browser, or not at all. The first two are readable by any script on your site. Pick one on purpose, and tell your users. Sessions compares them.

How to check. Find the signatureSecretStore you pass to openNimbusSession. Leaving it out means the tab store.

Errors reach your reports

Report what helps you fix a problem, and nothing secret:

  • For a NimbusSdkError, report its reason and message. The message never holds the token.
  • For a protocol refusal, isNimbusSolanaFlowError tells you it is one. Report its reason.
  • For a result that is not a success, report its kind.
  • Never report the session object. It holds the user's keys.

How to check. Load the app on a page without the isolation headers. Your reports show unsupported-browser and the message.

Balances update while the app is open

Payments sync the device on their own. Payments others make to your user arrive only with a sync. Run one on an interval while a session is open, as Use it with React shows.

How to check. Leave the app open, and pay its user from another account. The balance updates without a reload.

Users can release stuck funds

A payment that stops halfway, because its tab closed or a step failed, keeps its funds reserved. A sync frees one that never sent anything. Give users a button that calls releaseReservedNotes for the rest. Reserved funds shows the list and the button.

How to check. While listReservedSpends lists a payment, press the button. Its amount moves from reserved back to available once nothing of it can still land.

You tested the browsers you support

The SDK's own tests run in headless Chrome only. Test your app in every browser you support, including on phones if you support them. Browser support lists what each browser must offer.

How to check. Run a deposit, a Private Send and a withdrawal in each browser.

Next

Last updated

On this page