# PRD — evolve-infra

Evidence date: 2026-10-15. Source: `git@bitbucket.org:overdrive/evolve-infra.git`, `master` at `35effc1` (2019-03-15).

The stack was not started. Requirements below are what the files specify. Runtime success is **Unknown** until someone runs them.

Magus accreditation behaviour is specified in `silicon_ark/magus-core/prd.md`. This document covers the container repository only.

## Product purpose

Provide the Docker services a developer needs to run the Magus PHP application locally, with MariaDB initialised from the application's SQL dump and phpMyAdmin on a second port.

Provenance: **Documented** in `Readme.md`. **Implemented** as `docker-compose.yml` plus `nginx-site.conf` and `php/Dockerfile`.

## Users and interactions

| Actor | Interaction | Evidence |
|---|---|---|
| Developer | Clones this repo, initialises the submodule, runs `docker-compose up`, opens the app and phpMyAdmin | README |
| Developer | Runs `docker exec` into MariaDB as `root` | README |
| Developer | Commits changes under `magus-core` to the Magus git repo, not only to this repo | README |
| Magus end user (supplier, staff) | Not described here. Those journeys are in the application repository | No role, screen, or account logic in this tree |

There is no login to evolve-infra itself. The only credentials in this tree are the database and phpMyAdmin settings below.

## Main workflows

### W1 — Launch the development stack

Trigger: a developer follows the README.

Inputs the README names:

1. Docker and docker-compose installed from the Docker website.
2. git.
3. Clone `git@github.com:EvolveAV/evolve-infra.git`.
4. `git submodule init` then `git submodule update --recursive --remote`.
5. `docker-compose up`.

Expected result the README states: containers running, application at `http://localhost:8080`.

Provenance: **Documented**. The clone URL is not the Bitbucket remote this document was written from. `--remote` does not stay on the gitlink. See project plan.

### W2 — Inspect MySQL from the shell

Trigger: the developer runs the README command.

```text
docker exec -ti evolve-infra_database_1 mysql -h localhost -u root -proot magus_dev
```

Expected result the README states: a MySQL client session on database `magus_dev` as `root`.

Provenance: **Documented**. The container name is the Compose v1 pattern (`{directory}_{service}_1`). This repo does not set `container_name`. Whether that name is created is **Inferred** from Compose v1 defaults, and **Unknown** under Compose v2.

### W3 — Open phpMyAdmin

Trigger: containers are up. The developer opens `http://localhost:8081`.

Provenance: **Documented** in the README (added in `35effc1`). **Implemented** as service `phpmyadmin`, host port `8081:80`, linked to `database` as hostname `db`, with `PMA_USER` and `PMA_PASSWORD` set to `root`.

Whether that image auto-logs-in when those variables are set was not executed. Provenance: **Unknown**.

### W4 — Change the application

The README says changes in the `magus-core` folder are committed to the magus-core git repo. Compose bind-mounts `./magus-core` to `/code` on both `http` and `php`, so a file save on the host is the file the containers see. No rebuild step is documented for PHP source edits. Provenance: **Documented** and **Implemented** (the mount). Image rebuild is required only when `php/Dockerfile` changes. That rebuild rule is **Inferred**; the README does not say it.

## Functional requirements

### FR-001 — HTTP entry on port 8080

The `http` service publishes host port 8080 to container port 80, using image `nginx:stable-alpine`.

Evidence: `docker-compose.yml` service `http`.

Implementation: **Implemented** in the file. Not executed.

### FR-002 — Magus code is the nginx document tree

`./magus-core` is mounted at `/code`. `nginx-site.conf` sets `root /code/public` and `index index.php index.html`.

Evidence: `docker-compose.yml`, `nginx-site.conf`.

The pinned Magus tree has `public/index.php`. Provenance: **Implemented** in both repositories. See `silicon_ark/magus-core/`.

### FR-003 — Front controller for non-file URLs

For location `/`, nginx uses `try_files $uri $uri/ /index.php`. PHP files are passed to FastCGI `php:9000` with `SCRIPT_FILENAME` set from the document root. Missing PHP files return 404 (`try_files $uri =404` inside `location ~ \.php$`).

Evidence: `nginx-site.conf`.

Implementation: **Implemented** in the file. Whether Zend reads the original path correctly under this `try_files` was not executed. Provenance of compatibility: **Unknown / Requires Confirmation**.

### FR-004 — Block `.htaccess`

Requests matching `\.htaccess` are denied.

Evidence: `nginx-site.conf`.

Implementation: **Implemented** in the file. Apache would have executed `.htaccess`. This stack does not. The pinned Magus root `.htaccess` (`9b5b3e2`) redirects to `https://www.{host}`. That redirect does not run under this nginx site, because the document root is already `public/` and the server is nginx. Provenance: **Inferred** from the two configs. Not executed.

### FR-005 — PHP-FPM image with PDO MySQL and GD

The `php` service builds `./php` and tags the result `php:fpm-evolve`. The Dockerfile starts `FROM php:fpm-alpine`, installs Alpine package `libpng-dev`, and runs `docker-php-ext-install` for `pdo_mysql` and `gd`.

Evidence: `docker-compose.yml`, `php/Dockerfile`. History: `2cf321b` installed `mysqli` and `gd`; `3b4de76` replaced `mysqli` with `pdo_mysql`.

`mysqli` is not in the final Dockerfile. `mcrypt` is not installed. The Magus application adapter at the pin is `pdo_mysql`, which matches the extension that remains. Provenance: **Implemented** extension list. Application compatibility of the unpinned base image: **Unknown**.

### FR-006 — Development environment flag

The `php` service sets `APPLICATION_ENV=development`.

Evidence: `docker-compose.yml`.

Magus `public/index.php` reads `APPLICATION_ENV` and defaults to `production` when unset (`silicon_ark/magus-core/`). With this Compose file the variable is set, so the Zend `[development : production]` section applies. At gitlink `9b5b3e2` that section points at host `database`, database `magus_dev`, user `root`, password `root`. Provenance: **Implemented** in the pinned INI and in Compose. At Magus tip `f806a7e` the same section points at `localhost` / `magus` / empty password, which does not match Compose.

### FR-007 — MariaDB with a named development database

Service `database` uses image `mariadb` (no tag). It sets `MYSQL_ROOT_PASSWORD` to `root` and `MYSQL_DATABASE` to `magus_dev`. It bind-mounts `./magus-core/admin_magus.sql` onto `/docker-entrypoint-initdb.d/dump.sql`.

Evidence: `docker-compose.yml`.

There is no volume for the server data directory. Provenance: **Implemented** absence. Data surviving `docker-compose down` (container removed) is **Inferred** not to survive, because nothing in this file mounts the data directory. Not executed.

The dump file has no `CREATE DATABASE` statement. The phpMyAdmin header comment names database `admin_magus` (generated 2019-03-15, server 5.7.23). Which schema the image creates tables in was not executed. Provenance: **Unknown / Requires Confirmation**.

### FR-008 — phpMyAdmin on port 8081

Service `phpmyadmin` uses image `phpmyadmin/phpmyadmin`, publishes `8081:80`, links `database` as `db`, and sets `PMA_USER` and `PMA_PASSWORD` to `root`.

Evidence: `docker-compose.yml`. README URL `http://localhost:8081`. Added in `35effc1`.

### FR-009 — Submodule is the application

`.gitmodules` records path `magus-core`, URL `git@github.com:EvolveAV/magus-core.git`, branch `master`. The gitlink at `35effc1` is `9b5b3e2`.

Earlier pin, at `a5b8870` only, was `d5d0227` (the commit that added `admin_magus.sql` in the Magus history). `3b4de76` moved the pin to `9b5b3e2`. `dda9d6e` added `branch = master`.

Provenance: **Implemented**.

### FR-010 — Code mount shared by nginx and PHP

Both `http` and `php` mount `./magus-core` at `/code`. FastCGI `SCRIPT_FILENAME` uses `$document_root`, which nginx sets from `root /code/public`.

Evidence: `docker-compose.yml`, `nginx-site.conf`.

## Integrations

| System | Direction | Trigger | Data | Auth in this repo | Failure behaviour in this repo |
|---|---|---|---|---|---|
| Magus submodule (GitHub URL in `.gitmodules`) | This repo records a gitlink; the application is not vendored | Clone / submodule update | PHP tree and `admin_magus.sql` | SSH URL, no key stored here | Not described. If the submodule is empty, nginx root `/code/public` and the SQL mount have nothing to serve. **Inferred** |
| MariaDB image | Compose pulls and starts it | `docker-compose up` | Env `MYSQL_*`, init SQL file | `root` / `root` | Not described. No `depends_on`, no healthcheck |
| phpMyAdmin image | Compose pulls and starts it | `docker-compose up` | Link alias `db`, PMA user and password | `root` / `root` | Not described |
| nginx and PHP base images | Compose pulls; PHP image is built locally | `docker-compose up` | Site file, Dockerfile | None | Not described |
| Magus SMTP, Google Geocoding, Footprint | Not configured here | — | — | — | Those clients are inside `magus-core`. This repo does not set mail or API hosts |

No webhook, queue, or monitoring integration is in the tree.

## Important constraints

- Compose file `version: '3'`. No named networks, no `depends_on`, no healthchecks, no restart policy, no resource limits.
- Service coupling is `links` (`http` to `php`, `php` to `database`, `phpmyadmin` to `database:db`).
- Host ports are published without a bind address (`"8080:80"`, `8081:80`), so they listen on all host interfaces. Provenance: **Implemented** in the port syntax.
- `APPLICATION_ENV` is fixed to `development`. There is no production override file.
- Image tags are floating. Rebuilding in 2026 does not reproduce the image that existed on 2019-03-15. Provenance: **Inferred** from unpinned tags. The 2019 digest was not recorded.
- `nginx.conf` at the repo root is not mounted. The running nginx process uses the image's own main config plus the mounted site file. Provenance: **Inferred** from the Compose volume list.

## Behaviour that is documented but not what the files do

| Documented | What the files do |
|---|---|
| README clone URL `git@github.com:EvolveAV/evolve-infra.git` | Inspected remote is Bitbucket `overdrive/evolve-infra` |
| README: submodule update `--remote` | Gitlink is `9b5b3e2`, not "whatever `master` is now" |
| README first draft (`fc79c98`) command `docker-compuse up` | Fixed to `docker-compose up` in `35effc1` |
| README heading "How to troubelshoot the MySQL database" | Spelling left as written |
| README: primitives for deployment of the Evolve applications | One development Compose file for Magus |
| `php-test` connects with `mysqli` and selects from `users` | Final PHP image has `pdo_mysql`, not `mysqli`. Compose does not mount `php-test` |
| Commit `2cf321b` message "Adding GD & MySQLi support" | `mysqli` was removed again in `3b4de76`. `gd` remains |
