---
title: CertificateValidator
summary: API reference for CertificateValidator.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-09-24
library: SAIF.Services
reference_type: package
---

# CertificateValidator

FluentValidation validator for `CertificateEdit`, the input model used when creating or editing a policy certificate. It enforces that a certificate holder is present and (for non-Bid certificates) internally valid via a nested `CertificateHolderValidator`, that policy number/period fields are populated, that free-text fields stay within storage-length limits, and — only when the certificate type is `OtherStates` (OSC) — that an OSC policy and OSC limits code are supplied.

## Purpose
- Requires a certificate holder and a certificate type on every submission.
- Delegates certificate-holder validation to `CertificateHolderValidator` for all certificate types except `Bid`.
- Enforces additional OSC-specific required fields (`OscPolicyId`, `OscLimitsCode`) only when `CertificateType` is `OtherStates`.
- Caps `JobDescription` and `OtherCoverages` at `MaxLengthJobDescription` (500) characters to match backing storage.

## Context
- Namespace: `SAIF.Services.Policies.Certificates.Validators`
- Assembly/package: `SAIF.Services` (packaged inside the `SAIF.SAIFCode.Core` NuGet package).

## Public members
| Member | Signature | Purpose |
| --- | --- | --- |
| MaxLengthJobDescription | `public const int MaxLengthJobDescription = 500` | Maximum character length allowed for `JobDescription` and `OtherCoverages`, used both in the length rule and its error message. |
| MaxOscLimitsLength | `public const int MaxOscLimitsLength = 50` | Reserved maximum length for an OSC limits description field; declared but not currently referenced by an active rule (the corresponding rule is commented out in source).* |
| CertificateValidator (constructor) | `public CertificateValidator()` | Registers all validation rules for `CertificateEdit`: required certificate holder and certificate type, conditional certificate-holder sub-validation, conditional OSC rules, required policy number/period, and length limits on job description and other coverages. |

## Behavioral notes
- `RuleFor(n => n.CertificateHolderEdit).SetValidator(new CertificateHolderValidator())` only applies `When(n => n.CertificateType != Certificate.CertificateTypes.Bid, ...)`, so Bid certificates skip certificate-holder sub-validation entirely.
- `AddOscRules` (invoked via `When(n => n.CertificateType == Certificate.CertificateTypes.OtherStates, AddOscRules)`) requires `OscPolicyId` and `OscLimitsCode` to be non-empty only for OSC certificates.
- Several historical rules (OSC period/policy/limits length checks) are commented out in source, indicating validation for those fields was intentionally disabled or deferred.*
- The class carries a `CA1710:IdentifiersShouldHaveCorrectSuffix` suppression, reflecting that FluentValidation's `AbstractValidator<T>` naming convention doesn't match the `...Validator`/`...Collection` suffix rule.*

## Constraints and usage notes
- A new `CertificateHolderValidator` instance is constructed per validation run rather than injected, coupling this validator directly to that concrete type.*
- Callers must supply a fully-populated `CertificateEdit`, including `CertificateType`, before invoking validation, since several rules are conditioned on that value.

> **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
- `Services/SAIF.Services/Policies/Certificates/Validators/CertificateValidator.cs`
