How the LGPD PDF Export Flow Uses LGPD_SIGNING_KEY and organizations.legal_name in DeskcommCRM

The LGPD PDF export flow embeds the organization's legal name in the document footer and conditionally applies a PAdES digital signature when the LGPD_SIGNING_KEY environment variable is configured, falling back to SHA‑256 integrity hashing when signing is unavailable.

The DeskcommCRM repository implements a legally‑compliant data export pipeline for Brazil's Lei Geral de Proteção de Dados (LGPD). This system ensures that every PDF export correctly identifies the data controller while providing cryptographic assurances through either PAdES signing or transparent unsigned warnings with hash verification.

Rendering the PDF with organizations.legal_name

The export process begins in lib/lgpd/pdf-renderer.tsx, where the React‑PDF component LgpdExportPdf constructs the final document. This component receives an ExportPayload object that includes organization_legal_name, populated directly from the organizations.legal_name database column.

Injecting the Controller Identity

The renderer explicitly guarantees that only the organization's registered legal name appears in the footer, preventing any white‑label branding from obscuring the data controller's identity. The implementation fixes the footer text using the fixed prop:

<View style={styles.footer} fixed>
  <Text>
    Controlador: {data.organization_legal_name || "—"} …
  </Text>
</View>

This pattern appears at lines 44‑48 of the renderer file, ensuring the PDF footer displays the controller name exactly as stored in the database schema. The pipeline deliberately separates this rendering logic from the signing layer to guarantee the legal attribution always succeeds regardless of cryptographic configuration.

Configuring Digital Signing with LGPD_SIGNING_KEY

The workers/lgpd-export-worker.ts orchestrator coordinates the signing phase by consulting lib/lgpd/pades-signer.ts to evaluate whether PAdES signing is available.

Detecting Signing Configuration

The isPadesConfigured() function checks for the presence and validity of the signing key:

export function isPadesConfigured(): boolean {
  const key = process.env.LGPD_SIGNING_KEY;
  return Boolean(key && key.length > 10);
}

When this function returns false, the worker instructs the renderer to display an unsigned warning banner. This banner, defined at lines 32‑38 of lib/lgpd/pdf-renderer.tsx, alerts recipients that the document lacks a PAdES signature. The design ensures the system never falsely claims a legally signed document when the LGPD_SIGNING_KEY is absent.

The PAdES Signing Implementation

When isPadesConfigured() returns true, the worker invokes signPdfPades(buffer) from lib/lgpd/pades-signer.ts. The current implementation operates as a stub that prepares for full PAdES compliance while maintaining audit trails.

Stub Behavior and Integrity Verification

Even when the signing key is present, the current code returns an unsigned result while logging a SHA‑256 hash for integrity verification:

export async function signPdfPades(buffer: Buffer): Promise<SignResult> {
  if (!isPadesConfigured()) {
    return {
      signed: buffer,
      sha256: sha256Hex(buffer),
      signed_pades: false,
      warning: "pades_key_missing",
    };
  }

  // TODO: real PAdES signing once a certificate is provisioned
  return {
    signed: buffer,
    sha256: sha256Hex(buffer),
    signed_pades: false,
    warning: "pades_key_missing",
  };
}

The function returns a SignResult object containing the buffer, its SHA‑256 hash, a boolean signed_pades flag, and an optional warning string. This result structure allows the worker at lines 172‑184 of workers/lgpd-export-worker.ts to store both the PDF and its integrity hash in Supabase storage, creating a verifiable audit trail regardless of signature status.

Complete Export Pipeline Architecture

The flow follows a strict separation between rendering and signing:

  1. Export Request: The worker receives a request containing the organization ID
  2. Data Collection: lib/lgpd/export-collector.ts (referenced but not shown) assembles the ExportPayload including organization_legal_name
  3. PDF Generation: renderLgpdPdf creates the buffer with the legal name fixed in the footer
  4. Signing Decision: isPadesConfigured() checks LGPD_SIGNING_KEY
  5. Signature Application: signPdfPades either stubs or (future) applies PAdES, always returning SHA‑256 hashes
  6. Storage: The resulting buffer and metadata upload to Supabase with signed download URLs

This architecture ensures that rendering succeeds independently of signing infrastructure, preventing system failures from blocking legally required data exports.

Practical Implementation Examples

Checking Signing Configuration

import { isPadesConfigured } from "@/lib/lgpd/pades-signer";

if (isPadesConfigured()) {
  console.log("PAdES signing will be attempted.");
} else {
  console.log("LGPD_SIGNING_KEY missing – PDF will carry an unsigned warning.");
}

Rendering with Conditional Warnings

import { renderLgpdPdf } from "@/lib/lgpd/pdf-renderer";
import { isPadesConfigured } from "@/lib/lgpd/pades-signer";

const pdfBuffer = await renderLgpdPdf(exportPayload, {
  unsignedWarning: !isPadesConfigured(),
});

Processing the Signature Result

import { signPdfPades } from "@/lib/lgpd/pades-signer";

const signResult = await signPdfPades(pdfBuffer);
console.log("SHA‑256:", signResult.sha256);
console.log("Signed?", signResult.signed_pades);

// Upload to Supabase
await admin.storage.upload(pdfPath, signResult.signed, {
  contentType: "application/pdf",
});

Summary

  • The organizations.legal_name value from the database populates the PDF footer via lib/lgpd/pdf-renderer.tsx, ensuring transparent identification of the data controller.
  • LGPD_SIGNING_KEY drives the isPadesConfigured() check in lib/lgpd/pades-signer.ts, determining whether the system attempts PAdES signing or adds an unsigned warning banner.
  • The current signPdfPades implementation provides SHA‑256 integrity hashing even when actual signing is stubbed, maintaining auditability.
  • The workers/lgpd-export-worker.ts orchestrates the complete flow, separating rendering concerns from cryptographic operations to guarantee export availability.

Frequently Asked Questions

What happens if LGPD_SIGNING_KEY is not set?

The PDF exports successfully but includes an unsigned warning banner in the rendered output. The signPdfPades function returns the original buffer with signed_pades: false and a SHA‑256 hash for integrity verification, stored alongside the document in Supabase for audit purposes.

The organization_legal_name field originates from the organizations.legal_name database column, passed through the ExportPayload interface defined in lib/lgpd/export-collector.ts. The React‑PDF component in lib/lgpd/pdf-renderer.tsx renders this value in the footer using a fixed position to prevent pagination issues.

Is the PAdES signing currently functional?

No. According to the source code in lib/lgpd/pades-signer.ts, the signPdfPades function contains a TODO comment indicating that real PAdES signing awaits certificate provisioning. The function currently returns the unsigned buffer with a SHA‑256 hash regardless of whether LGPD_SIGNING_KEY is present.

Where are the signed PDFs stored?

The workers/lgpd-export-worker.ts uploads the result to Supabase storage using the admin client, storing the buffer returned by signPdfPades along with its metadata. The worker then generates signed download URLs for secure recipient access, with the SHA‑256 hash preserved for integrity validation.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →