Secrets
A secret field holds a value your site needs but must never publish: an API key, a webhook signing secret, a third-party token. archival itself only guarantees that a secret never reaches a template. This page covers what the archival editor adds on top of that: a secret you set in the editor is stored encrypted in your site's repository, and handed to your carriers in plaintext.
This is automatic only for sites that archival deploys, and only for secrets set through the editor. A secret you write into an object file by hand, or a site you build and host yourself, is not covered. See when this applies.
What the editor stores
When you publish from the editor, the value of every secret field is encrypted before it is written to your repository. You type the secret, and this is what gets committed:
# objects/settings.toml
title = "My Site"
api_key = "archival-secret-v1:gzmYwEUNEgV7BpS8XUyKfZyX8TwdbPmzZQgRjq9D6_oMbrQdouz-eWaICQ"
Only the secret's own value changes. The rest of the file, including your comments and formatting, is committed as you left it.
- Each site has its own key. It is generated the first time the site stores a secret and is kept by archival. It is never written to your repository and never sent to your browser, so there is nothing to manage and nothing to leak from a clone.
- Encryption happens on archival's servers, as part of publishing. The editor in your browser sends the value you typed, and the stored form is produced before the commit is made.
- The same value always encrypts to the same text within a site. Publishing a change to another field leaves the secret's line untouched, so your git history stays readable. It also means two fields holding the same secret look identical in the repository.
- An empty secret stays empty. A field with no value is stored as
"", so the repository does show whether a secret is set.
The editor also records each publish's list of edits in the commit message, which is what lets you revert a publish later. When a publish touches an object that has secret fields, that list is encrypted with the same key, so the value does not appear there either.
Where a secret can be read
- In the editor, by the site's owner and the people it is shared with. The field is masked until you reveal it. Opening the site decrypts its secrets for you; someone who can read the repository but is not one of the site's editors gets the stored form.
- In your carriers. archival decrypts secrets when it deploys your carriers, so
objects.settings.api_keyis the value you typed. See reading secrets in a carrier. - Nowhere else. Templates never receive a secret at all, encrypted or not. A clone of the repository, a fork, or the repository's page on GitHub shows only the stored form, and it cannot be decrypted outside archival.
If a carrier deploy finds a secret it cannot decrypt, the deploy fails with the name of the object file rather than handing your carrier the stored form to send on as if it were the real value.
When this applies
Two things have to be true for a secret to be encrypted and for your carriers to still read it:
- The secret was set through the editor. Encryption is part of publishing from the editor. A value you write into an object file yourself and
git pushis committed exactly as you wrote it. - archival deploys the site. That is any site created at editor.archival.dev, and any site that deploys with the archival GitHub Action. Decryption for carriers happens in that deploy.
What that means in the other cases:
- You edit object files by hand, or with the CLI.
archivalon your machine never encrypts. A plaintext secret you push stays plaintext in the repository until that object is next published from the editor, which encrypts it then. Until that happens it still works: a carrier reads a plaintext secret as it is. - You host the build yourself.
archival buildworks as usual, since no template can read a secret either way. But nothing outside archival can decrypt the stored form, so server-side code you deploy yourself would receive thearchival-secret-v1:…text instead of the value. If you host your own carriers or functions, keep their secrets in that platform's own configuration rather than in an object. - You use the rust library.
FieldValue::as_secretreturns what the file holds, which for a secret published from the editor is the stored form.
archival's command line and library treat a secret as a string. The encryption described here belongs to the editor and to archival's hosting, not to the file format.
Working in the repository
You can keep editing a site's files directly alongside the editor.
- Leave a stored secret as it is when you change other fields in the same file. It is carried through untouched.
- To change a secret from the repository, replace the stored form with the new plaintext value. It works immediately, and is encrypted the next time that object is published from the editor. To have it encrypted from the start, set it in the editor instead.
- Don't copy a stored secret to another site. Each site has its own key, so a value encrypted for one site cannot be decrypted by another. Set the secret again in the other site's editor.
- Don't put a stored secret in a field that isn't a
secret. Onlysecretfields are decrypted. Anywhere else it is an ordinary string, and a template would publish it as written.
Secrets already in your repository
A secret that was committed before the editor encrypted it is not rewritten on its own. It is encrypted the next time the object holding it is published from the editor.
Encrypting it does not remove the earlier commits. The old plaintext value is still in your git history, so treat any secret that was ever committed in plaintext as exposed to everyone who can read the repository: issue a new one from the service it belongs to, and set the new value in the editor.
Previews
A preview stores its secrets encrypted the same way, under a key of its own, and its carriers are deployed with the decrypted values. When a preview becomes a site, its secrets are re-encrypted with the new site's key, so the site's first commit already holds them in stored form.