from django.conf import settings from django.db import models from infrasynth.tenancy.managers import AllObjectsManager class ModelChangeLog(models.Model): tenant = models.ForeignKey( "tenancy.Tenant", on_delete=models.CASCADE, null=True, blank=True, related_name="+", help_text="Null = platform action; set for tenant-scoped actions.", ) model_label = models.CharField(max_length=200, db_index=True) object_id = models.CharField(max_length=200, db_index=True) action = models.CharField( max_length=10, choices=[("create", "create"), ("update", "update"), ("delete", "delete")], ) changes = models.JSONField(help_text="Dict with {field_name: [old_value, new_value]}") actor = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True) timestamp = models.DateTimeField(auto_now_add=True, db_index=True) request_id = models.CharField(max_length=64, help_text="UUID for request correlation") class Meta: db_table = "audit_model_change_log" indexes = [ models.Index(fields=["tenant_id", "model_label", "object_id"]), models.Index(fields=["tenant_id", "timestamp"]), ] objects = AllObjectsManager() class APIInteractionLog(models.Model): tenant = models.ForeignKey( "tenancy.Tenant", on_delete=models.CASCADE, null=True, blank=True, related_name="+", ) method = models.CharField(max_length=10, db_index=True) path = models.CharField(max_length=500, db_index=True) status_code = models.PositiveSmallIntegerField(db_index=True) request_body = models.JSONField(null=True, blank=True) response_body = models.JSONField(null=True, blank=True) ip_address = models.GenericIPAddressField(null=True) actor = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True) duration_ms = models.PositiveIntegerField() timestamp = models.DateTimeField(auto_now_add=True, db_index=True) request_id = models.CharField(max_length=64, db_index=True) user_agent = models.TextField(blank=True, default="") class Meta: db_table = "audit_api_interaction_log" indexes = [models.Index(fields=["tenant_id", "timestamp"])] objects = AllObjectsManager() class SecurityEvent(models.Model): tenant = models.ForeignKey( "tenancy.Tenant", on_delete=models.CASCADE, null=True, blank=True, related_name="+", ) event_type = models.CharField(max_length=50, db_index=True) actor = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True) ip_address = models.GenericIPAddressField(null=True) metadata = models.JSONField(default=dict) timestamp = models.DateTimeField(auto_now_add=True, db_index=True) request_id = models.CharField(max_length=64) class Meta: db_table = "audit_security_event" indexes = [models.Index(fields=["tenant_id", "event_type"])] objects = AllObjectsManager()