10 KiB
Phase 4: Entity Updates Through Sacred Pipeline - COMPLETE
Date: 2025-11-08
Status: ✅ Complete
Previous Phase: Phase 3 - API Endpoints Creation
Overview
Phase 4 successfully routes all entity UPDATE operations (PUT/PATCH endpoints) through the Sacred Pipeline by integrating them with the submission services created in Phase 2.
Objectives Achieved
✅ All PUT endpoints now use update_entity_submission()
✅ All PATCH endpoints now use update_entity_submission()
✅ No direct .save() calls in update endpoints
✅ Authentication required on all update endpoints
✅ Moderators get 200 responses with updated entities
✅ Regular users get 202 responses with submission IDs
✅ Error handling for ValidationErrors
✅ Comprehensive logging throughout
✅ Response schemas updated for 202 status
Changes Made
1. Parks Endpoints (django/api/v1/endpoints/parks.py)
update_park() - PUT Endpoint
Before:
@router.put("/{park_id}", ...)
def update_park(request, park_id: UUID, payload: ParkUpdate):
park = get_object_or_404(Park, id=park_id)
# ... coordinate handling
park.save() # ❌ DIRECT SAVE
return park
After:
@router.put("/{park_id}",
response={200: ParkOut, 202: dict, 404: ErrorResponse, 400: ErrorResponse, 401: ErrorResponse}, ...)
@require_auth
def update_park(request, park_id: UUID, payload: ParkUpdate):
user = request.auth
park = get_object_or_404(Park, id=park_id)
submission, updated_park = ParkSubmissionService.update_entity_submission(
entity=park,
user=user,
update_data=data,
latitude=latitude,
longitude=longitude,
source='api',
ip_address=request.META.get('REMOTE_ADDR'),
user_agent=request.META.get('HTTP_USER_AGENT', '')
)
if updated_park: # Moderator
return 200, updated_park
else: # Regular user
return 202, {'submission_id': str(submission.id), ...}
partial_update_park() - PATCH Endpoint
- Same pattern as PUT
- Uses
exclude_unset=Trueto update only provided fields - Flows through Sacred Pipeline
2. Rides Endpoints (django/api/v1/endpoints/rides.py)
update_ride() - PUT Endpoint
Changes:
- Added
@require_authdecorator - Replaced direct
.save()withRideSubmissionService.update_entity_submission() - Added dual response pattern (200 for moderators, 202 for users)
- Updated response schema to include 202 status
- Added comprehensive error handling
- Added logging for all operations
partial_update_ride() - PATCH Endpoint
- Same pattern as PUT
- Properly handles partial updates
3. Companies Endpoints (django/api/v1/endpoints/companies.py)
update_company() - PUT Endpoint
Changes:
- Added
@require_authdecorator - Replaced direct
.save()withCompanySubmissionService.update_entity_submission() - Added dual response pattern
- Updated response schema
- Added error handling and logging
partial_update_company() - PATCH Endpoint
- Same pattern as PUT
- Flows through Sacred Pipeline
4. Ride Models Endpoints (django/api/v1/endpoints/ride_models.py)
update_ride_model() - PUT Endpoint
Changes:
- Added
@require_authdecorator - Replaced direct
.save()withRideModelSubmissionService.update_entity_submission() - Added dual response pattern
- Updated response schema
- Added error handling and logging
partial_update_ride_model() - PATCH Endpoint
- Same pattern as PUT
- Properly routes through Sacred Pipeline
Technical Implementation Details
Authentication Pattern
All update endpoints now require authentication:
@require_auth
def update_entity(request, entity_id: UUID, payload: EntityUpdate):
user = request.auth # Authenticated user from JWT
Dual Response Pattern
For Moderators (200 OK)
if updated_entity:
logger.info(f"Entity updated (moderator): {updated_entity.id}")
return 200, updated_entity
For Regular Users (202 Accepted)
else:
logger.info(f"Entity update submission created: {submission.id}")
return 202, {
'submission_id': str(submission.id),
'status': submission.status,
'message': 'Update pending moderation. You will be notified when approved.'
}
Error Handling Pattern
try:
submission, updated_entity = Service.update_entity_submission(...)
# ... response logic
except ValidationError as e:
return 400, {'detail': str(e)}
except Exception as e:
logger.error(f"Error updating entity: {e}")
return 400, {'detail': str(e)}
Response Schema Updates
All endpoints now include 202 status in their response schemas:
response={200: EntityOut, 202: dict, 404: ErrorResponse, 400: ErrorResponse, 401: ErrorResponse}
Sacred Pipeline Flow
Update Flow Diagram
User Request (PUT/PATCH)
↓
@require_auth Decorator
↓
Extract user from request.auth
↓
Get existing entity
↓
Service.update_entity_submission()
↓
Is User a Moderator?
├─ YES → Apply changes immediately
│ Return 200 + Updated Entity
│
└─ NO → Create ContentSubmission
Set status = 'pending'
Return 202 + Submission ID
↓
[Moderator reviews later]
↓
ModerationService.approve_submission()
↓
Apply changes + Notify user
Verification Checklist
-
Parks
update_park()uses submission servicepartial_update_park()uses submission service- Special coordinate handling preserved
-
Rides
update_ride()uses submission servicepartial_update_ride()uses submission service
-
Companies
update_company()uses submission servicepartial_update_company()uses submission service
-
Ride Models
update_ride_model()uses submission servicepartial_update_ride_model()uses submission service
-
Common Requirements
- All endpoints have
@require_authdecorator - All endpoints use submission services
- No direct
.save()calls remain - All have dual response pattern (200/202)
- All have updated response schemas
- All have error handling
- All have logging
- All endpoints have
Files Modified
-
django/api/v1/endpoints/parks.py- Updated
update_park()(line ~260) - Updated
partial_update_park()(line ~330)
- Updated
-
django/api/v1/endpoints/rides.py- Updated
update_ride()(line ~480) - Updated
partial_update_ride()(line ~550)
- Updated
-
django/api/v1/endpoints/companies.py- Updated
update_company()(line ~160) - Updated
partial_update_company()(line ~220)
- Updated
-
django/api/v1/endpoints/ride_models.py- Updated
update_ride_model()(line ~180) - Updated
partial_update_ride_model()(line ~240)
- Updated
Testing Recommendations
Manual Testing Checklist
-
As a Regular User:
- PUT/PATCH request returns 202 status
- Response includes submission_id
- ContentSubmission created with status='pending'
- Entity remains unchanged until approval
- User receives notification after approval
-
As a Moderator:
- PUT/PATCH request returns 200 status
- Response includes updated entity
- Changes applied immediately
- No submission created (bypass moderation)
- History event created
-
Error Cases:
- 401 if not authenticated
- 404 if entity doesn't exist
- 400 for validation errors
- Proper error messages returned
API Testing Examples
Update as Regular User
curl -X PUT http://localhost:8000/api/v1/parks/{park_id} \
-H "Authorization: Bearer {user_token}" \
-H "Content-Type: application/json" \
-d '{"name": "Updated Park Name"}'
# Expected: 202 Accepted
# {
# "submission_id": "uuid",
# "status": "pending",
# "message": "Park update pending moderation..."
# }
Update as Moderator
curl -X PUT http://localhost:8000/api/v1/parks/{park_id} \
-H "Authorization: Bearer {moderator_token}" \
-H "Content-Type: application/json" \
-d '{"name": "Updated Park Name"}'
# Expected: 200 OK
# {
# "id": "uuid",
# "name": "Updated Park Name",
# ...
# }
Benefits Achieved
1. Content Quality Control
All entity updates now go through moderation (for regular users), ensuring content quality and preventing vandalism.
2. Audit Trail
Every update creates a ContentSubmission record, providing complete audit trail of who requested what changes and when.
3. Moderator Efficiency
Moderators can still make instant updates while regular user updates queue for review.
4. Consistent Architecture
Updates now follow the same pattern as creation (Phase 3), maintaining architectural consistency.
5. User Transparency
Users receive clear feedback about whether their changes were applied immediately or queued for review.
Next Steps
Phase 5: Entity Deletions Through Pipeline (Future)
- Route DELETE endpoints through submission service
- Handle soft deletes vs hard deletes
- Implement delete approval workflow
Immediate Priorities
- Test all update endpoints with various user roles
- Verify ContentSubmission records are created correctly
- Test moderation approval flow for updates
- Monitor logs for any issues
Related Documentation
- SACRED_PIPELINE_AUDIT_AND_IMPLEMENTATION_PLAN.md - Overall plan
- PHASE_1_SACRED_PIPELINE_FIXES_COMPLETE.md - Foundation fixes
- PHASE_2_ENTITY_SUBMISSION_SERVICES_COMPLETE.md - Service layer
- PHASE_3_API_ENDPOINTS_SACRED_PIPELINE_COMPLETE.md - Creation endpoints
Notes
- Parks have special coordinate handling that was preserved
- All services use the
update_entity_submission()method from BaseEntitySubmissionService - The implementation maintains backward compatibility for moderators who expect instant updates
- Regular users now have transparency into the moderation process via 202 responses
Phase 4 Status: COMPLETE ✅
All entity update operations now flow through the Sacred Pipeline, ensuring content quality control and maintaining a complete audit trail of all changes.