# Business rules — knowmore_current (Knowmore)

Evidence date: 2026-10-11. Source: `git@bitbucket.org:overdrive/knowmore_current.git`, `master` at `98e19240`.

Rules below are taken from page text or from code. **Documented** means the public pages or a comment state the rule. **Inferred** means the behaviour is what the code does and no separate requirement was found. Do not treat an inferred rule as an approved business decision.

No business-rules document exists in the source repository.

## Identity and audience

| ID | Rule | Provenance |
|---|---|---|
| BR-001 | KnowMore is owned by Old Mutual Wealth (Proprietary) Limited, registration number 2011/134187/07 | Documented, `privacy-policy.html` |
| BR-002 | The website and trademark are operated by Old Mutual Wealth Services Company (Pty) Ltd, and the terms contract is with that company | Documented, `terms-and-conditions.html` |
| BR-003 | Products and services are for financial planners and support staff in South Africa: business-management services, online courses, workshops and seminars, publications and newsletters. Supply is subject to availability | Documented, `terms-and-conditions.html` |
| BR-004 | Personal information supplied through the website is used for the purpose stated on the page, to meet KnowMore's obligations to the user, and to meet legal obligations. It is not disclosed to third parties unless the law requires it or the user has expressly authorised disclosure | Documented, `privacy-policy.html` |
| BR-005 | Website content is owned by KnowMore. Reproduction other than personal, non-commercial use needs prior written consent | Documented, `copyright.html` |
| BR-006 | Old Mutual Wealth disclaims liability for loss arising from use of the website or reliance on its content | Documented, `disclaimer.html` |
| BR-007 | `contact.us.php` still presents Celestis as the speaker, with a different telephone and postal address from the static footer | Implemented copy. Whether this is still a business rule is **Unknown / Requires Confirmation** |

## Who may use which area

| ID | Rule | Provenance |
|---|---|---|
| BR-010 | Public HTML does not require a session | Inferred from static files |
| BR-011 | Webadmin login requires a `sysUser` row whose security group has `blnActive = 1`, the user `blnActive = 1`, and a successful `NemoPassword` check for type `User` | Inferred, `login.php` |
| BR-012 | A failed or inactive webadmin login is recorded through `tblLoginInsert` and the browser is sent to `comms/log-in/` | Inferred, `login.php` |
| BR-013 | Webadmin menu children are visible only when `sysSecurity.blnView` is set for that security group and menu row. `blnDelete`, `blnSave`, and `blnSpecial` are selected with the row | Inferred, `webadmin/_nemo.menu.cls.php` |
| BR-014 | The tools home requires `$_SESSION["ADVISOR"]`. Without it the browser is sent to `../index.php` | Inferred, `tools/index.php` |
| BR-015 | The Business Assessment and the Client Satisfaction Survey are described as available exclusively to partner businesses | Documented on the marketing pages. The query that enforces this was not isolated |
| BR-016 | If the login code believes the email has more than one of webadmin, learner, and tools access, it stores `$_SESSION["ACCESS"]` and redirects to `portal.php` instead of signing the user in | Inferred, `login.php`. `portal.php` is not in the tree. The tools flag is never set in this file |

## Passwords

Defaults below are inserted only when the password table is missing (`webadmin/_nemo.password.cls.php`). After that, values come from `sysSettings`. The live values were not read from a database.

| ID | Rule | Provenance |
|---|---|---|
| BR-020 | When policy is enabled, the stored secret is SHA-256 of a 32-byte salt plus the password. The salt is stored beside the hash | Inferred, `createPassword` |
| BR-021 | Default minimum length is 8 | Inferred, seed row `PASSWORD_Strength_Check_MinLength` |
| BR-022 | Default strength check is on. Default restricted words are `password` and `123` | Inferred, seed rows |
| BR-023 | Default password history is 8. Reuse of a password in that history is rejected with "Your password has already been used." | Inferred, seed row and `PASSWORD_Already_Used` |
| BR-024 | Default maximum age is `false` (no expiry) until settings say otherwise. When expiry is in force, the message is "Your password has expired and needs to be reset." | Inferred |
| BR-025 | A reset link expires after `60 MINUTE` by default | Inferred, seed row `PASSWORD_Reset_Interval` |
| BR-026 | A locked account is rejected with "User account is locked." | Inferred, message constant. The condition that sets the lock was not fully traced |
| BR-027 | An old-password mismatch on change returns "Password not saved. The old password does not match the current password in the database." | Inferred, message constant |

## Registration and spam

| ID | Rule | Provenance |
|---|---|---|
| BR-030 | `register.php` is marked "NOT IN USE ANYMORE" and exits before validation or insert | Inferred from the comment and the `die` |
| BR-031 | The unreachable submit block treats an email containing `googlemail.com` as spam and calls `tblSpamInsert` | Inferred. It does not run on the current first lines |
| BR-032 | New-learner practice defaults to null in a 2016 comment on `register.php` ("ph2") | Documented as a code comment. Not executed |

## Courses and mail

| ID | Rule | Provenance |
|---|---|---|
| BR-040 | Course-start mail is sent for active learners, active courses, and licences with `strStatus = 'Active'` whose `dtStartDate` is five days ahead | Inferred, `webadmin/cron.daily.php`. A comment records a 2016 recommendation of five days instead of one week |
| BR-041 | Course type id 6 is the Executive Assistant course and uses the email template "Course Start EA" | Inferred, same file |
| BR-042 | Course type id 43 has its own branch immediately after the executive-assistant branch | Inferred. The template name was not copied here |
| BR-043 | Assignment reminders are sent on the Thursday before the due date and on the due date when the learner has not uploaded the assignment | Documented as a comment labelled "Comms: Tast 3" in `cron.daily.php`. **Inferred** that the code under that comment still does this |
| BR-044 | Module-available mail, course-end mail, and a CSS reminder are named as the other daily communication tasks | Documented as comments in the same switch |
| BR-045 | Learners are not deactivated four weeks after the last course end. That job is commented as switched off after the tools merger | Documented as a comment, 2013-10-01 |
| BR-046 | AML courses and IBC courses have their own processing actions. A comment says AML assignment reminders should use the pre-registration email plus "Reminder" in the subject. A comment says General Awareness (including Ghana) and the executive-assistant course use different templates | Documented as comments dated 2018–2019. Treat the exact template choice as **Inferred** from those comments |
| BR-047 | Licence renewal mail in the tools cron is described at about six weeks, two weeks, three days before expiry, and the day after expiry | Documented as a comment in `tools/cron.daily.php` |

## CPD

| ID | Rule | Provenance |
|---|---|---|
| BR-050 | Verifiable CPD points exist to support FPI and FSCA requirements. Activities without verifiable points may be claimed as non-verifiable FPI CPD only when they meet FPI rules | Documented, `cpd-points.html` |
| BR-051 | The learner downloads a report and submits it as proof of CPD earned through Old Mutual Wealth. The application does not submit the report to the FPI | Documented on the page. Inferred that no FPI API call exists, because none was found in `my.cpd.points.php` |
| BR-052 | The screen's current CPD window is 2024-06-01 through 2025-05-31. Comparison windows 2023-06-01–2024-05-31 and 2022-06-01–2023-05-31 are hardcoded beside it | Inferred, `training/my.cpd.points.php` |
| BR-053 | A June-to-May cycle that moves forward with the calendar is present only as comments. It is not the code that runs | Inferred |
| BR-054 | Wealth Intelligence CPD was changed so every third item is 0.5 points and the others are 0, instead of 0.1667 each | Documented as a comment, 2017-08-19. **Inferred** that the current function `matchCPDPoints` still applies it. That function body was not read line by line |
| BR-055 | The CPD report includes an ID number and a cycle label, and includes module CPD points | Documented as comments, 2019 |

## Business tools

| ID | Rule | Provenance |
|---|---|---|
| BR-060 | The Business Assessment looks at six elements of managing a financial-planning business. Marketing names strategy, business planning, and the operational environment among them | Documented, `business-assesment-tool.html` and `business-tools.html` |
| BR-061 | BAT results for the learner home are the current calendar year's rows in `dwfBatResults_2020` for questionnaire 4, grouped by pillar, for the learner's practice | Inferred, `training/index.php` |
| BR-062 | If the practice has no WPS id, the home uses WPS id `-10`. The WPS block and the user-category block are not shown | Inferred. A 2017 comment says the hide is permanent |
| BR-063 | The client survey is described as independent and anonymous, and as producing more honest client responses because of that | Documented, `client-satisfaction-survey-tool.html` |
| BR-064 | The TCF gap tool produces a report the business can turn into an action plan, and the marketing page associates it with verifiable CPD points | Documented, `gap-analysis.html` |
| BR-065 | Saving industry on the tools home writes `strIndustry` from `tblIndustry` when a real industry id is posted, and always writes `refSubCategoryID`, `strLastUser` from `$_SESSION['USER']->USERNAME`, and `strLastEdit` | Inferred, `tools/index.php`. The page otherwise requires `ADVISOR`, not `USER`. If `USER` is absent, that line has no username |
| BR-066 | Netcash's documented steps (transaction, invoice, licences, activation) do not run. The script stops immediately | Inferred, `tools/purchase.netcash.php` |

## Sessions and hosts

| ID | Rule | Provenance |
|---|---|---|
| BR-070 | The database is chosen by `$_SERVER["SERVER_NAME"]` | Inferred, `webadmin/system.php` |
| BR-071 | `www.knowmore.co.za` is environment `live`, database name `knowmore_2016` | Inferred, same file. Host name omitted here only where it would sit next to a password; the host is `sql21.cpt1.host-h.net` |
| BR-072 | `www.qa-celestis.co.za` is labelled environment `live` and uses database `knowmore_2016`, not the commented QA database | Inferred. The label and the database name disagree with the hostname "qa" |
| BR-073 | The `localhost` key uses database `knowmore_2016` on the same SQL host as the live key, and session files under `knowmore_current/webadmin/SESSION/`. Its `SERVER_PROTOCOL` is forced to `HTTPS` | Inferred |
| BR-074 | `dev.overdrive.co.za` is environment `QA`, database name `knowmore_2016qa` | Inferred |
| BR-075 | System settings rows (`sysSettings`) override the in-code array after connect. Ping, SMTP, SMS, AWS, and password policy values used at runtime come from that table when the row exists | Inferred, `webadmin/system.php` loop that copies `strSetting` / `strValue` |

## Content and CPD proof

Nothing in the terms grants a learner the right to copy course files. BR-005 is the only copyright rule found. Course files under `training/dcontent/` are gitignored. Files under `training7.4/dcontent/` are not. That is a repository rule, not a product rule.
