---
title: SAIF.Application.LogView business rules
summary: Enumerated business rules with per-rule trigger, enforcement, and outcomes.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Application.LogView
reference_type: package
---

# SAIF.Application.LogView business rules

This page captures business rules enforced by this library.

## BR-001: Search results are capped at 300 rows

| Field | Value |
| --- | --- |
| **Statement** | Error and info collection searches return at most 300 rows per retrieval query. |
| **Trigger** | Any `clsAppErrorCollection` or `clsAppInfoCollection` retrieval. |
| **Enforcement** | `RetrieveSQL` in both collection criteria classes uses `SELECT TOP 300`. |
| **Outcome** | Callers receive a page-limited row set and must use the matching count query for the full result total. |
| **Confidence** | Verified |
| **Tables** | [App_Error](database-tables.md#app_error), [App_Info](database-tables.md#app_info) |
| **SQL** | [SQL-005](sql/SQL-005-saif-application-logview.md), [SQL-006](sql/SQL-006-saif-application-logview.md), [SQL-007](sql/SQL-007-saif-application-logview.md), [SQL-008](sql/SQL-008-saif-application-logview.md) |
| **Source** | `Application\SAIF.Application.LogView\clsAppErrorCollection.vb`; `Application\SAIF.Application.LogView\clsAppInfoCollection.vb` |

---

## BR-002: All sentinel suppresses selected filters

| Field | Value |
| --- | --- |
| **Statement** | Filter values containing the literal `[ALL]` are treated as "no filter" for applicable collection criteria. |
| **Trigger** | Collection search criteria evaluate machine and application filters. |
| **Enforcement** | `BuildWhere()` omits corresponding predicates when the filter value contains `[ALL]`. |
| **Outcome** | Caller-selected "all" values do not constrain the SQL query. |
| **Confidence** | Verified |
| **Tables** | [App_Error](database-tables.md#app_error), [App_Info](database-tables.md#app_info) |
| **SQL** | [SQL-005](sql/SQL-005-saif-application-logview.md), [SQL-006](sql/SQL-006-saif-application-logview.md), [SQL-007](sql/SQL-007-saif-application-logview.md), [SQL-008](sql/SQL-008-saif-application-logview.md) |
| **Source** | `Application\SAIF.Application.LogView\clsAppErrorCollection.vb`; `Application\SAIF.Application.LogView\clsAppInfoCollection.vb` |

---

## BR-003: Semicolon-delimited filters expand to SQL IN lists

| Field | Value |
| --- | --- |
| **Statement** | Semicolon-delimited `Environment` and `UserName` filters are rewritten as SQL `IN (...)` lists. |
| **Trigger** | Collection search criteria receive multiple filter values in one string. |
| **Enforcement** | `BuildWhere()` splits the supplied value and emits an `IN (...)` predicate instead of a single-value comparison. |
| **Outcome** | One search request can match multiple environments or user names. |
| **Confidence** | Verified |
| **Tables** | [App_Error](database-tables.md#app_error), [App_Info](database-tables.md#app_info) |
| **SQL** | [SQL-005](sql/SQL-005-saif-application-logview.md), [SQL-006](sql/SQL-006-saif-application-logview.md), [SQL-007](sql/SQL-007-saif-application-logview.md), [SQL-008](sql/SQL-008-saif-application-logview.md) |
| **Source** | `Application\SAIF.Application.LogView\clsAppErrorCollection.vb`; `Application\SAIF.Application.LogView\clsAppInfoCollection.vb` |

---

## BR-004: Search text is normalized for full-text queries

| Field | Value |
| --- | --- |
| **Statement** | Free-text search input is rewritten into a SQL Server `CONTAINS(...)` predicate while preserving explicit logical operators. |
| **Trigger** | A collection search includes `SearchText`. |
| **Enforcement** | `GetSearchValue()` strips quotes, tokenizes terms, preserves `AND`/`OR`/`&`/`|`/`&!`, and quotes search tokens before SQL binding. |
| **Outcome** | Full-text search behavior is standardized before execution against the log tables. |
| **Confidence** | Verified |
| **Tables** | [App_Error](database-tables.md#app_error), [App_Info](database-tables.md#app_info) |
| **SQL** | [SQL-005](sql/SQL-005-saif-application-logview.md), [SQL-006](sql/SQL-006-saif-application-logview.md), [SQL-007](sql/SQL-007-saif-application-logview.md), [SQL-008](sql/SQL-008-saif-application-logview.md) |
| **Source** | `Application\SAIF.Application.LogView\clsAppErrorCollection.vb`; `Application\SAIF.Application.LogView\clsAppInfoCollection.vb`; `Application\SAIF.Application.LogView\modLogViewExtensions.vb` |

---

## BR-005: Single-object retrieval requires exactly one row

| Field | Value |
| --- | --- |
| **Statement** | Single-object retrieval is valid only when exactly one row is returned. |
| **Trigger** | `clsAppError.AfterRetrieve` or `clsAppInfo.AfterRetrieve` runs after a retrieve request. |
| **Enforcement** | `AfterRetrieve` throws `ApplicationException("Invalid Results")` when the result count is not exactly one. |
| **Outcome** | Zero-row or multi-row matches are treated as invalid object retrievals. |
| **Confidence** | Verified |
| **Tables** | [App_Error](database-tables.md#app_error), [App_Info](database-tables.md#app_info) |
| **Source** | `Application\SAIF.Application.LogView\clsAppError.vb`; `Application\SAIF.Application.LogView\clsAppInfo.vb` |

---

## BR-006: Inserts must affect exactly one row

| Field | Value |
| --- | --- |
| **Statement** | Insert operations are considered successful only when exactly one database row is affected. |
| **Trigger** | `clsAppError.AfterInsert` or `clsAppInfo.AfterInsert` runs after an insert request. |
| **Enforcement** | `AfterInsert` checks `RowsAffected <> 1` and adds `InsertError` when the count is not one. |
| **Outcome** | Failed inserts surface as business-object error messages rather than silently succeeding. |
| **Confidence** | Verified |
| **Tables** | [App_Error](database-tables.md#app_error), [App_Info](database-tables.md#app_info) |
| **SQL** | [SQL-003](sql/SQL-003-saif-application-logview.md), [SQL-004](sql/SQL-004-saif-application-logview.md) |
| **Source** | `Application\SAIF.Application.LogView\clsAppError.vb`; `Application\SAIF.Application.LogView\clsAppInfo.vb` |

---

## BR-007: Audit rows receive a 30-day purge date

| Field | Value |
| --- | --- |
| **Statement** | New `App_Info` rows are written with `Purge_Date` set 30 days after creation. |
| **Trigger** | `clsAppInfo` inserts a new audit/info row. |
| **Enforcement** | `BeforeInsert` binds `@Purge_Date` with `Now.AddDays(30)`. |
| **Outcome** | Each audit row carries a precomputed retention cutoff. |
| **Confidence** | Verified |
| **Tables** | [App_Info](database-tables.md#app_info) |
| **SQL** | [SQL-004](sql/SQL-004-saif-application-logview.md) |
| **Source** | `Application\SAIF.Application.LogView\clsAppInfo.vb` |

---

## BR-008: Audit searches exclude EPAY and DirectDeposit

| Field | Value |
| --- | --- |
| **Statement** | Standard `App_Info` collection searches exclude rows whose `App_Name` is `EPAY` or `DirectDeposit`. |
| **Trigger** | `clsAppInfoCollection` builds its search SQL. |
| **Enforcement** | Both `RetrieveSQL` and `RetrieveSQLCount` append `and not (App_Info.App_Name in ('EPAY','DirectDeposit'))`. |
| **Outcome** | Default audit searches omit those application names even when other filters would match them. |
| **Confidence** | Verified |
| **Tables** | [App_Info](database-tables.md#app_info) |
| **SQL** | [SQL-007](sql/SQL-007-saif-application-logview.md), [SQL-008](sql/SQL-008-saif-application-logview.md) |
| **Source** | `Application\SAIF.Application.LogView\clsAppInfoCollection.vb` |

---

## BR-009: Info search full-text scope is restricted by SearchType

| Field | Value |
| --- | --- |
| **Statement** | An `App_Info` collection search's full-text predicate targets `Message_Text` and `Data_Text` together, `Message_Text` alone, or `Data_Text` alone, depending on the criteria's `SearchType` selection. |
| **Trigger** | A `clsAppInfoCollection` search supplies non-empty `SearchText` and a `SearchType` of `MessageAndData`, `MessageOnly`, or `DataOnly`. |
| **Enforcement** | `BuildWhere()` selects on `m_searchType` and appends `CONTAINS((App_Info.Message_Text,App_Info.Data_Text),@SEARCHTEXT)`, `CONTAINS((App_Info.Message_Text),@SEARCHTEXT)`, or `CONTAINS((App_Info.Data_Text),@SEARCHTEXT)` accordingly. |
| **Outcome** | Callers can narrow full-text matching to only the message field, only the supplemental data field, or both, instead of always searching both columns. |
| **Confidence** | Verified |
| **Tables** | [App_Info](database-tables.md#app_info) |
| **SQL** | [SQL-007](sql/SQL-007-saif-application-logview.md), [SQL-008](sql/SQL-008-saif-application-logview.md) |
| **Source** | `Application\SAIF.Application.LogView\clsAppInfoCollection.vb` |

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

## Sources
- `Application\SAIF.Application.LogView\clsAppError.vb`
- `Application\SAIF.Application.LogView\clsAppErrorCollection.vb`
- `Application\SAIF.Application.LogView\clsAppInfo.vb`
- `Application\SAIF.Application.LogView\clsAppInfoCollection.vb`
- `Application\SAIF.Application.LogView\modLogViewExtensions.vb`

