Please don't post snarky dismissals like this on HN. The guidelines ask us to avoid shallow dismissals and snark. Please make an effort to observe them when participating here.
Re: what is this even about, see my comment here: https://news.ycombinator.com/item?id=45469167. Sorry I didn't write an elaborate intro to the article; I kind of meant it for a narrower audience of people looking for an answer to a technical question (how at:// resolves).
I'll say this preemptively — actually resolving at:// URIs isn't something you'd do much as an app author because the usual model for apps is to listen to all data commits over the network via websocket (like https://pdsls.dev/jetstream?instance=wss%3A%2F%2Fjetstream1....), and to write to a local database whatever you're interested in. So you'd mostly use at:// URIs as unique global identifiers for pieces of data, but you probably won't actually resolve them since the data will be pushed to you. But it's nice that you can always fetch it on demand too.
I focused on resolving in this article because I think "following along" the resolution procedure is a really good way to understand how handles, identity and hosting are tied up.
Not sure if you already replied to a similar question but regarding this quote
> the actual server storing my data is currently https://morel.us-east.host.bsky.network. I’m happy to keep hosting it there but I’m thinking of moving it to a host I control in the future
Is the process of moving hosts documented somewhere?
how can it be hacked? can i impersonate someone else? whats to stop me from making posts with someone elses handle. how secure is the data? or does it just ride over tls and use that for protection.
Excellent explanation as always from Dan, and timely with the latest news from Bluesky on moving the PLC management.
We picked the same DID systems for https://fair.pm/ to decentralise WordPress plugin distribution (and general management for user-facing packages; think App Store rather than Cargo).
The Bluesky folks (especially Bryan) were super helpful in helping us out - even shipping Ed25519 key support so we could use libsodium.
(We’re designing our protocol on top of DIDs and using Bluesky’s stackable moderation, but chose not to use atproto directly - but the great thing is that DIDs are a W3C standard, and PLC isn’t tied to atproto.)
Isn’t PLC (a did method created by bluesky) tied to bluesky (or some other central authority)?
Why do they call it a did when it’s centralised?
As did:plc isnt portable, why didn’t they just use did:web, and decorate the identity docs with PLC-like behaviour?
Why isn’t the method-specific-id part of the did something deterministic/portable, like a hash of a public key that can at least permit some revolver-driven portability?
Why didn’t they use some mechanism for decentralisation, like a DHT (e.g. did:pkarr)?
It seems to me that PLC is thinly veiled attempt for another master to exert control.
So any server storing such at:// links will need to do some DNS/HTTPS dance to get the canonical representation, or permalink as the author calls it.
Doesn't that make it quite fragile without functioning DNSSEC?
Haven't really thought it through but my immediate reaction is DNS poisoning seems like it could do some damage here, allowing bad actors to post in my name, given the public key is part of the DID that you found from the DNS entry. Or?
The recommendation to resolve from handles to DIDs for "permalinks" is concerning to me:
- My handle is something _I_ control. I can make it point at a different PDS at any time.
- My DID is something my PDS controls.
I could solve this by indirecting through a web DID under my control, but there's no recommendation anywhere in Bluesky's documentation. Is that something everyone needs to do to ensure real identity portability?
edit: I'm not sure this CAN be solved without running a PDS given that I can't use my own keys. What am I missing here?
This is verbose and unclear. An article like this should always start by explaining what problem it tries to solve before going into technical details.
I still don't understand how this project meaningfully addresses the problem of identity and data ownership.
When it come to identities, either you have your own domain, or you use someone else's domain (say, Bluesky). Most people don't have domains, and so their identity will be owned by a third party.
You also have the same problem when it comes to the data itself. The moment Bluesky or some other server bans you, your repo is shut down and you lose the ability to move the data somewhere else.
In short, this is exactly like email. Unless you have your own domain and server you don't control anything.
> Most people don't have domains, and so their identity will be owned by a third party.
Indeed, and as a result, such users will always be vulnerable to specific risks like sudden bans, i.e. when the hosting service becomes adversarial. The only full protection is to own your own domain off a neutral TLD, with protocols that use DNS to describe how traffic should be routed.
But, because most users don't have domains (as you pointed out), the state-of-the-art can still be improved upon with partial flexibility and protections, when the hosting service is cooperative. This project allows people to keep their Bluesky handle (because they don't own a domain) while (hypothetically) moving their data hosting to a different provider, unlike current Big Social where your data is stuck on Facebook/X/Instagram/TikTok/YouTube forever. Bluesky has an interest in this because it also allows people to set up their own handle and move their hosting to Bluesky.
Sometimes we improve upon the existing state of the art not by delivering perfect solutions, but by delivering improvements upon limitations that we accept as a given (like the fact that most users will not set up their own domains).
Owning a private key is the best way to prove your identity. As for hosting, I think BitTorrent is the most rock-solid? So maybe store your content in a Git repo, sign your commits, and publish on Torrent. And NNTP or RSS to notify users/followers of updates? Problems though are discoverability and passivity (e.g. no user comments from blogs etc.).
In AT, data is tied to identity (DID), not handles or hosting. That’s what my article tried to explain.
If you lose the “handle” domain, all it means is that you won’t have a valid handle (which apps will tell you about) but your posts will remain up (they’re still addressable by your DID, which is how apps look things up). In the Bluesky app, for example, it would say “invalid handle” instead of your username. However, it’ll work. It’s the same situation as what happens if your domain expires or you delete your records. Your data is still there, you’re still “followed“ by the same people, etc. A handle is just an alias.
All you’ll need to do is to change the handle, thereby attaching a new domain, through any app that has the “change handle” flow. (It’s enough to have one app that gives you free ones.)
With hosting, it is similar (although there are barriers which need to be lowered). If your repo shuts down, you absolutely can move it somewhere else provided that you have a backup of it. Backups are trivial to automate on AT so this is something I expect hosting providers to offer. There are already third-party apps that regularly do backups for you. And you can export your repository from some clients as well (eg from the official Bluesky client).
In the “happy” case, your hosting will cooperate with moving your repo to another host. See https://pdsmoover.com/info.html for the happy case.
For the “unhappy” case where your old hosting doesn’t cooperate, you also can move if you saved a rotational key. See https://www.da.vidbuchanan.co.uk/blog/adversarial-pds-migrat.... This requires some technical knowledge today but you can imagine a backup solution having that feature also.
And when your repo goes up again at a different host, the difference will be imperceptible to you or other users, since it's signed by the same identity. All your posts, followers, etc, will "come back" with no disruption or broken links.
This is very different from email. Yes, there's some technical know-how in setting up protections if you expect to be adversarial to your hosting, but you do have that ability, and I expect with the AT ecosystem developing, it'll be much more user-friendly to set them up than it is today.
You DID has to be hosted to some provider. Whoever controls that domain controls to which location your content resolves. There’s one extra layer of indirection, but the exact same issue is still there.
If you own the domain, that’s fine. If it’s a thirst party domain and they refuse to cooperate: you’re screwed.
Until you don't. As opposed to a server you host (together with its data), for domains you are at the mercy of the registrar.
This was one (tiny, to be honest) of the considerations I had when choosing a registrar in my country, we are under one legislation, so my hope is a bit higher to recover it if needed.
This seems to fill the same function as DNS, but adds a layer of abstraction on top of it, while also adding a dependency on a service provided by Bluesky. I fail to see how this improves things on the whole.
It builds on top of DNS (in at least in two places) so it’s not equivalent — and it fills a different function to it. See https://news.ycombinator.com/item?id=45469296 for a breakdown.
PLC is being spun out into an independent entity, the longer term goal is for it to operate somewhat similar to ICANN. Its code is easy to run so something else could conceivably replace it. It’s also possible for AT to allow other `did` methods in the future as long as they’re persistent and can be performantly resolved.
This is a nice write-up. I recently added post-to-bluesky support to my ongoing social-media-scheduler project [1], thinking it would be the simplest of the services to work on, but I ended up getting really confused instead.
DID and handle resolution was the easiest part of ATProto---as the author says, a library can do the job easily. For Ruby it's DIDKit [2]. Where ATProto really threw me was the seeming non-ownership of record types. Bluesky uses "app.bsky.feed.post" for its records, as seen in the article; there seem to be a lot of these record types, but there doesn't seem to be a central index of these like there are for DIDs, or a standard way of documenting them... and as far as I've been able to find, there's no standard method of turning an at:// URI into an http:// URL.
When my app makes a post on behalf of a user, Bluesky only sends an at:// URI back, which I have to convert myself into an http:// URL to Bluesky. I can only do that with string manipulation, and only because I know, externally, what format the URL should be in. There's no canonical resolution.
> I have to convert myself into an http:// URL to Bluesky
at:// URIs and specific lexicon are not limited to a single app. The NSID (app.bsky.feed.post) has authority based on domain, but Bluesky cannot prevent anyone from reading / writing records of that type.
There are alternative apps that read the same at:// but put them under a different https://...
tl;dr, there is not a 1-1 mapping between at:// and https://, it's 1-N
Reminds me of the various crypto protocols talking about theoretical decentralization while entirely bound to 1 platform with no other useful apps in sight.
It's an early time but https://tangled.org/ (sort of like GitHub) and https://leaflet.pub/ (sort of like Medium) are pretty cool and useful, in my opinion. As it gets easier to start new apps (e.g. with tools like https://slices.network/ that take care of indexing the network) I think we'll see more apps built on AT.
In my article, I tried to explain how that works and what makes it possible. "Making it possible" is usually a prerequisite to the kind of broad adoption you're talking about.
What I agree about 100% is that "normal" users don't care about any of this. They just want good apps. The interesting thing about Bluesky, in my opinion, and what makes it different from crypto in your analogy, is that the vast majority of Bluesky users are "normies" in that sense. They couldn't care less about "decentralization" and some are even actively against the idea. But the decentralized nature doesn't directly "show up" in the product much, just like it doesn't "show up" when you browse the web and hop between servers. I think that's key to adoption--it needs to "just work" behind the scenes.
After 3 years on Mastodon and some lurking on bsky, I believe the main issue is not technical but getting and keeping interesting content on a platform. This is a social issue as bubbles ruin everything over time. OTOH using algorithms to mix some „foreign“ content into the feeds causes outrages. Sure we can all go web3 and self-hosted but nobody will read. Mastodon is the posterchild of a failed experiment. I‘m interested in the creative, productive, inspiring long-tail content on all platforms instead of migrating the peer group over to a new platform every couple of years. I know them already, I have better ways to communicate with my direct peers and the rest is like having 500 contacts on LinkedIn: A social illusion. I appreciate and respect the technical efforts behind atproto, but yet I can‘t see that it solves the problem described above.
61 comments
[ 4.0 ms ] story [ 71.3 ms ] threadIt’s kind of annoying that a huge number of DID methods are specific to cryptocurrencies and are practically abandoned.
https://news.ycombinator.com/newsguidelines.html
Re: what is this even about, see my comment here: https://news.ycombinator.com/item?id=45469167. Sorry I didn't write an elaborate intro to the article; I kind of meant it for a narrower audience of people looking for an answer to a technical question (how at:// resolves).
I'll say this preemptively — actually resolving at:// URIs isn't something you'd do much as an app author because the usual model for apps is to listen to all data commits over the network via websocket (like https://pdsls.dev/jetstream?instance=wss%3A%2F%2Fjetstream1....), and to write to a local database whatever you're interested in. So you'd mostly use at:// URIs as unique global identifiers for pieces of data, but you probably won't actually resolve them since the data will be pushed to you. But it's nice that you can always fetch it on demand too.
I focused on resolving in this article because I think "following along" the resolution procedure is a really good way to understand how handles, identity and hosting are tied up.
> the actual server storing my data is currently https://morel.us-east.host.bsky.network. I’m happy to keep hosting it there but I’m thinking of moving it to a host I control in the future
Is the process of moving hosts documented somewhere?
Will it work if that link redirects to says https:// example.com/did.txt or even to a different host say https:// foo.bar/some/thing/did?
This is chicken and egg stuff. I don't get it and I've picked on the intro of the explainer. Why would I want "the JSON"?
Yes, I did skim the "read this" link.
It's not for me.
This all seems unnecessarily fragile.
So, DNS?
We picked the same DID systems for https://fair.pm/ to decentralise WordPress plugin distribution (and general management for user-facing packages; think App Store rather than Cargo).
The Bluesky folks (especially Bryan) were super helpful in helping us out - even shipping Ed25519 key support so we could use libsodium.
(We’re designing our protocol on top of DIDs and using Bluesky’s stackable moderation, but chose not to use atproto directly - but the great thing is that DIDs are a W3C standard, and PLC isn’t tied to atproto.)
Isn’t PLC (a did method created by bluesky) tied to bluesky (or some other central authority)?
Why do they call it a did when it’s centralised?
As did:plc isnt portable, why didn’t they just use did:web, and decorate the identity docs with PLC-like behaviour?
Why isn’t the method-specific-id part of the did something deterministic/portable, like a hash of a public key that can at least permit some revolver-driven portability?
Why didn’t they use some mechanism for decentralisation, like a DHT (e.g. did:pkarr)?
It seems to me that PLC is thinly veiled attempt for another master to exert control.
Doesn't that make it quite fragile without functioning DNSSEC?
Haven't really thought it through but my immediate reaction is DNS poisoning seems like it could do some damage here, allowing bad actors to post in my name, given the public key is part of the DID that you found from the DNS entry. Or?
- My handle is something _I_ control. I can make it point at a different PDS at any time.
- My DID is something my PDS controls.
I could solve this by indirecting through a web DID under my control, but there's no recommendation anywhere in Bluesky's documentation. Is that something everyone needs to do to ensure real identity portability?
edit: I'm not sure this CAN be solved without running a PDS given that I can't use my own keys. What am I missing here?
hence why it is called the "activity transfer protocol"
https://atproto.com/articles/atproto-for-distsys-engineers
When it come to identities, either you have your own domain, or you use someone else's domain (say, Bluesky). Most people don't have domains, and so their identity will be owned by a third party.
You also have the same problem when it comes to the data itself. The moment Bluesky or some other server bans you, your repo is shut down and you lose the ability to move the data somewhere else.
In short, this is exactly like email. Unless you have your own domain and server you don't control anything.
Indeed, and as a result, such users will always be vulnerable to specific risks like sudden bans, i.e. when the hosting service becomes adversarial. The only full protection is to own your own domain off a neutral TLD, with protocols that use DNS to describe how traffic should be routed.
But, because most users don't have domains (as you pointed out), the state-of-the-art can still be improved upon with partial flexibility and protections, when the hosting service is cooperative. This project allows people to keep their Bluesky handle (because they don't own a domain) while (hypothetically) moving their data hosting to a different provider, unlike current Big Social where your data is stuck on Facebook/X/Instagram/TikTok/YouTube forever. Bluesky has an interest in this because it also allows people to set up their own handle and move their hosting to Bluesky.
Sometimes we improve upon the existing state of the art not by delivering perfect solutions, but by delivering improvements upon limitations that we accept as a given (like the fact that most users will not set up their own domains).
In AT, data is tied to identity (DID), not handles or hosting. That’s what my article tried to explain.
If you lose the “handle” domain, all it means is that you won’t have a valid handle (which apps will tell you about) but your posts will remain up (they’re still addressable by your DID, which is how apps look things up). In the Bluesky app, for example, it would say “invalid handle” instead of your username. However, it’ll work. It’s the same situation as what happens if your domain expires or you delete your records. Your data is still there, you’re still “followed“ by the same people, etc. A handle is just an alias.
All you’ll need to do is to change the handle, thereby attaching a new domain, through any app that has the “change handle” flow. (It’s enough to have one app that gives you free ones.)
With hosting, it is similar (although there are barriers which need to be lowered). If your repo shuts down, you absolutely can move it somewhere else provided that you have a backup of it. Backups are trivial to automate on AT so this is something I expect hosting providers to offer. There are already third-party apps that regularly do backups for you. And you can export your repository from some clients as well (eg from the official Bluesky client).
In the “happy” case, your hosting will cooperate with moving your repo to another host. See https://pdsmoover.com/info.html for the happy case.
For the “unhappy” case where your old hosting doesn’t cooperate, you also can move if you saved a rotational key. See https://www.da.vidbuchanan.co.uk/blog/adversarial-pds-migrat.... This requires some technical knowledge today but you can imagine a backup solution having that feature also.
And when your repo goes up again at a different host, the difference will be imperceptible to you or other users, since it's signed by the same identity. All your posts, followers, etc, will "come back" with no disruption or broken links.
This is very different from email. Yes, there's some technical know-how in setting up protections if you expect to be adversarial to your hosting, but you do have that ability, and I expect with the AT ecosystem developing, it'll be much more user-friendly to set them up than it is today.
If you own the domain, that’s fine. If it’s a thirst party domain and they refuse to cooperate: you’re screwed.
Until you don't. As opposed to a server you host (together with its data), for domains you are at the mercy of the registrar.
This was one (tiny, to be honest) of the considerations I had when choosing a registrar in my country, we are under one legislation, so my hope is a bit higher to recover it if needed.
PLC is being spun out into an independent entity, the longer term goal is for it to operate somewhat similar to ICANN. Its code is easy to run so something else could conceivably replace it. It’s also possible for AT to allow other `did` methods in the future as long as they’re persistent and can be performantly resolved.
DID and handle resolution was the easiest part of ATProto---as the author says, a library can do the job easily. For Ruby it's DIDKit [2]. Where ATProto really threw me was the seeming non-ownership of record types. Bluesky uses "app.bsky.feed.post" for its records, as seen in the article; there seem to be a lot of these record types, but there doesn't seem to be a central index of these like there are for DIDs, or a standard way of documenting them... and as far as I've been able to find, there's no standard method of turning an at:// URI into an http:// URL.
When my app makes a post on behalf of a user, Bluesky only sends an at:// URI back, which I have to convert myself into an http:// URL to Bluesky. I can only do that with string manipulation, and only because I know, externally, what format the URL should be in. There's no canonical resolution.
[1]: https://toucanpost.com [2]: https://github.com/mackuba/didkit
at:// URIs and specific lexicon are not limited to a single app. The NSID (app.bsky.feed.post) has authority based on domain, but Bluesky cannot prevent anyone from reading / writing records of that type.
There are alternative apps that read the same at:// but put them under a different https://...
tl;dr, there is not a 1-1 mapping between at:// and https://, it's 1-N
In my article, I tried to explain how that works and what makes it possible. "Making it possible" is usually a prerequisite to the kind of broad adoption you're talking about.
What I agree about 100% is that "normal" users don't care about any of this. They just want good apps. The interesting thing about Bluesky, in my opinion, and what makes it different from crypto in your analogy, is that the vast majority of Bluesky users are "normies" in that sense. They couldn't care less about "decentralization" and some are even actively against the idea. But the decentralized nature doesn't directly "show up" in the product much, just like it doesn't "show up" when you browse the web and hop between servers. I think that's key to adoption--it needs to "just work" behind the scenes.
Even with having a cache as explained.
Most protocols already support usernames: user@domain. All you need to do is make the part after @ optional like it is for email.