# Business rules — ieb-inde-6

Evidence date: 2026-10-12. Inspected revision: `main` at `d9e4836`.

Rules below are **Inferred** from implementation unless the heading says **Documented**. None of these rules were found in a separate business-rules document. The readme does not state them.

Website root: `INDE-6/Evolution Software Unified Framework/Evolution Software Unified Framework/core_custom/INDE-6/`.

## Site identity

### BR-001 — Moderator provisioning runs only for setup code INDE-6

**Inferred.** `surface_form.ascx.cs` calls `CreateUserForModerator` and `RegionalModerationSubjectUpdated` only when `handler.ReturnSetup().code` equals `INDE-6` and the surface name is `RegionalModerators`.

The same save method still contains a registration email path for setup code `SHOU-1`. That path is not an INDE-6 rule.

### BR-002 — Postbox is the name used in seeded mail

**Documented** in SQL, **Implemented** as seed data:

- Subject to schools: `IEB Postbox - New Document Notice [{ParentFolder}]` (`INDE-6-1.0.1`).
- Subject to IEB: `IEB Postbox - New Document Submission [{SchoolName - SchoolType}]` (`INDE-6-1.0.3`).
- Submissions mailbox seeded as `submissions@ieb.co.za` (`INDE-6-1.0.4`).

The application reads the setup columns at send time. A later database edit would change the live subject without a code change.

## Canvases and folders

### BR-003 — A group postbox opens three canvases

**Inferred.** On save, if a canvas with that parent id and name does not exist, the form creates Materials, Correspondence, and Records canvases. Names drop whitespace from the group name and append `P` or `S`. User types stored on those canvases are `1,2,3,4`. Module id on the metadata row is `65` (File Explorer).

### BR-004 — Master folders are the source of a new canvas directory

**Inferred.** Group masters: `~/upload/explorer/_{Primary|Secondary}Master_{Materials|Correspondence|Records}`.

Regional-moderation masters: `~/upload/explorer/_{Primary|Secondary}Master_RegModDocs` and `_RegModReport`.

`CopyDirectory` throws if the source directory does not exist. It copies subdirectories only; it does not copy files that sit directly in the source root (the loop iterates `GetDirectories` and not `GetFiles`).

### BR-005 — Parent canvas ids are fixed literals

**Inferred.** `PostboxCanvasNums.ParentCanvas` uses Materials `5561`, Records `2109`, Correspondence `3148`, Submissions `2129`, GroupPostbox `6097`, SchoolSubmissions `6098`, Circulars `2113`. School type lookup ids are Primary `1094` and Secondary `1095`.

These match a database only if that database was given the same identity values. **Requires Confirmation.**

### BR-006 — School type from a canvas display is the bracket letter

**Inferred.** `DetermineSchoolNameAndType` expects `...: {name} [{letter}]`. Letter `S` becomes `Secondary`. Any other letter becomes `Primary`. Missing `:` leaves the name and type unchanged (empty if the caller started with empty strings).

`CreateCanvas` instead treats a bracket token that contains `P` as Primary and every other token as Secondary.

### BR-007 — A new regional-moderation canvas is restricted

**Inferred.** `CreateSpecificCanvas` sets `isAccessible`, `isActive`, `isRestricted`, and `isPanelShown` true, `userTypes` `1,2,3,4,5`, and `customUsers` to the moderator id only. File-explorer config sets view, add, and delete to `1`, max size 100 MB, page size 20.

The framework's meaning of role value `1` was not re-derived. **Requires Confirmation** that `1` means "allowed".

## Uploads and mail

### BR-008 — Only a new file sends mail

**Inferred.** `StoreFile` updates metadata when a row already exists and does not call the email methods. Mail runs only in the insert branch.

### BR-009 — Path tokens choose the upload workflow

**Inferred.** Evaluated in this order:

1. Path contains `groupMaterials`, `groupCorrespondence`, or `groupRecords` → replicate to linked schools and email each destination.
2. Path contains `submissions` → replicate to school submissions and email the source.
3. Path contains `regmoddocs` (case-insensitive) → regional-moderation document email, no copy.
4. Path contains `regmodreport` (case-insensitive) → copy into `RegionalModeration` and email the report notice.
5. Otherwise → `SendPostboxEmail`.

`submissions` is matched case-sensitively against the lowercased enum name. `groupMaterials` is matched case-sensitively against the concatenated token.

### BR-010 — School notices go to active contacts of that school and type

**Inferred.** Materials, Records, and Correspondence displays resolve school name and type from the canvas display, then load `publ_` `oSchoolContacts` where `isActive`, school name, and school type match. Addresses are separated with `;`. No contacts means no email.

The contact's IEB-liaison and principal flags are not filters on this query.

### BR-011 — Submissions go to the setup submissions address

**Inferred.** Display containing `Submissions` sends to `handler.ReturnSetup().submissionsEmail`, not to school contacts. The body still includes school name and type. Empty submissions address skips the send.

From address for both school and IEB mail is `communicationEmail`. The send is `Task.Run` around `communication.SendAnEmail`.

### BR-012 — Circulars and newsletters do not send Postbox mail

**Inferred.** `SendPostboxEmail` has branches only for Materials, Correspondence, Records, and Submissions. A circular or newsletter that reaches the final `else` builds no message.

Circulars do change the default grid sort to name ascending (`ParentCanvas.Circulars` = `2113`).

### BR-013 — Group replication emails the destination, not the group file

**Inferred.** After a successful copy, `SendPostboxEmail` is called with the destination metadata. A per-school exception is logged and the loop continues.

### BR-014 — School submission folders split on the last character of the canvas name

**Inferred.** If the source canvas name ends with `p` (compared after `ToLower` on the last character only), the destination folder is `Primary`. Otherwise it is `Secondary`. Origin text is `{school} [{first character of the resolved school type}]`.

This is a different test from BR-006.

### BR-015 — Regional document mail depends on the uploader's user type

**Inferred.**

- `WebsiteUser` or `PowerUser`: recipient is the regional moderator email on the matching active `RegionalModerationSubjects` row. BCC is `communicationEmail`. Templates are the "to Moderator" subject and body.
- Any other type, including `CustomUser`: recipients are active school contacts. Templates are the school subject and body.

If the recipient string is empty, nothing is sent. Failures are caught and logged.

`CreateUserForModerator` stores `userType` CustomUser and `mimicUserType` WebsiteUser. BR-015 does not read `mimicUserType`. A moderator created by that method does not take the moderator mail branch unless something else changes `userType` before they upload.

### BR-016 — A regional report notice is sent to the communication mailbox

**Inferred.** `SendRegModReportUploaded` sets both from and to to `communicationEmail`. The subject and body are the moderator templates (school postbox name and unique subject). It does not mail the moderator or the school contacts. Empty `communicationEmail` skips the send.

The file is also copied under `RegionalModeration/{Primary|Secondary}/{unique subject}`. Primary is chosen when the resolved school type starts with `P`.

### BR-017 — Template lookup is by exact template name and Postbox template type

**Inferred.** `GetPostboxTemplate` loads templates of type `pNums.TemplateType.Postbox` and returns the first whose `templateName` equals the requested name, ordinal ignore case. No match returns an empty body, and the send still runs.

Welcome mail is different: it scans `OutboundResponse` templates for a name that contains `welcome email` and prefixes the subject with `IEB - `.

Placeholders replaced on Postbox bodies include `{logo}`, `{ParentFolder}`, `{SubfolderPath}`, `{FileName}`, `{UploadedBy}`, `{UploadDate}`, and for some templates `{SchoolName}`, `{SchoolType}`, `{SubjectName}`. The logo URL is `{WebAddy}/images/logo.png`.

### BR-018 — Parent folder labels are fixed strings

**Inferred.** `DetermineParentFolder` maps a canvas name that contains a display token to:

| Token contained | Label |
|---|---|
| Materials | Assessment Materials |
| Records | Assessment Records |
| Correspondence | Correspondence |
| Submissions | School Submissions |
| Circulars | Circulars |
| Newsletters | Newsletters |
| RegModDocs | Regional Moderation Documents |
| RegModReport | Regional Moderation Report |

The first enum match in declaration order wins. No match returns an empty label.

## Moderators and subjects

### BR-019 — One login per email per customer code

**Inferred.** `CreateUserForModerator` checks `pal_` users for `email` plus setup `code`. If the row exists, it returns true and does not update the user, the canvas, or the password. The commented throw for "already exists" is not active.

A new user is `CustomUser`, mimics `WebsiteUser`, `isTermsAccepted` true, `isReset` true, `isActive` true, `resetCode` a 6-character random string, password an encrypted 8-character random string. The user id is appended to `SchoolPostbox` canvas `customUsers` with a leading comma. Welcome mail is required for success; a failed send throws. A save that does not return a positive `recId` throws.

This block runs only when the surface item `recId` is `0` (first save). Later edits do not create another user. Subject assignment still runs on later saves.

### BR-020 — Up to three subjects, each with a school list

**Inferred.** Fields whose names end with `Subject1`, `Subject2`, `Subject3` supply the unique subject text. Fields whose names end with `Subject1Schools`, `Subject2Schools`, `Subject3Schools` supply comma-separated school postbox item ids. Each pair is processed even when an earlier pair is empty. An empty school list or empty subject returns false from `RegionalModerationSubjectUpdated` and the caller ignores that false result.

### BR-021 — A subject row is not duplicated for the same school and unique name

**Inferred.** Existence requires an active `RegionalModerationSubjects` row with that unique name and school postbox name. School postbox names have single quotes doubled in the filter. The inserted row copies level, code, name, and unique name from active `SubjectManagement` via `Subjects_SubjectDetails_SubjectUniqueName`.

### BR-022 — Canvas names strip punctuation

**Inferred.** Display keeps the readable form `Reg Mod Docs:{school postbox} - {unique subject}` (and the report equivalent). The stored canvas `name` removes space, colon, dot, parentheses, quote, comma, brackets, hyphen, and slashes. Existence is checked with a contains query on that stripped name.

### BR-023 — An empty address line 5 becomes South Africa

**Inferred.** `SetAddressFieldValue` writes `~5~South Africa~|~` when the fifth comma-separated part is empty. This is used by the regional-moderation field builder.

## Downloads and files

### BR-024 — A download writes a tracking row before the response

**Inferred.** Single file: one row. Multi-select: one row per expanded file, then the zip is returned as `Combined.zip`. The row stores the session user's name, surname, and email, the file name, parent folder, subfolder, school name, and metadata id. The surface name loaded for the new item is `FileExplorerDownloads`.

### BR-025 — Replacing a file keeps the old metadata identity

**Inferred.** `StoreFile` finds an existing row by canvas, file explorer type, path, and name, then updates date, type, size, and uploaded-by. It does not call `base.StoreFile` in the update branch (the physical store is only in the insert branch). **Requires Confirmation** of what the operator sees when they upload a file that already has metadata.

### BR-026 — Delete removes the metadata row that matches path and name

**Inferred.** File delete and directory delete each delete one metadata row (the loop breaks after the first) and then call the base delete.

## Access

### BR-027 — Upload GET requests that hit the protection handler need a session user

**Inferred.** Missing session redirects to `{WebAddy}/admin`. The site root and `{WebAddy}/admin` are excluded. Non-GET verbs are ignored. Session timeout is 60 minutes.

No login-page credential rule was re-derived for this document. Sign-in is the framework `Admin_SignIn.aspx` / reset flow. Password policy for ordinary users was not traced beyond the moderator random password in BR-019.

### BR-028 — Group canvases exclude custom users from the type list

**Inferred.** Group canvas `userTypes` is `1,2,3,4`. Regional-moderation canvases include `5` and also set `customUsers`. These are stored values. The page-level allow/deny combination is **Requires Confirmation**.

## Examination module (present, not named as Postbox)

### BR-029 — Subject resource roles and compliance states exist in code

**Inferred** from `examNums` and `examHandler`, and **Requires Confirmation** before treating them as Postbox policy.

Subject resource roles: Examiner `1`, Reviewer `2`, Internal Moderator `3`, External Moderator `4`, Assessment Specialist `5`.

Subject status ids run from `1083` through `1110` (examiner uploaded, reviewer uploaded, reviewer query, internal moderation, not compliant, compliant and ready for external moderation, no activity, external outcomes, translation, print ready).

Compliance: No compliance `1125` through compliance in all respects `1128`. Overall: approved `1129`, two conditional-approval states `1130` and `1131`, not approved `1132`.

`surfaceNotes.ascx.cs` asks `examHandler.GetSubjectResourceRole` and can email a log status. This runs for whatever surface the notes control is attached to in the database.

## Rules that were not found

- A rule that a school contact must have an email format check before save. Not traced in the generated school-contact form.
- A rule that NSC year or PSI year is mandatory. The fields exist on `oSchools`. Required flags would be surface-field rows in the database.
- A rule that names the production environment or forbids the demo catalog.
- An approval step before a file becomes visible to a school.
- A retention or deletion schedule for explorer files.
