@trupdf/security
DRM, watermark, audit log, structural redaction.
DRMEngine
Permission gate. Doesn't encrypt — that's the secure-mode + structural-
redaction job. enforce(permission) throws on denial.
const drm = new DRMEngine({
permissions: new Set(['view', 'print']), // 'view'|'print'|'copy'|'edit'|'export'|'annotate'|'redact'|'sign'
expiresAt: '2026-12-31T23:59:59Z',
maxOpens: 10,
});
drm.enforce('print');RedactionEngine
Structural removal of content from the PDF byte stream, audited and non-cancellable. There is no visual-only fallback — if the structural adapter is unreachable, the burn refuses.
import { RedactionEngine, AuditLogger, bindPdfboxRedactionAdapter } from '@trupdf/security';
// Call once at app boot. Wires the engine to the TruPDF document
// service (the self-hosted container that powers structural redaction
// and full ISO 19005 PDF/A validation).
bindPdfboxRedactionAdapter({
endpoint: process.env.NEXT_PUBLIC_TRUPDF_DOCSERVICE_URL!,
internalSecret: process.env.NEXT_PUBLIC_TRUPDF_DOCSERVICE_SECRET, // optional auth gate
});
const audit = new AuditLogger();
const redactor = new RedactionEngine();
const result = await redactor.apply(
srcBytes,
[{ page: 4, x: 100, y: 200, width: 80, height: 14, exemptionCode: 'FOIA b6' }],
{ audit },
);RedactionMark fields: page, x, y, width, height, plus
optional exemptionCode, overlayText, color, opacity for the
drawn indicator box.
The audit entry is appended before the bytes are returned. If the audit append throws, the burn aborts and the original bytes are left untouched.
Custom adapters
Hosts that prefer their own structural-removal backend register via
registerStructuralRedactionAdapter:
import { registerStructuralRedactionAdapter } from '@trupdf/security';
registerStructuralRedactionAdapter(async () => ({
async removeIntersectingObjects(bytes, marks) {
// structurally remove content intersecting the marks
return { bytes: rewritten, removed: opsRemoved };
},
}));registerPdfiumAdapter is an exported alias of the same function —
use it when binding a native-engine (WASM) removal backend.
From the viewer
ViewerEngine exposes applyRedactions() which collects every
redaction-mark annotation, calls the engine, replaces the loaded
document with the burned bytes, and removes the marks from the
annotation manager.
const result = await engine.applyRedactions({ actor: currentUser });
console.log(result.objectsRemoved);The TruPDF document service
The reference adapter targets the TruPDF document service — a self-hosted container shipped with the distribution. Its burn pipeline runs a two-pass content-stream rewrite: pass 1 tags every text-showing operator whose glyph bbox intersects a redaction rect; pass 2 rewrites the page content stream removing those operators. A solid black rectangle is then drawn on top as a visual indicator, so the output is verifiably clean in any viewer.
docker compose --profile phase8 up -dIf the service runs with its shared-secret auth gate enabled, pass the
matching secret via the adapter's internalSecret option (sent as
X-TruPDF-Internal-Secret). A secret shipped to a browser app is
visible to end users — front the service with your own authenticated
proxy for stronger control.
Watermark
applyWatermark(input, { text, fontSize? = 60, rotation? = 30, opacity? = 0.18, color?, pages? })
draws into the page stream so the watermark survives flattening.
AuditLogger
Append-only event log. Events are frozen; subscribers forward to backend
storage via the appended event.