# Technical documentation — RGBC_ScoreCard

Evidence date: 2026-10-05.

Source: `git@bitbucket.org:overdrive/rgbc_scorecard.git`, `master` at `c1c7ceb` (2026-08-04).

## Stack

| Item | Evidence |
|---|---|
| Language | VB.NET for the site. One C# file: `Mobile/Default.aspx.cs` (empty load, Mozilla MPL header) |
| UI | ASP.NET Web Forms, master pages, `SqlDataSource`, repeaters, GridView |
| Framework | `RGBC ScoreCard.vbproj` `TargetFrameworkVersion` **v4.6.1**. `Web.config` `<compilation targetFramework="4.6.2">`. **Requires confirmation** which one is deployed |
| Assembly | Title `RGBC ScoreCard`, version `1.0.0.1`, file version `1.0.0.0`, copyright 2018, GUID `0e426282-dd08-4893-8e11-215b43544e21` |
| Master version label | Constant `1.2.0`, date string `1 September 2018`, plus `[Dev]` or `[Live]` from the DEBUG compile symbol |
| Web server | **Inferred** IIS, because of Web Forms, `Web.config`, and Windows authentication. No IIS script is in the repo |
| Database | SQL Server (`System.Data.SqlClient`). No `.sql` schema script and no migrations |
| Reports | `Microsoft.Reporting.WebForms.LocalReport`, embedded `PeopleBalanceSheetReport.rdlc` and subreport `PeopleBalanceSheetSubReport_Questions.rdlc` |
| Front-end libraries | jQuery 2.0.3, jQuery UI 1.10.3, Modernizr 2.6.2, a local calendar control |
| Mobile detection | User-agent regex in `setMasterPage`, plus a checked-in `51Degrees.mobi.config` (package 2.1.19.4) |

`packages.config` also lists Entity Framework 5, DotNetOpenAuth 4.1.4, ASP.NET Universal Providers, Web Optimization, WebGrease, Newtonsoft.Json 5.0.8. Page code that was read uses ADO.NET and `SqlDataSource`, not EF or OpenAuth.

## Repository layout

```text
rgbc_scorecard/
  .gitignore                  # ignores RGBC_ScoreCard/.env
  $tf                         # TFS local metadata
  Backup 20170306/            # one old SalesCapabilities.aspx
  BuildProcessTemplates/      # TFS 11 XAML templates
  RGBC_ScoreCard/
    .env.example
    RGBC_ScoreCard.sln
    RGBC_ScoreCard/           # web root
      *.aspx, *.master
      Web.config
      SecureConfig.vb
      db.generic.vb
      App_Code/VB/
      Data Sources/           # typed datasets
      Reports/PDF/            # generated PDT PDFs checked in
      My Project/PublishProfiles/
```

The web project folder name inside the solution directory is also `RGBC_ScoreCard`. Paths in this document use the inner web root unless they say otherwise.

`obj/`, `bin/`, and `.vs/` are in the clone. They are build outputs. Behaviour was read from the source files, not from `obj/Release/Package`.

## Application structure

| Path | Responsibility |
|---|---|
| `Global.asax.vb` | Empty application events |
| `Index.aspx` | Login and session clear. Default document |
| `Home.aspx` | Dashboard |
| `PeopleBalanceSheetNew.aspx` | Current survey |
| `Survey.aspx` | Survey grid |
| `Questionnaire.aspx`, `QuestionEdit.aspx` | Question bank |
| `TeamSetup.aspx`, `TeamSetupEdit.aspx` | Role and manager |
| `OverallPerformance.aspx` | Multi-year grid |
| `HelpPeopleBalanceSheet.aspx` | Images |
| `ScoreCard.aspx`, `SalesCapabilities.aspx` | Older flows, menu commented out |
| `PeopleBalanceSheet.aspx`, `zPeopleBalanceSheet.aspx`, `sandbox.aspx` | Older copies |
| `Admin.Master`, `Mobile.Master` | Shell and menu. `Site.Mobile.Master` is a separate, older mobile shell and is not what `setMasterPage` returns |
| `SecureConfig.vb` | `.env` and connection lookup |
| `EnvConnectionStringsExpressionBuilder.vb` | `<%$ EnvConnectionStrings:Name %>` |
| `db.generic.vb` | Shared `SqlConnection`, `doQuery`, `getRow`, `CleanString`, `nz` |
| `db.cls.vb` | `xdb` subclasses `db` |
| `App_Code/VB/SystemFunctions.vb` | `LogginUser`, `setMasterPage`, date and fiscal helpers |
| `App_Code/VB/ProjectFunctions.vb` | User SQL, logging, unused Brand QF and promo helpers |
| `App_Code/VB/Duodecimal.vb` | Number-base helper. No page caller was found |

`Admin.Master` references `Scripts/scripts.js`. That file is not in the `Scripts` folder.

## Configuration and secrets

`Web.config` `<connectionStrings>` is empty. A comment says names are kept for `SqlDataSource`.

`SecureConfig.MapConnectionNameToEnvVar`:

| Config name still used in markup | Environment variable |
|---|---|
| `SuperbowlConnectionString` | `RGBC_SCORECARD_CONNECTION_STRING` |
| `SuperbowlConnectionStringLIVE` | `RGBC_SCORECARD_CONNECTION_STRING_LIVE` |
| `SuperbowlConnectionStringDEV` | `RGBC_SCORECARD_CONNECTION_STRING_DEV` |

`GetDbConnectionString` (the shared `db.conn` used by `doQuery`):

- DEBUG compile: `RGBC_SCORECARD_DB_CONNECTION_DEBUG`, else `RGBC_SCORECARD_CONNECTION_STRING`.
- RELEASE compile: `RGBC_SCORECARD_DB_CONNECTION_RELEASE`, else `RGBC_SCORECARD_CONNECTION_STRING`.
- Missing value throws.

`.env.example` lists those five variables and says to copy it to `.env` next to the web project (parent of the site physical path). `.gitignore` ignores `RGBC_ScoreCard/.env`. `LoadDotEnvFile` sets process environment variables and returns without error if the file is absent.

Typed dataset `dsSurvey.xsd` still records the old property name `SuperbowlConnectionString`. `OverallPerformance.aspx` is the page that binds `SuperbowlConnectionStringDEV`. Other live pages bind `SuperbowlConnectionString`.

Application settings that are not secrets:

| Setting | Committed value |
|---|---|
| `intDecimals` | `1` |
| `intColumnWidthDefault` | `56` |
| `intColumnWidthRegion` | `105` |
| `SMTPHost` | `10.0.0.17` |
| `dtSeasonStart` | `01-01` |
| `dtSeasonEnd` | `12-31` |
| `SQLConnectionDebug` / `SQLConnectionRelease` | empty elements |

Other `Web.config` facts:

- `<authentication mode="Windows" />`
- `<sessionState mode="InProc" />` with a provider entry. No `timeout` attribute. ASP.NET's default of 20 minutes is **not** confirmed as what IIS uses.
- `<customErrors mode="Off" />`
- `<trace localOnly="false" mostRecent="true" pageOutput="true" />`
- `<roleManager enabled="false" />`
- Membership provider is configured against `DefaultConnection`, which is not in `<connectionStrings>`
- `<httpRuntime requestValidationMode="2.0" />`
- Default document `Index.aspx`

`Web.Debug.config` and `Web.Release.config` exist. They were not the source of the connection-string removal; the base `Web.config` already has an empty connection section.

A commented SMTP credential remains in `PeopleBalanceSheetNew.aspx.vb`. Do not copy it into new docs or tickets. Remove it from source in a code change; that change is outside this documentation task.

## Authentication

1. IIS authenticates the Windows user (**inferred** from config).
2. `LogginUser` looks up:

```sql
SELECT *
FROM mstUserGroupScoreCard
INNER JOIN mstUser
  ON mstUserGroupScoreCard.UserGroupID = mstUser.refUserGroupScoreCardID
WHERE mstUser.strDomainLogin = '<identity>'
```

3. Session keys: `USER` (the data row), `USERNAME`, `USERID`, `USERGROUP`.
4. Insert into `mstUsageLog (mstUserID, dtStamp, strSystem)` with `strSystem = 'Forecast'` and a `yyyyMMddHHmmss` stamp. Then `Thread.Sleep(13)`.

There is no forms-login ticket that the app checks later. `Index.aspx` still calls `FormsAuthentication.SignOut()`.

Session rebuild: Home and the PDT page call `LogginUser` when `Session("USER")` is nothing. The master page, in a release build, redirects to `Index.aspx?M=1` before that if the session was already empty at master `Page_Load`. Master `Page_Load` runs after the content page `Page_Load` (comment in `Admin.Master.vb`). Order is easy to get wrong. **Requires confirmation** against a running site if session-loss behaviour matters.

Commit `60534ed` cleared the session at the start of PDT load and save, which forced a new login each time. That `Session.Clear()` is not in the current PDT page.

## Data

No CREATE TABLE scripts. Tables and views named by SQL in the current pages:

| Object | Used for |
|---|---|
| `mstUser` | People, domain login, email, region, `blnManager`, `blnView`, `refUserGroupScoreCardID` |
| `mstUserGroupScoreCard` | Group name (`strUserGroup`) |
| `scrUser` | Job role (`refQuestionnaireID`) and manager (`refManagerID`) |
| `scrQuestionnaire` | Named questionnaires |
| `scrQuestion` | Questions, category, option type, order, active, comments flag |
| `scrSurvey` | Header: date, reviewer, questionnaire, employee, status, manager comments, shared values |
| `dwfScoreCard` | Answer rows copied at save time |
| `vieSCRManager` | Permission read on an existing survey |
| `sysQuery` | Email HTML, ids 42 and 62 |
| `mstUsageLog` | Login audit |
| `stgSuperbowlLog` | `WriteLog` default table |
| `dwdCustomer`, `mstRep` | Store lookup on the old scorecard page |
| `mstCompany`, `mstPeriod` | Fiscal helpers with no page caller |
| `sysCronJob`, `logPromo` | Helpers with no page caller |

`dwfPeopleBalanceSheet` appears only in commented SQL.

PDF header query (`dsSurvey.xsd`) joins `scrSurvey` to the employee and to the manager through `scrUser.refManagerID`, and selects region from the manager row.

Database name, server, and whether LIVE and DEV are different catalogs are **Unknown / Requires Confirmation**. They live only in environment variables.

## Survey save path

First save (`SurveyID = 0`) uses `SecureConfig.GetDbConnectionString()` and a `SqlTransaction`:

1. `INSERT scrSurvey (..., strStatus) VALUES (..., 'Draft')` and `SCOPE_IDENTITY()`.
2. `INSERT dwfScoreCard` per question, parameterized.
3. Commit, then redirect to `PeopleBalanceSheetNew.aspx?SurveyID=`.

Updates use string-built `UPDATE` statements through `db.doQuery`.

`GetQuestionOptionTypeAndAnswer` throws if a radio has no value. That message is shown on the page.

## PDF and email

`createPDF` renders the embedded RDLC to a byte array, tries to write `Reports/PDF/{fileName}.pdf`, and returns the bytes even if the disk write fails.

`sendEmail` attaches the bytes. If the byte array is empty and a file with that name already exists, it attaches the file instead.

`SmtpClient` is constructed with `My.Settings.SMTPHost` only. Port, SSL, and credentials are not set on the live path. The commented credential block is not active.

Submit order: `UPDATE strStatus = 'Submitted'`, then `sendEmail()`, then `Redirect` to Home. Email failure is logged and does not undo the status.

## Deployment

Publish profiles are filesystem copies, not a server definition:

| Profile | URL | Delete existing |
|---|---|---|
| `ScoreCard_Module.pubxml` | `C:\Scorecard` | false |
| `SrC - PJ.pubxml` | `C:\Users\PJ\Desktop\SrC` | true, last configuration Release |

No Docker file, no Bitbucket Pipelines file, no web deploy publish profile, and no `sonar-project.properties` on this revision. The OVER-259 snapshot listed a Sonar properties file and `sonarqube_scan.bat` at the root. They are not on `c1c7ceb`.

Where the site is hosted, and whether a pipeline exists outside this repository, is **Unknown / Requires Confirmation**.

## Background work

None. No Windows service, no scheduled task definition, no queue consumer. `sql_insert_BrandQF_Job` writes `sysCronJob` rows of type `BrandQF`, and nothing in the pages calls it.

## Logging and monitoring

`ProjectFunctions.WriteLog` inserts into `stgSuperbowlLog` (`strStamp`, `dtLog`, `strType`, `strProcess`, `strAction`, `txtLog`, `blnEmail`). Survey load, save, PDF, and email paths call it.

There is no application metrics or health endpoint in the tree.

`Web.config` trace is enabled with page output for non-local clients.

## Testing

No test project, no test files, and no CI definition were found.

## Security notes for reviewers

Observed in this revision. Not a pentest.

- Identity override via query string.
- Trace and custom errors expose detail.
- Commented mailbox password in `PeopleBalanceSheetNew.aspx.vb`.
- Employee PDT PDFs committed under `Reports/PDF`.
- SQL built by concatenation outside the transactional insert.
- Menu hiding is the only barrier on admin pages.
- Connection names still say Superbowl. A wrong env var name fails fast with `InvalidOperationException` or `ArgumentOutOfRangeException`.

## Development process

History is on Bitbucket `master`. Recent work landed through pull requests (`feature/TASK-001-pdt-survey-hardening`, PR #2). Commit subjects since 2026-07 use a `TASK-001` tag. There is no `docs/` folder and no task file in the repository.

Local secret file: copy `RGBC_ScoreCard/.env.example` to `RGBC_ScoreCard/.env`. The loader looks in the parent of the site physical path, which matches that location when the site root is the inner `RGBC_ScoreCard` folder.
