Skip to content

Secrets

Your integration needs a third-party API key or token. These are secrets you do not want stored in plaintext. What the platform does with them:

Each secret value is sealed with a post-quantum hybrid envelope the moment the platform receives it, and stored only in that sealed form. It is decrypted only to be delivered to your own app’s container.


You never put secret values in your manifest or your app config. They travel in the deploy request’s env map, and each value is sealed at intake, before anything is stored.

There are two deploy paths, and they converge on the same sealed env map:

hsuite deploy and hsuite redeploy build that map for you by forwarding your env file (--env, default .env.local). The deployed app runs with the same settings you run locally, with no allowlist to maintain.

Every non-empty key in the file is forwarded, even ones the CLI has never heard of, except these:

Withheld key Why it’s never forwarded
SMART_HOST_URL, VALIDATOR_URL, GATEWAY_URL Locally these point at the public testnet gateway. In your container the platform sets its own values for them, together with APP_TOKEN.
DEV_MODE, ALLOW_INSECURE Local-only safety switches. A stale true in your env file must never reach a live deployment.
SUBSCRIPTION_PENDING_CREATE, SUBSCRIPTION_PENDING_PAYMENT, SUBSCRIPTION_PENDING_TOPUP_PAYMENT The CLI’s own bookkeeping.

Two more rules make the merge predictable:

  • A non-empty value in your env file wins over manifest.backend.env. The manifest only fills keys your env file doesn’t set, and the CLI warns on each collision. Keep secrets in your env file and only non-secret settings (ports, feature flags) in the manifest; the CLI also warns if a secret-shaped key appears in the manifest. Empty values in the env file are dropped.
  • Credential-less deploys fail loud. Your XRPL_SEED (the wallet that holds the subscription NFT, used for owner-signed operations) is forwarded. If the resolved env has no XRPL_SEED, hsuite deploy aborts rather than ship an app that boots in open mode — unless you pass --allow-open-mode for an intentional zero-credential deploy, which withholds the seed from the container while still using it locally to sign the build attestation.

Each value is sealed with a post-quantum hybrid envelope:

  • ML-KEM-768 (a post-quantum key-encapsulation scheme) wraps a fresh AES key for the value, using the cluster’s public encryption key. The matching private key is derived by the validators’ distributed key generation.
  • AES-256-GCM encrypts the value itself with that fresh key.
  • HKDF-SHA-384 derives the AES key from the encapsulated secret, with a label specific to deployment secrets.

Every value gets its own AES key, so two secrets never share one. The sealed envelope records the algorithms used, the encapsulated key, the ciphertext with its authentication tag, and when it was sealed.


When your app is deployed, the secret travels from sealed storage into your container’s environment:

sequenceDiagram
    autonumber
    participant You as hsuite deploy / SDK
    participant Host as Smart Host
    participant Store as App record (validators)
    participant Dep as Platform deployer
    participant K8s as Secret in your app's namespace
    participant App as Your container

    You->>Host: deploy request with env (over TLS, signed)
    Host->>Host: seal each value (ML-KEM-768 + AES-256-GCM)
    Host->>Store: store the sealed envelopes
    Dep->>Store: read the envelopes
    Dep->>Dep: decrypt
    Dep->>K8s: write the values
    K8s->>App: environment variables
    App->>App: process.env.PAYMENT_API_KEY

Your code reads the value like any env var — process.env.PAYMENT_API_KEY. You never see, and never handle, the envelope.

Plaintext exists in these places: the Smart Host process while it seals the value, the deployer process while it decrypts it, the Kubernetes Secret in your app’s own namespace that feeds your container, and your container’s process for its lifetime. Delivery through a secrets vault, which adds an access audit trail, is built, not yet enabled.


  • There is no per-app key to rotate. Each value is sealed under its own fresh AES key.
  • To rotate a secret, change it in your env file and run hsuite redeploy (or send a new env map with client.deployment.deploy). The new value is sealed and replaces the old one.
  • To revoke a secret, revoke it at the service that issued it, then redeploy without it.
  • Retiring the app (hsuite delete) tears down its namespace, including the Secret your container read.

Don’t Why Do instead
Put secret values in smart-app.manifest.json The manifest is usually committed to git. The CLI warns on secret-shaped keys there. Keep secrets in your env file; the CLI forwards them sealed.
Log a secret Defeats the whole model. Read it from process.env, use it, don’t print it.
Assume the platform protects you inside your container Anything in your own process is your responsibility. Treat a compromised container as “secret exposed”; rotate.
Reuse one secret across apps One leak then exposes every app that shares it. One secret per app; rotate each independently.
Commit your env file It holds your secrets and XRPL_SEED, which controls your wallet. Keep it out of git.