Closed Gozala closed 5 years ago
I need to do some exploration to be certain but I think <iframe sandbox>
might be able to offer alternative to subdomains & greatly simplify proposed architecture. Specifically following quote from MDN
allow-same-origin: If this token is not used, the resource is treated as being from a special origin that always fails the same-origin policy.
Seems to suggest that sandboxed iframes might be given some unique origin, in which case we don't need subdomains to separate origin and might be able to just use same lunen.link SW across them.
If that doesn't work out there is also some hope with blob URLs.
In other words if we can somehow isolate apps / sites from each other we won't need to deal with subdomains which I think would be really amazing & as it simplifies everything greatly!
Sadly without allow-same-origin
load does not goes through service worker & however setting allow-same-origin
doesn't prevent document in iframe from accessing storage which is also not good because that would allow things to mess with lunet itself.
I have gave up on making using <iframe sandbox />
to avoid need for sub-origins, because with allow-same-origin
iframe is pretty pointless and without out SW API isn't available nor top document SW is being triggered.
Instead I've set up https://celestial.link/ static site on S3 which serves same content across all the subdomains like https://mycid.celestial.link/. Content served right now does not really do much but I plan to make it bootstrap SW proxy to lunet. Lunet will be able to infer CID based of off origin that is going to be subdomain & serve content that corresponds to it.
In this setup visiting https://lunet.link/peerdium.gozala.io/${dataCID}
will do following:
appCID
that corresponds to peerdium.gozala.io
via dnslink.<iframe
src=`://${appCID}.celestial.link/`
data-src=`/ipfs/${dataCID}`
sandbox="allow-same-origin allow-scripts allow-presentation allow-popups allow-pointer-lock allow-orientation-lock allow-modals allow-forms"
style="width: 100%; height: 100%; left: 0px; top: 0px; position: absolute;"
/>
${appCID}.celestial.link
will do register proxy service worker that on request messages corresponding document (meaning ${appCID}.celestial.link
).${appCID}.celestial.link
listens to those messages and routes them to window.top
in this instance https://lunet.link/peerdium.gozala.io/${dataCID}
that captures event.origin
and data-src
routing request to the SharedWorker
.SharedWorker
takes care of handling requests & imposing restrictions:
${appCID}
or ${dataCID}
.${dataCID}
in which case it will produce response containing ${dataCID2}
which https://lunet.link/*
uses to update data-src
attribute. I think there is an opportunity to use navigator.registerProtocolHandler
to allow use your own "lunet" instance. e.g https://lunet.link
could register protocol like:
navigator.registerProtocolHandler(
"web+lunet",
"https://lunet.link/?redirect=%s",
"Peer-to-Peer Web");
In such case we could embrace web+lunet://${appCID}/${dataCID}/
URLs enabling anyone to deploy own copy of lunet and use it instead. This also implies that such links may load different lunet deployment based on recipient, which I think is great.
It just occurred to me that this can be untied from specific protocol & embrace diversity by registering web+dat://
, web+ipfs://
, web+ssb://
, web+torrent://
etc... to resolve to https://lunet.link/ipfs/${appCID}/${data}
and web+dat://dat/appKey/
etc... not only that, it could in fact allow you to have app from IPFS operating on data in Dat protocol.
- Application hosted on p2p network is disconnected from all the servers and there for can't really aggregate data.
This might have being little too bold of a statement as page could .unregister()
service worker and there for overcome all the limitations.
- Application hosted on p2p network is disconnected from all the servers and there for can't really aggregate data.
This might have being little too bold of a statement as page could
.unregister()
service worker and there for overcome all the limitations.
However, according to the spec
Note: The unregister() method unregisters the service worker registration. It is important to note that the currently controlled service worker client's active service worker’s containing service worker registration is effective until all the service worker clients (including itself) using this service worker registration unload. That is, the unregister() method only affects subsequent navigations.
So, if unregister()
only affects next load that means that means that all requests will still be handled by SW in the given load & next load will register SW before loading app anyhow, so maybe we can prevent apps loaded this way to talk with remote origins.
Prototype is live! Now you can go to
https://lunet.link/peerdium.gozala.io/
And it will load peerdium fork. This time it no longer needs any bootstrap just a DNS TXT record for gozala.io
:
_dnslink.peerdium TXT dnslink=/ipfs/QmYjtd61SyXU4aVSKWBrtDiXjHtpJVFCbvR7RgJ57BPZro/
Following also works https://lunet.link/webui.lunet.link/
In this instance through following record for lunet.link
:
_dnslink.webui TXT dnslink=/ipfs/QmSDgpiHco5yXdyVTfhKxr3aiJ82ynz8V14QcGKicM3rVh/
Finally you can load anything from IPFS in same way just via CID, for example following loads same peerdium fork:
https://lunet.link/QmYjtd61SyXU4aVSKWBrtDiXjHtpJVFCbvR7RgJ57BPZro/
At the moment each app is hosted by an author on some domain which on first load imports lunet client which will setup a service worker to load app and generally make it available across sessions online or offline without having to interact with servers.
@jimpick and up implementing a simple server which generates bootstrapping doc / sw from subdomain. Specifically when loading
https://cid.lunet.link/
it would serve html which mounts corresponding cid andlunet.js
SW script.@autonome in our conversation made a good point that user in this case needs to trust
lunet.link
because all the apps do more or less go through it.This got me thinking about alternative way to architect lunet that would address both things in a really neat way.
https://lunet.link/
could be just a static site with a service worker setup such that when sayhttps://lunet.link/peerdium.gozala.io/doc
is loaded it will redirect tohttps://lunet.link/?redirect=peerdium.gozala.io/doc
which will install SW and redirects back tohttps://lunet.link/peerdium.gozala.io/doc
causing a SW to serve it.SW on request to
https://lunet.link/peerdium.gozala.io/doc
will do following:Will lookup dnslink TXT record to determine CID, let's say it's a
$cid1
.Will respond with a following markup:
lunet will serve same thing under all subdomains meaning that
cid1.lunet.link
will just register SW which will route requests (similar to how it's done today) to the corresponding client document in this casecid1.lunet.link
that will route them back to the parent dochttps://lunet.link/peerdium.gozala.io/doc
which will take care of fetching cid1 from the IPFS and serving it.Why / How is this better
In this setup
lunet.link
becomes commodity, you don't have to trust it. You can deploy it anywhere (in fact fork github repo & enabling gh-pages probably will do fine). So in a way it addresses point made by @autonome you don't have to trust it just fork & deploy, best part being you'll need to load it once per device.We remove whole bootstrapping out of the equation. Knowing CID is just enough, better yet on first load we could allow user to choose to "install" it in local namespace meaning map it to say
https://lunet.link/peerdium/
. App could provide name suggestions, lunet could pick on that isn't taken and allow user to use that or override in place.Unlike current setup which requires app / site to cooperate (by serving bootstrap code which embeds lunet client from that domain) it always doc from own subdomain which will then serve corresponding app / site. In other words no cooperation is required.
In a way we are removing dependency on DNS, well not really because we made it far more loosely coupled because
We put browser in your browser! However maybe in a future we could remove top browser layer.