Safely write patches to voters_patch with audit
Use this skill when applying verified corrections to voter records via the patch system.
[!CAUTION] NEVER overwrite base roll rows. All corrections go to
voters_patchonly.
[!IMPORTANT] Every patch MUST be audited with user ID and timestamp.
Before applying, verify:
# Check EPIC exists in base table
SELECT id FROM electoral.voters WHERE epic_no = 'ABC1234567';
# Check field name is valid
VALID_FIELDS = ['name_en', 'age', 'gender', 'house_no', 'relation_name_en']
assert field_name in VALID_FIELDS
# Verify user has access to this tenant
SELECT tu.role
FROM electoral.tenant_users tu
WHERE tu.user_id = auth.uid()
AND tu.tenant_id = '<tenant_id>'
AND tu.is_active = true;
SELECT electoral.resolve_review_item(
'<review_queue_id>',
'corrected_value',
'human',
'Corrected based on source document'
);
from handwritten.db_writer import DatabaseWriter
db = DatabaseWriter()
result = db.apply_patch(
voter_id=12345,
field_name="name_en",
original_value="JOHN DOE",
patched_value="JOHN DOE SR",
source="manual",
user_id="<user_uuid>",
confidence=0.95,
)
SELECT *
FROM campaign.audit_events
WHERE resource_type = 'voters_patch'
ORDER BY created_at DESC
LIMIT 10;
If a patch needs to be reverted:
-- Soft delete (keeps audit trail)
DELETE FROM electoral.voters_patch
WHERE base_voter_id = 12345 AND field_name = 'name_en';
-- Log rollback
INSERT INTO campaign.audit_events (action, resource_type, details)
VALUES ('rollback_patch', 'voters_patch', '{"voter_id": 12345, "field": "name_en"}');
voters_patch