Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Force users to refresh the frontend when there has been a breaking backend change #309

Closed
davidlaprade opened this issue Mar 18, 2022 · 3 comments · Fixed by #653
Closed
Labels
app A change related to the Umbra frontend enhancement New feature or request

Comments

@davidlaprade
Copy link
Contributor

Background

In the event that there is ever a serious bug with the frontend or backend, we want to be able to force users to update their clients.

Imagine the following:

  • user X loads app.umbra.cash in a new browser tab
  • we discover that there is a serious bug in the frontend (and/or how it interacts with the backend)
  • we patch the bug and deploy the new code to the server that distributes it
  • user X still has the old, vulnerable code running in his/her browser tab
  • user X does not refresh his/her tab before using the frontend
  • user X uses the stale frontend and BAD THING happens

Unless we have a mechanism to force refresh clients, there will always be a long tail of outdated versions in the wild.

Implementation

There are two obvious triggers we could use for refreshes:

  1. refresh after a certain amount of time (e.g. a week) even if there has been no backend update
  2. refresh each time there is a (major|minor|patch) version update to the backend

Trigger 1 has the benefit of refreshing the app even if no backend calls have been made. For example, after you've connected to the network, you can send funds with the protocol without touching the backend again. You just sign the transaction that the frontend creates for you, and your wallet sends it to the network.

I think 2 would probably be all that we need, though. Most wallets will require you to reconnect after a prolonged period away from a dapp, and doing so will hit the /tokens route of the backend.

As it is, the backend already returns a version number with each response which we could use:

{
    name: 'Umbra',
>>  version: { major: 0, minor: 0, patch: 1 },
    keywords: [ 'umbra', 'stealth', 'payments', 'defi' ],
    tokens: [...],
    timestamp: '2021-04-23T20:11:22.472Z'
}

My suggestion would be to refresh on every major or minor release of the backend. Refreshing on patch releases would likely just result in a lot of refreshing for our users, which isn't great UX.

To implement this, it would probably be sufficient to just store the backend version in a cookie or local storage or something, TBD. When the frontend first loads, it stores the first version it sees from the backend. Then, each time it makes a request to the backend, it confirms that the version in the cookie matches the version coming back from the API. If it doesn't, we force the user to refresh. A power user could always manipulate his/her cookies to get around the check. But I think at that point, it's on them and we just let them do what they want. The protocol is ultimately open anyway.

An alternative to this approach would be to give the frontend a version too. Then on each API request we check that the frontend version is >= the backend version. Then we don't have to worry about power users getting around our protections by modifying cookies (now they'd have to modify the javascript itself). But the downside of this approach is that we'd be coupling frontend and backend deploys: it wouldn't be possible to deploy the backend without first deploying the frontend. We'd also need to be careful: if the backend was deployed before the frontend, users could be stuck in an infinite refresh loop where the frontend keeps telling them to refresh b/c its version lags the backend version, but when it does refresh it just pulls frontend code with a version that is still out of date.

UX

We probably want to put an overlay on the app to disable it, with copy to the effect of "Your application is out of date, please reload [button]". This is what google sheets does, for example, when I've had a tab open for months. It's straightforward. You just click the button (it's all you can do) and that's it.

@davidlaprade davidlaprade added the app A change related to the Umbra frontend label Mar 28, 2022
@garyghayrat garyghayrat added the enhancement New feature or request label Jul 6, 2022
@garyghayrat garyghayrat assigned garyghayrat and jferas and unassigned garyghayrat Jul 22, 2022
@davidlaprade
Copy link
Contributor Author

Another (all too timely) usecase for this... if a version of your frontend calls out to an address that was recently sanctioned 😬 you'd want a way to immediately prevent anyone who still has that code in their browser from using it

@jferas
Copy link
Contributor

jferas commented Sep 21, 2022

The 'version' that already exists that is described above is not an API version.. it is a TokenList version that comes from the uniswap library type definitions in the Umbra API. A change in this version value indicates a change in the token list being provided by the Umbra API.. not a change in the API itself. I'd propose that as we make the Umbra API return a 'version' from every API endpoint ( https://github.com/ScopeLift/umbra-api/issues/58 ), we name it something different to uniquely identify it, such as umbraApiVersion.

@apbendi
Copy link
Member

apbendi commented Sep 27, 2022

Thanks to @jferas's work, the API now includes an umbraApiVersion parameter. We can proceed with the frontend portion of this task.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
app A change related to the Umbra frontend enhancement New feature or request
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

4 participants