# Business rules — supplier.sarugby.online

Evidence date: 2026-10-01. Source: `master` at `6f0e6c2`.

Rules are taken from code that enforces them, or from text the application shows to the user. A rule that is only in an email or the FAQ is marked **Documented**. A rule that the code applies is marked **Implemented**. A rule inferred from the code and not stated to the user is marked **Inferred**. Conflicts are listed at the end and are not resolved here.

Secret values (database password, mailbox password, login override) are not written in this file.

## Identity and access

| ID | Rule | Provenance |
|---|---|---|
| BR-001 | Dashboard, permits, company profile, and staff require a `Zend_Auth` identity. Otherwise the user is redirected to `/login/`. | Implemented |
| BR-002 | Login matches `CompaniesLogin.Email` to the typed email and `CompaniesLogin.password` to the MD5 of the typed password. | Implemented |
| BR-003 | If the typed password equals a hardcoded string, the system substitutes the stored password for that email and then runs BR-002. Any existing account can be opened by someone who knows that string and the account email. | Implemented. Human review required. |
| BR-004 | A successful login sets session `EVENT.EID` to 61 for the rest of the session. | Implemented |
| BR-005 | Logout clears the auth identity and destroys the session. | Implemented |
| BR-006 | Registration refuses a company registration number that already exists, and refuses a person whose ID number or email already exists. Both cases return the same "account already exist" message. | Implemented |
| BR-007 | The first user is stored with role `Administrator`. | Implemented |
| BR-008 | South African country value `SOUTH AFRICA` sets `IDType` 1. Any other country sets `IDType` 2. | Implemented |
| BR-009 | Email confirmation requires the `Validate_Key` from the link. On success the key is cleared, `Email_Confirmed` is 1, and `AllowLogin` is 1. | Implemented |
| BR-010 | Login does not read `AllowLogin` or `Email_Confirmed`. | Implemented. Conflicts with the confirmation page, which says the account is now active and the user may login, implying the link is what activates login. |
| BR-011 | Password reset requires a matching `ResetKey`. The new password is stored as MD5, the key is cleared, and `AllowLogin` and `Email_Confirmed` are set to 1. The new password is included in the email. | Implemented |
| BR-012 | Staff roles offered in the form are Administrator, Director, Management, Operations, Driver, Technician, and General Staff. | Implemented |
| BR-013 | Only one administrator is allowed per company. | Documented (FAQ). Not implemented. |
| BR-014 | A staff profile or permit cancel/duplicate is not limited to rows owned by the signed-in company. Permit profile view is limited to the company. | Implemented (the view check). Inferred defect for the unchecked actions. |
| BR-015 | `LoginController` does not require an existing session for `companypic` or `uploadremotecompany`. `uploadremotecompany` writes a company image for the posted `cid`. | Implemented |

## Registration and company state

| ID | Rule | Provenance |
|---|---|---|
| BR-016 | A new company is inserted with `Active` = 1. | Implemented |
| BR-017 | An administrator reviews the registration before the company profile can be activated. The process can take up to 48 hours. | Documented (registration email). Contradicts BR-016. |
| BR-018 | The new company is linked in `Company_Events` to event id 44 with status 2. | Implemented |
| BR-019 | Without additional information or documents the company cannot sign up and connect to an event. | Documented (registration email). No document checklist is enforced in this repository. |
| BR-020 | The confirmation link in the registration email is hard-coded to host `supplier.sarugby.online` over HTTP. | Implemented |
| BR-021 | Company profile saves replace the company row with the posted `data` array for the signed-in `CID`. There is no field allow-list. | Implemented |

## Permits

| ID | Rule | Provenance |
|---|---|---|
| BR-022 | A new or duplicated permit is stored with status 2. | Implemented |
| BR-023 | Status below 4 is shown as Pending. 4 Approved. 5 Cancelled. 6 Declined. 7 Checked-In. 8 Delayed. 9 Checked-Out. | Implemented (labels). The names of statuses 1 and 3 individually are Unknown; both display as Pending. |
| BR-024 | This application does not approve, decline, check in, delay, or check out a permit. | Implemented (absence). Inferred that another system writes those statuses on `Accreditation_Permits`. |
| BR-025 | Permit number is the accreditation `PreFix` for the session event plus the permit id padded to 6 digits, upper-cased. | Implemented (`getRef`) |
| BR-026 | Load type 1 is Load-In. Load type 2 is Load-Out. | Implemented (form options) |
| BR-027 | Service type `SID` 3 is not offered on the create or profile dropdown. | Implemented. The meaning of `SID` 3 is Unknown. |
| BR-028 | Selectable dates come from JSON `LoadinActiveDate` or `LoadOutActiveDate` on the accreditation, formatted `d/m/Y` in the JSON. | Implemented |
| BR-029 | On create, a date is offered only when it is after today and the current time is before 12:00 on the previous day. | Implemented |
| BR-030 | On the permit profile, the request is locked when the current time is at or after 13:00 on the day before `RequestDate`. While unlocked, dates already inside that 13:00 window are omitted. | Implemented |
| BR-031 | Cancellations and changes may be submitted until 1pm daily. Changes for the next day after that time are not accepted. | Documented (permit email). The code uses 12:00 in one place and 13:00 in another (BR-029, BR-030). |
| BR-032 | Cancelling sets status 5, the member id, the time, and the posted message. | Implemented |
| BR-033 | Duplicating clears approval, decline, cancel, gate, and zone fields and creates a new pending request for the posted date. | Implemented |
| BR-034 | A permit is for a single day and a single vehicle. A previous request may be duplicated to another day. | Documented (FAQ). The form has one date. Uniqueness is not enforced. |
| BR-035 | A delivery permit cannot be longer than 2 hours and is limited in access areas. A work permit is for contracted work and requires a health and safety file. | Documented (FAQ). Not enforced in the controller. |
| BR-036 | Nobody enters the venue without a valid permit and a Vehicle Access Pass. A printed permit is required. Staff must carry identification. | Documented (FAQ). Not enforced in this repository. The OAC is described as next to the venue. |
| BR-037 | An occupant or driver with type 1 is replaced by the `Company_Members` row with the same ID number, when one exists. | Implemented |
| BR-038 | Administrators may change the requested date and time to balance load. | Documented (permit email). No such editor exists in this repository. |
| BR-039 | The permit email chooses the words "Load-Out" when the permit row's `Surname` equals 2, otherwise "Load-In". | Implemented. Inferred defect: load type is `LoadType`, not `Surname`. |
| BR-040 | Health and safety file contents listed in the FAQ (37(2) agreement, public liability, induction, letter of good standing, safety plan, legal appointments, tools list, PPE, risk assessment, toolbox talks, MSDS, medical records, training records, professional registration, method statements, emergency procedures). Approval can take up to an hour if the file is labelled. | Documented (FAQ). Not stored in this application. |
| BR-041 | Event-day accreditation is applied for by each staff member on a separate accreditation portal. | Documented (FAQ). The URL in the answer is the literal placeholder `[www]`. |

## Contacts stated to the user

| ID | Rule | Provenance |
|---|---|---|
| BR-042 | General enquiries: `accreditation@sarugby.co.za`. Registration contact centre +27 21 928 7000. | Documented (emails) |
| BR-043 | Load-in and load-out enquiries: `permits@sarugby.co.za`. | Documented (current permit email) |
| BR-044 | Health and safety: `HealthandSafety7s@sarugby.co.za`. Security: `security@sarugby.co.za`. | Documented (FAQ) |
| BR-045 | The FAQ names one health-and-safety contact as "Danie" with the surname redacted in the source as `xxxxxx`. | Documented. The full name is not in the repository. |

## Data handling (inferred from implementation)

| ID | Rule | Provenance |
|---|---|---|
| BR-046 | Passwords are MD5 with no salt visible in this code. | Inferred from `md5($password)` before storage and before login. |
| BR-047 | Random ids use `mcrypt_create_iv` and uppercase hex. | Implemented |
| BR-048 | Uploaded images are written under `public/archives/`, which `.gitignore` ignores for `public/archives/`. Company pictures and accreditation photos are therefore not in Git. `public/files/pics/` is also ignored. | Implemented |
| BR-049 | The signed-in user's permit list on the dashboard is filtered by company and by the session event. The permit count is filtered by company only. | Implemented. Inferred inconsistency. |
| BR-050 | Queries build SQL by concatenating request parameters. | Implemented. Recorded as a defect. |

## Conflicts that need a human decision

1. **Event id.** Login forces event 61. Registration links the company to event 44. The dashboard then shows permits for 61, not for the event the company was attached to.
2. **Activation.** The email promises a review of up to 48 hours. The insert marks the company active immediately, and the confirmation page says the account is active after the email link. Login does not check either flag.
3. **Cutoff time.** Email says 1pm. Profile lock uses 13:00 the day before. Create and dashboard date lists use 12:00 the day before.
4. **One administrator.** FAQ forbids a second administrator. The staff screen can create another user with role Administrator.
5. **Delivery length and safety file.** FAQ states them as entry rules. This repository does not check them.
6. **Company boundary.** Viewing a permit checks the company. Cancelling, duplicating, and editing a staff id do not.
