Signed agreements workflow
Spec: ETSI EN 319 142-2, §5.1 ETSI EN 319 142-2 §5.1 Spec: ISO 32000-2:2020, §12.8 ISO 32000-2:2020 §12.8 Evidence: Mixed evidence
At a glance
Section titled “At a glance”A signed agreement is not “a PDF with a signature on it.” It is a document prepared so the signature protects the right bytes. It is signed at a level that matches the obligation. It is packaged so it still verifies after the signing certificate expires. This page walks that scenario from blank document to long-lived contract. It is candid about which steps the engine wires today and which it exposes as a frozen surface.
Why this matters
Section titled “Why this matters”A contract that verifies the day it is signed and fails three years later in a dispute is worse than no signature at all, because someone relied on it. The failure is rarely the cryptography. It is usually a missing timestamp or missing revocation evidence, decided long after the signer has moved on.
Choosing the signature obligation up front, and producing the evidence the obligation needs at signing time, is the difference between an agreement that holds up and one that quietly decays. This is a decision to make once, in the workflow, rather than to rediscover with each dispute.
The short version
Section titled “The short version”- Prepare, then sign. A signature covers exactly the byte range it was computed over. Decide the document is final — including any later appended revisions — before you sign, not after.
- Pick the level for the obligation, not the other way around. PAdES defines a progression: a basic signature, a timestamped one, one with embedded validation material, and one re-stamped for indefinite archival validity (ETSI EN 319 142-2 §5.1).
- Long-term validity is a structure, not a property. It is a Document Security Store plus a document timestamp, written into the file (ISO 32000-2:2020 §12.8).
- Be precise about the seam. NextPDF’s high-level
Document::setSignature()freezes the public API but fails fast rather than emitting an unsigned file. The wired path is the lower-level orchestrator. This page does not pretend otherwise.
How NextPDF approaches it
Section titled “How NextPDF approaches it”NextPDF separates the decision from the mechanism. The decision is which PAdES level the obligation needs. The mechanism is how the bytes are signed and how the validation material is carried. Treating these as one thing is how teams end up with a signature that is valid but not durable.
The scenario has four stages.
- Prepare the document Compose the agreement and treat it as final. The signature will protect this exact byte range and nothing added outside it without a new revision.
- Choose the obligation B-B proves who. B-T adds trusted time. B-LT embeds the material to validate later. B-LTA re-stamps for indefinite validity.
- Sign A CMS signature is embedded in the signature dictionary over the byte range; a timestamp is requested from a TSA if the level needs one.
- Preserve For long-term levels, the Document Security Store and a document timestamp are written so the signature outlives its certificate.
The level enum is real, and it encodes the obligation honestly. B-B proves
the signer’s identity. B-T adds a trusted timestamp. “When” is asked as
firmly as “who”. B-LT embeds the certificates and revocation responses
needed to validate the signature after the signing certificate expires.
B-LTA adds document timestamps so the chain of trust can be extended
indefinitely by re-stamping before each timestamp certificate lapses. The
enum knows which levels require a timestamp and which require embedded
validation material, so the engine can refuse an impossible combination
rather than produce a misleadingly “signed” file.
What the evidence says
Section titled “What the evidence says”The progression is standard-backed. Evidence: Standard-backed Spec: ETSI EN 319 142-2, §5.1 ETSI EN 319 142-2 §5.1 describes PAdES levels layered on the EN 319 142-1 building blocks, from a basic embedded signature upward. The long-term structure is fixed by Spec: ISO 32000-2:2020, §12.8 ISO 32000-2:2020 §12.8 : long-term validation rests on a Document Security Store and a document timestamp dictionary written into the file.
The level model is code-backed. Evidence: Code-backed The
SignatureLevel enum has the four PAdES cases (B-B, B-T, B-LT,
B-LTA) with predicate methods for “requires a timestamp”, “requires
embedded validation material”, and “requires document timestamps”. The
high-level Document::setSignature() is wired to a fail-fast guard that
raises a blocking, actionable diagnostic rather than emitting an unsigned
document — a verifiable behaviour, not a claim.
The long-term maintenance behavior is documented at capability level for the Premium tier: the archival surface writes the DSS and per-signature VRI, inspects archival completeness with a health check, and re-stamps with a document timestamp before the timestamp certificate expires. The documentation states plainly that the verifier still decides.
Practical example
Section titled “Practical example”This shows the decision — selecting the obligation — using the real enum. The wired signing path is the lower-level orchestrator. The high-level call is shown only to make the fail-fast behaviour explicit.
<?php
declare(strict_types=1);
use NextPDF\Security\Signature\SignatureLevel;
/** * Map a business obligation to a PAdES level. * * The obligation drives the level, not the reverse — choosing B-B for a * 10-year contract is a decision you do not want to make implicitly. */function levelForObligation(string $obligation): SignatureLevel{ return match ($obligation) { // Internal sign-off, short retention, signer identity is enough. 'internal_approval' => SignatureLevel::PAdES_B_B,
// Counterparty agreement: prove the moment of signing. 'counterparty_agreement' => SignatureLevel::PAdES_B_T,
// Regulated contract that must verify after cert expiry. 'regulated_contract' => SignatureLevel::PAdES_B_LT,
// Long-lived legal record: indefinite, re-stampable validity. 'long_term_legal_record' => SignatureLevel::PAdES_B_LTA,
default => throw new \InvalidArgumentException( "Unknown obligation: {$obligation}", ), };}
$level = levelForObligation('regulated_contract');
// The enum carries the obligation's implications with it.$needsTsa = $level->requiresTimestamp(); // true for B-T+$needsDss = $level->requiresDss(); // true for B-LT+$needsArchive = $level->requiresDocumentTimestamp(); // true only for B-LTAThe level object is not a label. It answers what the obligation entails, so the wiring downstream does not have to re-derive it.
Common misconception
Section titled “Common misconception”The recurring misconception is “the signature is valid, so we are done.” Validity today is necessary but not sufficient. A signature is computed over a byte range. Anything appended outside that range in a later revision is not covered by it, which is exactly why preparation comes before signing. And a signature that verifies now can fail later when its certificate expires unless the validation material was embedded at signing time. “Valid” and “durable” are different guarantees, and only the obligation tells you which one you actually need.
A related trap specific to this engine: assuming the high-level
setSignature() produces a signed file today. It does not. It fails fast
on purpose. Treat the diagnostic as the contract.
Limits and boundaries
Section titled “Limits and boundaries”Document::setSignature()is a frozen public surface, not a wired signer. It fails fast with a blocking diagnostic. It never emits an unsigned PDF in place of a signed one. The wired path is the lower-level two-phase orchestrator.- Long-term validation maintenance (DSS/VRI, health check, the archival timestamp loop) is a Premium-tier capability. Core does not provide the archival loop. See the boundary below.
- A signature protects exactly its byte range. Later appended revisions are separate. The engine does not retroactively extend coverage.
- NextPDF produces and maintains the structures; it does not adjudicate. Whether a signature is trusted depends on the verifier’s trust anchors and policy, which are outside the engine.
- B-LTA does not make a signature eternal by itself. It enables indefinite validity only if the re-stamping loop runs on schedule before each timestamp certificate expires.
- This page is behavior-level on the Premium archival surface. It asserts no acceptance by any specific court or authority.
| Edition | Availability |
|---|---|
| Core | Core exposes the |
| Pro | PAdES baseline signing (B-B / B-T) via the orchestrator is available. |
| Enterprise | Adds B-LT / B-LTA, the Document Security Store and per-signature VRI maintenance, the LTV health check, and the document-timestamp archival loop for indefinite validity. |
Related docs
Section titled “Related docs”- PAdES baseline profiles — B-B, B-T, B-LT, B-LTA explained as a progression and how to choose.
- Long-term validation — why a signature that verifies today can fail in ten years, and how LTV embeds the evidence.
- The integration decision guide — which ecosystem package fits a signing workflow, including the human-approval seam in NextPDF Connect.
Glossary
Section titled “Glossary”- PAdES — PDF Advanced Electronic Signatures: the ETSI profile family defining how an advanced electronic signature is carried in a PDF.
- Byte range — the contiguous span of file bytes a signature is computed over; content outside it is not protected by that signature.
- Signature level (B-B / B-T / B-LT / B-LTA) — the PAdES progression: who signed, when, with embedded validation material, and re-stampable for indefinite archival validity.
- TSA — Time-Stamping Authority: an RFC 3161 service that asserts a document state existed at a given UTC instant.
- DSS (Document Security Store) — the in-file store of certificates, OCSP responses, and CRLs needed to validate a signature after its certificate expires.
- LTV (Long-Term Validation) — keeping a signature verifiable over time by embedding the validation evidence and re-stamping it.
- Fail-fast — refusing to produce a misleading artifact and raising an actionable error instead, rather than emitting a quietly wrong file.