diff --git a/DocumentOperator.Application/Common/Configurations/Pkcs11Options.cs b/DocumentOperator.Application/Common/Configurations/Pkcs11Options.cs
new file mode 100644
index 0000000..7ed64e6
--- /dev/null
+++ b/DocumentOperator.Application/Common/Configurations/Pkcs11Options.cs
@@ -0,0 +1,94 @@
+using DocumentOperator.Application.Common.Enums;
+using System.ComponentModel.DataAnnotations;
+
+namespace DocumentOperator.Application.Common.Configurations;
+
+///
+/// Represents PKCS#11 signing configuration for PDF signing workflows.
+/// This options model maps to the Crypt:Pkcs11 configuration section.
+///
+public sealed class Pkcs11Options
+{
+ ///
+ /// Configuration section path used for binding PKCS#11 options.
+ ///
+ public const string SectionName = "Crypt:Pkcs11";
+
+ ///
+ /// Optional base directory that contains the pkcs11 folder.
+ /// If null/empty, runtime uses the application base directory.
+ ///
+ public string? AssetsRootPath { get; set; }
+
+ ///
+ /// Optional numeric slot identifier used to directly select the target token slot.
+ ///
+ public ulong? SlotId { get; set; }
+
+ ///
+ /// Optional token label used as a fallback token selector when is not provided.
+ ///
+ public string? TokenLabel { get; set; }
+
+ ///
+ /// Optional PKCS#11 proxy endpoint (for example tcp://host:port).
+ ///
+ public string? ProxySocket { get; set; }
+
+ ///
+ /// Resolved absolute PKCS#11 proxy module path used at runtime.
+ /// Computed from and runtime defaults.
+ ///
+ public string ResolvedLibraryPath { get; private set; } = string.Empty;
+
+ ///
+ /// Resolved absolute pkcs11-tool path used at runtime.
+ /// Computed from and runtime defaults.
+ /// Can be null when tool fallback is not available.
+ ///
+ public string? ResolvedToolPath { get; private set; }
+
+ public void SetResolvedPaths(string resolvedLibraryPath, string? resolvedToolPath)
+ {
+ ResolvedLibraryPath = resolvedLibraryPath;
+ ResolvedToolPath = resolvedToolPath;
+ }
+
+ ///
+ /// User PIN used to authenticate to the PKCS#11 token session.
+ ///
+ [Required]
+ [MinLength(1)]
+ public required string UserPin { get; set; }
+
+ ///
+ /// Label of the private key object used to create digital signatures.
+ ///
+ [Required]
+ [MinLength(1)]
+ public required string PrivateKeyLabel { get; set; }
+
+ ///
+ /// Label of the certificate object returned/embedded with the signature.
+ ///
+ [Required]
+ [MinLength(1)]
+ public required string CertificateLabel { get; set; }
+
+ ///
+ /// Optional global default signing reason used when request-level options do not specify a value.
+ ///
+ public string? DefaultReason { get; set; }
+
+ ///
+ /// Application name embedded into PDF signature metadata.
+ /// This value is controlled via app settings and is not client-overridable.
+ ///
+ public string? ApplicationName { get; set; }
+
+ ///
+ /// Controls how fallback signing time is created when request-level options do not specify a value.
+ /// true uses , false uses .
+ ///
+ public bool UseUtcSigningTime { get; set; } = true;
+}
diff --git a/DocumentOperator.Application/Common/Dto/PdfSignOptionsDto.cs b/DocumentOperator.Application/Common/Dto/PdfSignOptionsDto.cs
new file mode 100644
index 0000000..47d5e27
--- /dev/null
+++ b/DocumentOperator.Application/Common/Dto/PdfSignOptionsDto.cs
@@ -0,0 +1,54 @@
+using DocumentOperator.Application.Common.Enums;
+
+namespace DocumentOperator.Application.Common.Dto;
+
+///
+///
+///
+public sealed record PdfSignOptionsDto
+{
+ ///
+ ///
+ ///
+ public long DocumentElementId { get; set; }
+
+ ///
+ ///
+ ///
+ public string Name { get; set; } = null!;
+
+ ///
+ ///
+ ///
+ public string Reason { get; set; } = null!;
+
+ ///
+ ///
+ ///
+ public string Location { get; set; } = null!;
+
+ ///
+ ///
+ ///
+ public string? Email { get; set; }
+
+ ///
+ ///
+ ///
+ public string? Phone { get; set; }
+
+ ///
+ ///
+ ///
+ public string ApplicationName { get; set; } = null!;
+
+ ///
+ ///
+ ///
+ public PdfSignatureCertificationLevel CertificationLevel { get; set; }
+
+ ///
+ ///
+ ///
+ public PdfSignatureAppearanceDto? Appearance { get; set; }
+}
diff --git a/DocumentOperator.Application/Common/Dto/PdfSignatureAppearanceDto.cs b/DocumentOperator.Application/Common/Dto/PdfSignatureAppearanceDto.cs
new file mode 100644
index 0000000..4497d36
--- /dev/null
+++ b/DocumentOperator.Application/Common/Dto/PdfSignatureAppearanceDto.cs
@@ -0,0 +1,96 @@
+namespace DocumentOperator.Application.Common.Dto;
+
+///
+///
+///
+public enum PdfSignatureCoordinateUnit
+{
+ ///
+ ///
+ ///
+ Point = 0,
+
+ ///
+ ///
+ ///
+ Inch = 1
+}
+
+///
+///
+///
+public enum PdfSignatureCoordinateOrigin
+{
+ ///
+ ///
+ ///
+ BottomLeft = 0,
+
+ ///
+ ///
+ ///
+ TopLeft = 1
+}
+
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+public sealed record PdfSignatureAppearanceDto(
+ int PageNumber,
+ double Left,
+ double Bottom,
+ double Width,
+ double Height,
+ bool ShowLabels = false,
+ bool ShowName = false,
+ bool ShowDate = false,
+ bool ShowReason = false,
+ bool ShowLocation = false,
+ bool ShowDistinguishedName = false,
+ string DateTimeFormat = "dd.MM.yyyy HH:mm:ss zzz",
+ PdfSignatureCoordinateUnit CoordinateUnit = PdfSignatureCoordinateUnit.Point,
+ PdfSignatureCoordinateOrigin CoordinateOrigin = PdfSignatureCoordinateOrigin.BottomLeft)
+{
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public sealed record FontDto(string FamilyName = "Helvetica", float Size = 10, bool IsBold = false, bool IsItalic = false, bool IsUnderline = false)
+ {
+ ///
+ ///
+ ///
+ public RgbaColorDto Color { get; init; } = new();
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public sealed record RgbaColorDto(double R = 0, double G = 0, double B = 0);
+
+ ///
+ ///
+ ///
+ public FontDto Font { get; init; } = new();
+}
diff --git a/DocumentOperator.Application/Common/Dto/PdfSignatureCheckResultDto.cs b/DocumentOperator.Application/Common/Dto/PdfSignatureCheckResultDto.cs
new file mode 100644
index 0000000..2aa4575
--- /dev/null
+++ b/DocumentOperator.Application/Common/Dto/PdfSignatureCheckResultDto.cs
@@ -0,0 +1,57 @@
+namespace DocumentOperator.Application.Common.Dto;
+
+public sealed record PdfSignaturePrincipalDto(
+ string? CommonName,
+ string? Organization,
+ string? Country,
+ string? Full);
+
+public sealed record PdfSignatureCertificateInfoDto(
+ PdfSignaturePrincipalDto IssuedTo,
+ PdfSignaturePrincipalDto IssuedBy,
+ string? SerialNumber,
+ DateTimeOffset? ValidFrom,
+ DateTimeOffset? ValidTo,
+ bool SelfSigned,
+ bool Expired,
+ bool NotYetValid,
+ bool IsSigner,
+ int? Version,
+ string? KeyAlgorithm,
+ string? SignatureAlgorithm,
+ string? Pem,
+ int? KeySizeBits);
+
+public sealed record PdfSignatureCheckItemDto(
+ bool CoversWholeDoc,
+ string? Reason,
+ string? BusinessReason,
+ string? Location,
+ string? DeclaredName,
+ string? ContactInfo,
+ string? Email,
+ string? Phone,
+ string? DigestAlgorithm,
+ string? SignatureAlgorithm,
+ string? SignerName,
+ string? Issuer,
+ string? SerialNumber,
+ DateTimeOffset? ValidFrom,
+ DateTimeOffset? ValidTo,
+ string ExpiryCheckedAgainst,
+ IReadOnlyList Certificates,
+ bool Unchanged,
+ string? FieldName,
+ bool IsCryptographicallyValid,
+ string? SigningTime,
+ string? Filter,
+ string? SubFilter,
+ string? ApplicationName,
+ long? DocumentElementId,
+ string? OriginalDocumentSha256,
+ string? MessageDigestHex,
+ string? Error);
+
+public sealed record PdfSignatureCheckResultDto(
+ bool Signed,
+ IReadOnlyList Signatures);
diff --git a/DocumentOperator.Application/Common/Dto/Pkcs11SelfTestStatusDto.cs b/DocumentOperator.Application/Common/Dto/Pkcs11SelfTestStatusDto.cs
new file mode 100644
index 0000000..81751f8
--- /dev/null
+++ b/DocumentOperator.Application/Common/Dto/Pkcs11SelfTestStatusDto.cs
@@ -0,0 +1,10 @@
+namespace DocumentOperator.Application.Common.Dto;
+
+public sealed record Pkcs11SelfTestStatusDto(
+ bool Completed,
+ bool Success,
+ string Mode,
+ string Summary,
+ DateTimeOffset? CheckedAtUtc,
+ string? InteropError,
+ string? ToolError);
diff --git a/DocumentOperator.Application/Common/Enums/PdfSignatureCertificationLevel.cs b/DocumentOperator.Application/Common/Enums/PdfSignatureCertificationLevel.cs
new file mode 100644
index 0000000..d8078e9
--- /dev/null
+++ b/DocumentOperator.Application/Common/Enums/PdfSignatureCertificationLevel.cs
@@ -0,0 +1,27 @@
+namespace DocumentOperator.Application.Common.Enums;
+
+///
+///
+///
+public enum PdfSignatureCertificationLevel
+{
+ ///
+ /// All changes are allowed
+ ///
+ NoCertification = 0,
+
+ ///
+ /// No changes are allowed
+ ///
+ NoChangesAllowed,
+
+ ///
+ /// Allows users to fill in forms and sign the document.
+ ///
+ FillForms,
+
+ ///
+ /// Allows users to fill in forms, create, modify and delete annotations, and sign the document.
+ ///
+ FillFormsAndAnnotate
+}
diff --git a/DocumentOperator.Application/Common/Interfaces/Services/IPdfDigitalSignatureService.cs b/DocumentOperator.Application/Common/Interfaces/Services/IPdfDigitalSignatureService.cs
new file mode 100644
index 0000000..5dc5fdb
--- /dev/null
+++ b/DocumentOperator.Application/Common/Interfaces/Services/IPdfDigitalSignatureService.cs
@@ -0,0 +1,29 @@
+using DocumentOperator.Application.Common.Dto;
+
+namespace DocumentOperator.Application.Common.Interfaces.Services;
+
+///
+/// Defines PDF digital-signing operations for the application boundary.
+///
+public interface IPdfDigitalSignatureService
+{
+ ///
+ /// Creates a digital signature for the provided PDF bytes and returns
+ /// a new signed PDF document.
+ ///
+ /// Source PDF content stream.
+ /// Destination stream for signed PDF output.
+ /// Optional signing options that map to PDF signature metadata fields.
+ /// Optional image stream for signature appearance.
+ /// Cancellation token for cooperative cancellation.
+ Task SignPdfAsync(Stream inputPdf, Stream outputPdf, PdfSignOptionsDto? options = null, Stream? image = null, CancellationToken cancellationToken = default);
+
+ ///
+ /// Checks whether the provided PDF contains signature field(s) and whether
+ /// those signatures are cryptographically valid.
+ ///
+ /// PDF content stream to inspect.
+ /// Cancellation token for cooperative cancellation.
+ /// A structured result containing signature presence and per-signature details.
+ Task CheckPdfSignatureAsync(Stream inputPdf, CancellationToken cancellationToken = default);
+}
diff --git a/DocumentOperator.Application/Common/Interfaces/Services/IPkcs11SelfTestStatusProvider.cs b/DocumentOperator.Application/Common/Interfaces/Services/IPkcs11SelfTestStatusProvider.cs
new file mode 100644
index 0000000..7633b1d
--- /dev/null
+++ b/DocumentOperator.Application/Common/Interfaces/Services/IPkcs11SelfTestStatusProvider.cs
@@ -0,0 +1,8 @@
+using DocumentOperator.Application.Common.Dto;
+
+namespace DocumentOperator.Application.Common.Interfaces.Services;
+
+public interface IPkcs11SelfTestStatusProvider
+{
+ Pkcs11SelfTestStatusDto GetStatus();
+}
diff --git a/DocumentOperator.Application/DependencyInjection.cs b/DocumentOperator.Application/DependencyInjection.cs
new file mode 100644
index 0000000..a5087ae
--- /dev/null
+++ b/DocumentOperator.Application/DependencyInjection.cs
@@ -0,0 +1,18 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace DocumentOperator.Application;
+
+public static class DependencyInjection
+{
+ public static IServiceCollection AddDocumentOperatorApplication(this IServiceCollection services, IConfiguration configuration)
+ {
+ services.AddMediatR(cfg =>
+ {
+ cfg.LicenseKey = configuration.GetValue("LuckyPennySoftLicenseKey");
+ cfg.RegisterServicesFromAssembly(typeof(DependencyInjection).Assembly);
+ });
+
+ return services;
+ }
+}
diff --git a/DocumentOperator.Application/DocumentOperator.Application.csproj b/DocumentOperator.Application/DocumentOperator.Application.csproj
new file mode 100644
index 0000000..dd6be39
--- /dev/null
+++ b/DocumentOperator.Application/DocumentOperator.Application.csproj
@@ -0,0 +1,15 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
diff --git a/DocumentOperator.Application/SignPdf/SignPdfCommand.cs b/DocumentOperator.Application/SignPdf/SignPdfCommand.cs
new file mode 100644
index 0000000..d88967a
--- /dev/null
+++ b/DocumentOperator.Application/SignPdf/SignPdfCommand.cs
@@ -0,0 +1,22 @@
+using DocumentOperator.Application.Common.Dto;
+using DocumentOperator.Application.Common.Interfaces.Services;
+using MediatR;
+
+namespace DocumentOperator.Application.SignPdf;
+
+public sealed record SignPdfCommand : IRequest
+{
+ public required Stream InputPdf { get; init; }
+ public required PdfSignOptionsDto Options { get; init; }
+ public Stream? SignatureImage { get; init; }
+}
+
+public sealed class SignPdfCommandHandler(IPdfDigitalSignatureService signer) : IRequestHandler
+{
+ public async Task Handle(SignPdfCommand command, CancellationToken cancellationToken)
+ {
+ using var output = new MemoryStream();
+ await signer.SignPdfAsync(command.InputPdf, output, command.Options, command.SignatureImage, cancellationToken);
+ return output.ToArray();
+ }
+}