Add stable /project/{slug}/latest/ permalink #119
No reviewers
Labels
No labels
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
qwc-open/asiakirjat!119
Loading…
Reference in a new issue
No description provided.
Delete branch "feature/latest-version-permalink"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
There was no shareable URL that always points to a project's newest version. The in-page "latest" link resolved to a concrete version tag, so any link you copied or shared went stale the moment a newer version was uploaded.
What this adds
A rolling permalink that always tracks the current latest version:
handleServeLatestresolves the latest version and 302-redirects to the concrete version's doc URL, preserving the sub-path. MarkedCache-Control: no-storeso caches don't pin it to one version.latestVersionTagrule — pinned version if set, else highest semver — matching the project page's "Latest" badge and the frontpage. So pinning a version also repoints the permalink.handleServeDoc: the redirect never reveals that versions exist on a project the user can't view (anonymous on a non-public project → login).latestsegment is registered as a more-specific route than{version}, so it wins for that path.latestis therefore a reserved URL segment (documented).Docs
first-projecttutorial gains a "Linking to the latest version" section.pin-versionsnotes the permalink follows the pin.Tests
latest_version_test.go: redirect-to-newest, sub-path preservation, pin precedence, no-versions → 404, and anonymous-on-private →/login. Handler package green.Design note
Implemented as a redirect (not serve-in-place) so it reuses all the existing, tested serving logic — access checks, PDF viewer, overlay injection, security-header exemptions — with no duplication. The stable
/latest/URL is the thing you share; clicking it always resolves to whatever is newest at that moment.🤖 Generated with Claude Code
There was no shareable URL that always points to a project's newest version — links had to bake in a concrete version tag, so they went stale on the next upload. Add a rolling permalink that redirects to the current latest: - GET /project/{slug}/latest and /project/{slug}/latest/{path...} resolve the latest version (handleServeLatest) and 302-redirect to the concrete version's doc URL, preserving the sub-path. The redirect is marked Cache-Control: no-store so caches don't pin it to one version. - "Latest" uses the existing latestVersionTag rule (pinned version if set, else highest semver), matching the project page's "Latest" badge and the frontpage. Access is gated identically to handleServeDoc, so the redirect never leaks versions on a project the user can't see. - The literal "latest" segment is registered as a more-specific route than {version}, so it wins for that path; "latest" is therefore a reserved URL segment (documented). - Project detail page shows a read-only "Latest version permalink" field with a Copy button. - Docs: first-project tutorial gains a "Linking to the latest version" section; pin-versions notes the permalink follows the pin. - Tests: redirect-to-newest, path preservation, pin precedence, no-versions 404, and anonymous-on-private → login. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Switch the /project/{slug}/latest/ permalink from a 302 redirect to serving the resolved version's content directly at the /latest/ URL. The address bar stays /latest/, so relative links inside the docs keep resolving under /latest/ and a visitor who lands on the permalink keeps browsing "latest" rather than being bounced to a versioned URL. - Extract the PDF/overlay/HTML serving body of handleServeDoc into a shared serveVersionDoc helper; handleServeDoc and handleServeLatest both call it, so explicit-version and latest serving behave identically (PDF viewer, overlay injection, path safety all reused, no duplication). - handleServeLatest now resolves the latest tag (still pin-aware), loads the version, sets Cache-Control: no-cache (revalidate so a new upload is picked up next request), and serves in place. - Bare /project/{slug}/latest (no trailing slash) 301-redirects to /latest/ so the served index page's relative links resolve correctly. - Docs/tests updated to reflect serve-in-place behavior. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Serving the latest version in place means the URL segment ("latest") differs from the resolved concrete tag the overlay reports in data-current (e.g. v1.5). The overlay JS computed the in-doc path suffix by stripping "/project/{slug}/{current}" from window.location.pathname — but the path actually contains "latest", so the stripping cut into the wrong characters and produced malformed version-switch, compare-fetch, and link-intercept URLs. Derive urlVersion from the actual URL path segment and use it for all path math (suffix extraction, internal-link prefix matching); keep `current` (the resolved tag) for concrete-version concerns (dropdown selection, download link, diff target). Now switching versions and comparing work correctly whether the page was reached via /latest/ or an explicit version URL. Server side already passes the resolved concrete tag to the overlay; added a test asserting /latest/ serves data-current="v2.0.0" so the JS always has a real version to build comparison URLs from. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>