Repository source: docs/plans/backlog/forte_activity_read_model_compatibility_error_handling_plan.md
Forte activity read-model compatibility and recovery plan
Problem
/forte/activity/ now renders a persisted Commits pane on every request. That
pane queries the commits table even when the visitor has selected an ordinary
activity view. Read models created before the Commits feature do not contain
that table, so SQLite raises no such table: commits. FrontController catches
the exception and presents it as a generic PHP-host configuration error. This
is a stale derived-data problem, not a host-configuration problem, and the raw
database exception is not actionable for visitors.
Desired behavior
A visitor never sees a raw
SQLSTATEmessage for an expected stale or incomplete read-model condition.A current read model renders the complete Forte activity page, including Commits.
An older read model either renders the five activity views without Commits or presents a clear, safe recovery page; it must not turn the entire activity route into a 503 host-configuration error.
Operators can identify the database path, missing schema capability, and exact rebuild command without exposing private filesystem paths to visitors.
Rebuild is the only way to populate commits; request handling must not query git or mutate the database to conceal a stale model.
Implementation stages
1. Define and inspect read-model capabilities
Add a small read-model schema/capability inspector next to
ReadModelConnection(or a similarly focused service).It should safely check
sqlite_masterfor required tables and, if practical, record a monotonic schema version in the existingmetadatatable during every full rebuild.Model the Commits feature as an explicit capability (
commitstable and its required columns/indexes), rather than treating an arbitrary PDO exception as a compatibility signal.Keep checks read-only and cache them only for the duration of one request.
2. Make Forte activity degrade safely
Determine Commits availability before calling
fetchCommits()orcountCommitsTotal().When unavailable, continue rendering the normal five activity panes. Omit the Commits filter and its related client-side data/endpoints from the page, and show a compact non-technical notice that commit history will return once the site finishes updating.
Make
/api/forte_activity_page?view=commitsreturn a structured 409/503 JSON response with a stable error code such asread_model_capability_unavailable; existing activity-page views continue normally.Make
/api/forte_commit_detailreturn the same safe structured response before it accessescommitsor cached manifests.
3. Classify errors at the host boundary
Add a dedicated read-model-unavailable response in
FrontController, separate from genuine PHP-host setup failures.Convert known read-model absence/staleness conditions into a visitor-safe page: explain that site data is being updated, offer a retry link and a link back to Forte, and avoid PDO/SQL text and absolute paths.
Retain detailed exception context in server logs. For local/development mode, expose the diagnostic only behind an explicit development setting, never by default.
Reserve the existing "PHP host configuration" response for invalid host roots, permissions, or other actual boot/configuration failures.
4. Give operators a deterministic recovery path
- Extend `/api/read_model_status` (and, if useful, the tools/status surface)
with schema version/capabilities and a `rebuild_required` reason. Do not
publish filesystem paths to regular visitors.
- Update the deployment and recovery runbooks: deploy the application code,
then rebuild the same `FORUM_REPOSITORY_ROOT` and `FORUM_DATABASE_PATH` used
by the vhost, then validate `/api/read_model_status` and
`/forte/activity/?view=commits`.
- Document the local recovery command:
```bash
php scripts/rebuild_read_model.php
```
In a configured deployment, pass the vhost's repository and database paths
explicitly, as the production runbook already prescribes.
5. Cover the compatibility contract
Add a fixture database with normal activity tables but no
commitstable.Assert
/forte/activity/remains successful, shows regular activity, omits Commits, and contains no SQL/PDO text.Assert the two commit-specific APIs return the stable structured error and do not return a PHP error page.
Assert a rebuilt current database shows Commits and continues to paginate and render commit detail.
Add a host-boundary test proving a known read-model error receives the recovery response while a genuine configuration failure remains distinct.
Rollout and acceptance criteria
Deploy the compatibility handling before or with the feature code.
Rebuild every configured read model after deployment.
Confirm current models report the Commits capability and successfully render the Commits view.
During a simulated pre-feature database case, confirm ordinary Forte activity works, commit-only interfaces degrade safely, and no visitor-facing response includes
SQLSTATE,SQLite, table names, exception messages, or absolute paths.
The immediate operational recovery for the observed error is to rebuild the read model that the PHP vhost actually uses. The code change above prevents a missed rebuild from presenting that internal failure to visitors again.