README.md
wf-agent
wf-agent - Linux/Python агент для сбора Wi-Fi телеметрии, событий journald, координат и выполнения команд. Проект построен как модульный монолит на Python 3.12+ с asyncio, FastAPI, SQLite, SQLAlchemy 2.x и Pydantic v2.
Назначение
Агент нужен, чтобы:
- собирать данные из нескольких источников на Linux-хосте;
- нормализовать входные события в каноническую модель;
- хранить latest state, event log, journal cursor и служебные статусы отдельно;
- выполнять команды через D-Bus command path;
- экспортировать часть данных сразу, а часть по расписанию;
- строить корреляции между Wi-Fi, journald, координатами и командами;
- предоставлять HTTP API, CLI, метрики и операционные команды.
Архитектура
Поток данных
adapter -> internal envelope -> validation -> normalization -> canonical model -> persistence -> delivery overlay -> transport outbox -> northbound/API/observability
Основные принципы
- модульный монолит, а не набор микросервисов;
- весь входящий поток проходит через
raw envelope -> validation -> normalization; - сначала persist, потом send;
- кешированные данные остаются транспорт-агностичными;
- состояние доставки хранится отдельно от
cached_events; - outbox pattern обязателен для доставляемых сущностей;
- transport outbox хранится в отдельной SQLite БД;
- API не вызывает adapters напрямую, только services;
- timestamps всегда UTC-aware;
- latest state и event log разделены;
- journal cursor хранится персистентно;
- тесты не должны использовать production-like DSN.
Разделение конфигурации
Системные и пользовательские настройки разделены на два файла:
.env.exampleиdeployment/env/wf-agent.env.example- переменные окружения для приложения;deployment/config/wf-agent.toml.example- ACL, transports, интервалы и другие системные правила.
По умолчанию приложение ищет:
/opt/wf-agent/.env;/etc/wf-agent/wf-agent.toml.
В .env хранятся:
APP_NAME;APP_ENV;DATABASE_DSN;OUTBOX_DATABASE_DSN;LISTEN_HOST;LISTEN_PORT.
В TOML хранятся:
wifi_interface_name;cache_ttl_seconds;history_ttl_seconds;[[transports]];[acl].
Если параметры CLI --config-file и --env-file не переданы, используются значения по умолчанию.
Экспорт кешированных сообщений
Кешированные сообщения экспортируются по transport schedule:
[[transports]]задает outbound transports;- transport
defaultобязателен и используется как fallback для cached deliveries; - в ACL можно указать
transport <name>для конкретного правила; kind = "none"не создает packet и помечает due-сообщения какdelivered;kind = "webhook"собирает JSON packet и отправляет его наружу.
Компоненты
app.adapters
navigationчитает координаты и формирует navigation envelopes;journalчитаетsystemd-journalс persistent cursor;dbus_wpaподключается к system D-Bus, получает сигналыwpa_supplicantи выполняет D-Bus команды;- client-модули содержат test-friendly абстракции и fake clients.
app.ingestion
IngestionDispatcherмаршрутизирует envelopes по каналам;SourceManagerуправляет жизненным циклом adapters и health state;- queues служат внутренней транспортной прослойкой между source runtime и services.
app.normalization
validatorпроверяет форму входных данных;mapperсоздает canonical records;classifierназначает delivery mode и priority;dedupсодержит dedup и idempotency helpers.
app.services
CanonicalIngestionServiceвыполняетvalidate -> map -> classify -> persist;StateServiceиEventServiceразделяют latest-state и event-log persistence;OutboxServiceсоздает transactional outbox rows для доставляемых сущностей;ReplayServiceуправляет retry/replay абстракциями;CommandServiceи command state machine управляют жизненным циклом команд.
app.correlation
LocationMatcherсвязывает Wi-Fi event с ближайшей валидной location snapshot;JournalLinkerсвязывает Wi-Fi event с journald evidence;CommandLinkerсвязывает command с observed effects;DerivedEventEngineпревращает корреляции в derived events.
app.delivery
NorthboundExporterпревращает outbox row в стабильный payload;- packet builder собирает JSON packet для cached exports;
WebhookTransportClientотправляет packet наружу;FakeNorthboundClientиспользуется в тестах.
app.workers
CachedExportWorkerобрабатывает cached messages по transport schedule;SourceHealthWorkerпишет health snapshots;- retention worker очищает просроченные cached rows.
app.api
/health/liveи/health/ready;/admin/sources,/admin/outbox,/admin/cache-retention,/admin/scan-results;/commandsи retry endpoints;/metrics.
app.cli
show messages list;show messages content;show outbox state;show outbox content --id <packet_id>;show outbox counters;inspect outboxкак alias кshow outbox state;clear outbox;clear outbox counters.
app.storage
- main DB bootstrap;
- outbox DB bootstrap;
- ORM schema;
- repositories;
- unit of work;
- record mappers для source registry, health, state, events, journal cursors, commands, derived events, cached event delivery overlay и packet outbox.
Структура репозитория
wf-agent/
app/
adapters/ # navigation, journal, dbus_wpa adapters and client abstractions
api/ # FastAPI entrypoint, health/admin/command/metrics routes
bootstrap/ # application factory, dependency wiring, lifecycle
cli/ # local diagnostic CLI
commands/ # command state machine and dispatcher
correlation/ # location matcher, journal linker, command linker, derived events
core/ # config, clock, ids, logging, constants
delivery/ # northbound client, packet builder, exporter helpers
ingestion/ # envelopes, queues, dispatcher, source manager
monitoring/ # metrics, health snapshots, source-health worker support
normalization/ # validator, mapper, classifier, dedup helpers
services/ # canonical ingestion, state/event/outbox/replay/command services
storage/ # DB bootstrap, schema, repositories, UoW
workers/ # cached export worker, source health worker, retention worker
deployment/
config/ # example runtime config files, including ACL and transports
env/ # example environment file for system deployment
systemd/ # systemd service unit baseline
docs/
adr/ # architecture decision records
architecture/ # policy and architecture notes
operations/ # runbook, support guide, procedures
migrations/
tests/
pyproject.toml
README.md
Конфигурация и запуск
Основные примеры файлов:
- deployment/config/wf-agent.toml.example
- deployment/env/wf-agent.env.example
- deployment/systemd/wf-agent.service
Локальный запуск:
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -e .[test]
pytest -q
Примеры CLI:
wf-agent show messages list
wf-agent show outbox state
wf-agent show outbox content --id <packet_id>
wf-agent inspect outbox