Artykuł techniczny

PDFlibPas: compliance and signing workbench in Delphi

losLab PDF Library zapewnia zespołom Delphi i C++Builder silnik PDF z dostępnym kodem źródłowym dla przepływów desktopowych, serwerowych, DLL, ActiveX i Dylib, z wbudowanymi kontrolami PDF/A i PDF/UA, podpisami PAdES oraz wyborem renderera bez wysyłania dokumentów do zewnętrznej usługi PDF.

Ten artykuł jest przeznaczony dla teams combining validation, remediation, signature preparation, and evidence review in one Delphi workflow. Traktuje compliance and signing workbench jako produkcyjną inżynierię dokumentów, a nie pojedyncze wywołanie komponentu.

Praktyczne ryzyko polega na tym, że separate validation and signing tools can disagree about the document state, leaving operators unsure which revision was checked and which revision was signed. Dlatego przepływ wymaga spisanego kontraktu, obserwowalnej diagnostyki i realistycznych plików regresyjnych.

Decyzje architektoniczne

Use one workbench record for the document lifecycle. validation profiles required before signing and after signing / remediation actions allowed inside the workbench versus upstream templates

  • validation profiles required before signing and after signing
  • remediation actions allowed inside the workbench versus upstream templates
  • certificate source, timestamp authority, revocation source, and operator roles
  • waiver workflow for compliance warnings that do not block signing

Przebieg implementacji

Validate before the signing revision is created. Poniższa kolejność zachowuje czytelność przepływu pracy dla zespołów Delphi i C++Builder.

  1. create a workbench record and hash the source file before analysis
  2. run compliance validation and classify findings into fix, waive, or block
  3. apply approved remediation before the signature field is reserved
  4. sign the validated revision and immediately run post-sign validation
  5. package reports, hashes, certificate data, and operator decisions together

Dowody walidacji

Workbench evidence that survives audit. Zachowaj te pola wraz z wynikiem lub rekordem wsparcia.

  • source hash, validation profile, issue summary, remediation list, and waiver list
  • certificate fingerprint, timestamp result, revocation status, and signer identity
  • pre-sign and post-sign validation reports with matching document references
  • final file hash and workbench decision trail

Validation and signing must agree on bytes

A compliance and signing workbench should tie the input hash, validation profile, remediation decisions, signing certificate, timestamp, and final validation result together. Without that chain, a signed file can be difficult to explain later.

Operational metrics to watch

The first release should expose enough metrics to prove the workflow is healthy under real files, not only under curated samples.

  • count and rate for source hash, validation profile, issue summary, remediation list, and waiver list
  • warning trend for fixing compliance issues after signing changes the revision that was trusted
  • latency of the stage that must create a workbench record and hash the source file before analysis
  • profile usage for validation profiles required before signing and after signing

Notatki przeglądu inżynierskiego dla compliance and signing workbench

Użyj tych notatek przeglądu, aby upewnić się, że funkcja wyszła poza demonstrację i da się ją obronić podczas wydania, wsparcia i eskalacji klienta.

  • Decyzja: validation profiles required before signing and after signing. Punkt nacisku implementacji: run compliance validation and classify findings into fix, waive, or block. Dowody akceptacji: pre-sign and post-sign validation reports with matching document references. Wyzwalacz regresji: operators need a clear blocked state when the source cannot be trusted
  • Decyzja: remediation actions allowed inside the workbench versus upstream templates. Punkt nacisku implementacji: apply approved remediation before the signature field is reserved. Dowody akceptacji: final file hash and workbench decision trail. Wyzwalacz regresji: fixing compliance issues after signing changes the revision that was trusted
  • Decyzja: certificate source, timestamp authority, revocation source, and operator roles. Punkt nacisku implementacji: sign the validated revision and immediately run post-sign validation. Dowody akceptacji: source hash, validation profile, issue summary, remediation list, and waiver list. Wyzwalacz regresji: waivers should identify an owner and expiry rather than becoming permanent silence
  • Decyzja: waiver workflow for compliance warnings that do not block signing. Punkt nacisku implementacji: package reports, hashes, certificate data, and operator decisions together. Dowody akceptacji: certificate fingerprint, timestamp result, revocation status, and signer identity. Wyzwalacz regresji: timestamp services and validators may fail independently of PDF generation

Przypadki brzegowe

  • fixing compliance issues after signing changes the revision that was trusted
  • waivers should identify an owner and expiry rather than becoming permanent silence
  • timestamp services and validators may fail independently of PDF generation
  • operators need a clear blocked state when the source cannot be trusted

Delphi / C++Builder notes

PDFlibPas should sit behind a small service boundary that receives files, streams, profiles, and credentials, then returns output paths, warnings, metrics, and validation status. Important terms include compliance, PAdES, preflight, timestamp, waiver, validation report.

Przykład kodu Delphi

Poniższy szkic Delphi pokazuje praktyczną granicę usługi dla tego tematu. Kontrole zasad, logowanie i walidację trzymaj poza wąskim blokiem wywołań produktu, aby przepływ pozostał testowalny.

procedure RunComplianceSigningJob(const InputFile, OutputFile: string; const Policy: TSigningPolicy);
var
  Pdf: TPDFlib;
begin
  Pdf := TPDFlib.Create;
  try
    Pdf.LoadFromFile(InputFile, Policy.OpenPassword);
    PrepareComplianceEvidence(Pdf, Policy);
    CompleteSigningWorkflow(Pdf, OutputFile, Policy);
    ValidateSignedOutput(OutputFile, Policy.ProfileName);
  finally
    Pdf.Free;
  end;
end;

Lista produkcyjna

  • Uruchom przepływ pracy na pustym pliku, zwykłym pliku klienta i pliku z najgorszego scenariusza
  • Otwórz wygenerowany plik PDF w docelowej przeglądarce, walidatorze, drukarce lub aplikacji nadrzędnej
  • Zaloguj wersję produktu, wersję profilu, hash wejścia, ścieżkę wyjścia, czas wykonania i liczbę ostrzeżeń
  • Przechowuj hasła, certyfikaty, pliki tymczasowe i dane klienta zgodnie z jednoznacznymi zasadami retencji
  • Dodaj dokument regresyjny, gdy plik klienta ujawni nowy przypadek brzegowy

Dokumentacja produktu

PDFlibPas

Dodatkowe przykłady kodu

ProcessID := PDF.NewSignProcessFromFile('invoice-fixed.pdf', '');
if ProcessID = 0 then
  raise Exception.Create('Cannot open source for signing');
PDF.SetSignProcessField(ProcessID, 'ApprovalSig');
PDF.SetSignProcessPFXFromFile(ProcessID, 'company.pfx', PfxPassword);
PDF.SetSignProcessInfo(ProcessID, 'Invoice approval', 'Berlin', 'billing@example.com');
PDF.SetSignProcessCustomSubFilter(ProcessID, 'ETSI.CAdES.detached');  // PAdES baseline
PDF.SetSignProcessDigestAlgorithm(ProcessID, 2);                      // SHA-256
PDF.SetSignProcessReserveContentsBytes(ProcessID, 8192);              // room for a later timestamp
PDF.EndSignProcessToFile(ProcessID, 'invoice-signed.pdf');
if PDF.GetSignProcessResult(ProcessID) <> 1 then
  Writeln('Sign failed, code ', PDF.GetSignProcessResult(ProcessID));
PDF.ReleaseSignProcess(ProcessID);
var
  Doc: TPDFlibSignDoc;
  Names: TStringList;
  FS: TFileStream;
  I: Integer;
  SourceSize, RangeStart, GapStart, TailStart, TailLen: Int64;
begin
  // Capture the size before Open: the audit object holds a share lock on the file
  FS := TFileStream.Create('invoice-signed.pdf', fmOpenRead or fmShareDenyNone);
  SourceSize := FS.Size;
  FS.Free;
  Doc := TPDFlibSignDoc.Create;
  Names := TStringList.Create;
  try
    if not Doc.Open('invoice-signed.pdf', '', False) then Exit;
    Doc.GetSignatureFieldNames(Names);
    for I := 0 to Names.Count - 1 do
      if Doc.GetSignatureValueObjNum(Names[I]) > 0 then  // > 0 means the field is signed
      begin
        RangeStart := StrToInt64(string(Doc.GetSignatureValueByName(Names[I], 11)));
        GapStart   := StrToInt64(string(Doc.GetSignatureValueByName(Names[I], 12)));
        TailStart  := StrToInt64(string(Doc.GetSignatureValueByName(Names[I], 13)));
        TailLen    := StrToInt64(string(Doc.GetSignatureValueByName(Names[I], 14)));
        if (RangeStart = 0) and (TailStart + TailLen = SourceSize) then
          Writeln(Names[I], ': signature covers the file to EOF')
        else
          Writeln(Names[I], ': earlier revision, or unusual ByteRange layout');
      end;
    Doc.Close;
  finally
    Names.Free;
    Doc.Free;
  end;
end;