JOB-EASY

Resumes

Secure object storage, signed URL delivery, and cryptographically safe public sharing.

The resumes feature slice owns the uploading, versioning, and secure delivery of candidate resumes. Because these files contain highly sensitive PII (addresses, phone numbers, employment history), the slice enforces a strict security posture around asset delivery.

Secure Object Storage

The Resume model stores metadata like the original fileName and mimeType, but the file itself lives in a Cloudinary object storage bucket.

Authenticated-Only Storage

Resumes are uploaded to Cloudinary specifically as authenticated asset types. This means that if an attacker were to guess the storageKey and construct a bare Cloudinary URL, the CDN will explicitly return a 401 Unauthorized. The file can only be downloaded via a short-lived signed URL minted server-side by our application.

The standard /api/resumes/[id]/download route enforces strict session ownership. If the authenticated user does not own the resume, the request is instantly rejected before the storage key is even queried.

Public Share Links

Often, users need to generate a link to share their resume externally. This is handled by a specialized shareToken mechanism.

Historically, applications might attempt to use the row's database ID (like a CUID) as the public share URL (e.g. /api/resumes/[cuid]/public). This is dangerous. A CUID v1 is heavily composed of a millisecond timestamp, a counter, and a host fingerprint. They are predictable. If an attacker knew roughly when a resume was uploaded, they could enumerate CUIDs to scrape sensitive PII.

The Cryptographic Token

To solve this enumeration vulnerability, the schema uses a dedicated shareToken field: 32 CSPRNG (Cryptographically Secure Pseudorandom Number Generator) bytes encoded as base64url.

  • Unguessable: True entropy prevents enumeration attacks.
  • Revocable: A user can disable the share link by simply nulling the shareToken, without having to delete the underlying resume.
  • Expirable: The token optionally supports an expiration timestamp (shareExpiresAt).

The /api/resumes/[token]/public route is the only endpoint specifically exempted from the standard authentication proxy guard, allowing recruiters to download the asset securely without a session.