Response Editing
Response editing rules, version tracking, audit trail, and conflict detection
Edit Rules
Survey responses can be edited after submission, subject to configurable rules:
class EditRules(BaseModel):
enabled: bool # Allow editing at all
time_limit_hours: Optional[int] # Edit window (e.g., 24h)
max_edits: Optional[int] # Maximum revisions
require_reason: bool # Require change reason
require_approval: bool # Re-approval after editVersion Tracking
Every edit creates a new version:
{
"id": "response-uuid",
"survey_id": "survey-uuid",
"current_version": 3,
"versions": [
{
"version": 1,
"data": { "q1": "initial answer" },
"edited_by": "user-uuid",
"edited_at": "2026-05-13T10:00:00Z",
"reason": "Initial submission"
},
{
"version": 2,
"data": { "q1": "corrected answer" },
"edited_by": "user-uuid",
"edited_at": "2026-05-13T11:30:00Z",
"reason": "Data entry correction"
}
],
"audit_trail": [...]
}Edit Flow
User submits edit
│
▼
Check edit rules
├── Time limit expired? → Reject
├── Max edits reached? → Reject
│
▼
Create new version
├── Store delta (only changed fields)
├── Increment version number
│
▼
Generate audit event (response.edited)
│
▼
Require re-approval? → Notify approversConflict Detection
When editing a response that was also edited elsewhere:
async def edit_response(response_id, new_data, expected_version):
response = await get_response(response_id)
if response.current_version != expected_version:
raise ConflictError(
"Response has been modified since you loaded it. "
f"Expected version {expected_version}, got {response.current_version}."
)API
PUT /responses/{id}
{
"data": { "q1": "updated answer" },
"reason": "Corrected typo in patient name",
"expected_version": 2
}
# Response
{
"id": "response-uuid",
"current_version": 3,
"status": "pending_approval"
}Audit
Every edit is recorded in the audit log:
await log_audit(
event_type="response.edited",
resource_type="response",
resource_id=response_id,
metadata={
"previous_version": 2,
"new_version": 3,
"changed_fields": ["q1"],
"reason": "Corrected typo"
}
)