# Business rules — clientModule

Evidence date: 2026-10-18. Revision: `master` `aa88a34`.

`README.md` states the phase goals. It does not state policies for duplicates, status, or who may call a page. Unless a rule is marked **Documented**, it is **Inferred** from the HTML and PHP at HEAD. Inferred rules describe what the code does. They are not a confirmed business policy.

Database passwords are not copied here.

## Who may use the screens

**BR-001 — Any browser that can open the files can insert and list.**
`formClient.html` is static. `displayClient.php` and `insertClient.php` run their SQL without reading a session, cookie, or role. **Inferred.**

**BR-002 — The README does not require a login.**
The phase list has no authentication step. **Documented.** BR-001 matches that silence. It is not evidence that open access was an explicit decision. **Requires Confirmation** if these pages were later placed behind something outside this repository.

**BR-003 — Client type is a label, not a permission.**
`SLA-Software`, `SLA-AWS`, and `Technical` are options on the form and a column on the row. No branch checks `str_type` before insert or list. **Inferred.**

**BR-004 — Account status does not hide a row.**
The list selects every row and prints `str_status`. It does not filter on `Yes` or `No`. **Inferred.**

## Identity and the ID number

**BR-005 — The ID number is 13 numbers.**
**Documented** in phase 1: "ID number (13 numbers)".

**Implemented** in the form as `maxlength="13"` and in `showInput()` as "empty, or `isNaN`, or length not 13". The server stores `$_POST["identityNumber"]` unchanged. A POST that skips the script can store another length. No `UNIQUE` constraint is in the repository. **Requires Confirmation** of the live column.

**BR-006 — Nothing in this repository treats the ID as unique.**
Insert does not look for an existing `str_idNum`. The list can show two rows with the same number if the database accepts them. **Inferred.**

**BR-007 — The list key that is shown is `int_ID`, and the edit page does not use it.**
The link text is `int_ID`. The URL has no id. The only query that would filter on `int_ID` is commented out. **Inferred** from `displayClient.php` and `editClient.php`.

## Names, gender, type, and status

**BR-008 — First name and last name must be non-empty, and must not be purely numeric, before the script is satisfied.**
**Inferred** from `showInput()`. A letter-only regex is declared in that function and never applied, so a mixed value is not rejected by that regex. The server does not apply either check. The button does not return the function result, so the alerts do not by themselves stop the POST.

**BR-009 — Gender is male or female, and the form starts on female.**
**Documented** as a radio. **Implemented** stored values from a normal submit are `male` and `female`. If `gender` is absent, the insert stores `Female`. **Inferred** default.

**BR-010 — Type on a browser submit is one of the three option values.**
**Documented** labels: SLA-Software, SLA-AWS, Technical. The placeholder option is disabled. The select is `required`. The server does not compare the posted string to that list. **Inferred.**

**BR-011 — A checked active box stores `Yes`. An omitted box stores `No`.**
**Inferred** from the checkbox `value="Yes"` and the `isset` ternary in `insertClient.php`. The form starts checked, so an unmodified submit stores `Yes`. The on-page preview uses `yes` and `no`, which are not written to the database. The README does not mention this flag.

**BR-012 — Date of birth is collected and stored as the date input string.**
The control is `required` in HTML, and `showInput()` alerts when it is empty. The README field list does not include date of birth. **Inferred** as behaviour that was added in `eb0b3d4` when the insert gained `str_dob`. The empty-date branch also calls `setAttribute("max", today)` with `today` undefined.

## What is written

**BR-013 — Insert writes seven strings and does not write the id or the created timestamp.**
**Inferred** from the `INSERT` column list. The list still reads `int_ID` and `tms_dateCreated`.

**BR-014 — The README asks the database to own `per_id` and `per_date_created`.**
**Documented** phase 1: auto-increment `per_id`, plus `per_date_created`. The PHP names are different, and no `CREATE TABLE` is in git. Whether `int_ID` auto-increments and whether `tms_dateCreated` has a default is **Unknown / Requires Confirmation**.

**BR-015 — A successful-looking insert message does not mean `execute` returned true.**
The success paragraph is printed after `execute` with no test of the result. **Inferred.**

**BR-016 — The operator should be returned to the form after five seconds.**
**Inferred** from `header("refresh:5;url=formClient.html")`. The header is called after the script has already echoed HTML, so the response behaviour depends on output buffering. **Requires Confirmation** on the host that ran this file.

## Edit, types, and the API post

**BR-017 — Phase 2 says a row click edits and saves.**
**Documented.**

**Implemented** behaviour is a link to `editClient.php` and a page that includes the list. No save runs. The HEAD commit subject is "can not update directly from php". Treating that as an accepted cancellation of phase 2 is **Requires Confirmation**.

**BR-018 — Phase 3 says types are their own table, with add and archive.**
**Documented.** Not implemented. The dropdown is fixed. **Requires Confirmation** whether phase 3 was dropped.

**BR-019 — Phase 1 says only the ID number is posted, and that the post goes to `api/`.**
**Documented.** The form posts every field to `insertClient.php`. This is a discrepancy, not a second rule that overrides the README. **Requires Confirmation** which behaviour was wanted.

## Connection choice

**BR-020 — Server name `localhost` uses the local MySQL settings. Every other server name uses the `lamp` settings.**
**Inferred** from the `switch` in `dbconnection.php` and the copy in `insertClient.php`. The `lamp` case is the `default` arm. Both arms use database `db_clientmodule` and user `root`. Passwords differ and are omitted here.

The two copies are the same at HEAD. Nothing in the code keeps them the same if one file is edited later. **Inferred.**
