# Phase 1 & 2 Implementation Verification (2026-04-21)

## Scope implemented

- Phase 1 infrastructure skeleton
  - Service container and plugin bootstrap wiring.
  - DB router with explicit members/mailshots database separation.
  - WordPress facade interfaces and production adapter.
  - Fixture harness (`tests/fixture/wp_shim.php`, `bootstrap.php`, `router.php`).
  - Structured error and logging primitives.

- Phase 2 data source pipeline
  - DSL lexer/parser.
  - Semantic validator (source checks, filter-source rules, join-path validation, missing-email warning).
  - Parameterized SQL compiler.
  - Source metadata provider (built-ins + custom table metadata via information schema).
  - `mailshot_queries` repository and application service.
  - Data Sources admin page + API operations (`list`, `fields`, `validate`, `preview`, `save`, `delete`).

## Validation commands and outcomes

1. `find feca_mailshots_plugin/src tests -name '*.php' -print0 | xargs -0 -n1 php -l`
- Result: pass (no syntax errors).

2. `php tests/unit/test_dsl_pipeline.php`
- Result: pass.
- Verifies parser/validator/compiler happy path and key invalid-path checks.

3. `php tests/unit/test_preview_shape.php`
- Result: pass.
- Verifies deterministic expected-field contract derivation.

4. `php tests/fixture/test_api_smoke.php`
- Result: pass.
- Verifies fixture bootstrap + WP shim + admin menu/page registration path.

## Notes

- Fixture smoke test intentionally avoids remote DB calls in sandboxed execution.
- API operations that execute SQL (`preview`, `list`, `save`, `delete`) require DB connectivity at runtime.

## Extended Phase 2 DB-access validation (2026-04-21)

5. `php tests/integration/test_phase2_db_access.php`
- Result: pass.
- Environment: tunnelled MySQL on `127.0.0.1:13306`.
- Verified:
  - Live DB read-path preview via `MEMBERS_REMOTE_MYSQL_DB` (source discovered dynamically from `information_schema`).
  - Live DB write-path create/read/delete via `MAILSHOTS_REMOTE_MYSQL_DB.mailshot_queries`.
  - Test artefact cleanup confirmed (temporary data source row deleted in `finally`).

### Fix discovered by DB test

- `mailshot_queries` repository insert SQL used unquoted `sql` column name, which fails on MySQL.
- Fixed by quoting as `` `sql` `` in:
  - `feca_mailshots_plugin/src/Repository/MailshotQueryRepository.php`

## Phase 3 implementation and validation (2026-04-21)

### Implemented

- Mailshot CRUD service/repository and admin API/page.
- Attachment CRUD + binary file handling service/repository and admin API/page.
- PDF asset CRUD + binary file handling service/repository and admin API/page.
- Last-run repository operations (`listForMailshot`, `clearForMailshot`, `create`).
- Token insertion helper generation from selected datasource expected fields.
- Fixture user-test pages under `tests/fixture/`.
- Fixture runner script `scripts/run_fixture_server.sh` (start/stop/status/restart).

### Validation

1. `php tests/integration/test_phase3_db_access.php`
- Result: pass.
- Verified end-to-end on tunnelled DB:
  - datasource creation for test,
  - attachment create/delete,
  - pdf asset create/delete,
  - mailshot create/delete with datasource validation,
  - token helper output generation,
  - last-run insert/list/clear behavior.
- Cleanup: test artefacts removed in `finally` block.

2. `php tests/fixture/test_api_smoke.php`
- Result: pass.
- Verified fixture bootstrap and menu/page registration with shared plugin wiring.

3. `bash -n scripts/run_fixture_server.sh`
- Result: pass.
- Script shell syntax validated.

## Phase 4 implementation and validation (2026-04-21)

### Implemented

- Twig template rendering pipeline service for `Subject`, `Message`, `PDFAttachment`.
- SMTP sender abstraction with concrete SMTP client implementation.
- IMAP sent-copy abstraction with concrete `imap_append` implementation.
- Mail credentials provider backed by WordPress options (`feca_mailshots_mail_credentials`).
- `MailshotRunService` with:
  - `renderTest` (no send),
  - `sendTest` (validation + SMTP + IMAP warning semantics),
  - `runMailshot` (clear last run + send loop + counters + per-recipient last_run rows),
  - `retryFailed`,
  - `retryRecipient`,
  - `MAILSHOT_TEST_TO_DEFAULT` default exposure.
- Admin pages/endpoints added for:
  - Credentials,
  - Mailshot Test API,
  - Run Mailshot API.

### Validation

1. `php tests/integration/test_phase4_run_flow.php`
- Result: pass.
- Verified:
  - render-test behavior,
  - blank test-email validation,
  - test-send path through injected SMTP/IMAP transports,
  - run-mailshot counters and last-run row persistence,
  - retry-failed endpoint behavior.

2. Existing regression checks
- `php tests/unit/test_dsl_pipeline.php` pass
- `php tests/unit/test_preview_shape.php` pass
- `php tests/fixture/test_api_smoke.php` pass
- `php tests/integration/test_phase2_db_access.php` pass
- `php tests/integration/test_phase3_db_access.php` pass

### Runtime fix included

- Added Composer autoload loading in plugin autoload bootstrap so Twig/Dompdf classes resolve when vendor deps exist.

### Phase 4 UI completion (Mailshot Test + Run Mailshot)

- Replaced placeholder pages with server-rendered WordPress admin UI for:
  - Mailshot selection,
  - Recipient selection/sample display,
  - `Render Test (No Send)` action,
  - `Send Test Email` action,
  - Run controls (`Run Mailshot`, `Retry Failed Sends`),
  - Last-run table with per-row `Retry` actions.
- UI actions use admin-post handlers and persist most recent action result in option-backed result panes.
- Added recipient-preview helper API in run service to support UI recipient picker.

Validation: syntax + fixture smoke + phase4 integration test all pass after UI implementation.

## Change set: per-user encrypted credentials + access split + no-fallback runtime config (2026-04-21)

### Implemented

1. Per-user SMTP/IMAP credential storage in `MAILSHOTS_REMOTE_MYSQL_DB`
- Added `mailshot_credentials` repository with table ensure/create and per-user upsert/load.
- Password fields are stored encrypted (`smtp_password_enc`, `imap_password_enc`) using AES-256-CBC with key material derived from WordPress salts.

2. New Profile admin page for per-user credentials
- Added `Profile` page under FECA Mailshots (editor-capable users).
- Credentials are saved/loaded for the current user id.
- Password inputs support blank-as-keep-existing behavior.

3. Runtime credential resolver switched to per-user DB-backed provider
- Replaced global option-based provider with `PerUserMailCredentialsProvider`.
- Run/test send paths now resolve credentials by current WordPress user.

4. Production DB config path made explicit (fallbacks removed)
- Bootstrap now reads DB settings from Setup page option only.
- No fallback chain to env vars in production bootstrap.
- Fixture remains explicitly env-driven via `tests/fixture/bootstrap.php`.

5. Access control split
- Setup page remains admin-only (`manage_options`).
- Operational pages/APIs use editor-level capability (`edit_pages`):
  - Data Sources, Mailshots, Attachments, PDF Assets,
  - Profile,
  - Mailshot Test,
  - Run Mailshot.

### Validation

- `php tests/fixture/test_api_smoke.php` pass
- `php tests/integration/test_per_user_credentials.php` pass
- `php tests/integration/test_phase4_run_flow.php` pass
- syntax checks pass for updated files
