Каркас администрирования для FastAPI

Админка, плагины и реплики — из одного объекта настроек

Вы передаёте настройки — keepup возвращает приложение, в котором уже соединены панель управления, плагинная среда, пользователи и роли, слой базы данных, аудит, метрики и согласование реплик.

  • версия 0.5.0
  • Python 3.11+
  • Apache-2.0
  • PostgreSQL · SQLite
pip install keepup-admin
pip install "keepup-admin[panel,postgres]"

Ставится как keepup-admin, импортируется как keepup. База — конструктор: ядро, каталог плагинов, реестр служб, жизненный цикл и шов транспорта, без единой чужой библиотеки, даже FastAPI. Возможности ставятся extras: полная панель — keepup-admin[panel,postgres].

main.py
import os

from keepup import KeepupSettings, create_app

PLUGINS = os.path.join(os.path.dirname(os.path.abspath(__file__)), "plugins")

app = create_app(KeepupSettings(
    title="Your product",
    plugins_dir=PLUGINS,
    static_mounts=(),  # У приложения нет своей статики: оболочка панели приходит с keepup-http.
))
$ SECRET_KEY=… uvicorn main:app → панель на /selfcare

Что внутри

То, что каждый раз пишется заново, уже написано

Восемь частей, которые обычно собирают вокруг FastAPI руками, — набором дистрибутивов при одной точке настройки. База не тянет ни одной чужой библиотеки, даже FastAPI: каждая возможность объявляет свои. Полная панель — pip install "keepup-admin[panel,postgres]".

appСборка

create_app(settings) — ленивая обёртка: FastAPI, посредники, жизненный цикл и точки монтирования приходят с keepup-http.

extПлагины

Возможности подключаются плагинами; маршруты — данные, а не декораторы.

uiПанель

Оболочка /selfcare и разделы — keepup-http, темы — keepup-ui, каталог разделов и выдачи ролям — keepup-modules; восемь разделов из коробки.

idПользователи

Локальные учётные записи, роли, сессии панели, вход через внешний OIDC-провайдер.

dbБаза данных

keepup-db: SQLAlchemy с пулом; таблица объявляется один раз для PostgreSQL и SQLite, без миграций.

n×Реплики

keepup-cluster: распределённые блокировки, шина сообщений между процессами, реестр кластера.

⏱Фоновые задачи

keepup-tasks: один планировщик на процесс; задачи видны в панели и запускаются оттуда вручную.

obsНаблюдаемость

keepup-audit, keepup-metrics, keepup-log-shipping: аудит входящих запросов, журнал событий, метрики Prometheus, отправка логов.

Как устроено

Каркас не несёт продукта

Всё, чего каркас знать не может, приходит в KeepupSettings: имя и версия, куда отправлять логи, какие поля запроса секретны, каким должен быть пароль, какие страницы закрыты, каким источникам можно читать ответы.

Публичное объявлено явно: имена в __all__ — это контракт, и тест держит пакет в его рамках. Всё остальное внутреннее и может измениться без предупреждения.

Ваше приложениеmain.py · KeepupSettings
Ваши плагиныplugins/*.py · config/modules.json
keepupядро · настройки · роли · блокировки · шина · кэш
keepup-db · keepup-auth · keepup-httpFastAPI · Starlette · SQLAlchemy · APScheduler · PyJWT
keepup-postgreskeepup-sqlite — для разработки
plugins/hello.py
from keepup.plugins.base import BasePlugin

class HelloPlugin(BasePlugin):
    def __init__(self, config=None):
        super().__init__("hello", "Hello", config or {})

    async def initialize(self) -> bool:
        return True

    def get_handlers(self):
        return {}

    def get_api_routes(self):
        return [{"path": "/api/hello", "methods": ["GET"],
                 "handler": self.hello}]

    async def hello(self, current_user: dict, **kwargs):
        return {"hello": current_user["username"]}

Закрыто по умолчанию

Где пришлось бы угадывать, каркас закрывает

  • Без SECRET_KEY приложение не стартует — ключа подписи в исходниках нет.
  • Пароль первого администратора задаёт тот, кто разворачивает, иначе он случайный и печатается в журнал один раз.
  • CORS закрыт, пока приложение не назовёт источники; /metrics — только с учётными данными.
  • Аудит хранит имена полей, а не значения.
  • Незнакомый параметр маршрута — ответ 400, а не молчаливое игнорирование.
  • Вход через провайдер отказывает неизвестной учётной записи, пока приложение не решит иначе.

Дальше

Куда идти