Handover workspace

ERS, Todo, OfferReview, and Docu in one view

Imported from live server docs, code structure, and deployment notes.

Apr 3, 2026, 12:38 PM

DocuHandshake

Backend Architecture — Reza DocuHandshake

The live backend is a single Node.js Express application in `server/`.

BACKEND_ARCHITECTURE.md

Updated Apr 1, 2026, 4:33 AM

Backend Architecture — Reza DocuHandshake

Overview

The live backend is a single Node.js Express application in server/.

There is no Supabase runtime in the current codebase. The backend is responsible for:

  • magic-link token creation and verification
  • session cookie issuance
  • document metadata storage in PostgreSQL
  • file persistence on the local filesystem
  • admin document listing and updates
  • signed-file uploads
  • email notifications
  • OpenAI-backed document analysis and signature helper endpoints
  • shared admin signature preset storage

Runtime Components

ConcernCurrent Implementation
HTTP serverExpress 5
DatabasePostgreSQL via pg
Auth tokensJWT via jsonwebtoken
Upload parsingMulter in memory
File storageLocal filesystem under STORAGE_ROOT
Email deliveryResend
AI analysisOpenAI gpt-4o-mini
Signature helper endpointOpenAI gpt-image-1, SVG fallback

Backend Module Map

  • server/index.ts
    • boots the API
    • enables CORS and cookie parsing
    • serves a small HTML utility page at /
    • mounts all /api/* routers
  • server/config.ts
    • environment parsing and defaults
  • server/db.ts
    • PostgreSQL pool and query helper
  • server/middleware/auth.ts
    • session-required user middleware
    • admin password validation helper
  • server/routes/auth.ts
    • magic-link request, verify, session, logout
  • server/routes/documents.ts
    • upload, owner/admin file streaming, public signed download
  • server/routes/admin.ts
    • admin listing, audit trail lookup, shared signature preset, document updates, signed-file upload, AI helpers
  • server/routes/notifications.ts
    • dispatches lifecycle emails
  • server/services/email.ts
    • Resend integration plus dev fallback logging
  • server/services/session.ts
    • JWT signing/verification for user sessions and download links
  • server/services/storage.ts
    • storage-root creation, safe path resolution, file writes/reads

Authentication Model

User Uploaders

  • Email address is submitted to POST /api/auth/magic-link/request
  • Backend stores a hashed token in magic_link_tokens
  • Resend email links back to /auth/verify?token=...
  • Successful verification sets the rdh_user_session cookie
  • Protected user routes rely on requireUser

Admin

  • Frontend gate compares the entered password to VITE_ADMIN_PASSWORD
  • Backend is the real enforcement layer and validates ADMIN_PASSWORD
  • Admin password can be provided via JSON body, query string, or x-admin-password header depending on the endpoint

Request Lifecycles

Upload Flow

  1. User uploads a PDF through POST /api/documents/upload
  2. Multer reads the file into memory
  3. Backend validates session, MIME type, and file size
  4. File is written to disk under documents/...
  5. Metadata is inserted into documents
  6. Audit row is inserted into document_audit_trail
  7. Notification email to Reza is attempted

Signing Flow

  1. Admin fetches the current PDF through GET /api/documents/:id/file
  2. Browser signs the PDF with pdf-lib
  3. Final signed PDF is uploaded to POST /api/admin/upload-signed-file
  4. POST /api/admin/update-document updates status, signed_at, signature_data, and file_path
  5. Notification route emails the signed file back to the uploader

Rejection Flow

  1. Admin updates the document through POST /api/admin/update-document
  2. Current UI sets status = 'completed'
  3. Audit trail records action = 'rejected'
  4. Notification route emails the rejection reason

Database and Storage

PostgreSQL

The backend stores:

  • document rows in documents
  • audit events in document_audit_trail
  • magic-link records in magic_link_tokens
  • shared settings in app_settings

documents.updated_at is maintained by a PostgreSQL trigger.

Filesystem Storage

Files are stored under the resolved STORAGE_ROOT path:

  • originals: documents/{timestamp}-{uuid}-{sanitized-name}
  • signed files: signed/{documentId}/{timestamp}_{sanitized-name}

The backend never stores absolute paths in the database. It stores relative paths and resolves them through resolveStoragePath().

Integrations and Fallbacks

Resend

  • Used for magic links, upload notifications, signed-document emails, and rejection emails
  • In development, if RESEND_API_KEY is missing, email sending is skipped and a warning is logged instead of crashing the request

OpenAI

  • POST /api/admin/analyze-document sends extracted PDF text to gpt-4o-mini
  • POST /api/admin/generate-signature can request a transparent signature image from gpt-image-1
  • If no OpenAI key is configured, generate-signature falls back to an inline SVG signature

Current Implementation Notes

  • The backend root / serves a simple HTML utility page for local inspection of key endpoints.
  • Signed files do not overwrite the original upload; a new signed file is written and documents.file_path is updated.
  • analyze-document, generate-signature, and notifications/send are currently callable without admin authentication.
  • There is no dedicated rejected document status in the schema; the UI uses completed plus an audit event.