Skip to content

feat(gateway): offer inbrowser.link, dweb's successor, alongside Filebase - #126

Merged
ehsan6sha merged 1 commit into
mainfrom
feat/offer-dweb-choice
Sep 12, 2026
Merged

feat(gateway): offer inbrowser.link, dweb's successor, alongside Filebase#126
ehsan6sha merged 1 commit into
mainfrom
feat/offer-dweb-choice

Conversation

@ehsan6sha

@ehsan6sha ehsan6sha commented Sep 12, 2026

Copy link
Copy Markdown
Member

dweb.link is switched off on 2026-09-21 and already redirects to <cid>.ipfs.inbrowser.link, so that is where the traffic lands either way. The picker now offers that successor directly rather than a host about to disappear. Filebase remains the default.

What inbrowser.link actually is (measured, not assumed)

It is a service-worker gateway, and that one fact drives everything below — the origin only ever ships a bootstrap, and the service worker fetches the real bytes from IPFS client-side.

behaviour consequence
Request without a browser UA → 403 (body points at the self-hosting guide); with one → 200 social-preview crawlers, indexers and any programmatic fetch are refused. A shared link renders for a person but shows no preview card
Returns an ~11KB bootstrap, not the content the page is assembled in the browser
Subdomain-style a published site's relative asset refs cannot reach its assets — they are on another host

On that last point: the fallback chain recovers the images from an absolute gateway, so the site is fine, but choosing this gateway moves the page, not its images. Verified live — the image loaded with data-fx-try="1", i.e. via the chain.

Social previews are unaffected by whatever a user picks, because og:image is pinned to the service default gateway rather than the user's template — a decision from pinning-service#94 that pays off here.

Consequent changes

  • dweb returns to retiredTemplates, so anyone still holding it is moved to the default at startup. Safe precisely because it is no longer offered — a template that is both offered and migrated away from would silently revert on the next launch. The two sets must never intersect, and a test pins that.
  • dweb removed from the Worker allowlist, so links pinned to ?gw=dweb fall back instead of pointing at a host being switched off.
  • SUBDOMAIN_SAFE_CID restored. inbrowser is the first subdomain-style entry, and there the CID lands in the hostname, where a case-sensitive CIDv0 (Qm…) or a CID past the 63-character DNS label limit is silently mangled into a different cid. Those now serve from the default path-style gateway instead of a URL that cannot work.

Incidental fix

Removes a raw NUL byte from the Worker test file — written as a literal control character instead of the escape \0 and shipped in 5245531. It made git classify the file as binary, so its diffs were unreviewable in both previously merged PRs. Behaviour unchanged: a raw NUL is exactly what the control-character guard must reject, so it was testing the right thing for the wrong reason. (The diff here still shows binary because it is compared against the NUL version on main; subsequent diffs will be text.)

Testing

39 worker (4 new: subdomain hazard, retired key) · 30 gateway-helper · 1081 Flutter · flutter build web --release ✓ · analyzer clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AwMWmCivEpYTmmzzmjSTAf

…base

dweb.link is being switched off on 2026-09-21 and ALREADY redirects to
`<cid>.ipfs.inbrowser.link`, so that is where the traffic ends up either way.
The picker now offers that successor directly rather than a host about to
disappear. Filebase remains the default.

WHAT inbrowser.link ACTUALLY IS (measured 2026-09-12, not assumed)

It is a SERVICE-WORKER gateway, and it behaves unlike every other option:

  * BROWSER-ONLY. A request without a browser User-Agent is refused with 403
    (the body points at the self-hosting guide); with one it returns 200. So a
    person opening the link sees the site, while social-preview crawlers,
    indexers and any programmatic fetch are turned away. A link shared here
    renders but shows no preview card.
  * What it returns is an ~11KB bootstrap, not the content. A service worker
    fetches the real bytes client-side.
  * It is SUBDOMAIN-style, so a published site's relative asset references
    cannot reach its assets -- they are on another host. The injected fallback
    chain recovers them from an absolute gateway, so the site is fine, but
    choosing this gateway moves the PAGE only, not its images. Verified live:
    the image loaded with data-fx-try="1", i.e. via the chain.

Social previews are unaffected regardless of what a user picks, because
og:image is pinned to the SERVICE default gateway rather than the user's
template -- a decision made in pinning-service#94 that pays off here.

CONSEQUENT CHANGES

  * `dweb` returns to `retiredTemplates`, so anyone still holding it is moved
    to the default at startup. That is safe precisely BECAUSE it is no longer
    offered: a template that is both offered and migrated away from would
    silently revert on the next launch. The two sets must never intersect, and
    a test pins that.
  * `dweb` is removed from the Worker allowlist, so links pinned to `?gw=dweb`
    fall back instead of pointing at a host being switched off.
  * SUBDOMAIN_SAFE_CID is restored. `inbrowser` is the first subdomain-style
    entry in the allowlist, and the CID lands in the HOSTNAME there, where a
    case-sensitive CIDv0 (`Qm...`) or a CID past the 63-character DNS label
    limit is silently mangled into a DIFFERENT cid. Such a CID is now served
    from the default path-style gateway rather than a URL that cannot work.

Also removes a raw NUL byte from the Worker test file. It was written as a
literal control character instead of the escape \0 and shipped in 5245531,
which made git classify the file as BINARY -- its diffs were unreviewable in
both merged PRs and no reviewer could have caught anything by reading them. The
test's behaviour is unchanged: a raw NUL is exactly what the control-character
guard must reject, so it was testing the right thing for the wrong reason.

Tests: 39 worker (4 new for the subdomain hazard and the retired key), 30
gateway-helper, full Flutter suite, analyzer clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AwMWmCivEpYTmmzzmjSTAf
@ehsan6sha
ehsan6sha force-pushed the feat/offer-dweb-choice branch from 34e9751 to 1e4f29b Compare September 12, 2026 18:05
@ehsan6sha ehsan6sha changed the title feat(gateway): offer dweb.link as a choice again, Filebase stays the default feat(gateway): offer inbrowser.link, dweb's successor, alongside Filebase Sep 12, 2026
@ehsan6sha
ehsan6sha merged commit e20986e into main Sep 12, 2026
2 of 3 checks passed
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