docs: roundtable rename sweep
Sweeps README, docs/, example configs, code docstrings, report and notification subject lines, plugin catalog URL default, and stray comments in Dockerfile/entrypoint.sh/.gitignore. Adds a legacy note to docs/core/configuration.md explaining the FABLEDSCRYER_* fallback. docker-compose DB credentials intentionally left as fabledscryer to preserve the existing pgdata volume.
This commit is contained in:
+13
-13
@@ -1,12 +1,12 @@
|
||||
# Architecture
|
||||
|
||||
Fabled Scryer is a single Quart (async Python) process. There are no separate worker processes, no message brokers, and no build pipeline for the frontend. All monitoring, scheduling, and request handling runs on a single asyncio event loop.
|
||||
Roundtable is a single Quart (async Python) process. There are no separate worker processes, no message brokers, and no build pipeline for the frontend. All monitoring, scheduling, and request handling runs on a single asyncio event loop.
|
||||
|
||||
---
|
||||
|
||||
## Startup Sequence
|
||||
|
||||
`create_app()` in `fabledscryer/app.py` runs these steps synchronously before the event loop starts:
|
||||
`create_app()` in `roundtable/app.py` runs these steps synchronously before the event loop starts:
|
||||
|
||||
| Step | What happens |
|
||||
|---|---|
|
||||
@@ -32,14 +32,14 @@ All routes are Quart Blueprints registered in `app.py`:
|
||||
|
||||
| Prefix | Blueprint | Module |
|
||||
|---|---|---|
|
||||
| `/auth/` | `auth_bp` | `fabledscryer/auth/routes.py` |
|
||||
| `/` | `dashboard_bp` | `fabledscryer/dashboard/routes.py` |
|
||||
| `/hosts/` | `hosts_bp` | `fabledscryer/hosts/routes.py` |
|
||||
| `/ping/` | `ping_bp` | `fabledscryer/ping/routes.py` |
|
||||
| `/dns/` | `dns_bp` | `fabledscryer/dns/routes.py` |
|
||||
| `/alerts/` | `alerts_bp` | `fabledscryer/alerts/routes.py` |
|
||||
| `/ansible/` | `ansible_bp` | `fabledscryer/ansible/routes.py` |
|
||||
| `/settings/` | `settings_bp` | `fabledscryer/settings/routes.py` |
|
||||
| `/auth/` | `auth_bp` | `roundtable/auth/routes.py` |
|
||||
| `/` | `dashboard_bp` | `roundtable/dashboard/routes.py` |
|
||||
| `/hosts/` | `hosts_bp` | `roundtable/hosts/routes.py` |
|
||||
| `/ping/` | `ping_bp` | `roundtable/ping/routes.py` |
|
||||
| `/dns/` | `dns_bp` | `roundtable/dns/routes.py` |
|
||||
| `/alerts/` | `alerts_bp` | `roundtable/alerts/routes.py` |
|
||||
| `/ansible/` | `ansible_bp` | `roundtable/ansible/routes.py` |
|
||||
| `/settings/` | `settings_bp` | `roundtable/settings/routes.py` |
|
||||
| `/plugins/<name>/` | plugin blueprint | `plugins/<name>/routes.py` |
|
||||
|
||||
Plugin blueprints are mounted automatically by `load_plugins()` using the plugin directory name as the URL prefix.
|
||||
@@ -48,7 +48,7 @@ Plugin blueprints are mounted automatically by `load_plugins()` using the plugin
|
||||
|
||||
## Scheduler
|
||||
|
||||
`fabledscryer/core/scheduler.py` exports two things:
|
||||
`roundtable/core/scheduler.py` exports two things:
|
||||
|
||||
- `ScheduledTask` dataclass — holds a `name`, `coro_factory` (zero-argument callable returning a coroutine), `interval_seconds`, and optional `run_on_startup` flag
|
||||
- `start_scheduler(tasks)` — async function that loops every second, calling `asyncio.create_task()` for each task whose interval has elapsed
|
||||
@@ -93,9 +93,9 @@ This means the only file you must touch to get the app running is the database U
|
||||
|
||||
No JavaScript framework, no build step. The frontend is:
|
||||
|
||||
- **Jinja2 templates** rendered server-side (`fabledscryer/templates/`)
|
||||
- **Jinja2 templates** rendered server-side (`roundtable/templates/`)
|
||||
- **HTMX** for live-updating fragments (dashboard widgets, ping pills, DNS status)
|
||||
- A single CSS design system in `fabledscryer/templates/base.html` using CSS custom properties
|
||||
- A single CSS design system in `roundtable/templates/base.html` using CSS custom properties
|
||||
|
||||
Live-updating widgets use HTMX polling:
|
||||
```html
|
||||
|
||||
@@ -14,7 +14,7 @@ When any monitor or plugin calls `record_metric()`:
|
||||
4. If a state transition occurs, an `AlertEvent` row is written
|
||||
5. Notification I/O is deferred outside the transaction via `asyncio.create_task()`
|
||||
|
||||
**Key function:** `fabledscryer/core/alerts.py` → `record_metric(session, source_module, resource_name, metric_name, value)`
|
||||
**Key function:** `roundtable/core/alerts.py` → `record_metric(session, source_module, resource_name, metric_name, value)`
|
||||
|
||||
`record_metric()` must always be called inside an active transaction:
|
||||
|
||||
@@ -130,7 +130,7 @@ Webhook is skipped if `webhook.url` is empty.
|
||||
|
||||
## Data Models
|
||||
|
||||
Defined in `fabledscryer/models/alerts.py`:
|
||||
Defined in `roundtable/models/alerts.py`:
|
||||
|
||||
- **`alert_rules`** — one row per configured rule
|
||||
- **`alert_states`** — one row per rule, tracks current state and consecutive failure count
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Ansible Integration
|
||||
|
||||
Fabled Scryer can browse, trigger, and stream output from Ansible playbooks directly from the web UI. Runs execute as asyncio tasks inside the same process — no Celery, no external workers.
|
||||
Roundtable can browse, trigger, and stream output from Ansible playbooks directly from the web UI. Runs execute as asyncio tasks inside the same process — no Celery, no external workers.
|
||||
|
||||
---
|
||||
|
||||
@@ -115,7 +115,7 @@ Output stored in the DB is capped at 1 MB. If truncated, `[output truncated]` is
|
||||
|
||||
## Data Model
|
||||
|
||||
`ansible_runs` table (defined in `fabledscryer/models/ansible.py`):
|
||||
`ansible_runs` table (defined in `roundtable/models/ansible.py`):
|
||||
|
||||
| Column | Type | Description |
|
||||
|---|---|---|
|
||||
@@ -137,7 +137,7 @@ Runs older than `data.retention_days` (default 90) are pruned by the `data_clean
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `fabledscryer/ansible/sources.py` | Source discovery, git pull logic |
|
||||
| `fabledscryer/ansible/executor.py` | Subprocess execution and output streaming |
|
||||
| `fabledscryer/ansible/routes.py` | HTTP routes (browse, trigger, stream, history) |
|
||||
| `fabledscryer/models/ansible.py` | `AnsibleRun` model |
|
||||
| `roundtable/ansible/sources.py` | Source discovery, git pull logic |
|
||||
| `roundtable/ansible/executor.py` | Subprocess execution and output streaming |
|
||||
| `roundtable/ansible/routes.py` | HTTP routes (browse, trigger, stream, history) |
|
||||
| `roundtable/models/ansible.py` | `AnsibleRun` model |
|
||||
|
||||
+12
-10
@@ -1,6 +1,6 @@
|
||||
# Configuration
|
||||
|
||||
Fabled Scryer uses a two-layer configuration system. Only the bare minimum needed to boot lives in files or environment variables. Everything else is stored in the database and managed through the Settings UI.
|
||||
Roundtable uses a two-layer configuration system. Only the bare minimum needed to boot lives in files or environment variables. Everything else is stored in the database and managed through the Settings UI.
|
||||
|
||||
---
|
||||
|
||||
@@ -10,29 +10,31 @@ These three values are read at startup from `config.yaml` and/or environment var
|
||||
|
||||
| Key | Env var | Default | Description |
|
||||
|---|---|---|---|
|
||||
| `database.url` | `FABLEDSCRYER_DATABASE_URL` | — | PostgreSQL async URL. **Required.** |
|
||||
| `secret_key` | `FABLEDSCRYER_SECRET_KEY` | auto-generated | Flask/Quart session signing key. Auto-generated and saved to `/data/secret.key` if not set. |
|
||||
| `plugin_dir` | `FABLEDSCRYER_PLUGIN_DIR` | `plugins` | Path to the plugins directory. |
|
||||
| `database.url` | `ROUNDTABLE_DATABASE_URL` | — | PostgreSQL async URL. **Required.** |
|
||||
| `secret_key` | `ROUNDTABLE_SECRET_KEY` | auto-generated | Flask/Quart session signing key. Auto-generated and saved to `/data/secret.key` if not set. |
|
||||
| `plugin_dir` | `ROUNDTABLE_PLUGIN_DIR` | `plugins` | Path to the plugins directory. |
|
||||
|
||||
**Resolution order for `database_url`:** env var `FABLEDSCRYER_DATABASE_URL` → env var `FABLEDSCRYER_DATABASE__URL` (legacy double-underscore) → `database.url` in `config.yaml`.
|
||||
**Resolution order for `database_url`:** env var `ROUNDTABLE_DATABASE_URL` → env var `ROUNDTABLE_DATABASE__URL` (legacy double-underscore) → `database.url` in `config.yaml`.
|
||||
|
||||
**Resolution order for `secret_key`:** env var `FABLEDSCRYER_SECRET_KEY` → `secret_key` in `config.yaml` → `/data/secret.key` file → auto-generate and write to `/data/secret.key`.
|
||||
**Resolution order for `secret_key`:** env var `ROUNDTABLE_SECRET_KEY` → `secret_key` in `config.yaml` → `/data/secret.key` file → auto-generate and write to `/data/secret.key`.
|
||||
|
||||
### Minimal config.yaml
|
||||
|
||||
```yaml
|
||||
database:
|
||||
url: "postgresql+asyncpg://user:password@localhost/fabledscryer"
|
||||
url: "postgresql+asyncpg://user:password@localhost/roundtable"
|
||||
```
|
||||
|
||||
### Minimal env-only setup (Docker)
|
||||
|
||||
```bash
|
||||
FABLEDSCRYER_DATABASE_URL=postgresql+asyncpg://user:password@db/fabledscryer
|
||||
ROUNDTABLE_DATABASE_URL=postgresql+asyncpg://user:password@db/roundtable
|
||||
```
|
||||
|
||||
A `.env` file is loaded automatically if present.
|
||||
|
||||
> **Legacy env vars:** `FABLEDSCRYER_*` env vars are still accepted as a fallback for existing deployments. They will be removed in a future release — migrate to `ROUNDTABLE_*` when convenient.
|
||||
|
||||
---
|
||||
|
||||
## App Settings (Database-backed)
|
||||
@@ -66,7 +68,7 @@ Default webhook template:
|
||||
### Reading and Writing Settings in Code
|
||||
|
||||
```python
|
||||
from fabledscryer.core.settings import get_setting, set_setting
|
||||
from roundtable.core.settings import get_setting, set_setting
|
||||
|
||||
# Read
|
||||
async with current_app.db_sessionmaker() as session:
|
||||
@@ -82,7 +84,7 @@ async with current_app.db_sessionmaker() as session:
|
||||
|
||||
### The DEFAULTS Dict
|
||||
|
||||
`fabledscryer/core/settings.py` contains the `DEFAULTS` dict — the canonical list of all recognised settings and their default values. Add new settings here to make them recognised by `get_all_settings()` and the settings UI.
|
||||
`roundtable/core/settings.py` contains the `DEFAULTS` dict — the canonical list of all recognised settings and their default values. Add new settings here to make them recognised by `get_all_settings()` and the settings UI.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# Core Monitors
|
||||
|
||||
Fabled Scryer ships two built-in monitors: Ping and DNS. Both run as asyncio scheduled tasks on the same event loop as the web server, with no separate processes.
|
||||
Roundtable ships two built-in monitors: Ping and DNS. Both run as asyncio scheduled tasks on the same event loop as the web server, with no separate processes.
|
||||
|
||||
---
|
||||
|
||||
## Ping Monitor
|
||||
|
||||
**Source:** `fabledscryer/monitors/ping.py`
|
||||
**Scheduler task:** `ping_monitor` in `fabledscryer/app.py`
|
||||
**Source:** `roundtable/monitors/ping.py`
|
||||
**Scheduler task:** `ping_monitor` in `roundtable/app.py`
|
||||
**Interval:** `monitors.poll_interval_seconds` (default 60s), runs on startup
|
||||
|
||||
### How It Works
|
||||
@@ -29,7 +29,7 @@ Each probe writes a `PingResult` row and calls `record_metric()`:
|
||||
|
||||
### Data Model
|
||||
|
||||
`ping_results` table (defined in `fabledscryer/models/monitors.py`):
|
||||
`ping_results` table (defined in `roundtable/models/monitors.py`):
|
||||
|
||||
| Column | Type | Description |
|
||||
|---|---|---|
|
||||
@@ -51,8 +51,8 @@ Old rows are pruned by the `data_cleanup` task (default: 90 days).
|
||||
|
||||
## DNS Monitor
|
||||
|
||||
**Source:** `fabledscryer/monitors/dns.py`
|
||||
**Scheduler task:** `dns_monitor` in `fabledscryer/app.py`
|
||||
**Source:** `roundtable/monitors/dns.py`
|
||||
**Scheduler task:** `dns_monitor` in `roundtable/app.py`
|
||||
**Interval:** `monitors.poll_interval_seconds` (default 60s), runs on startup
|
||||
|
||||
### How It Works
|
||||
@@ -70,7 +70,7 @@ Each check writes a `DnsResult` row and calls `record_metric()`:
|
||||
|
||||
### Data Model
|
||||
|
||||
`dns_results` table (defined in `fabledscryer/models/monitors.py`):
|
||||
`dns_results` table (defined in `roundtable/models/monitors.py`):
|
||||
|
||||
| Column | Type | Description |
|
||||
|---|---|---|
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# fabledscryer-plugins / index.yaml
|
||||
# roundtable-plugins / index.yaml
|
||||
#
|
||||
# This file is the catalog index for the fabledscryer plugin repository.
|
||||
# This file is the catalog index for the roundtable plugin repository.
|
||||
# It is fetched by the app's Settings → Plugins → Plugin Catalog UI.
|
||||
#
|
||||
# Fabled Scryer reads this file from:
|
||||
# https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/raw/branch/main/index.yaml
|
||||
# Roundtable reads this file from:
|
||||
# https://git.fabledsword.com/bvandeusen/Roundtable-plugins/raw/branch/main/index.yaml
|
||||
#
|
||||
# After adding or updating a plugin entry, commit and push — the change is
|
||||
# live immediately for anyone whose app fetches the catalog (cache TTL: 5 min).
|
||||
@@ -25,7 +25,7 @@
|
||||
#
|
||||
# Download URL conventions:
|
||||
# Gitea release assets (recommended):
|
||||
# https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/releases/download/traefik-v1.0.0/traefik.zip
|
||||
# https://git.fabledsword.com/bvandeusen/Roundtable-plugins/releases/download/traefik-v1.0.0/traefik.zip
|
||||
# Upload the zip as a release attachment in Gitea; paste the URL here.
|
||||
# Source archive tarballs work too but release assets are preferred (smaller, plugin-only).
|
||||
|
||||
@@ -37,12 +37,12 @@ plugins:
|
||||
- name: http
|
||||
version: "1.0.0"
|
||||
description: "Synthetic HTTP endpoint monitoring — status code, response time, content match, TLS expiry"
|
||||
author: "FabledScryer"
|
||||
author: "Roundtable"
|
||||
license: "MIT"
|
||||
min_app_version: "0.1.0"
|
||||
repository_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins"
|
||||
homepage: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/src/branch/main/http"
|
||||
download_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/releases/download/http-v1.0.0/http.zip"
|
||||
repository_url: "https://git.fabledsword.com/bvandeusen/Roundtable-plugins"
|
||||
homepage: "https://git.fabledsword.com/bvandeusen/Roundtable-plugins/src/branch/main/http"
|
||||
download_url: "https://git.fabledsword.com/bvandeusen/Roundtable-plugins/releases/download/http-v1.0.0/http.zip"
|
||||
checksum_sha256: ""
|
||||
tags:
|
||||
- monitoring
|
||||
@@ -53,12 +53,12 @@ plugins:
|
||||
- name: docker
|
||||
version: "1.0.0"
|
||||
description: "Docker container status, resource usage, and restart tracking via Docker socket"
|
||||
author: "FabledScryer"
|
||||
author: "Roundtable"
|
||||
license: "MIT"
|
||||
min_app_version: "0.1.0"
|
||||
repository_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins"
|
||||
homepage: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/src/branch/main/docker"
|
||||
download_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/releases/download/docker-v1.0.0/docker.zip"
|
||||
repository_url: "https://git.fabledsword.com/bvandeusen/Roundtable-plugins"
|
||||
homepage: "https://git.fabledsword.com/bvandeusen/Roundtable-plugins/src/branch/main/docker"
|
||||
download_url: "https://git.fabledsword.com/bvandeusen/Roundtable-plugins/releases/download/docker-v1.0.0/docker.zip"
|
||||
checksum_sha256: ""
|
||||
tags:
|
||||
- containers
|
||||
@@ -68,12 +68,12 @@ plugins:
|
||||
- name: traefik
|
||||
version: "1.0.0"
|
||||
description: "Traefik reverse proxy metrics and access log integration"
|
||||
author: "FabledScryer"
|
||||
author: "Roundtable"
|
||||
license: "MIT"
|
||||
min_app_version: "0.1.0"
|
||||
repository_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins"
|
||||
homepage: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/src/branch/main/traefik"
|
||||
download_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/releases/download/traefik-v1.0.0/traefik.zip"
|
||||
repository_url: "https://git.fabledsword.com/bvandeusen/Roundtable-plugins"
|
||||
homepage: "https://git.fabledsword.com/bvandeusen/Roundtable-plugins/src/branch/main/traefik"
|
||||
download_url: "https://git.fabledsword.com/bvandeusen/Roundtable-plugins/releases/download/traefik-v1.0.0/traefik.zip"
|
||||
checksum_sha256: "" # fill in after running: sha256sum traefik.zip
|
||||
tags:
|
||||
- proxy
|
||||
@@ -83,12 +83,12 @@ plugins:
|
||||
- name: unifi
|
||||
version: "1.0.0"
|
||||
description: "UniFi Network controller integration — WAN health, devices, clients, DPI"
|
||||
author: "FabledScryer"
|
||||
author: "Roundtable"
|
||||
license: "MIT"
|
||||
min_app_version: "0.1.0"
|
||||
repository_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins"
|
||||
homepage: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/src/branch/main/unifi"
|
||||
download_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/releases/download/unifi-v1.0.0/unifi.zip"
|
||||
repository_url: "https://git.fabledsword.com/bvandeusen/Roundtable-plugins"
|
||||
homepage: "https://git.fabledsword.com/bvandeusen/Roundtable-plugins/src/branch/main/unifi"
|
||||
download_url: "https://git.fabledsword.com/bvandeusen/Roundtable-plugins/releases/download/unifi-v1.0.0/unifi.zip"
|
||||
checksum_sha256: ""
|
||||
tags:
|
||||
- network
|
||||
@@ -98,12 +98,12 @@ plugins:
|
||||
- name: ups
|
||||
version: "1.0.0"
|
||||
description: "UPS monitoring via NUT (Network UPS Tools) with Ansible shutdown automation"
|
||||
author: "FabledScryer"
|
||||
author: "Roundtable"
|
||||
license: "MIT"
|
||||
min_app_version: "0.1.0"
|
||||
repository_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins"
|
||||
homepage: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/src/branch/main/ups"
|
||||
download_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/releases/download/ups-v1.0.0/ups.zip"
|
||||
repository_url: "https://git.fabledsword.com/bvandeusen/Roundtable-plugins"
|
||||
homepage: "https://git.fabledsword.com/bvandeusen/Roundtable-plugins/src/branch/main/ups"
|
||||
download_url: "https://git.fabledsword.com/bvandeusen/Roundtable-plugins/releases/download/ups-v1.0.0/ups.zip"
|
||||
checksum_sha256: ""
|
||||
tags:
|
||||
- ups
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Plugin System Overview
|
||||
|
||||
Plugins extend Fabled Scryer with new data sources, UI pages, scheduled tasks, and dashboard widgets. Only enabled plugins are imported — disabled or unlisted plugins have zero runtime overhead.
|
||||
Plugins extend Roundtable with new data sources, UI pages, scheduled tasks, and dashboard widgets. Only enabled plugins are imported — disabled or unlisted plugins have zero runtime overhead.
|
||||
|
||||
---
|
||||
|
||||
## How Plugins Are Loaded
|
||||
|
||||
Plugin loading happens in step 9 of `create_app()`, after all core blueprints and tasks are registered. The entrypoint is `load_plugins(app)` in `fabledscryer/core/plugin_manager.py`.
|
||||
Plugin loading happens in step 9 of `create_app()`, after all core blueprints and tasks are registered. The entrypoint is `load_plugins(app)` in `roundtable/core/plugin_manager.py`.
|
||||
|
||||
For each plugin listed as `enabled: true` in the `PLUGINS` config:
|
||||
|
||||
@@ -57,7 +57,7 @@ description: "Does a thing"
|
||||
|
||||
# Optional
|
||||
author: "Your Name"
|
||||
min_app_version: "0.1.0" # Minimum Fabled Scryer version required
|
||||
min_app_version: "0.1.0" # Minimum Roundtable version required
|
||||
|
||||
# Default config — merged with user overrides at runtime
|
||||
# Access at runtime via: app.config["PLUGINS"]["myplugin"]["my_setting"]
|
||||
@@ -90,7 +90,7 @@ def setup(app):
|
||||
Returns a list of `ScheduledTask` objects. Return `[]` if the plugin has no background tasks. Called after `setup()`, so any app references set in `setup()` are available.
|
||||
|
||||
```python
|
||||
from fabledscryer.core.scheduler import ScheduledTask
|
||||
from roundtable.core.scheduler import ScheduledTask
|
||||
|
||||
def get_scheduled_tasks():
|
||||
app = _app
|
||||
@@ -154,7 +154,7 @@ A plugin can contribute a dashboard widget by:
|
||||
1. Adding a `GET /widget` route to its blueprint that returns an HTMX HTML fragment
|
||||
2. The dashboard template polling that endpoint with HTMX
|
||||
|
||||
The dashboard (`fabledscryer/templates/dashboard/index.html`) currently includes the Traefik widget conditionally based on `traefik_enabled`. To add a new plugin widget, the dashboard route and template both need to be updated to detect and render the new widget. See the Traefik widget implementation as a reference.
|
||||
The dashboard (`roundtable/templates/dashboard/index.html`) currently includes the Traefik widget conditionally based on `traefik_enabled`. To add a new plugin widget, the dashboard route and template both need to be updated to detect and render the new widget. See the Traefik widget implementation as a reference.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ config:
|
||||
|
||||
## Step 3: Define Models (if needed)
|
||||
|
||||
If your plugin stores data, define SQLAlchemy models using the shared `Base` from `fabledscryer.models.base`.
|
||||
If your plugin stores data, define SQLAlchemy models using the shared `Base` from `roundtable.models.base`.
|
||||
|
||||
```python
|
||||
# plugins/myplugin/models.py
|
||||
@@ -55,7 +55,7 @@ import uuid
|
||||
from datetime import datetime
|
||||
from sqlalchemy import String, Float, DateTime
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
from fabledscryer.models.base import Base
|
||||
from roundtable.models.base import Base
|
||||
|
||||
|
||||
class MyPluginMetric(Base):
|
||||
@@ -79,7 +79,7 @@ Generate the initial migration:
|
||||
# From the project root
|
||||
alembic --config alembic.ini revision \
|
||||
--autogenerate \
|
||||
--head=fabledscryer@head \
|
||||
--head=roundtable@head \
|
||||
--branch-label=myplugin \
|
||||
-m "myplugin initial"
|
||||
```
|
||||
@@ -106,8 +106,8 @@ Keep task logic in a separate file so `__init__.py` stays clean.
|
||||
# plugins/myplugin/scheduler.py
|
||||
from __future__ import annotations
|
||||
import logging
|
||||
from fabledscryer.core.scheduler import ScheduledTask
|
||||
from fabledscryer.core.alerts import record_metric
|
||||
from roundtable.core.scheduler import ScheduledTask
|
||||
from roundtable.core.alerts import record_metric
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -174,8 +174,8 @@ async def _fetch_value(url: str) -> float:
|
||||
```python
|
||||
# plugins/myplugin/routes.py
|
||||
from quart import Blueprint, current_app, render_template
|
||||
from fabledscryer.auth.middleware import require_role
|
||||
from fabledscryer.models.users import UserRole
|
||||
from roundtable.auth.middleware import require_role
|
||||
from roundtable.models.users import UserRole
|
||||
from .models import MyPluginMetric
|
||||
|
||||
myplugin_bp = Blueprint("myplugin", __name__, template_folder="templates")
|
||||
@@ -215,7 +215,7 @@ Templates live in `plugins/myplugin/templates/myplugin/` (the extra nesting avoi
|
||||
```html
|
||||
{# plugins/myplugin/templates/myplugin/index.html #}
|
||||
{% extends "base.html" %}
|
||||
{% block title %}My Plugin — Fabled Scryer{% endblock %}
|
||||
{% block title %}My Plugin — Roundtable{% endblock %}
|
||||
{% block content %}
|
||||
<div class="page-title">My Plugin</div>
|
||||
{% for row in rows %}
|
||||
@@ -283,7 +283,7 @@ On next startup, the plugin will be loaded, its migrations applied, and its blue
|
||||
`record_metric()` is how plugins feed data into the alert pipeline. Any metric you write here can be the target of an alert rule created in the UI.
|
||||
|
||||
```python
|
||||
from fabledscryer.core.alerts import record_metric
|
||||
from roundtable.core.alerts import record_metric
|
||||
|
||||
# Must be inside an active transaction
|
||||
async with session.begin():
|
||||
@@ -302,11 +302,11 @@ async with session.begin():
|
||||
|
||||
## Auth in Routes
|
||||
|
||||
Use the `@require_role` decorator from `fabledscryer.auth.middleware`:
|
||||
Use the `@require_role` decorator from `roundtable.auth.middleware`:
|
||||
|
||||
```python
|
||||
from fabledscryer.auth.middleware import require_role
|
||||
from fabledscryer.models.users import UserRole
|
||||
from roundtable.auth.middleware import require_role
|
||||
from roundtable.models.users import UserRole
|
||||
|
||||
@myplugin_bp.get("/admin-only")
|
||||
@require_role(UserRole.admin)
|
||||
@@ -325,13 +325,13 @@ Role hierarchy: `admin > operator > viewer`. Requiring `viewer` grants access to
|
||||
|
||||
## Publishing to the Catalog
|
||||
|
||||
The official plugin catalog is hosted at `https://git.fabledsword.com/bvandeusen/FabledScryer-plugins`. Anyone can submit a plugin by opening a pull request — first-party and third-party plugins are treated identically by the catalog system.
|
||||
The official plugin catalog is hosted at `https://git.fabledsword.com/bvandeusen/Roundtable-plugins`. Anyone can submit a plugin by opening a pull request — first-party and third-party plugins are treated identically by the catalog system.
|
||||
|
||||
### Repo layout
|
||||
|
||||
```
|
||||
fabledscryer-plugins/
|
||||
├── index.yaml ← catalog index — the only file Fabled Scryer fetches
|
||||
roundtable-plugins/
|
||||
├── index.yaml ← catalog index — the only file Roundtable fetches
|
||||
├── myplugin/
|
||||
│ ├── plugin.yaml
|
||||
│ ├── __init__.py
|
||||
@@ -381,7 +381,7 @@ myplugin.zip
|
||||
Generate the zip and its checksum:
|
||||
|
||||
```bash
|
||||
cd fabledscryer-plugins
|
||||
cd roundtable-plugins
|
||||
zip -r myplugin.zip myplugin/
|
||||
sha256sum myplugin.zip # paste this into index.yaml checksum_sha256
|
||||
```
|
||||
|
||||
+59
-59
@@ -8,15 +8,15 @@ Quick reference for where key functions, models, and entry points live in the co
|
||||
|
||||
| What | File | Function / Class |
|
||||
|---|---|---|
|
||||
| App factory | `fabledscryer/app.py` | `create_app()` |
|
||||
| CLI entry point | `fabledscryer/cli.py` | `main()` |
|
||||
| Bootstrap config loading | `fabledscryer/config.py` | `load_bootstrap()` |
|
||||
| Secret key resolution | `fabledscryer/config.py` | `_resolve_secret_key()` |
|
||||
| DB engine init | `fabledscryer/database.py` | `init_db()` |
|
||||
| Core migrations | `fabledscryer/core/migration_runner.py` | `run_core_migrations()` |
|
||||
| Plugin migrations | `fabledscryer/core/migration_runner.py` | `run_plugin_migrations()` |
|
||||
| Core task registration | `fabledscryer/app.py` | `_register_core_tasks()` |
|
||||
| Scheduler loop | `fabledscryer/core/scheduler.py` | `start_scheduler()` |
|
||||
| App factory | `roundtable/app.py` | `create_app()` |
|
||||
| CLI entry point | `roundtable/cli.py` | `main()` |
|
||||
| Bootstrap config loading | `roundtable/config.py` | `load_bootstrap()` |
|
||||
| Secret key resolution | `roundtable/config.py` | `_resolve_secret_key()` |
|
||||
| DB engine init | `roundtable/database.py` | `init_db()` |
|
||||
| Core migrations | `roundtable/core/migration_runner.py` | `run_core_migrations()` |
|
||||
| Plugin migrations | `roundtable/core/migration_runner.py` | `run_plugin_migrations()` |
|
||||
| Core task registration | `roundtable/app.py` | `_register_core_tasks()` |
|
||||
| Scheduler loop | `roundtable/core/scheduler.py` | `start_scheduler()` |
|
||||
|
||||
---
|
||||
|
||||
@@ -24,15 +24,15 @@ Quick reference for where key functions, models, and entry points live in the co
|
||||
|
||||
| What | File | Function |
|
||||
|---|---|---|
|
||||
| All defaults | `fabledscryer/core/settings.py` | `DEFAULTS` dict |
|
||||
| Read a setting | `fabledscryer/core/settings.py` | `get_setting(session, key)` |
|
||||
| Write a setting | `fabledscryer/core/settings.py` | `set_setting(session, key, value)` |
|
||||
| Read all settings | `fabledscryer/core/settings.py` | `get_all_settings(session)` |
|
||||
| Sync load at startup | `fabledscryer/core/settings.py` | `load_settings_sync(db_url)` |
|
||||
| Extract SMTP dict | `fabledscryer/core/settings.py` | `to_smtp_cfg(settings)` |
|
||||
| Extract webhook dict | `fabledscryer/core/settings.py` | `to_webhook_cfg(settings)` |
|
||||
| Extract Ansible dict | `fabledscryer/core/settings.py` | `to_ansible_cfg(settings)` |
|
||||
| Extract plugins dict | `fabledscryer/core/settings.py` | `to_plugins_cfg(settings)` |
|
||||
| All defaults | `roundtable/core/settings.py` | `DEFAULTS` dict |
|
||||
| Read a setting | `roundtable/core/settings.py` | `get_setting(session, key)` |
|
||||
| Write a setting | `roundtable/core/settings.py` | `set_setting(session, key, value)` |
|
||||
| Read all settings | `roundtable/core/settings.py` | `get_all_settings(session)` |
|
||||
| Sync load at startup | `roundtable/core/settings.py` | `load_settings_sync(db_url)` |
|
||||
| Extract SMTP dict | `roundtable/core/settings.py` | `to_smtp_cfg(settings)` |
|
||||
| Extract webhook dict | `roundtable/core/settings.py` | `to_webhook_cfg(settings)` |
|
||||
| Extract Ansible dict | `roundtable/core/settings.py` | `to_ansible_cfg(settings)` |
|
||||
| Extract plugins dict | `roundtable/core/settings.py` | `to_plugins_cfg(settings)` |
|
||||
|
||||
---
|
||||
|
||||
@@ -40,9 +40,9 @@ Quick reference for where key functions, models, and entry points live in the co
|
||||
|
||||
| What | File | Function |
|
||||
|---|---|---|
|
||||
| Plugin loading | `fabledscryer/core/plugin_manager.py` | `load_plugins(app)` |
|
||||
| ScheduledTask dataclass | `fabledscryer/core/scheduler.py` | `ScheduledTask` |
|
||||
| Task runner | `fabledscryer/core/scheduler.py` | `start_scheduler(tasks)` |
|
||||
| Plugin loading | `roundtable/core/plugin_manager.py` | `load_plugins(app)` |
|
||||
| ScheduledTask dataclass | `roundtable/core/scheduler.py` | `ScheduledTask` |
|
||||
| Task runner | `roundtable/core/scheduler.py` | `start_scheduler(tasks)` |
|
||||
|
||||
---
|
||||
|
||||
@@ -50,11 +50,11 @@ Quick reference for where key functions, models, and entry points live in the co
|
||||
|
||||
| What | File | Function |
|
||||
|---|---|---|
|
||||
| Write metric + evaluate alerts | `fabledscryer/core/alerts.py` | `record_metric(session, source_module, resource_name, metric_name, value)` |
|
||||
| Init alert pipeline | `fabledscryer/core/alerts.py` | `init_alerts(app)` |
|
||||
| Rule evaluation | `fabledscryer/core/alerts.py` | `_evaluate_rule()` (internal) |
|
||||
| Notification dispatch | `fabledscryer/core/alerts.py` | `_dispatch_notification()` (internal) |
|
||||
| Email + webhook send | `fabledscryer/core/notifications.py` | `dispatch_notifications()` |
|
||||
| Write metric + evaluate alerts | `roundtable/core/alerts.py` | `record_metric(session, source_module, resource_name, metric_name, value)` |
|
||||
| Init alert pipeline | `roundtable/core/alerts.py` | `init_alerts(app)` |
|
||||
| Rule evaluation | `roundtable/core/alerts.py` | `_evaluate_rule()` (internal) |
|
||||
| Notification dispatch | `roundtable/core/alerts.py` | `_dispatch_notification()` (internal) |
|
||||
| Email + webhook send | `roundtable/core/notifications.py` | `dispatch_notifications()` |
|
||||
|
||||
---
|
||||
|
||||
@@ -62,9 +62,9 @@ Quick reference for where key functions, models, and entry points live in the co
|
||||
|
||||
| What | File | Function |
|
||||
|---|---|---|
|
||||
| Ping a host | `fabledscryer/monitors/ping.py` | `ping_check(host, session)` |
|
||||
| DNS check a host | `fabledscryer/monitors/dns.py` | `dns_check(host, session)` |
|
||||
| Data cleanup | `fabledscryer/core/cleanup.py` | `run_cleanup(app)` |
|
||||
| Ping a host | `roundtable/monitors/ping.py` | `ping_check(host, session)` |
|
||||
| DNS check a host | `roundtable/monitors/dns.py` | `dns_check(host, session)` |
|
||||
| Data cleanup | `roundtable/core/cleanup.py` | `run_cleanup(app)` |
|
||||
|
||||
---
|
||||
|
||||
@@ -72,9 +72,9 @@ Quick reference for where key functions, models, and entry points live in the co
|
||||
|
||||
| What | File | Function / Class |
|
||||
|---|---|---|
|
||||
| Role-based access decorator | `fabledscryer/auth/middleware.py` | `@require_role(UserRole.X)` |
|
||||
| Login / session handling | `fabledscryer/auth/middleware.py` | `login_user()`, `logout_user()` |
|
||||
| User count (for first-run) | `fabledscryer/auth/middleware.py` | `get_user_count(app)` |
|
||||
| Role-based access decorator | `roundtable/auth/middleware.py` | `@require_role(UserRole.X)` |
|
||||
| Login / session handling | `roundtable/auth/middleware.py` | `login_user()`, `logout_user()` |
|
||||
| User count (for first-run) | `roundtable/auth/middleware.py` | `get_user_count(app)` |
|
||||
|
||||
---
|
||||
|
||||
@@ -82,18 +82,18 @@ Quick reference for where key functions, models, and entry points live in the co
|
||||
|
||||
| Model | File | Table |
|
||||
|---|---|---|
|
||||
| `Host` | `fabledscryer/models/hosts.py` | `hosts` |
|
||||
| `PingResult` | `fabledscryer/models/monitors.py` | `ping_results` |
|
||||
| `DnsResult` | `fabledscryer/models/monitors.py` | `dns_results` |
|
||||
| `AlertRule` | `fabledscryer/models/alerts.py` | `alert_rules` |
|
||||
| `AlertState` | `fabledscryer/models/alerts.py` | `alert_states` |
|
||||
| `AlertEvent` | `fabledscryer/models/alerts.py` | `alert_events` |
|
||||
| `PluginMetric` | `fabledscryer/models/metrics.py` | `plugin_metrics` |
|
||||
| `AnsibleRun` | `fabledscryer/models/ansible.py` | `ansible_runs` |
|
||||
| `User` | `fabledscryer/models/users.py` | `users` |
|
||||
| `AppSetting` | `fabledscryer/models/settings.py` | `app_settings` |
|
||||
| `Host` | `roundtable/models/hosts.py` | `hosts` |
|
||||
| `PingResult` | `roundtable/models/monitors.py` | `ping_results` |
|
||||
| `DnsResult` | `roundtable/models/monitors.py` | `dns_results` |
|
||||
| `AlertRule` | `roundtable/models/alerts.py` | `alert_rules` |
|
||||
| `AlertState` | `roundtable/models/alerts.py` | `alert_states` |
|
||||
| `AlertEvent` | `roundtable/models/alerts.py` | `alert_events` |
|
||||
| `PluginMetric` | `roundtable/models/metrics.py` | `plugin_metrics` |
|
||||
| `AnsibleRun` | `roundtable/models/ansible.py` | `ansible_runs` |
|
||||
| `User` | `roundtable/models/users.py` | `users` |
|
||||
| `AppSetting` | `roundtable/models/settings.py` | `app_settings` |
|
||||
| `TraefikMetric` | `plugins/traefik/models.py` | `traefik_metrics` |
|
||||
| SQLAlchemy `Base` | `fabledscryer/models/base.py` | (shared declarative base) |
|
||||
| SQLAlchemy `Base` | `roundtable/models/base.py` | (shared declarative base) |
|
||||
|
||||
---
|
||||
|
||||
@@ -101,16 +101,16 @@ Quick reference for where key functions, models, and entry points live in the co
|
||||
|
||||
| URL pattern | Blueprint | File |
|
||||
|---|---|---|
|
||||
| `/` (dashboard) | `dashboard_bp` | `fabledscryer/dashboard/routes.py` |
|
||||
| `/auth/login`, `/auth/logout` | `auth_bp` | `fabledscryer/auth/routes.py` |
|
||||
| `/hosts/` | `hosts_bp` | `fabledscryer/hosts/routes.py` |
|
||||
| `/ping/`, `/ping/rows`, `/ping/settings` | `ping_bp` | `fabledscryer/ping/routes.py` |
|
||||
| `/dns/`, `/dns/rows` | `dns_bp` | `fabledscryer/dns/routes.py` |
|
||||
| `/alerts/` | `alerts_bp` | `fabledscryer/alerts/routes.py` |
|
||||
| `/ansible/` | `ansible_bp` | `fabledscryer/ansible/routes.py` |
|
||||
| `/settings/` | `settings_bp` | `fabledscryer/settings/routes.py` |
|
||||
| `/` (dashboard) | `dashboard_bp` | `roundtable/dashboard/routes.py` |
|
||||
| `/auth/login`, `/auth/logout` | `auth_bp` | `roundtable/auth/routes.py` |
|
||||
| `/hosts/` | `hosts_bp` | `roundtable/hosts/routes.py` |
|
||||
| `/ping/`, `/ping/rows`, `/ping/settings` | `ping_bp` | `roundtable/ping/routes.py` |
|
||||
| `/dns/`, `/dns/rows` | `dns_bp` | `roundtable/dns/routes.py` |
|
||||
| `/alerts/` | `alerts_bp` | `roundtable/alerts/routes.py` |
|
||||
| `/ansible/` | `ansible_bp` | `roundtable/ansible/routes.py` |
|
||||
| `/settings/` | `settings_bp` | `roundtable/settings/routes.py` |
|
||||
| `/plugins/traefik/`, `/plugins/traefik/widget` | `traefik_bp` | `plugins/traefik/routes.py` |
|
||||
| `/health` | (inline) | `fabledscryer/app.py` |
|
||||
| `/health` | (inline) | `roundtable/app.py` |
|
||||
|
||||
---
|
||||
|
||||
@@ -118,12 +118,12 @@ Quick reference for where key functions, models, and entry points live in the co
|
||||
|
||||
| Template | Purpose |
|
||||
|---|---|
|
||||
| `fabledscryer/templates/base.html` | Layout, navigation, full CSS design system |
|
||||
| `fabledscryer/templates/dashboard/index.html` | Dashboard with stat strip and widget grid |
|
||||
| `fabledscryer/templates/ping/rows.html` | HTMX fragment: ping pill rows (shared by dashboard and /ping/) |
|
||||
| `fabledscryer/templates/ping/index.html` | Full /ping/ page |
|
||||
| `fabledscryer/templates/dns/rows.html` | HTMX fragment: DNS status rows |
|
||||
| `fabledscryer/templates/dns/index.html` | Full /dns/ page |
|
||||
| `roundtable/templates/base.html` | Layout, navigation, full CSS design system |
|
||||
| `roundtable/templates/dashboard/index.html` | Dashboard with stat strip and widget grid |
|
||||
| `roundtable/templates/ping/rows.html` | HTMX fragment: ping pill rows (shared by dashboard and /ping/) |
|
||||
| `roundtable/templates/ping/index.html` | Full /ping/ page |
|
||||
| `roundtable/templates/dns/rows.html` | HTMX fragment: DNS status rows |
|
||||
| `roundtable/templates/dns/index.html` | Full /dns/ page |
|
||||
| `plugins/traefik/templates/traefik/widget.html` | HTMX fragment: Traefik dashboard widget |
|
||||
| `plugins/traefik/templates/traefik/index.html` | Full Traefik detail page |
|
||||
|
||||
@@ -133,6 +133,6 @@ Quick reference for where key functions, models, and entry points live in the co
|
||||
|
||||
| Location | Covers |
|
||||
|---|---|
|
||||
| `fabledscryer/migrations/versions/` | Core schema (hosts, users, monitors, alerts, app_settings) |
|
||||
| `roundtable/migrations/versions/` | Core schema (hosts, users, monitors, alerts, app_settings) |
|
||||
| `plugins/traefik/migrations/versions/` | `traefik_metrics` table |
|
||||
| `alembic.ini` | Alembic config; `version_locations` lists all migration directories |
|
||||
|
||||
Reference in New Issue
Block a user