Skip to content

Events

The EventBus broadcasts typed lifecycle events. Handlers are plain functions; they may be synchronous or coroutines.

from authority.events import Event, EventBus

bus = EventBus()

def on_register(payload):
    print("New user:", payload["email"])

async def on_login(payload):
    await notify_slack(f"user {payload['user_id']} logged in")

bus.on(Event.USER_REGISTERED, on_register)
bus.on(Event.USER_LOGIN_SUCCESS, on_login)

bus.emit(Event.USER_REGISTERED, {"user_id": 1, "email": "a@b.com"})
await bus.emit_async(Event.USER_LOGIN_SUCCESS, {"user_id": 1})

EventBus

Method Signature Purpose
on on(event, handler) Register a handler for an event
off off(event, handler) Remove a handler
emit emit(event, data=None) Fire handlers synchronously; async handlers are scheduled on the running loop (skipped with a log if none)
emit_async emit_async(event, data=None) Fire handlers, awaiting coroutine handlers
clear clear() Remove all handlers

event may be an Event member or the raw string value (e.g. "user.registered"). data is a dict passed to every handler. Handler exceptions are caught and logged; one failing handler does not stop the others.

Event enum

Event(str, Enum) — all 22 lifecycle events:

Event Value Emitted when
USER_REGISTERED user.registered A user registers
USER_LOGIN_SUCCESS user.login_success Login succeeds
USER_LOGIN_FAILED user.login_failed Login fails
USER_LOGOUT user.logout A user logs out
USER_PASSWORD_CHANGED user.password_changed Password changed
USER_PASSWORD_RESET user.password_reset_requested Password reset requested
USER_EMAIL_CHANGED user.email_changed Email changed
USER_DELETED user.deleted A user is deleted
MFA_SETUP_INITIATED mfa.setup_initiated MFA setup started
MFA_ENABLED mfa.enabled MFA enabled
MFA_DISABLED mfa.disabled MFA disabled
MFA_FAILED mfa.failed MFA verification failed
TOKEN_REFRESHED token.refreshed Refresh token rotated
TOKEN_REUSE_DETECTED token.reuse_detected A rotated token was reused
TOKEN_REVOKED token.revoked A token was revoked
WEBAUTHN_CREDENTIAL_ADDED webauthn.credential_added Passkey registered
WEBAUTHN_CREDENTIAL_REMOVED webauthn.credential_removed Passkey removed
RBAC_ROLE_ASSIGNED rbac.role_assigned Role assigned to a user
RBAC_ROLE_REVOKED rbac.role_revoked Role removed from a user
API_KEY_CREATED api_key.created API key created
API_KEY_REVOKED api_key.revoked API key revoked
AUDIT_EVENT_LOGGED audit.event_logged An audit entry was written

Wiring the bus to a manager

Pass an EventBus to the manager constructor to receive its events:

from authority import AuthConfig
from authority.core import AuthManager
from authority.events import Event, EventBus
from authority.storage.sqlite import SQLiteStorage

bus = EventBus()
bus.on(Event.TOKEN_REUSE_DETECTED, lambda p: security_alert(p))

auth = AuthManager(
    AuthConfig(jwt_secret_key="your-secret-key-min-32-chars"),
    SQLiteStorage("authority_data.db"),
    event_bus=bus,
)