PURL Identity Model (OriginalPURL / EffectivePURL / CanonicalKey)
← Back to README.md
A 3-layer structure to balance stable internal matching with complete preservation of user input.
Field
Persistence Scope
Mutation
Purpose
Example
OriginalPURL
Returned externally
Write-once
Exact user input (preserving case / collapsed forms). For audit logs & reproducibility
pkg:npm/React
EffectivePURL
Returned externally
Updated during resolution
Resolved/normalized form used for API calls (may add version, expand coordinates)
pkg:npm/react@18.3.1
CanonicalKey
Internal only
Lazily generated
Stable key with version stripped + lowercased (dedup / EOL matching). Not exposed to users
pkg:npm/react
DisplayPURL() — Prefers OriginalPURL, falls back to EffectivePURL
IsVersionResolved() — True if EffectivePURL contains @version
EnsureCanonical() — Generates CanonicalKey if empty (uses Original preferentially)
Case preservation : Prevents corruption in case-sensitive ecosystems (Maven paths / Go import paths)
User input preservation : Maintains original input for audit and reproducible reruns
Non-destructive rewrites : Version resolution and path expansion do not modify the original request
Centralized matching : Consolidates internal maps / EOL matching to a single deterministic transform (CanonicalKey)
Common Divergence Scenarios
Scenario
OriginalPURL
EffectivePURL
npm Mixed Case
pkg:npm/React
pkg:npm/react@18.3.1
Maven collapsed coordinates
pkg:maven:org.slf4j:slf4j-api@2.0.16
pkg:maven/org.slf4j/slf4j-api@2.0.16
GitHub URL base + version resolution
pkg:golang/github.com/gin-gonic/gin
pkg:golang/github.com/gin-gonic/gin@v1.10.0
Resolution failure (no version)
pkg:pypi/Django
pkg:pypi/Django
Record raw input as OriginalPURL exactly once at ingestion
Reflect transformation results in EffectivePURL only
Call EnsureCanonical() immediately before storing in internal maps / merge logic
Arbitrary lowercasing is performed only via CanonicalKey utilities
OriginalPURL = Exact input as-is
EffectivePURL = Final resolved/fetched form
CanonicalKey = Internal versionless lowercase key (generated by EnsureCanonical())
DisplayPURL() = Display form (Original preferred)