Document security / Who can reach the document
Rotating the API credential a document pipeline depends on
Replacing the key your pipeline authenticates with, without an outage, which is easy to plan and routinely never practised.
The exposure
Rotation is one of those operations that is straightforward in principle and fails in practice because it has never been done. The key is in an environment variable set once at deployment, nobody knows every place it is configured, and the first attempt is made under pressure after a suspected exposure. For a document pipeline the stakes are specific: a failed rotation stops document generation, and a monthly run that cannot authenticate is an outage with a deadline attached.
The decisions
Reasons rather than a description of the code. Each one has a default that is fine for a page and wrong for a file somebody keeps.
- Support two valid credentials at once, so a rotation is add, switch, verify, remove rather than a swap.
- Know where the credential is configured. Every deployment target, every scheduled job, every CI environment, written down, because the one you forget is the one that fails a month later.
- Rotate on a schedule so it is practised. A rotation that has been done four times is a routine change; the first one is an incident.
- Set an expiry on the credential where the platform supports it, since keys carry an expires_at, and let the expiry be the forcing function.
- Verify with a real render after switching rather than assuming, because the failure mode is silent until the next call.
- Never rotate during a scheduled run window. The one time it will be needed urgently is exactly when a run is due, and that is the argument for practising it beforehand.
In practice
A fragment, with the thing that goes wrong kept in a comment where it is the more instructive half.
/* Add, switch, verify, remove. Not a swap.
1. mint a new key alongside the old one
2. deploy it to every target below, old key still valid
3. verify each target with a real render
4. revoke the old key
5. confirm nothing broke, over a full cycle including the runs */
// Two accepted at once, so step 2 cannot cause an outage.
const KEYS = [process.env.PDFPIPE_KEY, process.env.PDFPIPE_KEY_PREVIOUS]
.filter(Boolean);
/* Every place it is configured. The one that is missing from this list
is the one that fails at month end.
web application env var
worker deployment env var
scheduled payroll job separate env
CI document tests repository secret
staging separate key entirely
the local .env somebody
still uses ask */
// Verify with a real call, because the failure is silent until the
// next one.
async function verifyCredential(key) {
const res = await fetch("https://api.pdfpipe.xyz/v1/pdf", {
method: "POST",
headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" },
body: JSON.stringify({ html: "<!doctype html><p>rotation check</p>" }),
});
if (!res.ok) throw new Error(`credential check failed: ${res.status}`);
}
// A key carries an expires_at. Let it be the forcing function rather
// than a calendar reminder nobody actions.What people do instead
Swapping the key in one place and deploying. Everything that reads it from somewhere else keeps using the old one, which works until the old one is revoked, and then a scheduled job nobody remembered fails at its next run.
How this is found out
A rotation that was never practised is discovered during the one that has to happen quickly, which is the worst time to find out that the key is configured in five places and only three are known.
Frequently asked
Does this page tell me what the law requires?
No, and deliberately not. Retention periods, erasure obligations and residency rules vary by jurisdiction, by industry and by the kind of document, and they change. What these pages describe is the shape of the problem and the mechanisms a system needs in order to implement whatever answer your own advisers give you. Where a genuine tension exists, such as an immutable record against a right to erasure, it is named as a tension rather than resolved.
Why is so much of this about the contents rather than access control?
Because access control decides who can obtain a copy and has no opinion at all about what happens to the copy. Once a document is on somebody's laptop, forwarded to a colleague or printed, every control listed here has already stopped applying to it. What is inside the file is therefore the part that keeps mattering, which is the opposite of the balance you would strike for a page.
How much of this applies at a small volume?
Most of it, because these are decisions rather than infrastructure. Redacting by omitting rather than covering costs nothing. Deciding what goes on a template costs one review. Classification is one object in code. Legal hold and an audit trail are the two that take real work, and both are far cheaper to build before they are requested than under the deadline that comes with the request.
Related security topics
The decisions that depend on each other, then the rest of the same group.
Keeping credentials out of a document template
The ways a credential ends up inside markup that is sent to a renderer, and why anything in that markup should be assumed to reach the document.
Access control on documents you stored rather than streamed
The authorisation model for documents that persist somewhere after generation, which is a longer-lived and larger surface than the render call itself.
Recording who generated, accessed and shared each document
The record of what happened to a document and who did it, which is asked for after an incident and cannot be reconstructed then.
Serving a generated document behind proper access control
Making sure the person downloading a document is entitled to it, which fails most often because the document lives somewhere the check does not.
Signed URLs for documents, and choosing an expiry that fits
Giving out a URL that carries its own authorisation for a limited time, which moves the access check to the moment the link is minted rather than the moment it is used.
Every document security topic
The full list, grouped by access, contents and what happens afterwards.
What this API actually does
The options and endpoints these decisions are built on, one page each.
Most of these are decisions rather than features, and the cheapest time to make them is before the first document is delivered rather than after one reaches the wrong person.