# Plugin Architecture Instructions

## Overview

Dangerous Pi uses a plugin system that supports:
- Remote installation from GitHub releases
- Automatic pip dependency management
- Hardware access (GPIO, I2C, SPI, serial) with permission enforcement
- WebSocket broadcasting for real-time updates
- Header widgets for UI notifications
- Permission declarations with user consent at install time

## Plugin Distribution Model

**Each plugin lives in its own GitHub repo** (e.g., `org/dangerous-pi-multi-flasher`).

### Registry Format
A central registry repo (`dangerous-pi-plugin-registry`) contains `plugins.json`:
```json
{
  "version": "1.0.0",
  "plugins": [
    {
      "id": "plugin_id",
      "name": "Plugin Name",
      "repo": "org/repo-name",
      "description": "Description",
      "author": "Author",
      "latest_version": "1.0.0"
    }
  ]
}
```

### Plugin Release Format
Each plugin repo publishes GitHub releases with:
- `plugin.tar.gz` - The plugin archive
- `plugin.json` - Metadata with checksum and dependencies

### plugin.json Schema
```json
{
  "id": "plugin_id",
  "name": "Plugin Name",
  "version": "1.0.0",
  "description": "Description",
  "author": "Author",
  "checksum": "sha256:...",
  "dependencies": ["package>=1.0.0"],
  "permissions": ["gpio", "i2c", "network_access"],
  "min_app_version": "1.0.0"
}
```

## Plugin Directory Structure

```
app/plugins/{plugin_id}/
    plugin.json                    # Metadata manifest
    main.py                        # Entry point (extends PluginBase)
    services/                      # Business logic
        __init__.py
        {service}.py
    api/                           # FastAPI router (optional)
        __init__.py
        router.py
```

## Creating a Plugin

### 1. Extend PluginBase
```python
from backend.managers.plugin_manager import PluginBase, PluginMetadata

class MyPlugin(PluginBase):
    async def on_load(self):
        # Initialize services
        pass

    async def on_enable(self):
        # Register hooks, start functionality
        self.register_hook("hook_name", self.my_callback)

    async def on_disable(self):
        # Stop functionality
        pass

    async def on_unload(self):
        # Cleanup resources
        pass
```

### 2. Register Hooks
Available hooks:
- `pm3_command` - Triggered on Proxmark3 commands
- `update_check` - Triggered on system update checks
- Custom hooks can be added

### 3. Add API Routes (Optional)
Plugins can expose their own FastAPI routers mounted under `/api/plugins/{plugin_id}/`

### 4. Register Header Widgets
Display notifications in the UI header:
```python
from backend.managers.plugin_manager import WidgetSeverity

class MyPlugin(PluginBase):
    async def on_enable(self):
        # Register a header widget
        self.register_widget(
            widget_id="status",           # Becomes "plugin.my_plugin.status"
            severity=WidgetSeverity.INFO,
            message="Plugin is active",
            icon="🔌",
            dismissible=True,
            action_label="Settings",      # Optional
            action_url="/settings#plugins"
        )

    async def on_disable(self):
        # Clean up widget
        self.unregister_widget("status")
```

Widget severity levels: `INFO`, `WARNING`, `ERROR`, `SUCCESS`

### 5. Broadcast WebSocket Events
Send real-time updates to connected clients (requires `websocket` permission):
```python
class MyPlugin(PluginBase):
    async def some_operation(self):
        # Broadcast event to all connected clients
        # Event type becomes: "plugin.my_plugin.progress"
        await self.broadcast_event("progress", {
            "percent": 50,
            "message": "Processing..."
        })
```

WebSocket events are rate-limited to 10 events/second per plugin.

### 6. Access Hardware
Get controlled access to hardware interfaces (requires permissions in plugin.json):
```python
class MyPlugin(PluginBase):
    def setup_hardware(self):
        # Requires "i2c" permission
        i2c = self.get_i2c(bus=1)

        # Requires "gpio" permission
        gpio = self.get_gpio()

        # Requires "spi" permission
        spi = self.get_spi(bus=0, device=0)

        # Requires "serial" permission
        serial = self.get_serial("/dev/ttyUSB0", baudrate=9600)
```

## Available Permissions

| Permission | Description | Methods Unlocked |
|------------|-------------|------------------|
| `gpio` | Access GPIO pins | `get_gpio()` |
| `i2c` | Access I2C bus | `get_i2c()` |
| `spi` | Access SPI bus | `get_spi()` |
| `serial` | Access serial ports | `get_serial()` |
| `websocket` | Broadcast WebSocket events | `broadcast_event()` |
| `camera` | Access camera | (future) |
| `network_access` | Make network requests | (unrestricted) |
| `pm3_flash` | Flash PM3 devices | (via hooks) |
| `script_execution` | Execute user scripts | (sandboxed) |

**Note:** Hardware permissions (`gpio`, `i2c`, `spi`, `serial`) require user consent at install time.
Attempting to use hardware methods without the required permission raises `PermissionError`.

## Hardware Libraries

Plugins can depend on these for hardware access:
- `RPi.GPIO` - GPIO pin control
- `smbus2` - I2C communication
- `spidev` - SPI communication
- `gpiozero` - Higher-level GPIO abstraction
- `pyserial` - Serial/UART communication
- `opencv-python-headless` - Camera/image processing

## Key Files

| File | Purpose |
|------|---------|
| `app/backend/managers/plugin_manager.py` | Core plugin framework, widgets, permissions |
| `app/backend/services/hardware_service.py` | Hardware access layer (I2C, GPIO, SPI, Serial) |
| `app/backend/websocket/notifications.py` | WebSocket event broadcasting |
| `app/backend/api/plugins.py` | Plugin API endpoints |
| `app/backend/api/system.py` | Widget API endpoints (`/api/system/widgets`) |
| `app/frontend/app/components/HeaderWidgets.tsx` | Widget UI component |
| `app/plugins/hello_world/` | Reference implementation |

## Installation Sources

1. **From registry** - Browse webstore → select plugin → auto-install
2. **Direct URL** - Install from any GitHub release URL

## Security Guidelines

- Verify SHA256 checksums before extraction
- Only install pip packages from PyPI
- Sandbox script execution (no os, sys, subprocess access)
- Display permissions to user before installation
- Log all plugin installations

## Related Plans

See `/home/work/.claude/plans/tranquil-toasting-clover.md` for the full implementation plan including:
- Multi-Flasher Plugin (parallel PM3 firmware flashing)
- Color Detector Plugin (webcam color detection + WebREPL)
