Manager
The Manager is the core service of AI Smart Redact. It exposes the Manager API, persists job state in a database, encrypts files at rest, and dispatches detection and redaction work to the Worker. Set environment variables on the Manager container to configure it; the default port is 9982. For the naming convention and shared notes, refer to Configuration reference.
Default appsettings.json
{
"Database": {
"DatabaseType": "SqlLite"
},
"FileStorage": {
"FileStorageType": "HostFileSystem",
"FilesDirectoryPath": "/app/storage_folder"
},
"Encryption": {
"EncryptionKey": "<ENCRYPTION_KEY>",
"DekTokenTtlMinutes": 1440
},
"ServiceCommunication": {
"ServiceCommunicationType": "Rest",
"ConnectionString": "http://localhost:4885/"
},
"JobOptions": {
"TimeoutMinutes": 60
},
"Licensing": {
"LicenseKey": "<LICENSE_KEY>",
"LgsURL": ""
},
"WebServer": {
"PortNumber": 9982,
"MaxFileSizeBytes": 104857600,
"MaxConcurrentConnections": 1000,
"RequestHeadersTimeout": null,
"KeepAliveTimeout": null,
"MinRequestBodyDataRateBytesPerSecond": null,
"MinRequestBodyDataRateGracePeriod": null
},
"LogFilePath": "./logs/smart-redact-manager-log.txt",
"LogRetentionDays": 7
}
Each section is described below.
Licensing
AI Smart Redact requires a valid license key. The Manager performs soft validation: it starts even with a missing or invalid key, but rejects API requests with 403 Forbidden until a valid key is configured.
Licensing__LicenseKey=<LICENSE_KEY>
| Setting | Default | Description |
|---|---|---|
LicenseKey | required | The AI Smart Redact license key issued by Pdftools. |
LgsURL | — | Optional URL of an on-premise License Gateway Service for air-gapped deployments. |
Database
The Manager stores job and file metadata in a relational database. The Database section selects the engine and provides a connection string.
Database__DatabaseType=PostgreSql
Database__ConnectionString=Host=...;Database=...;Username=...;Password=...
| Setting | Default | Description |
|---|---|---|
DatabaseType | required | One of PostgreSql, SqlLite. |
ConnectionString | required (except SqlLite) | Provider-specific connection string. |
File storage
PDFs uploaded through the Manager API and the FDF and redacted-PDF outputs produced by jobs are persisted to a file store. The Worker reads from and writes to the same store, so the Manager and Worker must share the FileStorage configuration.
FileStorage__FileStorageType=AwsS3
FileStorage__ConnectionString=<BUCKET_NAME>;<REGION>
| Setting | Default | Description |
|---|---|---|
FileStorageType | required | One of HostFileSystem, AwsS3, MinIO. |
ConnectionString | required for AwsS3, MinIO | Backend-specific connection string. Format depends on FileStorageType. |
FilesDirectoryPath | required for HostFileSystem | Filesystem path used when FileStorageType is HostFileSystem. |
Connection string formats
AwsS3:<BUCKET_NAME>;<REGION>(or the full formaws.s3://bucket=<BUCKET_NAME>;region=<REGION>).MinIO:minio.s3://keyId=<MINIO_ACCESS_KEY>;key=<MINIO_SECRET_KEY>;bucket=<BUCKET_NAME>;serviceUrl=<MINIO_URL>(oraws.s3://keyId=<MINIO_ACCESS_KEY>;key=<MINIO_SECRET_KEY>;bucket=<BUCKET_NAME>;serviceUrl=<MINIO_URL>). The MinIO secret key parameter is namedkey=, matching the underlying S3 client.HostFileSystem: not used; configureFilesDirectoryPathinstead.
Encryption
Files at rest are encrypted with AES-256-GCM. The Manager wraps each file’s data encryption key (DEK) in a short-lived, AES-GCM-encrypted token, the DEK token, returned to the client at upload time; subsequent operations on the file require the token. The Worker uses the same Encryption configuration as the Manager: both services must agree on the key.
Encryption__EncryptionKey=<ENCRYPTION_KEY>
Encryption__DekTokenTtlMinutes=1440
| Setting | Default | Description |
|---|---|---|
EncryptionKey | required | Base64-encoded 32-byte key encryption key (KEK). Generate with openssl rand -base64 32. |
DekTokenTtlMinutes | 1440 | DEK token lifetime in minutes (default: 24 hours). Files and jobs are retained for at least ceil(DekTokenTtlMinutes / 1440) days; sub-day TTLs still round up to one day. A daily cleanup then deletes expired entries, so files can outlive the TTL by up to another 24 hours. |
Service communication
The Manager dispatches detection and redaction jobs to the Worker. The transport, broker location, concurrency limits, and resilience policies live under ServiceCommunication.
Transport
Selects how the Manager sends jobs to the Worker. With Rest, the Manager calls the Worker directly over HTTP, suitable for single-Worker deployments. With RabbitMQ, the Manager publishes jobs to a queue and Workers consume them; this lets multiple Worker instances share the load.
ServiceCommunication__ServiceCommunicationType=RabbitMQ
ServiceCommunication__Host=<RABBITMQ_HOST>
ServiceCommunication__Username=<USERNAME>
ServiceCommunication__Password=<PASSWORD>
For REST transport, the connection string points to the Worker URL:
ServiceCommunication__ServiceCommunicationType=Rest
ServiceCommunication__ConnectionString=http://<WORKER_HOST>:4885/
| Setting | Default | Description |
|---|---|---|
ServiceCommunicationType | required | Rest or RabbitMQ. The Worker must use the same value. |
ConnectionString | required for Rest | Base URL of the Worker. |
Host | required for RabbitMQ | RabbitMQ host name. |
Username | required for RabbitMQ | RabbitMQ username. |
Password | required for RabbitMQ | RabbitMQ password. |
RetryCount | 3 | Retries on transport-level failures (Manager → Worker) before the message is moved to the error queue. Distinct from the Orchestrator’s MaxDetectionRetries, which retries at the Orchestrator → Manager layer. |
REST concurrency
Caps on how many concurrent REST calls the Manager sends to the Worker. Applies only when ServiceCommunicationType is Rest; with RabbitMQ, the broker handles dispatch and the per-Worker concurrency is configured on the Worker. The Worker-side limits live on the Worker configuration page.
ServiceCommunication__RestSemaphoreLimit=10
| Setting | Default | Description |
|---|---|---|
RestSemaphoreLimit | 10 | Maximum concurrent REST calls from the Manager to the Worker. |
RestSemaphoreTimeoutSeconds | null (infinite) | Time a request waits for a free semaphore slot before being rejected with 429. |
Admission control
A safeguard against unbounded queue buildup. When the in-progress job count reaches the configured limit, the Manager rejects new requests with 429 Too Many Requests instead of letting work pile up. Without it, a sustained burst of requests can grow the queue indefinitely and degrade end-to-end latency without any visible signal to clients.
Admission control is disabled by default. Set MaxPendingJobs to enable it. Optionally set HealthCheckPendingJobThreshold so the readiness probe reports Degraded before the hard limit is reached. The values below are an illustrative starting point:
ServiceCommunication__MaxPendingJobs=20
ServiceCommunication__HealthCheckPendingJobThreshold=15
| Setting | Default | Description |
|---|---|---|
MaxPendingJobs | null (disabled) | Maximum in-progress jobs across all types. New requests are rejected with 429 once the limit is reached. |
HealthCheckPendingJobThreshold | null (disabled) | Pending-job count at or above which /healthz/ready reports Degraded. |
BackpressureMonitorIntervalSeconds | 5 | How often the cached pending-job count is refreshed from the database. |
Circuit breaker
Detects repeated transport failures and fast-fails new requests instead of waiting for each one to time out. After the configured number of consecutive failures, the Manager rejects new requests for a cool-down period before probing again. This prevents cascading slowdowns when the Worker is unavailable. Enabled by default.
ServiceCommunication__CircuitBreakerFailureThreshold=3
ServiceCommunication__CircuitBreakerDurationSeconds=30
| Setting | Default | Description |
|---|---|---|
CircuitBreakerFailureThreshold | 3 | Consecutive transport failures before the circuit opens. Set to null to disable. |
CircuitBreakerDurationSeconds | 30 | Seconds the circuit stays open before allowing a probe request. |
Job options
JobOptions__TimeoutMinutes=60
| Setting | Default | Description |
|---|---|---|
TimeoutMinutes | 60 | Maximum total lifetime of a job, including queue time and Worker processing. Range 1 to 1440 minutes (24 hours). Jobs that exceed the deadline are marked as failed. |
Web server
The WebServer section configures the Kestrel HTTP server.
WebServer__PortNumber=9982
WebServer__MaxFileSizeBytes=104857600
WebServer__MaxConcurrentConnections=1000
| Setting | Default | Description |
|---|---|---|
PortNumber | 9982 | TCP port the Manager listens on. |
MaxFileSizeBytes | 104857600 (100 MB) | Maximum allowed multipart upload size. Oversized uploads return 413. Set to null, 0, or a negative value to remove the limit. |
MaxConcurrentConnections | 1000 | Maximum concurrent connections accepted by Kestrel. Excess connections are rejected at the TCP level. Set to null, 0, or a negative value to remove the limit. |
RequestHeadersTimeout | null (Kestrel default) | Maximum time spent waiting for request headers. Format: hh:mm:ss. |
KeepAliveTimeout | null (Kestrel default) | Idle-connection lifetime. Format: hh:mm:ss. |
MinRequestBodyDataRateBytesPerSecond | null (Kestrel default) | Minimum upload rate before Kestrel disconnects a slow client. Set to 0 to disable the check. |
MinRequestBodyDataRateGracePeriod | null (Kestrel default) | Grace period before the minimum upload rate is enforced. Format: hh:mm:ss. |
If both the Manager and the Orchestrator are deployed, configure the same MaxFileSizeBytes value on both. Otherwise the Orchestrator can accept files that the Manager later rejects.
Logging
Application logs are written to the console and, optionally, to a file. The fields are top-level (no section prefix).
LogFilePath=./logs/smart-redact-manager-log.txt
LogRetentionDays=7
| Setting | Default | Description |
|---|---|---|
LogFilePath | — | Path of the rolling-daily log file inside the container. Leave empty to disable file logging. |
LogRetentionDays | 7 | Number of days log files are retained on disk. |
The minimum log level isn’t a separate setting. It’s derived from the standard ASPNETCORE_ENVIRONMENT environment variable: when set to Development, the service emits Debug-level logs in a developer-friendly console format; any other value (the default) emits Information-level logs in JSON. Use Development only for local diagnostics.