e682bbccd1
Addresses review on PR #227. - setAlias confirmed-reassign branch: DELETE the target page's existing alias row(s) BEFORE retargeting `byName` onto the page, instead of after. The new partial unique index `(workspace_id, page_id)` is non-deferrable and checked at each statement, so retargeting first momentarily left two rows for the page -> immediate 23505 -> rolled-back tx surfaced as a misleading "Alias already taken" (regressing a previously-working swap onto a page that already had its own alias). The reordered branch needs no trailing self-heal. JSDoc updated to describe the real ordering. - catch block: the postgres@3.x driver exposes the violated index as `err.constraint_name` (with `.constraint` as a fallback). Map `share_aliases_workspace_id_alias_unique` -> "Alias already taken" and the new `share_aliases_workspace_id_page_id_unique` -> a distinct ALIAS_PAGE_RACE outcome (a concurrent same-page write, not a name clash). Always log the constraint name on any 23505 so the race is diagnosable. - migration 20260627T120000: document that the dedup DELETE is intended, irreversible data loss (old duplicate `/l/<old>` links start 404ing after upgrade; `down()` cannot restore the rows). Same note added to CHANGELOG [Unreleased] Fixed. Tests: - integration: confirmed reassign onto a page that ALREADY has its own alias (RED before the reorder); migration up() dedup scoping across pages and a second workspace; mid-transaction error -> BadRequest with clean rollback. - unit: constraint_name distinguishing (alias index, page_id index, fallback `.constraint`, no-info default) and non-unique error -> BadRequest; retarget test now asserts delete-before-update order. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>