DEV Community

DorianVale91583
DorianVale91583

Posted on

PDF Endpoints for Password-Protected Customer Files (Privacy Before Convenience)

Choose an asynchronous job endpoint with explicit deletion for most password-protected customer PDFs. Use a synchronous endpoint only for small, interactive documents with a firm latency budget; keep processing inside the customer's environment when policy forbids sending either the file or its password to a processor. For an edtech OCR pipeline, signature verification and an audit trail belong in the design from the first request.

Endpoint pattern Pick it when Fidelity and latency Privacy, retention, and operations
Synchronous upload and response A user is waiting and documents are predictably small Fastest path to the first answer, but bounded by one request Simple flow; cancellation, retries, and deletion still need explicit semantics
Asynchronous job Scans are large, multi-page, or variable Preserves room for richer OCR and page rendering; completion is polled or delivered later Best place for per-stage audit events and retention states; adds a job state machine
Customer-environment processing Files or passwords cannot cross the customer's boundary Network transfer is removed from the critical path, while local compute sets throughput Strongest data-location control; deployment, upgrades, and observability become shared work

This isn't a leaderboard.

It is a boundary decision. The table should eliminate one option before anyone compares OCR output: ask where plaintext may exist, how long encrypted input may remain, and who must prove deletion.

How should a US/EU SaaS choose PDF endpoints for password-protected customer files?

Start with the data boundary, then test fidelity and latency inside it. A US/EU SaaS may have different customer contracts and deployment regions, so one global default can hide the real constraint. Record the permitted processing region, maximum retention, password-handling rule, and deletion deadline as tenant policy. Legal review must supply those values; the endpoint should enforce them. I'm not sure any generic checklist can settle a particular customer's obligations without that contract and review. For the common hosted case, choose the asynchronous pattern. The request returns an opaque job identifier, and the worker moves through named states such as accepted, decrypting, rendering, recognizing, verifying, and complete. The audit record should capture state transitions, actor or service identity, timestamps, a document digest, policy version, and result location. It should not capture the password or extracted student text. Short-lived credentials should be passed only to the component that opens the document, kept out of logs, and discarded when that step ends. Pick synchronous processing when the product interaction truly depends on an immediate response and the accepted file envelope is narrow enough to enforce. Publish hard limits for bytes, pages, and request duration. On timeout, don't make the client guess whether another upload is safe: define an idempotency key and a status lookup in the contract. A two-call flow can still feel immediate while avoiding duplicate OCR work.

Customer-environment processing is the right change of direction when policy prohibits external transfer. The catch is operational ownership. Stick with hosted asynchronous jobs when the customer accepts the processing boundary and your team needs one controlled deployment; choose the customer-managed option when data-location control outweighs the extra release, telemetry, and support work.

Make the asynchronous contract auditable

A useful contract separates control data from document bytes. Submission accepts the encrypted PDF plus policy metadata. Status returns state and timestamps, not OCR text. Result retrieval is separately authorized. Deletion has its own acknowledged state so that a successful OCR result cannot be mistaken for proof that source bytes were removed.

Diagram in words: browser creates a file object -> upload boundary computes a digest -> encrypted object storage holds the source -> an isolated opener receives the password -> renderer emits page images -> OCR emits text and confidence data -> verifier checks the signed manifest -> result storage publishes the artifact -> retention worker deletes source and intermediate objects -> audit storage records each transition. Keep the password off every arrow except the one into the isolated opener.

The browser Blob interface is a clean handoff for file bytes: MDN describes a Blob as file-like, immutable raw data and documents methods such as arrayBuffer(), stream(), and slice(). That makes it useful at the client boundary without implying anything about server retention. A blob existing in browser memory is not a deletion guarantee for a remote copy.

This TypeScript sketch keeps transport details behind an interface, which lets a team test policy behavior without pretending that every processor uses the same URL layout:

type Region = "us" | "eu";
type JobState =
  | "accepted"
  | "decrypting"
  | "rendering"
  | "recognizing"
  | "verifying"
  | "complete"
  | "deleted";

type Submission = {
  file: Blob;
  password: string;
  region: Region;
  retentionSeconds: number;
  idempotencyKey: string;
};

type JobReceipt = {
  jobId: string;
  sourceDigest: string;
  state: JobState;
};

interface PdfOcrEndpoint {
  submit(input: Submission): Promise<JobReceipt>;
  status(jobId: string): Promise<{ state: JobState; changedAt: string }>;
  result(jobId: string): Promise<Blob>;
  erase(jobId: string): Promise<{ state: "deleted"; changedAt: string }>;
}

async function digest(file: Blob): Promise<string> {
  const bytes = await file.arrayBuffer();
  const hash = await crypto.subtle.digest("SHA-256", bytes);
  return Array.from(new Uint8Array(hash), byte =>
    byte.toString(16).padStart(2, "0"),
  ).join("");
}
Enter fullscreen mode Exit fullscreen mode

One caution: retentionSeconds is a requested policy, not evidence of deletion. Evidence comes from the endpoint's deletion acknowledgement plus your independently stored transition record. Sign the audit manifest after each append or sign a final manifest that covers the ordered event digests; verification should fail closed when the manifest, source digest, policy version, and result digest don't agree. The signing key should be separate from the worker credentials, because a worker that can rewrite both an artifact and its history has defeated the point of the trail.

Test fidelity, latency, and privacy as separate budgets

A single pass rate hides the failures that matter. Build a representative corpus with clean digital PDFs, skewed scans, faint worksheets, mixed orientations, tables, handwriting, and password-protected samples. Keep expected text and page structure under version control where policy permits. Compare candidate endpoint patterns with the same corpus and the same acceptance rules.

For fidelity, score character or word error, reading order, page count, table structure, and whether visible signatures remain associated with the correct page. A cryptographic signature and a handwritten mark are different test subjects: one concerns integrity metadata, while the other is page content that rendering and OCR must preserve. Define which kind the product promises before selecting an endpoint.

For latency, report a distribution rather than one average. Separate upload, queue, decrypt, render, OCR, verification, and result-fetch time.

The slow stage then has an owner.

Measure cold and warm runs, concurrency, and the largest supported document, but don't publish a universal target without workload evidence; your mileage may vary with scan resolution and page complexity.

Privacy tests should be blunt. Search application logs, traces, metrics labels, dead-letter payloads, and audit events for seeded passwords and extracted text. Confirm that cancellation and failure enter retention cleanup, not only successful completion. Then verify the deletion acknowledgement and attempt an authorized result read after the promised deadline.

No result should be returned.

Keep the observability labels boring: region, job state, page-count band, policy version, and normalized failure class. Document identifiers, filenames, passwords, and OCR text don't belong in metric dimensions. Alert on growing queue age, jobs stalled beyond a state budget, signature-verification failures, and deletion acknowledgements overdue against policy. This is where an asynchronous design earns its extra machinery — each stage is visible without exposing customer content.

Know when each endpoint pattern is the wrong fit

Synchronous endpoints are not suitable when upload plus OCR can exceed the request budget, when retries may duplicate work, or when deletion must be independently tracked. Asynchronous jobs are a poor fit for a tiny interaction that cannot tolerate polling or delayed completion. Customer-environment processing is the wrong default when the team cannot support distributed upgrades, key rotation, and diagnostic collection across customer installations.

There is no free option.

More fidelity can require higher-resolution rendering and more processing time. Lower latency can narrow the accepted document envelope. Stronger isolation can increase deployment complexity. Choose the privacy boundary first, make retention a state transition rather than prose in a policy, and use measured corpus results to decide the remaining trade-offs.

References

Further reading

Top comments (0)