From 88bbbbc57daddfba42fa2b851148e65773a49825 Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Sat, 16 May 2026 14:32:56 +0200 Subject: [PATCH] fix(templates): scope owner filter under @self in slug-collision lookup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `ApplicationsController::lookupOne` placed the optional `owner` filter at the top level of the OR search query, but OR records ownership under `@self.owner`. Every owner-scoped lookup therefore matched 0 rows. Net effect for the createFromTemplate flow (issue #51): when the same user re-cloned a template with an already-used slug, the collision check fell through, provisioning then hit the org-wide register-slug unique constraint, and the response went out as `clone_failed` 500 instead of the documented `slug_collision` 409. Moving the `owner` filter into the `@self` block restores the documented behaviour (REQ-OBT-005). Note: the cross-user case (different user, same slug) still mis-behaves because OR register slugs are organisation-wide unique and OpenBuilt provisions registers as `openbuilt-{slug}` regardless of owner — a deeper architectural change that warrants its own ticket. --- lib/Controller/ApplicationsController.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/Controller/ApplicationsController.php b/lib/Controller/ApplicationsController.php index 502ac7e6..4f7ca1d4 100644 --- a/lib/Controller/ApplicationsController.php +++ b/lib/Controller/ApplicationsController.php @@ -1312,7 +1312,13 @@ private function lookupOne( ]; if ($owner !== null) { - $query['owner'] = $owner; + // OR records ownership under `@self.owner`, not at the + // top level. Placing the filter on the top-level `owner` + // field made every owner-scoped lookup miss (#51) — the + // slug-collision check then fell through and the org-wide + // register-slug unique constraint raised `clone_failed` + // instead of the documented `slug_collision`. + $query['@self']['owner'] = $owner; } $results = $this->objectService->searchObjects(query: $query);