PDFPipe

Document security / How long it lives, and what happens after

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.

The exposure

Audit requirements for documents are specific and are usually discovered late: who generated this, who has read it, who was given a link, when was it delivered and to whom, and was it ever regenerated. Application logs cannot answer those, because they are retained for less time than the documents, indexed by time rather than by document, and frequently sampled. So the record has to be built deliberately, as data, early enough to cover the period somebody will eventually ask about.

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.

  • Record events as data in your own store rather than relying on logs, because retention, indexing and completeness all differ.
  • Record the events that matter: generated, stored, link minted, retrieved, delivered, regenerated, revoked, deleted. Each with an actor and a timestamp.
  • Record the actor for every event, including when it is a system: a scheduled run and a person clicking a button are different answers to who did this.
  • Make the trail append-only and keep it at least as long as the document, since a question about a document is asked while the document still matters.
  • Keep content out of it. The trail will outlive the document, and it should not become a second copy of it.
  • Make it queryable by document and by person, because both questions get asked and an index by time answers neither.

In practice

A fragment, with the thing that goes wrong kept in a comment where it is the more instructive half.

js
// Append-only, in your own store, with an actor on everything.
await audit.record({
  action: "document.generated",         // stored, link_minted, retrieved,
                                        // delivered, regenerated, revoked,
                                        // deleted
  documentId,
  subjectId: invoice.customerId,        // queryable by person
  actor: { type: "scheduled_run", id: runId },   // or user, or api_key
  at: new Date(),
  detail: { templateVersion: TEMPLATE_VERSION },
  // No content. This outlives the document.
});

/* The questions it exists to answer, none of which logs can:

     who generated this document, and when
     who has retrieved it
     who was given a link, and when did that link expire
     was it delivered, to what address
     was it ever regenerated, and did the two versions differ
     who revoked it

   Queryable by document and by person, because both get asked:

     SELECT action, at, actor FROM audit
     WHERE document_id = ? ORDER BY at;

     SELECT action, at, document_id FROM audit
     WHERE subject_id = ? ORDER BY at;                                */

// Kept at least as long as the document, and append-only: an audit
// trail that can be edited is not one.

What people do instead

Assuming application logs are an audit trail. They are retained for weeks against documents retained for years, they are indexed by time rather than by document, and they are often sampled, so the one specific question is exactly the one they cannot answer.

How this is found out

At the first request for one, which is typically part of an incident or an audit, and which is the worst moment to learn that the record starts from whenever logging happened to be configured.

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.

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.