Content
View differences
Updated by Kabiru Mwenja about 2 months ago
**As** a user of an OpenProject instance which is set to use project-based work package identifiers
**I want to** use URLs with those identifiers
**so that** I can copy those to other tools and people can from that URL see which project the work package belongs to
## Acceptance criteria
* - URLs like `/work_packages/PROJ-42` resolve to the correct work package (full view, split view, and BIM views)
*
- The API v3 endpoint `GET /api/v3/work_packages/PROJ-42` resolves the work package by its semantic identifier
*
- Scoped queries (e.g. `WorkPackage.visible(user).find("PROJ-42")`) resolve semantic identifiers transparently
*
- `WorkPackage.exists?("PROJ-42")` returns `true` when the semantic identifier exists
*
- Historical/aliased identifiers (from project renames) still resolve via the `work_package_semantic_aliases` table
*
- Numeric IDs continue to work in all URL positions — no regressions for classic mode
*
- When a semantic identifier is not found, the response is a standard 404 with a work-package-specific error message (not a generic 404)
*
- The API v3 work package form endpoint correctly handles semantic identifiers in parent references
* Adapt generated routes such as clipboard copy to use semantic Ids
## Technical notes
* - `WorkPackage::SemanticIdentifier::FinderMethods` module is included in `WorkPackage` and extended onto every AR relation, overriding `find` and `exists?` to dispatch via `semantic_id?`
*
- `semantic_id?` predicate: strips whitespace, rejects non-strings and numeric strings, returns true only for `PROJECTID-SEQ` patterns — replaces FriendlyId's FriendlyId's `Object#friendly_id?` monkey-patch
*
- Resolution chain: check `identifier` column first, then fall back to `work_package_semantic_aliases` table for historical identifiers
*
- `ID_ROUTE_CONSTRAINT` constant centralised in `WorkPackage::SemanticIdentifier` — single source of truth for both `config/routes.rb` and frontend `WP_ID_URL_PATTERN`
*
- Rails route constraint widened from `/\d+/` to accept both numeric and `PROJECTID-SEQ` patterns
*
- API v3 route parameter changed from `type: Integer` to `type: String` to accept semantic IDs
*
- Controller and ViewComponent finders updated to use `find_by_id_or_identifier` instead of `find`
*
- `RecordNotFound` raised with structured `model:`, `primary_key:`, and `id:` fields for error reporting
## Permissions and visibility considerations
* - **Visible to:** all users who have permission to view work packages — the identifier format in the URL does not change authorization checks
*
- **Not visible when:** the semantic work package identifiers feature flag is disabled at the instance level (routes still accept the pattern but no semantic identifiers will have been assigned)
*
- Authorization is unchanged: `WorkPackage.visible(user)` scoping applies before identifier resolution, so users cannot access work packages they lack permission to view by guessing semantic identifiers
## Translation considerations
* - No new user-facing strings — this is a routing/resolution layer change
*
- Error messages for "not found" "not found" reuse existing `WorkPackage` record-not-found translations
## Out of scope
* - Generating or displaying semantic identifiers in the UI (covered by PRs #22704 and #22710)
*
- Allocating semantic identifiers to work packages (covered by the sequence allocation feature)
*
- Admin settings for enabling/configuring semantic identifier format
*
- Redirecting numeric URLs to semantic URLs (both forms remain valid)
*
- Sharing/copy-to-clipboard UI for semantic URLs
## Acceptance criteria
*
*
-
*
-
*
-
*
-
*
-
*
-
*
-
* Adapt generated routes such as clipboard copy to use semantic Ids
*
*
-
*
-
*
-
*
-
*
-
*
-
*
-
*
*
-
*
-
*
*
-
*
*
-
*
-
*
-
*
-