# Business rules — efiling

Evidence date: 2026-10-15. Revision: `master` `67e722d`.

No business-rules document existed in the source repository or in Silicon Ark. The README does not state a rule. The Zend application that would hold the rules is not in git.

Each row is labelled.

- **Documented** — the words are in a file in git.
- **Inferred** — the behaviour is what the logs or the file actually did. It is not a signed business decision.
- **Unknown / Requires Confirmation** — the name exists and the rule does not.

Do not promote an inferred row to policy because it ran in 2018 or 2019.

## Identity

| ID | Rule | Source | Label |
|---|---|---|---|
| BR-001 | Pages in this commit title the product `SARU:: Efiling` | `index_test.php`, `down/index.phtml` | Documented |
| BR-002 | The maintenance page tells the visitor the site is down and will be back shortly. It does not give a time | `index_test.php` | Documented |
| BR-003 | The repository name is `efiling`. The README does not add a description | `README.md` | Documented |
| BR-004 | SARU is not expanded in the repository. Upload filenames are rugby union funding documents, which supports reading SARU as South African Rugby Union | Filenames under `uploads/`. No glossary | Inferred. Requires confirmation |

## Maintenance and public entry

| ID | Rule | Source | Label |
|---|---|---|---|
| BR-005 | `index_test.php` has no login and no form. A visitor cannot do work from that file | The file | Documented |
| BR-006 | Whether that file was what `http://saruefiling.com` served is not stated | File name is `index_test.php`. Logs boot `public/index.php` instead | Unknown / Requires Confirmation |

## Grants

Rules in this section are inferred from failed inserts. The success path was not logged.

| ID | Rule | Source | Label |
|---|---|---|---|
| BR-007 | A grant save persists a row in table `grantsrequest` | `Model_GrantsRequests::insertData` from `GrantsController::savegrantAction` in every ground-error file | Inferred |
| BR-008 | Column `RequiredGrant` is an integer. The value `undefined` is rejected by MySQL | Ground-error files 2019-02-07, 2019-03-07, 2019-03-19 | Inferred from the engine error. The user-facing message, if any, was not logged |
| BR-009 | The insert that was running built SQL column names from submitted text. MySQL then rejected unknown columns. That is a defect, not a rule that free text is a column | Ground-error files whose message is `Unknown column` | Inferred defect |
| BR-010 | A failed grant insert was not caught. PHP wrote the exception to an `Efiling_Grnd_Error*` file | Those files are uncaught `PDOException` / `Zend_Db_Statement_Exception` | Inferred |
| BR-011 | Who may save a grant, which fields are required besides the integer failure, and what statuses a grant can have | Not in git or in the summarised messages | Unknown / Requires Confirmation |
| BR-012 | An `ApproveArray` key is read by server code | PHP notice `Undefined index: ApproveArray` | Inferred that some screen posts an approval collection. Steps, roles, and outcomes are Unknown |

## Plans and money figures

| ID | Rule | Source | Label |
|---|---|---|---|
| BR-013 | The project list view reads five figures: budgeted cost, request cost, payment cost, allocated cost, and applicant count | Unset variables in `plan/listprojects.phtml` | Inferred from names. Formulas are Unknown |
| BR-014 | On 14 March 2018 those five variables were unset, so the view did not receive them from the controller | `error_log` | Inferred defect for that request. Not evidence that totals are optional |
| BR-015 | Currency, tax, financial year, and who may change an allocation | Not stated | Unknown / Requires Confirmation |

## Unions, members, and organisations

| ID | Rule | Source | Label |
|---|---|---|---|
| BR-016 | Lists and PDF output carry a union id (`unionid`, `UnionsArray`, `listUnions`, `Model_Unions`) | PDF URL and notices | Inferred that data is scoped or filtered by union. Whether an empty `unionid` means "all unions" or "missing filter" is Unknown. The failing PDF calls sent it empty |
| BR-017 | Member retrieval is `Model_Profile::getAllMembers` with at least seven parameters. Callers in the log omitted the last three | Warning: missing arguments 5, 6, and 7, defined at line 158, called at line 100 | Inferred. Parameter meanings Unknown |
| BR-018 | A username is expected from `Model_Profile::getUsername`, and that method was not defined on the class that was loaded | Fatal at caller line 473 | Inferred defect |
| BR-019 | Organisations have a controller | `OrganisationsController.php` path | Unknown beyond the file name |
| BR-020 | Notices read indexes `Started`, `Benched`, `Coloured`, `Indian`, and `White` | `error_log` | Inferred that a screen posts those keys. No rule in the repository defines squad selection or demographic reporting. Requires confirmation before anyone treats the keys as policy |

## Documents

| ID | Rule | Source | Label |
|---|---|---|---|
| BR-021 | Supporting files are stored under the server directory `public/uploads` | `unlink` warning path | Inferred |
| BR-022 | The snapshot's `uploads/` directory holds PDFs, Word, and Excel files named as funding applications, invoices, reports, and budgets | Directory listing. 491 pdf, 316 docx, 118 xlsx among 1,020 files | Inferred from filenames. Filenames are not a controlled vocabulary |
| BR-023 | Allowed extensions, maximum size, and whether a grant can be submitted without a file | Not stated. A missing `FileUpload` index only shows the key was read | Unknown / Requires Confirmation |
| BR-024 | One request called `unlink` on the uploads directory path. PHP refused because it is a directory | Warning at line 7512, `fileNameNew` unset on the same line | Inferred defect. Not a rule that the directory should be deleted |

## PDF output

| ID | Rule | Source | Label |
|---|---|---|---|
| BR-025 | Print output is requested from the application over HTTP at `/pdf/print`, with page, start, length, search, column, union id, current, and direction | `file_get_contents` warning quoting `http://saruefiling.com/pdf/print/...` | Inferred |
| BR-026 | Length `20` appears on concrete calls. It is not proven to be the only page size | Those URLs | Inferred example, not a documented page size |
| BR-027 | The string `undefined` is passed through when the caller has no page or length | URL containing `page/undefined/start/undefined/length/undefined` | Inferred defect |
| BR-028 | The print request that was logged did not succeed | `file_get_contents` HTTP failure | Inferred for those calls |

## Authentication and mail

| ID | Rule | Source | Label |
|---|---|---|---|
| BR-029 | The server application uses Zend session authentication | `Zend_Auth`, `Zend_Auth_Storage_Session` on the stack | Inferred. Password policy, roles, and timeout are Unknown |
| BR-030 | Theme JavaScript can show and animate `.loginBlock` | `js/actions.js` function `loginBlock` | Documented as theme code. Not a SARU credential rule |
| BR-031 | dompdf's demo header starts a session and calls `auth_check()` | `dompdf/www/head.inc` | Documented upstream demo. Not a SARU rule. The functions it requires are not in git |
| BR-032 | Server code calls `EmailTemplate3` on plugin `PG_Controller_Plugin_EmailLayout`. The method was undefined, so those calls did not send | Fatals at caller lines 948 and 1309 | Inferred that a third email template was expected. Subject, body, and recipients Unknown |

## Second deployment

| ID | Rule | Source | Label |
|---|---|---|---|
| BR-033 | The committed `error_log` records a second tree at `/home/zimrugby/public_html/` using the same kind of grant and plan views | Paths in `error_log` | Inferred that a related copy ran. Whether zimrugby users follow SARU rules is Unknown |
| BR-034 | That copy expected a `modules` directory at both `app/modules` and `application/modules`. Neither directory existed when the exception was thrown | `UnexpectedValueException` from `DirectoryIterator` | Inferred defect on that host |
| BR-035 | On that host, `iconv_get_encoding()` was missing, so Zend locale formatting could not run | Fatal in `Zend/Locale/Format.php` | Inferred environment gap |

## Data that must not be mistaken for rules

The ground-error messages quote pieces of what a user typed, including school names, because that text was inserted into SQL. Those strings are incident data. They are not the list of clubs, schools, or age grades the system supports.

Upload filenames mention programmes (Get Into Rugby, Vuka, ClubWise, youth training centre, women's rugby, referees, coaching). That is evidence of documents people filed. It is not evidence that each name is a system category with its own validation.

The database account name in the access-denied error is a credential leak in the log, not a business identity rule. It is omitted here.
