Skip to content

Configuration ​

Everything the module reads is in one section, GrydFiles, plus the engine's address in GrydClamAv. The reasons behind each value are in ADR 0010; the authoritative table of profile fields is §14 of the specification.

Nothing about the storage provider lives here. Bucket, region, credentials and DefaultPrefix stay in GrydStorage, which AddGrydObjectStorage already owns; the module reaches the object through IObjectStorageService and records the effective provider and bucket on each file.

The section ​

json
{
  "GrydFiles": {
    "PurgeGracePeriodDays": 30,
    "QuarantineRetentionDays": 365,
    "ScanQueueAlertThreshold": 100,
    "ScanQueueAlertMaxAge": "00:30:00",

    "Scanner": {
      "TimeoutSeconds": 120,
      "RetryDelays": [ "00:01:00", "00:05:00", "00:15:00" ],
      "StreamMaxLengthBytes": 67108864,
      "MaxFileSizeBytes": 67108864,
      "MaxScanSizeBytes": 419430400,
      "MaxRecursion": 16,
      "MaxFiles": 10000,
      "ConcurrentDatabaseReload": true,
      "AlertOnExceededLimits": true,
      "UseIdSession": false
    },

    "Profiles": {
      "gryd.report": {
        "MaxSizeBytes": 52428800,
        "AllowedContentTypes": [ "application/pdf", "text/csv", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ],
        "ScanRequired": false,
        "DefaultRetentionMode": "UntilReleased"
      },
      "gryd.notification-attachment": {
        "MaxSizeBytes": 10485760,
        "AllowedContentTypes": [ "application/pdf", "image/png", "image/jpeg", "text/csv" ],
        "ScanRequired": true,
        "DefaultRetentionMode": "RetainUntil",
        "DefaultRetentionDays": 30
      }
    }
  },

  "GrydClamAv": {
    "Host": "clamd",
    "Port": 3310
  }
}

Module-wide settings ​

KeyDefaultMeaning
PurgeGracePeriodDays30How long an UntilReleased file survives after its last reference is released — or after its verdict, if nobody ever referenced it — before the retention job purges it
QuarantineRetentionDays365How long infected content stays under _quarantine/ as evidence. Global, never per profile (D9): an infected file is not more or less evidence depending on how it was uploaded
ScanQueueAlertThreshold100Files waiting for a verdict above which the queue alert fires
ScanQueueAlertMaxAge00:30:00Age of the oldest waiting file above which the queue alert fires. Above the retry budget, so a file that is only retrying does not trip it

Scanner — the antivirus limits ​

clamd.conf is generated from this section, never written by hand (D15). The same numbers the application validates the profiles against are the numbers the daemon runs with, and an incoherent section — a profile ceiling above StreamMaxLengthBytes, a MaxScanSizeBytes below MaxFileSizeBytes — fails the start-up; it is not a warning in a log.

KeyDefaultMeaning
TimeoutSeconds120How long one pass may take before it counts as a Timeout (D14). Client-side; not a clamd directive
RetryDelays1, 5 and 15 minThe waits between passes after an infrastructure failure: the first pass and three more (D14). Client-side
StreamMaxLengthBytes67108864 (64M)StreamMaxLength — the largest stream INSTREAM accepts. Must be above the largest profile ceiling
MaxFileSizeBytes67108864 (64M)MaxFileSize
MaxScanSizeBytes419430400 (400M)MaxScanSize — how much the engine reads out of an archive
MaxRecursion16MaxRecursion — nesting depth of archives
MaxFiles10000MaxFiles — members read out of one archive
ConcurrentDatabaseReloadtrueKeeps scanning while the signature database reloads, at the cost of two copies in memory
AlertOnExceededLimitstrueAlertExceedsMax. Off, a file that exceeds a limit comes back stream: OK unread; on, it is a failure, never a release
UseIdSessionfalseReuses one connection for several scans. Client-side

Why 64M and not clamd's default of 25M (D13): 25M is exactly the largest profile in use (26 214 400 bytes), which leaves no room for the INSTREAM framing. Every parameter, its rendering and its rationale are on clamd.conf.

Profiles — a profile is configuration, not a table ​

Each profile is an entry of the dictionary, named in every upload. There is no default profile (D12): a name nobody configured is FILE_PROFILE_UNKNOWN. The framework declares only gryd.report and gryd.notification-attachment; a product adds its own (nexio.attachment, nexio.import, …) in its own appsettings.

FieldDefaultMeaning
MaxSizeBytes— (required)The ceiling, checked at the reservation, before any URL is issued (FILE_TOO_LARGE_UNPROCESSABLE). RN-GF-11: no profile without one
AllowedContentTypes— (required)An allow list, never a deny list. The declared type is checked at the reservation; the real one, by content, after the upload
ScanRequiredtruefalse waives the antivirus only. The content-type check and the server-side sha256 still run (D7), and the waiver is written to the audit trail at start-up
UploadUrlTtlMinutes15Validity of the upload URL, and the deadline of the confirmation (FILE_UPLOAD_EXPIRED_CONFLICT)
DownloadUrlTtlMinutes5Validity of each download URL
DefaultRetentionMode— (required)UntilReleased, RetainUntil or Permanent, inherited by an upload that declares none
DefaultRetentionDays—Required with RetainUntil: the module computes retainUntil from it

Who computes retainUntil ​

It depends on where the mode came from:

  • Declared in the upload as RetainUntil: the consumer sends the date. The module only checks that it is in the future.
  • Inherited from the profile: the module computes it from DefaultRetentionDays, counted from the reservation. Without that, every consumer of a 90-day profile would do the arithmetic itself.

Either way, the date only moves forward afterwards (RN-GF-09): PUT /files/{id}/retention with an earlier date is FILE_RETENTION_SHORTENED_UNPROCESSABLE. See Retention & Purge.

GrydClamAv — where the engine is ​

KeyDefaultMeaning
HostlocalhostThe clamd service — an address, never a replica
Port3310Its TCP port
ChunkSizeBytesadapter defaultSize of each INSTREAM chunk

The connection string ​

Resolved from ConnectionStrings:GrydFiles, then DefaultConnection, then DefaultPostgresConnection — the chain the other modules use. AddGrydFiles also accepts a configureDbContext callback when the host wants to configure the provider itself.

Released under the MIT License.