Skip to content

Application business rules

This page is the complete catalog of business rules that govern NDReimbursementWebApp. A rule appears here when it is enforced on a code path the application executes, whether the enforcing code is the application's own page model, manager and start-up code, or behavior inherited from the BolMiddleware and SAIF.NetCore packages. The application has no local libraries and no stored procedures of its own, so there are no library or stored procedure rules in scope.

Every rule heading below is the bare rule ID, so a link such as business-rules.md#br-scr-007 resolves to the rule.

Rule scope and coverage

Reachability was traced from the application's entry points: the page handlers of the single NDReimbursement screen, the four hosted endpoints, and the Startup and page-model infrastructure. Behavior of the four API-client packages (NDReimbursementAPI.Client, DigitalPaymentAPIClient, DocumentsCoreAPI.Client, OneIncAPIClient) is not documented anywhere retrievable, so any rules they enforce are unknown**.

Category Section Count
Application-level (cross-cutting) Application-level business rules 8
Screen-enforced Screen business rules 11
Library-defined, in scope None: the application has no local libraries 0
Stored procedure-enforced None: the application reaches no database directly 0
Inherited from framework packages Inherited business rules 12
Total in scope 31
Library-defined, not reachable Rules not reachable from this application 0

Rule index

Rule ID Statement Origin Reached from
BR-APP-001 Access to the page requires any one of the four NDR roles. Application Load screen, NDReimbursement
BR-APP-002 Without a current user id, PopulateModel returns false and sets ErrorMessage to "Invalid User"; display is subject to the view condition !IsSuccessful && !HasPolicyNumber. Application Load screen, NDReimbursement
BR-APP-003 Capability flags are derived per request, and a user with none of the four NDR roles is denied at the page-level gate (the PopulateModel "Not Authorized" fallback is a defensive branch). Application Load screen, NDReimbursement
BR-APP-004 External updaters may not change policy context. Application Change policy context
BR-APP-005 The developer-access type overrides the role flags. Application NDReimbursement
BR-APP-006 All POST handlers run without anti-forgery validation. Application Save requested amounts, NDReimbursement
BR-APP-007 The request-form value limit is 30000. Application Save requested amounts, Pay by mail
BR-APP-008 The application is served under a path base and the empty route maps to the screen. Application Load screen
BR-SCR-001 The due date is effective at 18:00; after that claims are read-only. NDReimbursement Load screen
BR-SCR-002 A due-date override must be between today and the due date plus 90 days (UI limits only). NDReimbursement Override due date
BR-SCR-003 A claim is editable only when the due date has not passed and its allowed amount is above zero. NDReimbursement Load screen
BR-SCR-004 Claims with bill code CF are flagged as cash flow. NDReimbursement Load screen
BR-SCR-005 Reimburse all sets each requested amount to the allowed amount. NDReimbursement NDReimbursement
BR-SCR-006 Reimbursable claims exist when claims are editable and Reimburse all applies or the user is a policyholder. NDReimbursement Load screen
BR-SCR-007 Pay online requires 0 < total <= max, with max supplied by the client. NDReimbursement Pay online
BR-SCR-008 Pending online payments block the "claims saved" state. NDReimbursement Load screen
BR-SCR-009 An HTTP 400 from the statements call yields the invalid-policy state. NDReimbursement Load screen
BR-SCR-010 Developer-access options depend on the policy number and the selected type. NDReimbursement Load screen
BR-SCR-011 The claims area renders only when a policy, an NDR statement and access are all present. NDReimbursement Load screen
INH-001 The BOL web context resolves in a fixed order. BolMiddleware† Load screen, Change policy context
INH-002 Policy access is validated softly through AccessAllowed. BolMiddleware† Load screen
INH-003 Remote context, menu and header failures are replaced with defaults. BolMiddleware† Load screen, Change policy context
INH-004 A user is external when the identity domain is not SAIF. BolMiddleware† Load screen
INH-005 External users' policy associations are filtered by user type. BolMiddleware† Load screen, Change policy context
INH-006 A session policy header is reused only on a policy match. BolMiddleware† Load screen, Change policy context
INH-007 Policy dropdown sorting, and duplicate policy numbers raise an exception. BolMiddleware† Load screen, Change policy context
INH-008 The BolContext cookie lives ten seconds and lacks Secure and SameSite. BolMiddleware† Change policy context
INH-009 SecurityApiAuthorize roles are evaluated with OR semantics. SAIF.NetCore.AuthService† Load screen, NDReimbursement
INH-010 The Windows domain is stripped before the Security API call. SAIF.NetCore.AuthService† Load screen
INH-011 A non-success Security API response throws. SAIF.NetCore.AuthService† Load screen
INH-012 Windows users always authorize remotely. SAIF.NetCore.AuthService† Load screen

Application-level business rules

Rules composed at the application level, enforced by NDReimbursementsModel or Startup with no single owning library.

BR-APP-001

Field Value
Title Page access requires an NDR role
Statement Access to the page requires any one of the four NDR roles: NonDisReimbViewResource, NonDisReimbUpdateResource, NonDisReimbViewExtResource, NonDisReimbUpdateExtResource.
Trigger Any request to the page
Enforcement [SecurityApiAuthorize] with arguments on NDReimbursementsModel. The declaration is application code and the evaluation is package code†.
Outcome The request is denied when the user holds none of the roles (INH-009)
Origin Application (declaration); SAIF.NetCore.AuthService† (evaluation)
Reached from Load screen, NDReimbursement
Source src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs

BR-APP-002

Field Value
Title Missing user is rejected
Statement A request without a CurrentUserId is rejected: PopulateModel sets ErrorMessage to "Invalid User" and returns false.
Trigger PopulateModel
Enforcement Check in NDReimbursementsModel.PopulateModel
Outcome No data is loaded. The guard returns before PopulateModel assigns HasPolicyNumber, so that property keeps the earlier value set in OnRequestStart from Header. The view's ErrorMessage block renders only when !IsSuccessful && !HasPolicyNumber, so whether "Invalid User" is displayed depends on that pre-existing value
Origin Application
Reached from Load screen, Change policy context, Pay by mail, Override due date, Delete statement, NDReimbursement
Source src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs

BR-APP-003

Field Value
Title Capability flags are derived per request
Statement The page derives the flags IsInternalUpdater, IsExternalUpdater, IsInternalITUser, CanPrint, IsInternalReadOnly and IsExternalReadOnly on every request. A user with none of the four NDR roles is denied first by the page-level [SecurityApiAuthorize] gate, which admits only those four roles, so such a request is ordinarily rejected before PopulateModel. If the fallback branch in PopulateModel is reached, it sets IsInvalidUser and ErrorMessage to "Not Authorized" and returns false; that message is not guaranteed to be displayed (see Outcome).
Trigger PopulateModel
Enforcement NDReimbursementsModel.PopulateModel
Outcome The view is shaped by the flags. The handlers do not enforce the flags (TD-APP-003). In the fallback branch the handler sets the error state only; the view's ErrorMessage block renders only when !IsSuccessful && !HasPolicyNumber, so display depends on the HasPolicyNumber value.
Origin Application
Reached from Load screen, Change policy context, Pay by mail, Override due date, Delete statement, NDReimbursement
Source src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs

BR-APP-004

Field Value
Title External updaters cannot change policy context
Statement External updaters may not change the policy context: ChangeContextPrivilege = !IsExternalUpdater.
Trigger Page model construction
Enforcement NDReimbursementsModel constructor
Outcome The context switch is hidden in the layout**. The server does not enforce the restriction on the reload-context handler.
Origin Application
Reached from Change policy context
Source src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs

BR-APP-005

Field Value
Title Developer-access type overrides role flags
Statement The developer-access type overrides the role flags: PolicyHolder forces IsExternalUpdater and DueDate forces IsInternalUpdater.
Trigger The DevAccess handler
Enforcement NDReimbursementsModel
Outcome The UI flags escalate to updater capabilities. The handler has no IT or QA check (TD-APP-002).
Origin Application
Reached from NDReimbursement (direct POST only; the form is commented out in the view)
Source src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs

BR-APP-006

Field Value
Title POST handlers skip anti-forgery validation
Statement Every POST handler runs without anti-forgery validation.
Trigger Every POST
Enforcement [IgnoreAntiforgeryToken] on NDReimbursementsModel, in addition to the same attribute on BolMenuModel†
Outcome The handlers are exposed to cross-site request forgery (TD-APP-001)
Origin Application
Reached from Save requested amounts, Pay by mail, Pay online, Override due date, Delete statement, NDReimbursement
Source src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs

BR-APP-007

Field Value
Title Form value limit of 30000
Statement The request-form size limit is 30000 values.
Trigger A form post
Enforcement [RequestFormLimits(ValueCountLimit = 30000)] on NDReimbursementsModel
Outcome Large claim tables can be posted
Origin Application
Reached from Save requested amounts, Pay by mail
Source src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs

BR-APP-008

Field Value
Title Path base and empty route
Statement The application is served under the path base /NDReimbursementWebApp, and the empty route maps to the NDReimbursement page.
Trigger Every request
Enforcement UsePathBase and AddPageRoute("/NDReimbursement", "") in Startup
Outcome URL shaping
Origin Application
Reached from Load screen, NDReimbursement
Source src/NDReimbursementWebApp/Startup.cs

Screen business rules

Rules enforced directly in the NDReimbursement page, its manager or its services rather than delegated to a package.

BR-SCR-001

Field Value
Title Due date effective at 18:00
Statement The due date is effective at 18:00. After that time claims are read-only (DueDatePassed).
Trigger Load and render
Enforcement NDReimbursementManager.GetDateData and NDReimbursementsModel
Outcome Claims render read-only
Origin NDReimbursement
Reached from Load screen, NDReimbursement
Source src/NDReimbursementWebApp/Managers/NDR/NDReimbursementManager.cs; src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs

BR-SCR-002

Field Value
Title Due-date override window
Statement A due-date override must be between today and the due date plus 90 days. Only the UI limits enforce this.
Trigger The due-date override form
Enforcement NDReimbursementsModel computes the limits and wwwroot/js/DatePicker.js applies them
Outcome The server does not re-check the window (TD-APP-008)
Origin NDReimbursement
Reached from Override due date, NDReimbursement
Source src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs; src/NDReimbursementWebApp/wwwroot/js/DatePicker.js

BR-SCR-003

Field Value
Title Claim editability
Statement A claim is editable only when the due date has not passed and its allowed amount is greater than zero.
Trigger Render
Enforcement NDReimbursementManager
Outcome The requested-amount input is editable
Origin NDReimbursement
Reached from Load screen, NDReimbursement
Source src/NDReimbursementWebApp/Managers/NDR/NDReimbursementManager.cs

BR-SCR-004

Field Value
Title Cash-flow claim flag
Statement A claim whose ReimbursementBillCode is CF is flagged as cash flow.
Trigger Render
Enforcement NDReimbursementManager
Outcome A warning indicator is shown
Origin NDReimbursement
Reached from Load screen, NDReimbursement
Source src/NDReimbursementWebApp/Managers/NDR/NDReimbursementManager.cs

BR-SCR-005

Field Value
Title Reimburse all
Statement Reimburse all sets each requested amount to the allowed amount.
Trigger The Reimburse all handler
Enforcement NDReimbursementsModel and NDReimbursementManager
Outcome The claims are updated and the screen is redisplayed
Origin NDReimbursement
Reached from NDReimbursement
Source src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs; src/NDReimbursementWebApp/Managers/NDR/NDReimbursementManager.cs

BR-SCR-006

Field Value
Title Reimbursable claims exist
Statement Reimbursable claims exist when claims are editable and either Reimburse all applies or the user is a policyholder.
Trigger Render
Enforcement NDReimbursementsModel
Outcome The Reimburse all button renders only then
Origin NDReimbursement
Reached from Load screen, NDReimbursement
Source src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs

BR-SCR-007

Field Value
Title Pay-online amount check
Statement Pay online requires 0 < total <= max, where max is supplied by the client.
Trigger The Pay online handler
Enforcement NDReimbursementsModel
Outcome When the check fails no payment request is created (the response is null). The client-supplied maximum is a weakness (TD-APP-006).
Origin NDReimbursement
Reached from Pay online, NDReimbursement
Source src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs

BR-SCR-008

Field Value
Title Pending online payments
Statement Pending online payments, meaning the NDR flag or a digital-payment count above zero, block the "claims saved" state. A 404 from the digital payment API counts as zero.
Trigger Load
Enforcement NDReimbursementsModel and DigitalPaymentService
Outcome A tooltip is shown and the state changes
Origin NDReimbursement
Reached from Load screen, NDReimbursement
Source src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs; src/NDReimbursementWebApp/Services/DigitalPaymentService.cs

BR-SCR-009

Field Value
Title Invalid policy and no NDR statements
Statement When GetPolicyStatements throws an HTTP status exception, the handler sets HasInvalidPolicyNumber and ErrorMessage ("is not a valid policy number" for HTTP 400) and returns false; it does not set HasNDR false. When there are no NDR statements, HasNDR is false and NdrWarningMessage is set.
Trigger Load
Enforcement NDReimbursementsModel
Outcome Handler: flags and messages are set and loading stops. View: the ErrorMessage block renders only when !IsSuccessful && !HasPolicyNumber and HasInvalidPolicyNumber is not referenced, so the invalid-policy message is not rendered while a policy number is present; the warning message shows only when ErrorMessage is empty
Origin NDReimbursement
Reached from Load screen, NDReimbursement
Source src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs

BR-SCR-010

Field Value
Title Developer-access options
Statement The user options (developer access types) depend on the policy number and the selected type.
Trigger Load
Enforcement NDReimbursementManager and NDReimbursementsModel
Outcome The dropdown content changes. The dropdown form itself is commented out in the view.
Origin NDReimbursement
Reached from Load screen, NDReimbursement
Source src/NDReimbursementWebApp/Managers/NDR/NDReimbursementManager.cs; src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs

BR-SCR-011

Field Value
Title Claims area render condition
Statement The claims area renders only when HasPolicyNumber && HasNDR && AccessAllowed. AccessAllowed comes from the base page model†.
Trigger Render
Enforcement Razor view Pages/NDReimbursement.cshtml
Outcome The claims area is hidden otherwise
Origin NDReimbursement
Reached from Load screen, NDReimbursement
Source src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml

No model validation exists: no handler checks ModelState and no data annotations or FluentValidation are used (TD-APP-012).

Inherited business rules

Rules that reach the application through base classes and attributes provided by BolMiddleware and SAIF.NetCore.AuthService. They are enforced by inherited behavior, not by code in this repository. The consuming type for every rule is NDReimbursementsModel (or Startup) in this application.

INH-001

Field Value
Title Web context resolution order
Statement The BOL web context resolves in order: BolContext cookie, re-read cookie, referring application, WebContextId form value or cid query value, session, new context.†
Trigger Every page request
Enforcement BolContextModel lifecycle in the base page-model chain
Outcome The context carries the policy number the screen loads
Origin BolMiddleware† — BolContextModel
Reached from Load screen, Change policy context
Consuming type NDReimbursementsModel in this application

INH-002

Field Value
Title Soft policy access check
Statement Policy access is validated through IsValidPolicyForCurrentUser. A failure sets an error message and AccessAllowed = false. Enforcement is soft: the derived page must check AccessAllowed.†
Trigger Policy header load
Enforcement BolPolicyModel; the page checks AccessAllowed in Pages/NDReimbursement.cshtml (BR-SCR-011)
Outcome The claims area is hidden. Handlers do not check the flag.
Origin BolMiddleware† — BolPolicyModel
Reached from Load screen, NDReimbursement
Consuming type NDReimbursementsModel in this application

INH-003

Field Value
Title Remote service failures replaced with defaults
Statement Failures in the remote context, menu and policy header services are logged and replaced with empty or default results.†
Trigger A failing BOL context, menu or policy header call
Enforcement Base page-model chain
Outcome The page loads with empty chrome or defaults instead of failing
Origin BolMiddleware† — BolContextModel, BolMenuModel, BolPolicyModel
Reached from Load screen, Change policy context
Consuming type NDReimbursementsModel in this application

INH-004

Field Value
Title External user definition
Statement A user is external when the domain of the authenticated identity name is not SAIF. External users get profile and logoff links.†
Trigger Layout and context load
Enforcement BolMiddleware identity handling
Outcome Drives the external-user outcomes of role checks and menu links
Origin BolMiddleware† — BolPolicyModel
Reached from Load screen
Consuming type NDReimbursementsModel in this application

INH-005

Field Value
Title External policy association filtering
Statement For external users, policy associations are filtered by user type: POLCY keeps those for the customer id, AGNCY keeps those whose policy AgencyId matches.†
Trigger Policy header and dropdown load
Enforcement BolMiddleware policy header service
Outcome External users see only their own policies
Origin BolMiddleware† — BolPolicyModel
Reached from Load screen, Change policy context
Consuming type NDReimbursementsModel in this application

INH-006

Field Value
Title Session policy header reuse
Statement A session policy header is reused only when it matches the requested policy number. Otherwise it is fetched and saved to session.†
Trigger Policy header load
Enforcement BolMiddleware policy header service
Outcome Avoids a stale header for a different policy
Origin BolMiddleware† — BolPolicyModel
Reached from Load screen, Change policy context
Consuming type NDReimbursementsModel in this application

INH-007

Field Value
Title Policy dropdown ordering and duplicates
Statement Policy dropdown entries sort by policy number descending with the current selection first. Duplicate policy numbers raise ArgumentException.†
Trigger Policy dropdown build
Enforcement BolMiddleware menu and header components
Outcome Ordered dropdown, or an exception for duplicates
Origin BolMiddleware† — BolMenuModel
Reached from Load screen, Change policy context
Consuming type NDReimbursementsModel in this application

INH-008

Field Value
Title BolContext cookie attributes
Statement The BolContext cookie lives ten seconds and is HttpOnly, without Secure or SameSite.†
Trigger Saving the web context
Enforcement SaveContext in the base page-model chain
Outcome The cookie is sent over any scheme and in cross-site requests
Origin BolMiddleware† — BolContextModel
Reached from Change policy context
Consuming type NDReimbursementsModel in this application

INH-009

Field Value
Title SecurityApiAuthorize OR semantics
Statement [SecurityApiAuthorize("A,B")] sets policy SecurityAPI.A,B. Roles are evaluated with OR semantics through the remote Security API.†
Trigger Every request to the page (BR-APP-001)
Enforcement SecurityApiAuthorize and its policy provider
Outcome A user holding any one listed role is admitted
Origin SAIF.NetCore.AuthService† — SecurityApiAuthorize
Reached from Load screen, NDReimbursement
Consuming type NDReimbursementsModel in this application

INH-010

Field Value
Title Domain stripped before the Security API call
Statement The handler strips the Windows domain before calling the Security API. SecurityClient rewrites backslashes in user ids to forward slashes.†
Trigger Role evaluation
Enforcement SecurityApiHandler and SecurityClient
Outcome The Security API receives a domain-less user id
Origin SAIF.NetCore.AuthService† — SecurityApiHandler
Reached from Load screen
Consuming type NDReimbursementsModel in this application

INH-011

Field Value
Title Security API failure throws
Statement A non-successful Security API response throws SecurityClientException rather than denying normally.†
Trigger Role evaluation when the Security API fails
Enforcement SecurityClient
Outcome The request fails with an exception instead of an access-denied result
Origin SAIF.NetCore.AuthService† — SecurityClient
Reached from Load screen
Consuming type NDReimbursementsModel in this application

INH-012

Field Value
Title Windows users authorize remotely
Statement Token users authorize locally through a role claim first, then through the Security API. Windows users always authorize remotely.†
Trigger Role evaluation
Enforcement SecurityApiHandler
Outcome Windows-authenticated users incur a Security API call on each evaluation
Origin SAIF.NetCore.AuthService† — SecurityApiHandler
Reached from Load screen
Consuming type NDReimbursementsModel in this application

Rules not reachable from this application

None. The application has no local libraries, so no library-documented rule is excluded. INH-001 to INH-012 are reachable through the page-model base chain, Startup or the SecurityApiAuthorize attribute. The packages DigitalPaymentAPIClient, DocumentsCoreAPI.Client, NDReimbursementAPI.Client and OneIncAPIClient have no retrievable rules, so what they enforce is unknown**.

Note: Statements marked with † are derived from dependency library documentation via the Legends CLI. Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs
  • src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml
  • src/NDReimbursementWebApp/Managers/NDR/NDReimbursementManager.cs
  • src/NDReimbursementWebApp/Services/DigitalPaymentService.cs
  • src/NDReimbursementWebApp/Startup.cs
  • src/NDReimbursementWebApp/wwwroot/js/DatePicker.js