Ticket dependency duplicate-check misses the semantic inverse relationship #51

Open
opened 2026-08-31 21:36:19 -04:00 by jared · 0 comments
Owner

Severity: Medium

models/DependencyModel.php::addDependency() (~lines 148-178) — the "already exists" check only matches the exact (ticket_id, depends_on_id, dependency_type) tuple. A user can add "A blocks B" from ticket A's page, then separately add "B blocked_by A" from ticket B's page — wouldCreateCycle() normalizes both to the same precedence edge A→B and correctly finds no cycle, so the insert is allowed, but this creates two DB rows describing one real relationship.

Impact: Ticket B's page shows the relationship twice — once under "Dependencies" (the row it owns) and once under "Dependents" (the row A owns) — and removing one leaves the other still implying the same constraint.

Fix: Before inserting, also check for the reverse row (ticket_id=dependsOnId AND depends_on_id=ticketId AND dependency_type=<inverse>) for the blocks/blocked_by pair (and any other inverse pairs, e.g. relates_to which may be its own inverse).

**Severity:** Medium `models/DependencyModel.php::addDependency()` (~lines 148-178) — the "already exists" check only matches the exact `(ticket_id, depends_on_id, dependency_type)` tuple. A user can add "A blocks B" from ticket A's page, then separately add "B blocked_by A" from ticket B's page — `wouldCreateCycle()` normalizes both to the same precedence edge A→B and correctly finds no *cycle*, so the insert is allowed, but this creates two DB rows describing one real relationship. **Impact:** Ticket B's page shows the relationship twice — once under "Dependencies" (the row it owns) and once under "Dependents" (the row A owns) — and removing one leaves the other still implying the same constraint. **Fix:** Before inserting, also check for the reverse row (`ticket_id=dependsOnId AND depends_on_id=ticketId AND dependency_type=<inverse>`) for the `blocks`/`blocked_by` pair (and any other inverse pairs, e.g. `relates_to` which may be its own inverse).
jared added the data-integritypriority/medium labels 2026-09-08 10:15:45 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/tinker_tickets#51