Severity: Low
Labels: data-integrity, backend, P3
Location: backend/services/graph_service.py:504-520 (select-then-insert-if-absent on user_id+source_node_id+target_node_id); schema supabase_schema.sql:95-103 (no UNIQUE)
Description
Edge creation is a check-then-insert race with no UNIQUE backstop, so two concurrent inserts for the same (user_id, source, target) both pass the check and insert duplicates. (Compounds the directional-dedup concern in the existing graph audit, which is a different root cause — orientation, not the missing constraint.)
Suggested fix
CREATE UNIQUE INDEX idx_graph_edges_unique ON graph_edges(user_id, source_node_id, target_node_id);
Upsert on insert.
Acceptance criteria
- Duplicate
(user_id, source, target) edges are impossible at the DB level; insert is an upsert.
Severity: Low
Labels: data-integrity, backend, P3
Location:
backend/services/graph_service.py:504-520(select-then-insert-if-absent onuser_id+source_node_id+target_node_id); schemasupabase_schema.sql:95-103(no UNIQUE)Description
Edge creation is a check-then-insert race with no UNIQUE backstop, so two concurrent inserts for the same
(user_id, source, target)both pass the check and insert duplicates. (Compounds the directional-dedup concern in the existing graph audit, which is a different root cause — orientation, not the missing constraint.)Suggested fix
Upsert on insert.
Acceptance criteria
(user_id, source, target)edges are impossible at the DB level; insert is an upsert.