3.5 KiB
Agent Rules
These rules are MANDATORY and MUST be followed without exception by all agents working on this codebase.
1. Entity Versioning MUST Be Automatic
Caution
NON-NEGOTIABLE REQUIREMENT
All versioned entities (Parks, Rides, Companies, etc.) MUST have their version history created automatically via Django signals—NEVER manually in views, serializers, or management commands.
Why This Rule Exists
Manual version creation is fragile and error-prone. If any code path modifies a versioned entity without explicitly calling "create version," history is lost forever. Signal-based versioning guarantees that every single modification is captured, regardless of where the change originates.
Required Implementation Pattern
# apps/{entity}/signals.py - REQUIRED for all versioned entities
from django.db.models.signals import pre_save
from django.dispatch import receiver
from .models import Park, ParkVersion
from .serializers import ParkSerializer
@receiver(pre_save, sender=Park)
def auto_create_park_version(sender, instance, **kwargs):
"""
Automatically snapshot the entity BEFORE any modification.
This signal fires for ALL save operations, ensuring no history is ever lost.
"""
if not instance.pk:
return # Skip for initial creation
try:
old_instance = sender.objects.get(pk=instance.pk)
ParkVersion.objects.create(
park=instance,
data=ParkSerializer(old_instance).data,
changed_by=getattr(instance, '_changed_by', None),
change_summary=getattr(instance, '_change_summary', 'Auto-versioned')
)
except sender.DoesNotExist:
pass # Edge case: concurrent deletion
Passing Context to Signals
When updating entities, attach metadata to the instance before saving:
# In views/serializers - attach context, DON'T create versions manually
park._changed_by = request.user
park._change_summary = submission_note or "Updated via API"
park.save() # Signal handles versioning automatically
What Is FORBIDDEN
The following patterns are strictly prohibited and will be flagged as non-compliant:
# ❌ FORBIDDEN: Manual version creation in views
def update(self, request, slug=None):
park = self.get_object()
# ... update logic ...
ParkVersion.objects.create(park=park, ...) # VIOLATION!
park.save()
# ❌ FORBIDDEN: Manual version creation in serializers
def update(self, instance, validated_data):
ParkVersion.objects.create(park=instance, ...) # VIOLATION!
return super().update(instance, validated_data)
# ❌ FORBIDDEN: Manual version creation in management commands
def handle(self, *args, **options):
for park in Park.objects.all():
ParkVersion.objects.create(park=park, ...) # VIOLATION!
park.status = 'updated'
park.save()
Compliance Checklist
For every versioned entity, verify:
- A
pre_savesignal receiver exists insignals.py - The signal is connected in
apps.pyviaready()method - No manual
{Entity}Version.objects.create()calls exist in views - No manual
{Entity}Version.objects.create()calls exist in serializers - No manual
{Entity}Version.objects.create()calls exist in management commands
Document Authority
This document has the same authority as all other source_docs/ files. Per the /comply workflow, these specifications are immutable law and must be enforced immediately upon detection of any violation.