Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

Identity Hub

CI PyPI Python License

Identity Hub — асинхронная Python-библиотека для управления парком внешних аккаунтов: их состояниями, эксклюзивной арендой, квотами, прокси, зашифрованными сессиями и событиями. Основной читатель этого руководства — разработчик Python 3.12+, который встраивает библиотеку в воркеры или веб-приложение.

Библиотека подходит, когда несколько процессов должны безопасно делить аккаунты Telegram, бирж или других платформ. Она не является клиентом этих платформ: сетевой вызов выполняет код приложения, а Identity Hub решает, какой аккаунт можно взять, и фиксирует результат операции.

Установка через uv

Для PostgreSQL и встроенных миграций Alembic:

uv add "identity-hub[postgres,alembic]"

Дополнительные зависимости подключаются отдельно: telegram для транспорта уведомлений через Telegram Bot API (httpx, без SDK), webhooks для HTTP-вебхуков, structlog для структурированных логов и testing для тестового MemoryStore и pytest-плагина.

Для разработки самого репозитория:

uv sync --all-extras
docker compose up -d postgres
uv run pytest

Быстрый старт

  1. Создайте 32-байтовый мастер-ключ. Не коммитьте его и не выводите в логи:

    uv run python -c "from identity_hub.crypto import generate_key; print(generate_key())"
    
  2. Сохраните результат в IDENTITY_HUB_KEK. Первый ключ в строке активен; прежние ключи оставляют после запятой на время ротации.

  3. Задайте URL PostgreSQL и примените миграции:

    export IDENTITY_HUB_DATABASE_URL='postgresql+asyncpg://app:password@localhost/app'
    export IDENTITY_HUB_KEK='k1:<base64-ключ>'
    uv run identity-hub migrate
    
  4. Объявите сервис в коде и создайте один IdentityHub на процесс:

    from datetime import timedelta
    
    from pydantic import BaseModel, SecretStr
    from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
    
    from identity_hub import EnvSecretsProvider, IdentityHub, OperationRule, Quota, Service
    
    
    class TelegramCredentials(BaseModel):
        phone: str
    
    
    class TelegramSession(BaseModel):
        auth_key: SecretStr
        dc_id: int = 2
    
    
    TELEGRAM = Service(
        name="telegram",
        title="Telegram",
        credentials=TelegramCredentials,
        session=TelegramSession,
        operations={
            "read_channel": OperationRule(
                quotas=(Quota(100, timedelta(hours=1)),),
            ),
        },
    )
    
    engine = create_async_engine(
        "postgresql+asyncpg://app:password@localhost/app",
        pool_pre_ping=True,
        hide_parameters=True,  # параметры запросов не попадают в тексты ошибок и логи
    )
    sessions = async_sessionmaker(engine, expire_on_commit=False)
    hub = IdentityHub(
        sessionmaker=sessions,
        secrets=EnvSecretsProvider(),
        services=[TELEGRAM],
    )
    
  5. На старте приложения синхронизируйте реестр сервисов, затем работайте через пространство и пул:

    from identity_hub import AuthState, IdentityCreate, Lifecycle
    
    await hub.start()
    space = await hub.spaces.ensure("production", "Production")
    
    await space.identities.create(
        IdentityCreate(
            service=TELEGRAM,
            external_ref="+12025550123",
            credentials={"phone": "+12025550123"},
            session={"auth_key": "secret-session"},
            tags=["parser"],
            lifecycle=Lifecycle.READY,
            auth=AuthState.AUTHENTICATED,
        )
    , actor="operator")
    
    parsers = space.pools.define("parsers", service=TELEGRAM, tags=["parser"])
    async with parsers.lease(for_operation="read_channel") as lease:
        session = await lease.session()
        async with lease.operation("read_channel", key="job:42"):
            # Здесь приложение вызывает Telegram-клиент с session и lease.proxy.
            messages = await telegram_client.read_history(session)
    

for_operation отбрасывает аккаунты, которые не удовлетворяют состояниям или верификации. Квоты при выборе не учитываются: контекст operation повторно проверяет состояние и атомарно списывает квоту до внешнего вызова, а при исчерпании бросает QuotaExhausted. Параметр key делает списание конкретной операции идемпотентным.

Полный самодостаточный сценарий находится в examples/telegram_service.py. Он использует память вместо PostgreSQL и имитирует платформенный клиент, поэтому запускается без внешних сервисов:

uv run python examples/telegram_service.py

Руководство

Как добавлять и регистрировать аккаунты, какие бывают состояния и кто ими управляет, как банить, верифицировать и синхронизировать статусы с платформой, какие бывают аренды и лимиты — в руководстве с диаграммами архитектуры и машин состояний. Сценарий из руководства целиком исполняется в examples/account_lifecycle.py.

Эксплуатация и тесты

Для быстрых тестов без БД установите extra testing. Pytest-плагин предоставляет фикстуры с префиксом identity_hub_, а пользовательский пример можно выполнить командой:

uv run pytest examples/test_memory_hub.py

MemoryStore предназначен для тестов и однопроцессных примеров. Конкурентные воркеры, долговечные аренды и эксплуатационный журнал требуют PostgreSQL.

Границы безопасности

  • Сессии, credentials, секреты прокси и токены доставок шифруются отдельными DEK; мастер-ключи предоставляет приложение.
  • Расшифрованные credentials и сессии воркер получает через объект действующей аренды: после освобождения, потери или отзыва он бросает LeaseLost. Вне аренды секрет раскрывают аудируемые команды space.secrets.reveal и space.proxies.url (автор и причина обязательны).
  • Потеря heartbeat отменяет владеющую задачу и вызывает on_lost; сетевой клиент должен быть отключён этим callback.
  • Диспетчер доставляет события как минимум один раз. Обработчики обязаны быть идемпотентными.
  • SpaceHandle.using(db_session) нужен, когда изменение Identity Hub должно участвовать во внешней транзакции приложения; обычные методы используют свои короткие транзакции.

Полная спецификация поведения — identity-hub-requirements.md, история реализации — docs/plan/PLAN.md.

In English

Identity Hub is an async Python library (3.12+, PostgreSQL 16) for managing a fleet of external accounts: their states, exclusive leases with heartbeat and fencing, rate limits, proxies, encrypted sessions and an event stream. It does not talk to the platforms itself — your code makes the network calls, the library decides which account may be used and records the outcome.

  • Install: uv add "identity-hub[postgres,alembic]", then identity-hub migrate against your database.
  • Status: alpha (1.0.0aN). The public API may still change between alpha releases; every breaking change is marked in CHANGELOG.md.
  • Language: documentation, error messages and logs are in Russian. Identifiers, error codes, event types and field names are English and stable for programmatic use.

Лицензия

MIT. Код поставляется «как есть», без каких-либо гарантий.

Metadata

Release files for identity-hub 1.0.0a1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for identity-hub 1.0.0a1
File Size Uploaded
identity_hub-1.0.0a1.tar.gz 688.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for identity-hub 1.0.0a1
File Interpreter ABI Platform
identity_hub-1.0.0a1-py3-none-any.whl Python 3 none any Details

Total release size: 1.1 MB

Release files / identity_hub-1.0.0a1.tar.gz

Download URL identity_hub-1.0.0a1.tar.gz
Size 688.0 kB
Tags Source
SHA-256 checksum
How to use checksums
f68f330a23ab0ecf756bddc88d4be0794cf1f2545258860399f3979fdbe802c7
BLAKE2b-256 checksum
How to use checksums
4b22417bc5682f068d19dd63874aa7a4db0d5c693c0f2b9d48c7edadeb2d4967
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release files / identity_hub-1.0.0a1-py3-none-any.whl

Download URL identity_hub-1.0.0a1-py3-none-any.whl
Size 443.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3f644c1614c1bdcfd1475f9301809a3d48dce188cd923810d99aa711e36c72c5
BLAKE2b-256 checksum
How to use checksums
34b361efc020d51f68a9446c45af143497f3b98fcdd637153904cb81d63f5f4c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.0a1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page