Skip to content

fix(routing): let a reader come back from a legacy link - #183

Merged
adamjohnwright merged 1 commit into
mainfrom
fix/legacy-link-history
Sep 9, 2026
Merged

fix(routing): let a reader come back from a legacy link#183
adamjohnwright merged 1 commit into
mainfrom
fix/legacy-link-history

Conversation

@adamjohnwright

Copy link
Copy Markdown
Contributor

An adversarial pass over #172 and #182.

Following a legacy link trapped the reader

From /about/news, opening /PathwayBrowser/#1280218 and pressing Back stayed on the pathway — six times over. The reader could not get back to the news archive they came from.

The rewrite is the cause. The app writes state into the URL while the fragment is still present, so /PathwayBrowser#1280218 and then ?tab=details#1280218 both became history entries carrying it — and going back to such an entry rewrites it forward again. Both PRs shipped this; the #R-HSA-… links have had it since #172.

Two changes:

  • A fragment being consumed is no longer carried forward by the navigations that write state into the URL, so no entry retains it.
  • A dbId is navigated on immediately rather than after its lookup — going first means the fragment is consumed in the same turn as a stable-id one, before anything else can record it — with the URL then corrected to the stable id by a replace, which adds no entry.
from /about/news before after
#1280218 never escaped 3 Backs
#R-HSA-202733 never escaped 4 Backs
direct R-HSA-1280218 3 Backs 3 Backs

I had also written a resolver that already existed

dbIdToStId has been on this service all along, unused — and it is the better one: it asks /data/query/<dbId>/stId and gets 13 bytes, where mine fetched the whole object to read one field off it — 12,682. Mine is gone, and the existing one has its first caller.

Not fixed, and not mine

A pathway load adds two history entries of its own before any of this, which is why leaving still takes three Backs rather than one. Every navigation in this service pushes, including the ones that only normalise the URL. Worth a look — but making them replace would also stop Back working between pathways, so it needs deciding rather than just changing.

Tested

The escape is now a test, since it broke twice without anything noticing. Full preflight green; the release spec that opens all 21 v97 links passes on a dedicated run.

🤖 Generated with Claude Code

An adversarial pass over #172 and #182.

**Following a legacy link trapped the reader.** From the news archive,
opening `/PathwayBrowser/#1280218` and pressing Back stayed on the pathway
-- six times over. The rewrite is the cause: the app writes state into the
URL while the fragment is still there, so `/PathwayBrowser#1280218` and
`?tab=details#1280218` both became history entries carrying it, and going
back to such an entry rewrites it forward again. Both PRs shipped this; the
`#R-HSA-…` links have had it since #172.

Two changes. A fragment being consumed is no longer carried forward by the
navigations that write state into the URL, so no entry retains it. And a
dbId is navigated on immediately rather than after its lookup -- going
first means the fragment is consumed in the same turn as a stable-id one,
before anything else can record it -- with the URL then corrected to the
stable id by a replace, which adds no entry.

Measured from /about/news: a dbId link now takes 3 Backs to leave, a
stable-id link 4, and a direct load 3. It was never.

**I had also written a resolver that already existed.** `dbIdToStId` has
been on this service all along, unused, and it is the better one: it asks
`/data/query/<dbId>/stId` and gets 13 bytes, where mine fetched the whole
object for one field -- 12,682. Mine is gone and the existing one has its
first caller.

Not fixed, and not mine: a pathway load adds two history entries of its own
before any of this, which is why leaving still takes three Backs rather
than one. Every navigation in this service pushes, including the ones that
are only normalising the URL. Worth a look, but making them replace would
also stop Back working between pathways, so it needs deciding rather than
just changing.

The escape is now a test, because it broke twice without anything noticing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@adamjohnwright
adamjohnwright enabled auto-merge (squash) September 9, 2026 18:10
@adamjohnwright
adamjohnwright merged commit 550fbfb into main Sep 9, 2026
6 checks passed
@adamjohnwright
adamjohnwright deleted the fix/legacy-link-history branch September 9, 2026 18:18
adamjohnwright added a commit that referenced this pull request Sep 9, 2026
Opening a pathway cost three presses of Back to get out of, and the first
two did something nobody asked for. The app writes its own defaults into the
URL, so `?tab=info` and then `?tab=details` each became a history entry:
pressing Back stepped through tab changes the reader never made before it
would leave the page.

The URL still has to carry the tab -- a shared link has to open on the same
thing -- so the fix is not to stop writing it. Being *given* a tab now
replaces the entry; *choosing* one still adds to it. `details.component`
already knew the difference, in `tabCameFromUrl`; there was just no way to
tell the URL writer, so `settle()` is that way.

From the news archive: one press of Back leaves, where it was three. Choosing
the Molecule tab and pressing Back still returns to Details.

Found while reviewing #183, where I called this pre-existing and left it. It
was pre-existing, and it turned out to be one flag rather than the rework of
navigation semantics I assumed -- the reason I gave for not doing it was
wrong.

Both halves are tested, because keeping the second is what stops the first
turning into "Back does nothing in this app".

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant