Skip to content

Instantly share code, notes, and snippets.

@bkerley
Created August 18, 2012 21:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bkerley/3389849 to your computer and use it in GitHub Desktop.
Save bkerley/3389849 to your computer and use it in GitHub Desktop.
decentralized microbloggin'

I'm using "microgbloggin'" as a euphemism for Twitter, which is also a company that owns servers and controls how content on those servers is disbursed.

Microbloggin' features:

  • canonical names for status feeds (e.g. BonzoESC on twitter)
  • creating, reading, and deleting statuses
  • creating, reading, and deleting followings
  • creating mentions inline with statuses
  • it's all https (or some caveman plaintext http crap) so making clients is easy

why http

Turnkey caches, proxies, libraries, and the firewall where your behind-the-times friends work support it. So does every smartphone platform worth talking about and blackberry too.

canonical names

You can't do these online without invoking DNS. What a shame!

DNS is a pain in the ass and most people just want to visit a site, so we can't just use bare DNS names, and need URLs with paths.

Canonical names look like http://hypothetical.example/bryce

aliases

URLs with paths are ugly as heck though: "@capotej had duck fat fries this week, they were good" would become "@http://juliocapote.com/ had duck fat fries this week, they were good" and that's terrible.

Aliases aren't globally unique. In case somebody follows two "johns," any given status from them needs to specify which one. To help this out, users are encouraged to have more than one alias. I'd have "bonzoesc," "bryce," "brycekerley," and some other ones.

An individual status has a hash of referred aliases to the originating feed.

authenticity

To enforce authenticity of feeds independent of somebody losing their DNS name we need to cryptographically sign it.

USERS SHOULDN'T HAVE TO DO KEY MANAGEMENT

USERS SHOULDN'T HAVE TO DO KEY MANAGEMENT

USERS SHOULDN'T HAVE TO DO KEY MANAGEMENT

USERS SHOULDN'T HAVE TO DO KEY MANAGEMENT

USERS SHOULDN'T HAVE TO DO KEY MANAGEMENT

USERS SHOULDN'T HAVE TO DO KEY MANAGEMENT

Seriously explain asymmetric cryptography to your parents some time. People want usernames and passwords.

People need OAuth (for making integration trustworthy; sometimes I want to identify myself to apps or have them post on my behalf but not read my statuses or vice versa).

Ideally the private key used to sign the feed is protected by the password and/or oauth tokens. How to do this is out of the scope of this document but I've got ideas…

the status feed

{
	"public_key": "the public key for the feed, should be unique",
	"preferred_alias": "the user's preferred alias",
	"alias_list": [
		"a list of the aliases the user is okay with"
	],
	"user_metadata", {
		"contents": "data about the user such as…",
		"first_name": "merasmus",
		"last_name": "magician",
		"website": "http://example.invalid/"
	},
	"signature", "signature for all of the above",
	"statuses": [
		"list of status entries"
	],
	"endpoints": {
		"follow": "follow endpoint",
		"direct_message": "dm endpoint",
		"mention": "mention endpoint"
	}
}

what is a status?

{
	"public_key": "the public key for the feed this status is from",
	"feed_url": "the url for the originating feed",
	"url": "the url for this status",
	"text": "the text of this status @bonzoesc",
	"timestamp": "the timestamp of this status",
	"in_reply_to": {
		"url": "the url this status is in reply to",
		"signature": "the signature from the status this is a reply to"
	},
	"mentions": {
		"mentions": "url and public_key for the feed i meant with any @mentions",
		"bonzoesc": {"url": "https://example.invalid/bonzoesc", "public_key": "adhjkshjkafsd"}
	},
	"media": "metadata about media or pictures and such",
	"signature": "signature for all of the above",
	"conversation": [
		"optional full statuses participating in this conversation, including signatures"
	]
}

mentions and conversations

When @mentioning somebody, the status needs to include in associated data where that points. This is a hashtable of which @name goes to which feed URL, with the referred feed's public key included.

"mentions": [
  "bonzoesc": {"url": "https://example.invalid/bonzoesc", "public_key": "adhjkshjkafsd"}
]

When participating in a conversation, the previous entry in the conversation can be referred to.

"in_reply_to": {"url": "https://example.invalid/bonzoesc/statuses/123", "signature": "jksdfjklf"}

Optionally, entire statuses from the prior conversation can be enclosed. It's a terrible waste in the main feed or when done recursively, but useful when viewing an individual status, especially when you've been referred to it by a reply_to field.

what is a reposted status?

{
	"public_key": "the public key for the feed this status is from",
	"feed_url": "the url for the originating feed",
	"url": "the url for this repost",
	"repost": "the entire status you're reposting, with public key and signature",
	"timestamp": "the timestamp of this repost",
	"signature": "signature of this repost (including the reposted status above)"
}

status crud

Creating is done by a POST to the feed endpoint. Reading is done by a GET to the feed endpoint or to an individual status's URL.

You can't update statuses, it'll change the signature. If two statuses have the same URL but different signatures, clients are free to make sense of it how they will.

Deleting is done by a DELETE to the individual status's URL. Since statuses are federated around, they can't be directly deleted. Instead, a feed includes a list of signatures of statuses that the user has disowned. Clients have the option of not respecting these, of course.

Live feed updates via websocket or comet or something are definitely possible, as are using webhooks to simplify the process of following somebody.

following

Anti-social following can be done simply by refreshing a feed.

Social following, however, includes lists of who somebody follows and who follows them. It's built out of "Followings:"

what's in a Following

  • public key of the follower
  • URL of the follower's status feed
  • public key of the followee
  • URL of the followee's status feed
  • preferred alias of the follower
  • list of aliases of the follower
  • timestamp of the Following
  • signature of the Following (just the above)
  • optional URL to receive webhooks

The follower POSTs the above Following to the followee's "followers" endpoint. (It's my intent to wear out and ruin these words.) To change the webhook URL or preferred alias,

To see who follows somebody, GET their "followers" endpoint. It returns an unsigned list of Followings.

what's in an unfollowing

  • public key of the follower
  • URL of the follower's status feed
  • public key of the followee
  • URL of the followee's status feed
  • signature of the original Following
  • timestamp of the unfollowing
  • signature of the unfollowing

To unfollow somebody, DELETE the above to their "followers" endpoint. In case of an unscrupulous followee who ignores these, the signatures of the original Following can be published in a "disavowed followings" feed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment