# Request lifecycle

## Public request

1. **Rewrite.** The web server sends non-file requests to `public/index.php`. Under the built-in PHP server, `public/router.php` returns `false` for existing static files so they are served directly.
2. **Bootstrap.** Autoloading, configuration, error handling and the file logger are initialised.
3. **Session and locale.** The session starts; the locale is resolved from the explicit choice, then the cookie, then `Accept-Language` when browser detection is enabled, then the site default.
4. **Settings and theme.** Settings load from the database; the active theme and its tokens are resolved.
5. **Plugins.** Active plugins load unless Safe Mode is engaged. A plugin that throws during load is recorded with a status and skipped.
6. **Routing.** The path is split into segments and matched. See [Routing](ROUTING.md).
7. **Authorisation and CSRF.** Writes require POST, an active account where applicable, and a valid CSRF token.
8. **Handler.** The route handler loads data through services and repositories.
9. **View.** The template renders, resolved through the theme manager so a theme override wins over the core view.
10. **Layout.** The shell adds metadata, structured data, tokens, widget regions, custom code and ads.
11. **Response.** Status, headers and body are sent.

## Failure handling

Failures degrade rather than cascade:

- A failing feed query logs and renders an empty state instead of a fatal page.
- A failing widget logs and renders nothing; the rest of the page survives.
- A failing plugin is isolated and logged.
- An unhandled error renders a translated error page, never a stack trace.

## Write requests

Writes follow one shape: method check → CSRF validation → authentication → authorisation → policy and spam assessment → transaction → post-commit events → redirect.

The redirect after a successful write is deliberate: it stops a refresh from re-posting, and the transient status parameter it carries is stripped from the canonical URL.

## Admin request

The admin front controller adds an administrator check before routing, and generates every URL through the admin URL helper so the configured path is preserved.

## API request

The API entry point resolves the route relative to `/api/v1`, authenticates a bearer token when present, applies rate limits, and returns JSON. Errors carry stable codes. See [API v1](../06-api/API-V1.md).

## Transactions and events

State changes run inside a transaction with their counter updates, so a rollback restores both the row and the counter. Post-success events fire **after** the commit, so a handler always observes committed state.
