# Plugins and hooks

Quaeriva's plugin layer is intentionally small because PHP plugins execute as trusted server code.

## Installation boundary

Install a plugin directory under `plugins/` using the filesystem (FTP/SFTP/deployment). Quaeriva does not upload or install PHP plugins from the browser.

A plugin should contain:

```text
plugins/example/
  plugin.json
  plugin.php
```

`plugin.json` is metadata and is safe to read while the plugin is disabled:

```json
{
  "name": "Example",
  "version": "1.0.0",
  "author": "Your name",
  "requires": "0.7.6",
  "description": "Example plugin"
}
```

`plugin.php` returns a descriptor array whose optional `register` callback attaches listeners. Top-level side effects are strongly discouraged; the runtime only requires this file for an explicitly active plugin outside Safe Mode.

## Activation

Administration stores the active slug list in `settings.plugins.active`. That setting is the runtime source of truth. Disabling a plugin means its PHP file is not required on subsequent requests.

Safe Mode is stronger: plugin metadata may still be discovered, but no plugin PHP executes.

The `requires` field is a minimum Quaeriva Core version. If the installed Core is older, the plugin remains non-executable and Administration reports it as incompatible.

## Core events currently emitted

Events are emitted after successful mutations; transaction-backed events fire after commit:

- `user.registered`
- `question.created`
- `question.published`
- `answer.created`
- `answer.accepted`
- `comment.created`

Listeners are isolated by `App\Support\Hooks`: a listener exception is logged and later listeners continue.

## Deliberate limits

The current system has no marketplace, remote auto-update, browser PHP upload, uninstall scripts, dependency solver, or plugin-provided widget registration. Those remain future work and should not be simulated in a plugin by editing Core files.

---

Plugins are trusted filesystem extensions. They may be enabled/disabled and run under failure isolation. There is no browser installer or remote marketplace. A plugin should declare compatibility, avoid global state, use hooks, and never bypass authorization/CSRF.
