# Phase 0/1 — WordPress security bridge

## Implemented

- Application factory at `platform/runtime/app_factory.py`.
- Explicit startup component registry for required apps.
- Public liveness endpoint at `GET /health`.
- Dependency-aware readiness endpoint at `GET /ready`.
- Control-plane database readiness check.
- Safe compatibility helpers restored for current app imports.
- WordPress development plugin at `wp-content/plugins/wp-flask-bridge`.
- RSA 2048-bit key generation on plugin activation.
- Short-lived RS256 JWTs (5 minutes).
- Flask public-key registry selected by JWT `kid`.
- Validation of algorithm, signature, issuer, audience, timestamps and required
  identity claims.
- Authenticated diagnostic endpoint:
  `GET /api/v1/platform/connection`.
- JWT enforcement on the generic application gateway.
- Tenant, app and user context derived from verified identity and route rather
  than untrusted request headers.
- App entitlement check before gateway dispatch.
- App-specific scope check for external gateway calls.
- Explicit trusted identity for in-process inter-app calls.

## Development configuration

WordPress defaults:

- Endpoint:
  `https://mail.absolutems.com.au/flask/api/v1/platform/connection`
- Issuer: WordPress `home_url()`
- Audience: `absolutems-api`
- Tenant: `absolutems`
- Key ID: `absolutems-wp-dev-1`

Flask defaults:

- Audience: `absolutems-api`
- Allowed issuer: `https://absolutems.com.au`
- Public keys: `platform/secrets/site_keys/<kid>.pem`

Environment overrides:

```env
JWT_AUDIENCE=absolutems-api
JWT_ALLOWED_ISSUERS=https://absolutems.com.au
JWT_PUBLIC_KEYS_DIR=/var/www/html/flask_server/platform/secrets/site_keys
```

## Verification

Automated checks:

```bash
cd /var/www/html/flask_server
venv/bin/python tests/platform/auth_checks.py
venv/bin/python tests/platform/startup_checks.py
```

End-to-end server-side test:

```bash
wp ams-bridge test \
  --path=/var/www/html/absolutems \
  --allow-root \
  --skip-plugins=ultimate-member
```

The `--skip-plugins` option is currently required because Ultimate Member
raises an unrelated FTP filesystem error during WP-CLI bootstrap.

The same test is available to WordPress administrators under:

`Tools → AMS Flask Bridge`

Production verification on 2026-07-19:

- `/health`: HTTP 200
- `/ready`: HTTP 200
- `platform_api`: ready
- `wp_invoices`: ready
- `leave_form_app`: ready
- control-plane database: ready
- WordPress authenticated connection: HTTP 200

## Phase 0 status

Phase 0 is complete for the current platform baseline:

- The WSGI entry point is minimal and reproducible.
- Required components expose observable startup status.
- A process can be alive while correctly reporting itself unavailable through
  readiness.
- Existing required app blueprints register successfully.
- Automated startup and security regression checks are available.

The current working tree still contains unrelated pre-existing deletions and
modified app submodules. Those changes were preserved and were not silently
reverted as part of Phase 0.

## Security boundaries

- The private key never travels to Flask.
- Flask stores only the WordPress public key.
- JWT payloads contain identity and authorization claims, never API
  credentials.
- The plugin admin actions require `manage_options` and WordPress nonces.
- The connection test verifies HTTPS certificates and does not follow
  redirects.

## Development-only limitations

- The WordPress private key is currently stored as a non-autoloaded WordPress
  option. Production must use protected key storage outside the database or a
  managed signing service.
- Revocation and replay protection for `jti` are not implemented yet.
- Public-key registration is manual.
- Tenant resolution still contains the single-tenant `absolutems` bootstrap.
- The project package `platform` conflicts with Python's standard-library
  module of the same name; the package should be renamed before a standard
  pytest suite is restored.
- App registration failures are reported through readiness instead of killing
  liveness; deployment and load-balancer configuration must use `/ready`.

## Next slice

1. Replace the fixed tenant bootstrap with control-plane site registration.
2. Add `site_id`, key status and key rotation records to the control plane.
3. Persist `jti` replay protection in Redis.
4. Add subscription and effective-entitlement enforcement tests.
