""" Webhook models — webhooks, webhook_deliveries, idempotency_keys. Maps to AGENT.md DBML: Lines 690-718. """ from django.conf import settings from django.db import models from core.models import BaseModel class Webhook(BaseModel): """Org-scoped webhook endpoint configuration.""" org = models.ForeignKey( "organizations.Organization", on_delete=models.CASCADE, related_name="webhooks", ) url = models.URLField() secret = models.CharField(max_length=255) # Encrypted HMAC key events = models.JSONField(default=list, blank=True) enabled = models.BooleanField(default=True) class Meta: db_table = "webhooks" ordering = ["-created_at"] def __str__(self) -> str: return f"Webhook {self.url}" class WebhookDelivery(BaseModel): """Records each webhook delivery attempt.""" class Status(models.TextChoices): SUCCESS = "success", "Success" FAILED = "failed", "Failed" PENDING = "pending", "Pending" webhook = models.ForeignKey( Webhook, on_delete=models.CASCADE, related_name="deliveries", ) payload_hash = models.CharField(max_length=64, blank=True, default="") status = models.CharField(max_length=20, choices=Status.choices, default=Status.PENDING) response_code = models.PositiveIntegerField(default=0) attempts = models.PositiveIntegerField(default=0) next_retry_at = models.DateTimeField(null=True, blank=True) class Meta: db_table = "webhook_deliveries" ordering = ["-created_at"] def __str__(self) -> str: return f"Delivery {self.pk} → {self.get_status_display()}" class IdempotencyKey(BaseModel): """Prevents duplicate request processing.""" key = models.CharField(max_length=255, unique=True) user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="idempotency_keys", ) request_hash = models.CharField(max_length=64, blank=True, default="") response_hash = models.CharField(max_length=64, blank=True, default="") expires_at = models.DateTimeField(null=True, blank=True) class Meta: db_table = "idempotency_keys" def __str__(self) -> str: return self.key