---
title: SAIF.Application.Services.AudioVideo business rules
summary: Enumerated business rules with per-rule trigger, enforcement, and outcomes.
status: draft
owner: <owner>
last_reviewed: 2026-09-15
library: SAIF.Application.Services.AudioVideo
reference_type: package
---

# SAIF.Application.Services.AudioVideo business rules

This page captures business rules enforced by `SAIF.Application.Services.AudioVideo`.

## BR-AV-01 CurrentUserId required

| Field | Value |
| --- | --- |
| **Statement** | `CurrentUserId` must not be empty on an import request. |
| **Trigger** | [ImportRecording](operations/import-recording.md) validation step, evaluated for every `ImportAudioRequest`. |
| **Enforcement** | `AudioVideoValidator` constructor — `RuleFor(x => x.CurrentUserId).NotEmpty()`. |
| **Outcome** | Validation failure aggregated into `SaifValidationException`; import aborted before any database, file, or vendor-system action. |
| **Source** | `Application\SAIF.Application.Services.AudioVideo\Services\Utilities\AudioVideo\AudioVideoValidator.cs` |

---

## BR-AV-02 CallRecording required

| Field | Value |
| --- | --- |
| **Statement** | `CallRecording` must be present (not empty/null) on an import request. |
| **Trigger** | Same as [BR-AV-01](#br-av-01-currentuserid-required). |
| **Enforcement** | `AudioVideoValidator` — `RuleFor(x => x.CallRecording).NotEmpty()`. |
| **Outcome** | Same as [BR-AV-01](#br-av-01-currentuserid-required). |
| **Source** | `Application\SAIF.Application.Services.AudioVideo\Services\Utilities\AudioVideo\AudioVideoValidator.cs` |

---

## BR-AV-03 Claim number required

| Field | Value |
| --- | --- |
| **Statement** | A claim number (`ClaimId`) is required for every import. |
| **Trigger** | Same as [BR-AV-01](#br-av-01-currentuserid-required). |
| **Enforcement** | `AudioVideoValidator` — `RuleFor(x => x.ClaimId).NotEmpty().WithMessage("Error: A claim number is required.")`. |
| **Outcome** | Same as [BR-AV-01](#br-av-01-currentuserid-required); displayed message: "Error: A claim number is required." |
| **Source** | `Application\SAIF.Application.Services.AudioVideo\Services\Utilities\AudioVideo\AudioVideoValidator.cs` |

---

## BR-AV-04 Investigation number required for Fraud

| Field | Value |
| --- | --- |
| **Statement** | An investigation/case number (`InvestigationId`) is required specifically when the recording is being imported for the Fraud recording system. |
| **Trigger** | Same as [BR-AV-01](#br-av-01-currentuserid-required), conditional on `RecordingSystem == RecordingSystemTypes.Fraud`. |
| **Enforcement** | `AudioVideoValidator` — `RuleFor(x => x.InvestigationId).NotEmpty().When(x => x.RecordingSystem == RecordingSystemTypes.Fraud).WithMessage("Error: A case number is required.")`. |
| **Outcome** | Same as [BR-AV-01](#br-av-01-currentuserid-required); displayed message: "Error: A case number is required." |
| **Source** | `Application\SAIF.Application.Services.AudioVideo\Services\Utilities\AudioVideo\AudioVideoValidator.cs` |

---

## BR-AV-05 Description length limit

| Field | Value |
| --- | --- |
| **Statement** | The combined recording description and notes must be ≤ 100 characters (the validator's displayed message states "less than 80 characters", but the coded rule checks `<= 100` — a description/message mismatch)*. |
| **Trigger** | Same as [BR-AV-01](#br-av-01-currentuserid-required). |
| **Enforcement** | `AudioVideoValidator` — `RuleFor(x => x.CallRecording).Must(x => CallRecordingExtensions.GetDescription(x).Length <= 100)`. |
| **Outcome** | Same as [BR-AV-01](#br-av-01-currentuserid-required). |
| **Source** | `Application\SAIF.Application.Services.AudioVideo\Services\Utilities\AudioVideo\AudioVideoValidator.cs` |

---

## BR-AV-06 Recording retention by system type

| Field | Value |
| --- | --- |
| **Statement** | Recording retention (`PurgeDate`) and the stored `RecordingSystemCode` vary by `RecordingSystemTypes`: Board Minutes → +90 years, code `"BRD"` (default); Claim → +75 years, code `"CLM"`; Fraud → +5 years, code `"FRD"`. |
| **Trigger** | [ImportRecording](operations/import-recording.md), evaluated for every new recording import, in `AudioVideoService.CreateRecording`. |
| **Enforcement** | `AudioVideoService.CreateRecording` switch statement. |
| **Outcome** | Sets `Recording.PurgeDate`/`Recording.RecordingSystemCode` on the persisted row; drives long-term retention/purge policy for the recording. |
| **Source** | `Application\SAIF.Application.Services.AudioVideo\Services\Utilities\AudioVideo\AudioVideoService.cs` |

---

## BR-AV-07 Discoverable classification

| Field | Value |
| --- | --- |
| **Statement** | A recording is classified discoverable (`IsDiscoverable`) only when it is a Claim-system recording **and** either there is no "Other Party" key/value or the "Other Party" is "Injured Worker". |
| **Trigger** | `AudioVideoService.CreateRecording` (via `request.CallRecording.IsDiscoverable(request.RecordingSystem)`), during [ImportRecording](operations/import-recording.md). |
| **Enforcement** | `CallRecordingExtensions.IsDiscoverable(this CallRecording, RecordingSystemTypes)`. |
| **Outcome** | Sets `Recording.IsDiscoverable`, a legal-discovery/e-discovery classification flag persisted with the recording. |
| **Source** | `Application\SAIF.Application.Services.AudioVideo\Services\Utilities\AudioVideo\CallRecordingExtensions.cs` |

---

## BR-AV-08 Recording description default

| Field | Value |
| --- | --- |
| **Statement** | The recording `Description` defaults to the "Other Party" key/value if present, else "Injured Worker"; if any `KeyValues` exist, the recording's free-text `Notes` are appended with a leading space. |
| **Trigger** | `AudioVideoService.CreateRecording` during [ImportRecording](operations/import-recording.md); also evaluated by `AudioVideoValidator` for [BR-AV-05](#br-av-05-description-length-limit). |
| **Enforcement** | `CallRecordingExtensions.GetDescription(this CallRecording)`. |
| **Outcome** | Produces the `Description` value persisted to `RECORDING.DESCRIPTION_TEXT` and validated for length by [BR-AV-05](#br-av-05-description-length-limit). |
| **Source** | `Application\SAIF.Application.Services.AudioVideo\Services\Utilities\AudioVideo\CallRecordingExtensions.cs` |

---

## BR-AV-09 Import requires vendor deletion

| Field | Value |
| --- | --- |
| **Statement** | A recording import is not considered successful unless the source recording is also deleted from the CallRex vendor system; failure to delete forces the import into an errored state even though local persistence and file conversion already succeeded. |
| **Trigger** | [ImportRecording](operations/import-recording.md), after `VerifyImport` succeeds. |
| **Enforcement** | `AudioVideoService.ImportRecording` — `if (!_recordingSystem.DeleteRecording(...))` block. |
| **Outcome** | Sets import status to Errored (`AudioImportStatus`) and throws `ApplicationException`; the local `Recording` row created earlier is **not** rolled back in this branch (only the earlier catch block deletes it) — an asymmetry noted as an open question in the analysis*. |
| **Source** | `Application\SAIF.Application.Services.AudioVideo\Services\Utilities\AudioVideo\AudioVideoService.cs` |

---

## BR-AV-10 Invalidate annotates vendor description

| Field | Value |
| --- | --- |
| **Statement** | Marking a recording invalid annotates the vendor system's attached-data `Description` with an `"Invalid:"` prefix rather than deleting vendor data. |
| **Trigger** | [InvalidateRecording](operations/invalidate-recording.md). |
| **Enforcement** | `CallRexServiceProxy.MarkInvalid`. |
| **Outcome** | Vendor-side `AttachedDataContainer.Description` updated via `UpdateAttachedDataByCallLogID`; local `AudioImportStatus` row removed via `ImportStatusManager.RemoveStatus`. |
| **Source** | `Application\SAIF.Application.Services.AudioVideo\Services\ClientProxies\ThirdParty\CallRexServiceProxy.cs` |

---

## BR-AV-11 Test and invalid detection via regex

| Field | Value |
| --- | --- |
| **Statement** | Whether a recording is treated as a "test" recording and whether it has an "invalid context number" are both derived by case-insensitive regex matching of the vendor attached-data `Description` for the literal substrings `"test"` and `"invalid"`, respectively. |
| **Trigger** | `CallRexServiceProxy.GetRecording` (private), evaluated for every recording returned from CallRex. |
| **Enforcement** | `Regex.IsMatch(data.Description ?? "", "test"/"invalid", RegexOptions.IgnoreCase)`. |
| **Outcome** | Sets `CallRecording.IsProductionRecording` (`= !isTestRecording`) and `CallRecording.HasInvalidContextNumber`; also strips the literal substring "test" (case-insensitive) from the description text via `Regex.Replace`. |
| **Source** | `Application\SAIF.Application.Services.AudioVideo\Services\ClientProxies\ThirdParty\CallRexServiceProxy.cs` |

---

## Notes
- Mark inferred statements with `*` and unknown statements with `**`. Do not use bold inline confidence labels.
- [BR-AV-05](#br-av-05-description-length-limit) and [BR-AV-09](#br-av-09-import-requires-vendor-deletion) document known message/rule mismatches and rollback asymmetries observed in source; these are recorded as-is without asserting they are defects.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Configuration](configuration.md)
- [Operations and processes](operations-processes.md)
- [API reference](api/index.md)

> **Note:** Statements marked with `*` were inferred from code structure, naming
> conventions, or contextual evidence where direct confirmation was not available
> in source artifacts. Statements marked with `**` could not be confirmed; treat
> as unknown until verified.

## Sources
- `Application\SAIF.Application.Services.AudioVideo\Services\Utilities\AudioVideo\AudioVideoValidator.cs`
- `Application\SAIF.Application.Services.AudioVideo\Services\Utilities\AudioVideo\AudioVideoService.cs`
- `Application\SAIF.Application.Services.AudioVideo\Services\Utilities\AudioVideo\CallRecordingExtensions.cs`
- `Application\SAIF.Application.Services.AudioVideo\Services\ClientProxies\ThirdParty\CallRexServiceProxy.cs`
