---
title: SAIF.Web.API.Core business rules
summary: Enumerated business rules with per-rule trigger, enforcement, and outcomes.
status: draft
owner: andmil
last_reviewed: 2026-09-15
library: SAIF.Web.API.Core
reference_type: package
---

# SAIF.Web.API.Core business rules

This page captures business rules enforced by this library.

## BR-CORE-001 InvalidDataException validation failure projection

| Field | Value |
| --- | --- |
| **Statement** | An `InvalidDataException` constructed from one or more `ValidationFailure` objects must expose those failures via its `ValidationErrors` property (usable by, for example, ASP.NET MVC `ModelState`, per source comment) and must derive its exception `Message` from the joined `ErrorMessage` values of those failures. |
| **Trigger** | `InvalidDataException(ValidationFailure failure)` or `InvalidDataException(IEnumerable<ValidationFailure> failures)` constructor invoked by a consumer. |
| **Enforcement** | `InvalidDataException` constructors (`SAIFException.cs`): the single-failure overload sets `Message` to `failure.ErrorMessage` and `ValidationErrors` to a one-item list; the multi-failure overload projects `failures.Select(x => x.ErrorMessage)` and joins them via `ToStringAll(";")` for `Message`, and materializes `failures` to a list for `ValidationErrors`. |
| **Outcome** | `ValidationErrors` is populated; `Message` is set to the joined error text (semicolon-delimited for the multi-failure overload). |
| **Source** | `src/SAIF.Web.API.Core/SAIFException.cs` |

---

## BR-CORE-002 HttpStatusCode carried by every SAIFException subtype

| Field | Value |
| --- | --- |
| **Statement** | Every `SAIFException`-derived type must be able to carry an associated `HttpStatusCode`, distinct from the .NET exception's own identity, so that HTTP-facing consumers can set/read the status after construction. |
| **Trigger** | Any code path constructing or catching a `SAIFException`-derived instance and needing to associate/read an HTTP status. |
| **Enforcement** | `SAIFException.HttpStatusCode` property (`SAIFException.cs`) — a plain settable property with no constructor-level default; the actual status-code-to-exception-type dispatch logic lives in the consuming library [SAIF.Web.API.Clients](../saif-web-api-clients/overview.md)'s `ExceptionHandler.ToKnownError`, not in this library. |
| **Outcome** | A settable `HttpStatusCode` property is available on every concrete exception subtype (`NoMatchingDataException`, `UnauthorizedAccessException`, `InternalServerError`, `InvalidDataException`). |
| **Source** | `src/SAIF.Web.API.Core/SAIFException.cs` |

---

## BR-CORE-003 Fixed default exception messages

| Field | Value |
| --- | --- |
| **Statement** | Each concrete `SAIFException` subtype has a fixed default human-readable message when constructed with no arguments (`"Error: No matching data."`, `"Error: Not authorized."`, `"Error: Internal server error."`, `"Error: Invalid data in request."` respectively), ensuring a non-empty message is always present even if a caller does not supply one. |
| **Trigger** | Parameterless construction of any of the four concrete exception types. |
| **Enforcement** | Each subtype's parameterless constructor (`SAIFException.cs`) passes its fixed default string to the base `Exception(string)` constructor. |
| **Outcome** | `Exception.Message` is populated with the fixed default string. |
| **Source** | `src/SAIF.Web.API.Core/SAIFException.cs` |

---

## BR-CORE-004 ErrorResponse default error message

| Field | Value |
| --- | --- |
| **Statement** | `ErrorResponse` must default `ErrorMessage` to `"Invalid Request."` when constructed with only an error code and no explicit message. |
| **Trigger** | `ErrorResponse(int errorCode)` constructed without the optional `errorMessage` argument. |
| **Enforcement** | `ErrorResponse(int errorCode, string errorMessage = "Invalid Request.")` constructor (`ErrorResponse.cs`). |
| **Outcome** | `ErrorMessage` is set to `"Invalid Request."` when not explicitly supplied. |
| **Source** | `src/SAIF.Web.API.Core/ErrorResponse.cs` |

---

## Notes
- No rules were found governing `ApiResponse<T>` (pure DTO, no constructor logic) or `BuildInfo` beyond a defensive-coding fallback (missing build-info file is tolerated, not an error) — this is not elevated to a business rule since it is not a domain rule.
- Mark inferred statements with `*` and unknown statements with `**`. Do not use bold inline confidence labels.

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

## Sources
- `src/SAIF.Web.API.Core/SAIFException.cs`
- `src/SAIF.Web.API.Core/ErrorResponse.cs`
- `src/SAIF.Web.API.Core/ApiResponse.cs`
- `src/SAIF.Web.API.Core/BuildInfo.cs`
