S
supero.docs
Documentation/Building Your App/Going to Production

Going to Production

The checklist to run before real customers touch your app: rotate the seeded credentials, close the permissive defaults, confirm which tenant your customers are in, and check your plan before launch day.

Overview

A generated Supero app is built to be usable in the first five minutes. That means it ships with demo accounts you can sign in as, access policies that let you see everything, and integrations pointed at test credentials. All of that is correct while you are building, and wrong the moment someone who is not you has an account.
This page is the list of things to change on the way out. Every item is something the platform will let you launch without — none of these will block a deploy or raise an error, which is exactly why they need a checklist. Work through it against the app you are about to publish, not against a copy.

ℹ️ Do the tenancy item first

Most items here can be fixed after launch. The tenancy decision cannot be undone cheaply: a record's tenant is part of its identity, so data written into the wrong tenant stays there. If you read nothing else on this page, read Where your customers live before you create your first real customer.

The Checklist

Each item is expanded in the sections below.
  • •Rotate or remove the seeded demo accounts your generated app shipped with.
  • •Confirm the published app carries no demo sign-in affordances.
  • •Confirm every real customer is in a dedicated tenant, and that nobody outside your own staff is in default-tenant.
  • •Replace the permissive default access policies with policies that deny by default.
  • •Audit which schemas you have marked public — they are readable by anyone, with no login.
  • •Switch every integration out of its provider sandbox and onto live credentials.
  • •Confirm the key store is enabled if you are self-hosting, and that its key is backed up.
  • •Give every API key an expiry, delete the ones you no longer use, and stop relying on key scopes.
  • •Check your plan has a live-deployment allowance before launch day.
  • •Publish, then verify with a real sign-in and a real write — not just a 200 from the URL.
  • •Confirm audit logging and API authentication are on for your deployment.

Rotate the Seeded Credentials

Every generated app is created with working user accounts so that the app is testable the moment it exists. Depending on how the app was generated you will have a tester account plus a demo admin and a demo user, or an admin and a staff user per tenant. They share a placeholder password, and that password is visible in the app's own configuration file — see Anatomy of a Supero App for where the account list lives.

🚨 These are real accounts with real roles

The seeded demo admin is a tenant_admin. Under the default access policy that is full create, read, update and delete on every entity in the project. An account you left in place because it was convenient during the build is a full administrator of your customers' data on launch day.
Before you publish, for each seeded account, do one of:
  • •Change its password to a real secret. A signed-in user can change their own with POST /api/v1/auth/change-password; an administrator can reset another user with POST /api/v1/auth/reset-password.
  • •Disable it. PUT /api/v1/users/{user_uuid}/disable removes access while keeping the account and its history — see Users & Roles.
  • •Remove it from the account list in your app configuration and regenerate, so the next build does not recreate it.
Then re-check after any regeneration. Regenerating an app re-runs setup, and an account you deleted but left in the configuration comes back.

💡 Keep one account you control

Do not disable every seeded account at once. Create your own administrator first, sign in as it, and confirm it works before you remove the last seeded admin — otherwise you can lock yourself out of your own app's admin surface.

Turn Off the Demo Sign-In Affordances

A preview build renders "Try a demo account" chips on the login page — one per seeded account, showing the email, and filling in the password when clicked. They exist so a preview link can be handed to someone who has no credentials.
How you deployedWhat happens to the demo chips
Preview on Supero CloudPresent. The credentials are part of the payload the browser receives.
Published (Go Live) on Supero CloudAbsent. A published deployment is not sent the credentials at all, so the chips cannot render.
Your own AWS or GCPOff unless you explicitly turned them on with the deploy-wizard toggle. Confirm the toggle is off for the build you are shipping.
Self-hosted / run locallyOff unless the deployment was explicitly configured to show them.

⚠️ The hide switch in System Settings is not a security control

The generated admin console has a toggle that hides the demo chips. It stores that preference in the browser it was clicked in and nothing else. The credentials remain in the configuration the app serves, readable by anyone who looks. Use it to tidy your own screen, never as the thing that removes demo access.
Verify rather than assume: open the published URL in a private window and confirm the login page shows only a normal email and password form.

Where Your Customers Live

This is the item that is expensive to get wrong, because it is the one you cannot fix by changing a setting.

🚨 Never provision a customer into default-tenant

Cross-tenant access is granted on two independent conditions, and only one of them is a role. Any user whose tenant is literally named default-tenant is given project-wide access to every tenant in that project, regardless of their role — a tenant_user in default-tenant can read every other tenant's records. The same is true of an API key minted against a default-tenant. This is deliberate behaviour for the built-in workspace tenant, and it makes default-tenant the one place a customer must never be. See Building Multi-Tenant Apps.
It is easy to end up there by accident. Every project gets a default-tenant automatically, a single-tenant generated app seeds all its data into it, and it is where a first walkthrough naturally leaves you. Before launch:
  • •List every user account in the project and check the tenant each one belongs to. Anyone who is not your own staff should be in a named tenant you created.
  • •Create a dedicated tenant per customer with POST /api/v1/tenants, and provision that customer's users into it.
  • •Check your API keys the same way. A key minted against any project's default-tenant resolves to a project-wide administrator, not a tenant-scoped one.
  • •Decide this before you write real customer data. A record's tenant is part of its fully-qualified name, so moving records between tenants is not a supported operation — you would be recreating them.

ℹ️ Single-tenant apps still need the decision

If your app genuinely serves one organisation — an internal tool, a single-company back office — leaving everything in default-tenant is fine, because everyone in it is staff. What matters is that you made the choice knowingly. The trap is the app that starts single-tenant, gets a second customer six months later, and discovers that everyone from the first year can see them.

Close the Permissive Defaults

For the complete set, see Roles & Permissions Reference.
Object-level access policy defaults to permissive, not to deny. With no policy configured for a role, viewer is read-only and every other role — tenant_user, tenant_admin, developer, project_user, domain_user, and any custom role built on them — gets full create, read, update and delete on every entity in the project.

🚨 An unconfigured schema is an open schema

Do not assume a new entity is protected because you have not written a rule for it. A schema you added last week, with no access_rule of its own, is fully writable by every non-viewer role in the project. Each time you add a schema, add its rules — or set the role's default_access to none so that new entities start closed.
The shape that holds up in production is deny-by-default plus explicit grants: an access_policy per role with default_access set to none, and an access_rule per entity that role is allowed to touch. Set all four of can_create, can_read, can_update and can_delete explicitly on every rule — the schema defaults are not symmetric, and a partial rule can grant read where you meant to deny it.
Then verify from the other side. Sign in as each role you ship and call GET /api/v1/crud/{domain}/access-policy/me to read back the policy that role actually resolves to, rather than trusting the rows you wrote. See Access Policies for the full reference and Access Control (RBAC) for how the two authorization layers combine.

⚠️ A revocation is not instant

Resolved policies are cached. If you tighten a policy for a project other than the one your own session is scoped to, affected users keep the old policy until the cache expires — up to five minutes. Never tell an operator that access has been revoked on the strength of a successful write; switch your session into that project first, then confirm as the affected role.

Audit What You Made Public

Generated apps declare a list of public schemas — the object types a storefront or landing page can read without anyone signing in. It is what makes a product catalog visible to a first-time visitor.

🚨 Public means public, across every tenant

A schema on that list is served to anonymous callers using the application's own service credential, which spans every tenant in the project. There is no per-tenant narrowing and no login. Anything on that list — including fields you did not think about, and rows belonging to customers other than the one whose page is being viewed — is readable by anyone with the URL. Put only genuinely public catalog data there, never anything tenant-scoped, personal, or internal.
Before launch, read the public-schema list in your app's configuration and justify every entry out loud. Then fetch one of them anonymously — no Authorization header, no API key — and read what comes back field by field. If a field should not be on a public page, remove the schema from the list, or move the sensitive fields to a separate type that is not public.
Separately, a project can enable an unauthenticated read API of its own with an explicit entity allowlist. That is off by default; if you turned it on, review the allowlist with the same suspicion.

Secrets, Keys, and Credentials

Confirm at-rest sealing if you self-host

Integration credentials — payment keys, messaging secrets, the config blobs you enter for catalog providers — are sealed at rest only when the deployment's key store is enabled. It is not on by default, and when it is off, sealing is a pass-through: the value is stored in plaintext, no error is raised, and the record looks identical through the API. On Supero Cloud the key store is managed for you. On a self-hosted or on-premise install, confirm it is enabled before you put a real vendor credential anywhere near it — see Security and On-Premise Deployment.

🚨 Back up the key before you need it

The encryption key is not stored with your data and is not recoverable from it. If you enable at-rest sealing and then lose the key, every sealed credential is permanently unreadable, and rotating the key without migrating orphans everything it previously sealed. Back it up out of band, to somewhere separate from the deployment, before launch.

API keys

  • •Give every key an expiry. Keys are created with no expiry unless you set expires_in_days, so a key minted during a spike of debugging is valid forever by default.
  • •Delete the keys you no longer use rather than leaving them enabled.
  • •Do not rely on a key's scopes list to make it read-only — treat every key as carrying its role's full authority, and scope it by the tenant it was minted against instead.
  • •Never mint a customer-facing or narrow-purpose key against a default-tenant — see the tenancy section above.
  • •Rotate anything that has been in a screenshot, a support ticket, a CI log, or a repository.
The full key value is shown once, at creation. Store it in a secrets manager or an environment variable, never in source control. Security covers key scoping and rotation in detail.

Self-hosted platform administration

A self-hosted install bootstraps a platform administrator account with a default password if you did not set one during installation. That account has global access across every domain on the install. Set the administrator password explicitly at install time, and if you did not, change it before the platform is reachable from anywhere but your own machine.

Take Everything Out of Test Mode

There is no single platform-wide sandbox switch to flip. The test-mode settings that matter live on your integrations, one per provider, and each one has to be changed individually.
ProviderWhat to change
Email (SendGrid)Set sandbox_mode to false. While it is true every send is validated and reported as successful without anything being delivered — which looks exactly like a working email system.
Stripe / PayPalSwap test keys for live keys; set paypal_mode to live.
PlaidSet plaid_environment away from sandbox.
SalesforceSet salesforce_is_sandbox to false.
QuickBooksSet qbo_environment to production and mint a production refresh token.
The full per-provider field list is on Managed Integrations & Provider Catalog; email specifically is covered on Email & Notifications. Credentials are per project, so the same app bundle runs against test keys in one project and live keys in another with no rebuild — use that rather than editing an app in place.
Two more things that look like sandbox switches and are not:
  • •The environment label on a tenant (development, staging, sandbox, production) is metadata. It does not change platform behaviour or restrict anything — set it for your own clarity, but do not treat it as a guard.
  • •If your console still shows a banner saying you are in the default domain, you are working in the shared sandbox workspace rather than your own. Create your own domain before you build anything you intend to keep.

⚠️ Starter test credentials are not launch credentials

The console offers a one-click action to provision starter test credentials for services that support them, clearly labelled for testing. Anything provisioned that way must be replaced with your own production credentials before launch — check every service on the Services tab, not just the ones you remember configuring.

Check Your Plan Before Launch Day

The most common launch-day surprise has nothing to do with your code: the plan the domain is on does not include what you are about to do.
What you tryWhat happens if the plan does not allow it
Publish a permanent live deploymentHTTP 402 with an upgrade prompt instead of a build starting. The lower tiers are build-and-preview only — they include zero live deployments.
Create another projectHTTP 402 once you are at the plan's project limit.
Run a connectorHTTP 402. Connector access starts above the entry tier.
Use the in-app AI agent past the free allowanceHTTP 402 naming the meter, your limit, and what you have used.
A 402 is a plan answer, not a bug — the body tells you which meter tripped, the limit, and the amount used, so a client can show a real message rather than a generic failure. See Rate Limits & Quotas for the response contract and Plans & Billing for the catalog.

💡 Check the day before, not the hour before

Read your domain's current plan and usage from the Billing screen in the console, or from GET /api/v1/billing/usage/summary, before the day you intend to launch. Plan changes are self-serve for a domain_admin, but a payment method that needs approval from someone else in your company is not a thing you want to discover at 9am.

ℹ️ Self-hosted deployments meter differently

Plan allowances are a hosted-platform concept. A self-hosted install is governed by its licence rather than by the plan catalog on this site, and the limits that apply to it are the licence's. Confirm which model your deployment is on before you plan capacity.

Publish, Then Actually Verify

Publishing is a separate action from previewing, and the two deployments are independent — stopping a preview cannot take a published app down, and a preview cannot overwrite one. If a live app already exists for the project, launching a preview over it is refused with a conflict rather than replacing it. Publish Your App covers the flow.
Before you flip:
  • •Confirm the build you are publishing is the one you tested — publishing names a specific completed build, not simply the latest state of the project.
  • •Set the project's region if location matters to you. The field accepts any short string without validation, so a typo is stored silently and reads back as whatever you typed.
  • •Have your custom domain conversation before launch, not after — talk to [email protected].
After the URL comes up, a 200 from the homepage is not proof of anything. Check all of these:
  • •The page renders your branding and real data, not an empty shell or generic placeholders.
  • •You can sign in as a real (non-seeded) user, and the login page offers no demo shortcuts.
  • •A create action persists across a reload.
  • •Signing in as each role you ship shows only what that role should see — check at least one restricted role, not just an admin.
  • •A record written by one tenant is invisible to a user in another tenant.
  • •A transactional email actually arrives in a real inbox.

After Launch

  • •Confirm audit logging is on for your deployment and that you can read your domain's trail through the audit_log object type. Entries are retained for 90 days by default. On a self-hosted install this is a deployment setting rather than something the product turns on for you — see Security.
  • •Confirm API authentication is enabled if you self-host. The packaged deployment manifests enable it; a hand-assembled deployment can leave it off, and nothing in the product will tell you.
  • •Know your backup story. On a self-hosted install this is yours to arrange, and it must include the key-store key as well as the data.
  • •Watch the two counters that actually stop you: your plan's live-deployment allowance and your usage against the meters you draw on. See Plans & Billing.
  • •Re-run the credential and policy items in this checklist after every regeneration. Regenerating an app re-runs setup with the configuration in the bundle, which can recreate accounts and policies you removed.
For a production launch, capacity planning, or a deployment into your own cloud, write to [email protected]. For anything behaving differently from these docs, [email protected]. Security reports go to [email protected] before anywhere public. For the complete set, see Roles & Permissions Reference.

Next Steps