- infrasynth.configs: typed multi-tenant config store (registry, service, secrets, cache) + public config_changed/config_reset signals and API - emit the declared-but-dead signals (features flags/overrides, scheduler task_completed/task_failed, tenancy tenant_updated, audit model_changed) and per-model audit field exclusions - security: permission catalog (security_permission), Django-style model-derived AutoPermission, PermissionRegistry, RoleAssignment, global-or-tenant Grant/Revoke, catalog API - consolidate the permission surface: PermissionRegistry only (drop the settings dict), IsAuthenticatedAndPermitted aliases HybridPermission, require_permission replaced by required_permissions + require_all - packaging: add [build-system]; add Forgejo publish workflow (.forgejo)
23 lines
888 B
Python
23 lines
888 B
Python
"""Public signals of ``infrasynth.configs``.
|
|
|
|
Both signals are a documented extension point: a consuming app connects them in
|
|
``apps.py:ready()`` to react to configuration changes (for example, to refresh a
|
|
third-party client). They are emitted from :class:`ConfigService` itself, so
|
|
correctness never depends on a receiver being connected, and every signal carries
|
|
``tenant_id`` explicitly (``TENANCY.md`` §7).
|
|
|
|
Secret values are **always masked**: ``old_value``/``new_value`` are ``None``
|
|
when the definition is secret, so no plaintext or ciphertext ever appears in a
|
|
signal payload.
|
|
"""
|
|
|
|
from django.dispatch import Signal
|
|
|
|
__all__ = ["config_changed", "config_reset"]
|
|
|
|
# kwargs: tenant_id (str|None), key, scope ("tenant"|"global"),
|
|
# old_value, new_value, actor_id
|
|
config_changed = Signal()
|
|
|
|
# kwargs: tenant_id, key, scope, previous_value, actor_id
|
|
config_reset = Signal()
|