DEV Community

WindwhisperBoren33
WindwhisperBoren33

Posted on

Node.js Tamper Detection API for Signed PDF Finance Records

A server-side PDF signature check is an evidence pipeline, and its largest observability cost is usually the document bytes retained around that pipeline. For a media company's finance team sharing a redacted contract, validate the submitted artifact, bind the result to its exact digest and policy version, and retain the compact decision record rather than another copy of the PDF.

TL;DR: A Node.js API should accept one bounded PDF, compute an artifact identifier, validate every relevant signature against an explicit trust policy, and return a structured result that distinguishes cryptographic integrity from business acceptance. Redaction must produce a new artifact whose signature state is evaluated on its own. Do not claim that a document is safe merely because a signature exists.

Start with bytes retained, not requests served

The expensive term is easy to hide in a request-rate dashboard. Let D be average document bytes, N the number of verification attempts, R the number of retained document copies per attempt, and T the retention multiplier imposed by replication and backup. The dominant storage input is D x N x R x T. A compact verification record has a different term: decision-record bytes multiplied by N and its retention multiplier.

That distinction matters for a media organization handling contributor agreements, acquisition invoices, and settlement paperwork. A 40 MB scan copied into an intake bucket, a debug attachment, a retry payload, and an audit export has R = 4 before backup is counted. The verification result may need only an artifact digest, signer identifiers appropriate to policy, validation time, policy version, signature-level outcomes, and a reason code. The exact byte totals depend on the corpus and retention controls, so they should be measured rather than guessed.

The first change that moves the bill is therefore architectural: stream or spool one bounded input through validation, keep the immutable source only under the records policy that actually requires it, and prevent application logs from acquiring the payload. Sampling log events cannot repair four full document copies.

Short-lived working storage still needs a deletion rule. A crashed worker must not turn a temporary PDF into an accidental archive.

How should a server-side API verify a PDF signature?

A useful response separates three questions. Did the cryptographic verification succeed for the signed byte ranges? Did the document change in a way the applicable PDF signature rules permit? Does the signer and certificate path satisfy the finance team's policy at the relevant validation time? These are related judgments, not synonyms.

The PDF specification is the governing format reference. In practice, the validator must parse the PDF structure rather than search for signature-shaped strings, enumerate the relevant signatures, and associate each result with the bytes and revision it covers. A green result for one signature must not silently stand in for all signatures in a multi-revision file.

The API contract should expose a small, stable vocabulary such as valid, invalid, and indeterminate, then attach machine-readable reasons. Indeterminate is operationally important. Missing trust material, unavailable status evidence, an unsupported signature construction, and malformed input are not the same outcome as a verified tamper. Collapsing them into false makes both incident response and finance review less accurate.

Here is a generic request shape for a Node.js service. The hostname is deliberately reserved for documentation, and the route represents an internal contract rather than a vendor API:

curl --fail-with-body \
  --request POST \
  --header "Content-Type: application/pdf" \
  --header "Idempotency-Key: 2d884c6e-2026-09-23-01" \
  --data-binary "@redacted-agreement.pdf" \
  "https://verification.example"
Enter fullscreen mode Exit fullscreen mode

The response should identify the artifact without echoing it. It should also state which policy was applied and report each signature separately. HTTP success means the service processed the request; it does not mean the signature passed.

Redaction changes the artifact

Redacting personal data before sharing a finance document creates the central fidelity trade-off. A visual overlay is not a trustworthy removal method. The publishing workflow needs to remove the sensitive content from the output artifact and verify that output as a distinct PDF.

Order is decisive. If the organization must preserve evidence about the received original, verify and record that original first. Then redact and render the shareable derivative. If the derivative must carry an approval signature, sign it after redaction and validate that final artifact before release. A signature on the original cannot be transferred conceptually to different bytes. Render fidelity deserves its own gate because cryptographic validation does not tell a reviewer whether a table wrapped onto another page, a disclosure disappeared, or a redaction annotation remained interactive. Compare representative pages and structurally difficult documents in a controlled test corpus. Spend rendering work where risk is concentrated: scanned agreements, embedded fonts, unusual page boxes, incremental revisions, and documents with several signatures. Do not render every page twice merely to make a dashboard look complete. Full-page raster comparisons increase compute and create more sensitive derived images to govern; sparse checks reduce render cost but may miss layout damage outside the sampled pages. For a finance release path, the defensible rule is risk-tiered: require complete review for high-impact documents and use a measured sampling policy for lower-impact batches. Record which rule ran.

That last field matters.

Build an audit record without rebuilding the document archive

Observability should describe decisions, not reproduce inputs. One verification event can carry an artifact digest, byte length, media type, signature count, final disposition, per-signature reason codes, elapsed time, policy identifier, validator build identifier, correlation identifier, and deletion status for working storage. Personal names, certificate subject strings, filenames, extracted text, and raw certificate material should be excluded unless the audit requirement explicitly calls for them.

Cardinality is part of the design. Artifact digests and correlation identifiers are valuable in an audit record, but disastrous as metric labels because nearly every value is unique. Keep metrics on bounded dimensions: disposition, reason family, policy version, workload class, and coarse size or latency buckets. Put high-cardinality identifiers in access-controlled event storage with shorter retention and targeted lookup.

Count before shipping. For example, five dispositions multiplied by twelve reason families, three policy versions, four workload classes, and ten latency buckets already permit 7,200 combinations before deployment, region, or status dimensions appear. Not every combination will occur, but the multiplication exposes the budget. A signer name or digest label destroys that bound.

Sampling also has a sharp edge. Aggregate counters should cover every decision, while verbose diagnostic events can be sampled by reason family. Always retaining invalid and indeterminate outcomes may be appropriate, but it raises the sensitivity and retention burden precisely where malformed or hostile documents appear. The policy should cap event size and prohibit payload fragments even on errors.

Failure handling is part of signature semantics

Set hard limits for upload bytes, parsing time, signature count, decompressed resource use, and concurrent work. Reject unsupported media before expensive processing. Run parsing in an isolated worker boundary, and make retries conditional: a transient dependency failure may merit a retry, while the same malformed PDF does not.

Idempotency prevents a client timeout from multiplying retained evidence records. It must bind to the artifact and operation, not merely to a user-supplied key. If the same key arrives with different bytes, the service should reject the conflict rather than overwrite history.

Deployment tests need valid, invalid, and indeterminate fixtures; multiple signatures; revisions after signing; truncated files; oversized inputs; and documents that survive validation but fail the redaction fidelity review. Keep expected reason codes under version control. The production canary should exercise the decision path without containing personal data.

There is no honest single latency target for every file. Parsing and rendering costs depend on document structure and size, while trust evaluation depends on the policy and available evidence. Publish service limits, measure distributions by bounded size class, and keep the synchronous endpoint narrow. Long work belongs behind an accepted-job contract with an authenticated result lookup, but that choice adds queue retention, cancellation, and duplicate-work concerns.

Retain the decision and accept the investigative limit

The deliberate endpoint is a compact, append-only verification record tied to the exact artifact digest and policy version. Keep the source PDF only for the period required by the organization's records and legal controls. Delete temporary copies promptly, do not retain rendered pages by default, and never put document bytes or extracted personal data in logs.

This reduces stored sensitive material and keeps telemetry cardinality bounded. It also has a real cost: after the source reaches the end of its authorized retention period, an investigator can prove what the service decided about a digest but cannot reconstruct the document or rerun a newer validator against it. Preserve longer only when that future revalidation value is explicit enough to justify another governed copy.

Further reading

Top comments (0)