drift Docs
Start
What is Drift?
The tour, if you are new here.
Use cases
Whether Drift does your thing.
Getting started
Nothing to deployed, in one command.
Architecture
How a slice is put together.
What it costs
The free grant, four unit prices, two rules.
Build
Canvas
Static sites, same origin as your API.
Tools
Operate
Auth
Route gates, API keys and your account.
Security
Boundaries, sandboxing and hardening.
Troubleshooting
Error codes
What went wrong, and what to do about it.
Legal
Acceptable use
What a slice may not be used for.
Data processing
The DPA, and every sub-processor.

Backbone Secrets

Encrypted at rest with AES-256-GCM. Declare which secrets a function may read with secrets: on its Driftfile entry, then read them with the SDK:

Driftfile
functions:
    - name: "post:charge"
      handler: PostCharge
      memory: 32MB
      auth: apikey
      secrets:
        - STRIPE_KEY
Go
key, _ := drift.Backbone.Secret.Get("STRIPE_KEY")

Before the subprocess starts, the runner fetches each declared secret and injects it twice: as the environment variable DRIFT_SECRET_<NAME> with the name uppercased, which is what Secret.Get reads, and inline in the request envelope's secrets field. Every language but Go exposes that field directly as req.secrets (or the local equivalent); Go's generated Request struct does not declare it, so a Go function reads a secret through Secret.Get only.

Shell
drift backbone secret set    STRIPE_KEY=sk-123abc
drift backbone secret get    STRIPE_KEY
drift backbone secret list
drift backbone secret delete STRIPE_KEY

You can also declare secrets in the Driftfile, as $ENV references resolved at deploy. Write a value out as a literal and it is committed to your repository, so the CLI warns about every one it finds.

Replacing a secret keeps the value it replaced readable for 24 hours. That is for a credential your handler verifies rather than presents: a webhook signing secret's sender keeps signing with the old value until they catch up, and checking only the current one would reject every request in between as forged. Read it with Secret.Previous, and ask whether the window is open with drift backbone secret previous KEY.

At runtime a function reads secrets and does not create them. The subprocess starts with a cleared environment and never holds the slice's internal token, so a secret the function did not declare cannot be fetched over HTTP, and Secret.Set answers 401. Secrets are provisioned out of band, with drift backbone secret set or in the Driftfile.

That makes Secrets the right home for a value your app must keep stable across cold starts, like a signing key: generate it out of band, set it once, declare it, then read it, validating the length so a missing or unreadable secret fails loudly instead of signing with garbage.

Shell
# provision once, out of band, never from inside a function
drift backbone secret set SIGNING_KEY=$(openssl rand -hex 32)
Go
// Driftfile: name post:sign, handler PostSign, secrets [SIGNING_KEY]
func signingKey() ([]byte, error) {
    hex, err := drift.Backbone.Secret.Get("SIGNING_KEY")   // from DRIFT_SECRET_SIGNING_KEY
    if err != nil || len(hex) != 64 {
        return nil, fmt.Errorf("SIGNING_KEY missing or malformed")
    }
    return decodeHex(hex)
}

If all you need is a token for user sessions, you don't need a key of your own at all: the platform's JWT signing key is managed for you.