Not legal advice
dpdpkit is software that helps you implement obligations under India's Digital Personal Data Protection Act, 2023 and the DPDP Rules, 2025. It does not provide legal advice and does not guarantee compliance.
Events and notifications¶
events
¶
In-process event bus and HMAC-signed outbound webhooks.
Event handlers run after the ledger write they describe. A failing handler is logged and recorded in
EventBus.failures; it never rolls back or blocks the state change.
Event
¶
EventBus
¶
EventBus()
subscribe
¶
subscribe(event_type: str, handler: Handler) -> Handler
Subscribe to one type, or "*" for all. Returns the handler so it works as a decorator.
WebhookEndpoint
¶
Bases: BaseModel
events
class-attribute
instance-attribute
¶
events: list[str] = Field(default_factory=lambda: ['*'])
WebhookDispatcher
¶
WebhookDispatcher(endpoints: Iterable[WebhookEndpoint] = (), *, sender: Sender = urllib_sender, retries: int = 3, backoff_seconds: float = 0.5, sleep: Callable[[float], None] = sleep)
Delivers events to customer-configured endpoints. Failed deliveries land in dead_letters.
Adapters that need durable retries persist dead_letters and call redeliver.
sign_payload
¶
sign_payload(secret: str | bytes, body: bytes, timestamp: int | None = None) -> str
Return the signature header value: t=<unix>,v1=<hex hmac of "t.body">.
verify_signature
¶
verify_signature(secret: str | bytes, body: bytes, header: str, *, tolerance: int = 300, now: int | None = None) -> bool
Verify a webhook signature header; rejects anything older than tolerance seconds.
notify
¶
Notification interface (email, SMS, WhatsApp) with delivery receipts.
Core never talks to a provider directly. A Notifier turns a Message into a
DeliveryReceipt. The default NullNotifier reports every message as failed, so
nothing that depends on a delivered warning (such as erasure) can run until a real transport is set.
Notifier
¶
Bases: Protocol
NullNotifier
¶
No transport configured: every send fails, which keeps fail-safe paths closed.
MemoryNotifier
¶
MemoryNotifier(status: DeliveryStatus = DELIVERED)
ConsoleNotifier
¶
ConsoleNotifier(write: Callable[[str], object] = print)
Prints messages. For local development only; it reports delivery without real delivery.
SmtpNotifier
¶
SmtpNotifier(host: str, port: int = 587, *, sender: str, username: str | None = None, password: str | None = None, starttls: bool = True, use_ssl: bool = False, timeout: float = 15.0)
Email over SMTP (stdlib). SMS and WhatsApp messages are refused (failed receipt).
render
¶
render(template: str, locale: str, context: Mapping[str, object]) -> tuple[str, str]
Render a template in locale, falling back to English.
ses
¶
Amazon SES email transport (pip install "dpdpkit-core[ses]").
By default a message SES accepts is reported as delivered, like SmtpNotifier.
With track_delivery=True it is reported as queued and tagged with the dpdpkit receipt id; the final
outcome comes from SES event publishing (configuration set → SNS → SQS) and is applied with
poll_ses_events. A pre-erasure warning then only counts once SES reports the mailbox accepted it.
Events are read from SQS with your AWS credentials rather than received on a public URL: a forged "delivered" event would start an erasure clock, so the channel must be authenticated.
SesNotifier
¶
SesNotifier(sender: str, *, region: str | None = None, configuration_set: str | None = None, track_delivery: bool = False, client: Any = None)
Send email with the SES v2 API. SMS and WhatsApp messages are refused (failed receipt).
poll_ses_events
¶
poll_ses_events(kit: Kit, queue_url: str, *, region: str | None = None, client: Any = None, max_batches: int = 10, wait_seconds: int = 0) -> int
Drain SES events from an SQS queue (subscribed to the configuration set's SNS topic, raw or not). A message is deleted only after it has been applied. Returns how many outcomes were recorded.
apply_ses_event
¶
apply_ses_event(kit: Kit, event: Mapping[str, Any]) -> str | None
Record the final outcome of a tracked message. Pending pre-erasure warnings are confirmed or
moved to needs_attention; other receipts are updated in place. Returns the receipt id, if any.
ses_event_outcome
¶
ses_event_outcome(event: Mapping[str, Any]) -> tuple[str, bool, str | None] | None
Read an SES event (or an SNS envelope around one). Returns (receipt_id, delivered, error), or
None when the event is not final (delay, open, complaint) or was not sent by dpdpkit.