A place to cache linked articles (think custom and personal wayback machine)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.html 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang="fr">
  4. <!-- Has to be within the first 1024 bytes, hence before the `title` element
  5. See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
  6. <meta charset="utf-8">
  7. <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
  8. <!-- The viewport meta is quite crowded and we are responsible for that.
  9. See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
  10. <meta name="viewport" content="width=device-width,initial-scale=1">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>Understanding A Protocol (archive) — David Larlet</title>
  13. <meta name="description" content="Publication mise en cache pour en conserver une trace.">
  14. <!-- That good ol' feed, subscribe :). -->
  15. <link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
  16. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  17. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
  18. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
  19. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
  20. <link rel="manifest" href="/static/david/icons2/site.webmanifest">
  21. <link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
  22. <link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
  23. <meta name="msapplication-TileColor" content="#f7f7f7">
  24. <meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
  25. <meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
  26. <meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
  27. <!-- Is that even respected? Retrospectively? What a shAItshow…
  28. https://neil-clarke.com/block-the-bots-that-feed-ai-models-by-scraping-your-website/ -->
  29. <meta name="robots" content="noai, noimageai">
  30. <!-- Documented, feel free to shoot an email. -->
  31. <link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
  32. <!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
  33. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  34. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  35. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  36. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  37. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  38. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  39. <script>
  40. function toggleTheme(themeName) {
  41. document.documentElement.classList.toggle(
  42. 'forced-dark',
  43. themeName === 'dark'
  44. )
  45. document.documentElement.classList.toggle(
  46. 'forced-light',
  47. themeName === 'light'
  48. )
  49. }
  50. const selectedTheme = localStorage.getItem('theme')
  51. if (selectedTheme !== 'undefined') {
  52. toggleTheme(selectedTheme)
  53. }
  54. </script>
  55. <meta name="robots" content="noindex, nofollow">
  56. <meta content="origin-when-cross-origin" name="referrer">
  57. <!-- Canonical URL for SEO purposes -->
  58. <link rel="canonical" href="https://aeracode.org/2022/12/05/understanding-a-protocol/">
  59. <body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">
  60. <article>
  61. <header>
  62. <h1>Understanding A Protocol</h1>
  63. </header>
  64. <nav>
  65. <p class="center">
  66. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  67. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
  68. </svg> Accueil</a> •
  69. <a href="https://aeracode.org/2022/12/05/understanding-a-protocol/" title="Lien vers le contenu original">Source originale</a>
  70. </p>
  71. </nav>
  72. <hr>
  73. <p>Yesterday I pushed out the <a href="https://docs.jointakahe.org/en/latest/releases/0.5/">0.5.0 release of Takahē</a>,
  74. and while there's plenty left to do, this release is somewhat of a milestone
  75. in its own right, as it essentially marks the point where I've implemented
  76. enough of ActivityPub to shift focus.</p>
  77. <p>With the implementation of image posting in this release, there are now only
  78. a few things left at a <em>protocol</em> level that I know I'm missing:</p>
  79. <ul>
  80. <li>
  81. <p>Custom emoji (these are custom per-server and a mapping of name-to-image
  82. comes with each post)</p>
  83. </li>
  84. <li>
  85. <p>Reply fan-out to the original author's followers</p>
  86. </li>
  87. <li>
  88. <p>Pinned posts on profiles (and collections in general)</p>
  89. </li>
  90. <li>
  91. <p>Shared inbox delivery (to reduce fan-out requests)</p>
  92. </li>
  93. </ul>
  94. <p>My current aim is to get Takahē to a point where a few small communities can
  95. run on it (including takahe.social), and while these are nice,
  96. they are not critical for that. The reply fan-out is probably most important,
  97. but is also the easiest given what we have written already.</p>
  98. <p>Instead, it's now time to shift and focus on stability and efficiency. My
  99. general tactic for big new projects like this is an initial "spike" period,
  100. where I am more focused on pushing out code with a roughly correct architecture
  101. rather than focusing on query efficiency, caching or the like, and to then
  102. shift gears into more of a "polish" period.</p>
  103. <p>Takahē is actually pretty useable for me as a daily driver for
  104. the <a href="https://takahe.social/@takahe@jointakahe.org/">@takahe@jointakahe.org</a>
  105. account - sure, I find a few bugs here or there, but it's honestly not bad.
  106. That means, to me, it's time to shift focus a bit more towards polishing.</p>
  107. <p>The other big missing feature for a community at this point is probably having
  108. mobile app support (which I plan to do by implementing a Mastodon-compatible
  109. client API) and better moderation features (reporting and user blocking,
  110. in addition to the existing server blocking).</p>
  111. <p>So, I'm going to focus on adding those, polishing, and improving efficiency; there's now
  112. quite a few other contributors to the project who have been helping out
  113. with bugfixes, efficiency, and plenty more, which is helping a great deal.</p>
  114. <p>I'll also be sending out a few
  115. invitations to <a href="https://takahe.social">takahe.social</a> to use that as a testbed
  116. as the first small community; nothing like dogfooding your own software to see
  117. what it needs (as well as asking some existing Mastodon admins for their
  118. thoughts, if they are gracious enough to lend me some of their time).</p>
  119. <p>Still, though, getting to this point is quite a big deal - I feel like I've
  120. learned a lot about ActivityPub and its related specifications by implementing
  121. them. So let's talk about it a little bit.</p>
  122. <h2>Fan-Out</h2>
  123. <p>ActivityPub is all about "fan-out" - the process of getting posts from their
  124. authors to their followers. At the basic level, this means one HTTP request
  125. per follower to deliver it to their inbox - but there's some efficiency gains
  126. to be made with "shared inboxes", where you can push things on a per-server
  127. basis rather than per-user.</p>
  128. <p>Obviously, doing this is noisy and takes a lot of requests, and has to be done
  129. as background workers - especially as the server on the other end might be
  130. down when you try and send the message over, and you need to retry.</p>
  131. <p>Plus, whenever you reply to someone, that reply is then sent to every one of
  132. their followers so that it can appear in reply threads. This means there's an
  133. increasing amplification effect as you get more and more followers, and your
  134. server spends a lot of its life just sending request and getting requests from
  135. other servers.</p>
  136. <p>There's other aspects to fan-out, though; there was an
  137. <a href="https://ar.al/2022/11/09/is-the-fediverse-about-to-get-fryed-or-why-every-toot-is-also-a-potential-denial-of-service-attack/">excellent blog post</a>
  138. about that last month that outlines the problems with link previews. See, when
  139. you post a message to a server's inbox, Mastodon (at least) goes and fetches
  140. any image attachments, and tries to generate web previews for any links. If
  141. people have mobile clients, some of those will <em>also</em> try to fetch previews.
  142. This does not end well for unprepared servers - and for those links, they
  143. could just be someone's random blog.</p>
  144. <p>Takahē does not do this prefetching yet - we'll likely never do it for the
  145. link previews (but some clients connected to us will, once there's a client API).
  146. Post attachments and profile images are a different story - we need to at
  147. least proxy those for user privacy, but we can hopefully make it a caching
  148. proxy. If users have their timelines open, there's not a big difference between
  149. a caching proxy and prefetching for the source server, either.</p>
  150. <p>How do we solve this? Well, bundling some of this data into the original post
  151. is one idea; having shared caching proxies split between multiple servers is
  152. another potential one as well.</p>
  153. <p>That brings us, though, to the push-pull of scaling that's at the heart of
  154. ActivityPub.</p>
  155. <h2>Two Axes Of Scaling</h2>
  156. <p>In a previous post about ActivityPub and Takahē, I referred to the fact that
  157. there are two "axes" of scaling available in the protocol:</p>
  158. <ul>
  159. <li>Having more people per server/instance</li>
  160. <li>Running more servers/instances</li>
  161. </ul>
  162. <p>Both of these have their pros and cons, and it's hard to go all in on one of
  163. them - having a million people on one server is difficult to scale for that
  164. individual server (you have to start building it as its own distributed
  165. system), but having a million servers makes the fan-out problem even worse
  166. (say hello to massive prefetching loads and shared inboxes being not very
  167. useful).</p>
  168. <p>It seems to me like a bit of a separation between domain, moderator, and
  169. caching store is needed - Takahē already lets multiple domains be on a single
  170. server, but the server moderation and caching are scoped just to that one server.</p>
  171. <p>I do believe that sharing moderation across domains is a very important scaling
  172. step; this doesn't have to purely be "multiple domains on the same server",
  173. either - I think there's scope for a moderation API where you can have a
  174. team of professional (volunteer or paid) moderators look after multiple
  175. servers.</p>
  176. <p>Sharing caching and previews is also important, though; if there was just ten
  177. or so link preview caches around, and all servers used one of them, then we
  178. still avoid centralisation while massively lowering the load on the target
  179. of links.</p>
  180. <h2>That Transport Layer</h2>
  181. <p>I both love that ActivityPub is all over HTTP, and hate it.</p>
  182. <p>On the plus side, it means there's all manner of pre-existing load balancers,
  183. gateways, frameworks and more at our disposal. Plus, every programming language
  184. on Earth has some way of slinging JSON over HTTP.</p>
  185. <p>On the negative side, it's wildly inefficient. There's a lot of overhead for
  186. each individual call, <code>Accept</code> headers have to be bandied around everywhere,
  187. and there's a lot of HTTP implementation variation that has to be accounted for.</p>
  188. <p>If, magically, I could change it - would I go to something like SMTP, with its
  189. own port and protocol? I'm not entirely sure, to be honest - I do like the ease
  190. of entry with HTTP, and it does mean there's a lot of framing and encoding
  191. already agreed. Maybe HTTP as a base protocol with an optional TCP alternate
  192. for high-traffic servers to talk to each other over.</p>
  193. <p>The one thing I would get rid of, though, is JSON-LD. If you're not aware,
  194. ActivityPub is not just JSON - it's JSON-LD, which has schemas, namespaces,
  195. expanded and compressed forms, transforms, and all manner of other stuff.
  196. You need to transform each message to a canonical form before you parse it!</p>
  197. <p>I get the idea, but I was never an RDF fan (it's just JSON RDF, basically) and
  198. it just makes everything so much more complex. A plain
  199. JSON specification with known keys would have been better, I think, though
  200. I was not there when the spec was written, so I'm sure there's more context
  201. I lack.</p>
  202. <p>I do want to stress, though, that while I am not a huge fan of the transport
  203. layer, I think the object model is quite decent. If we could get
  204. <code>preferredDomain</code> in there along with some proper multi-size image support,
  205. I would be even happier than my usual buoyant self.</p>
  206. <h2>Difference Is Strength</h2>
  207. <p>A virtual Mastodon monopoly is not good for almost anyone, I think - I'm
  208. actually quite excited for Tumblr to implement ActivityPub, because it stands
  209. a chance of forcing protocol changes and improvements to be discussed,
  210. rather than directed almost entirely by one project.</p>
  211. <p>If we can get Takahē to even 5% of active users on the Fediverse, that would
  212. be a significant impact, too. I'm not sure we'll get there, but I do at least
  213. hope the attempt will also place its own bit of pressure on the protocol in
  214. terms of evolving and trying to fix some of the scaling issues we're all
  215. sailing directly towards.</p>
  216. <p>How to do that responsibly is another question - I would ideally like to make
  217. sure we have a server that is designed to easily handle things like DMCA
  218. requests, GDPR requests, and the awful spectre of terrorist content and CSAM.
  219. I'm looking into starting a fund to pay for some legal and compliance
  220. consultations on this front; it's the sort of work that
  221. every admin should not have to do themselves, and I'd love us to have a server
  222. designed to handle the requirements easily, and written guides as to how to do it.</p>
  223. <p>Still, for me, the focus right now is on growing Takahē and hopefully fostering some
  224. communities under its wing, and that means getting stability, efficiency,
  225. and working closely with people who want to use us to run communities. It's
  226. also about slowly fostering a set of people who look after it with sensible
  227. governance, so I'm not needed as a decision-making leader forever.</p>
  228. <p>I'm not yet focused on people migrating servers from Mastodon - supporting
  229. that is eventually on the roadmap, and I've reserved the appropriate URL
  230. patterns so actor/object URLs can move over seamlessly, but it's still a lot
  231. of work, and we're not ready for that quite yet.</p>
  232. <p>If you're interested in helping out with Takahē, do pop over to our
  233. <a href="https://discord.gg/qvQ39tAMvf">Discord</a> or email me at andrew@aeracode.org
  234. and mention what you'd like to help out with - there's a large
  235. <a href="https://docs.jointakahe.org/en/latest/contributing/">number of areas</a> we need
  236. help with, not just coding!</p>
  237. </article>
  238. <hr>
  239. <footer>
  240. <p>
  241. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  242. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
  243. </svg> Accueil</a> •
  244. <a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
  245. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
  246. </svg> Suivre</a> •
  247. <a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
  248. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
  249. </svg> Pro</a> •
  250. <a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
  251. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
  252. </svg> Email</a> •
  253. <abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
  254. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
  255. </svg> Légal</abbr>
  256. </p>
  257. <template id="theme-selector">
  258. <form>
  259. <fieldset>
  260. <legend><svg class="icon icon-brightness-contrast">
  261. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
  262. </svg> Thème</legend>
  263. <label>
  264. <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
  265. </label>
  266. <label>
  267. <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
  268. </label>
  269. <label>
  270. <input type="radio" value="light" name="chosen-color-scheme"> Clair
  271. </label>
  272. </fieldset>
  273. </form>
  274. </template>
  275. </footer>
  276. <script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
  277. <script>
  278. function loadThemeForm(templateName) {
  279. const themeSelectorTemplate = document.querySelector(templateName)
  280. const form = themeSelectorTemplate.content.firstElementChild
  281. themeSelectorTemplate.replaceWith(form)
  282. form.addEventListener('change', (e) => {
  283. const chosenColorScheme = e.target.value
  284. localStorage.setItem('theme', chosenColorScheme)
  285. toggleTheme(chosenColorScheme)
  286. })
  287. const selectedTheme = localStorage.getItem('theme')
  288. if (selectedTheme && selectedTheme !== 'undefined') {
  289. form.querySelector(`[value="${selectedTheme}"]`).checked = true
  290. }
  291. }
  292. const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
  293. window.addEventListener('load', () => {
  294. let hasDarkRules = false
  295. for (const styleSheet of Array.from(document.styleSheets)) {
  296. let mediaRules = []
  297. for (const cssRule of styleSheet.cssRules) {
  298. if (cssRule.type !== CSSRule.MEDIA_RULE) {
  299. continue
  300. }
  301. // WARNING: Safari does not have/supports `conditionText`.
  302. if (cssRule.conditionText) {
  303. if (cssRule.conditionText !== prefersColorSchemeDark) {
  304. continue
  305. }
  306. } else {
  307. if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
  308. continue
  309. }
  310. }
  311. mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
  312. }
  313. // WARNING: do not try to insert a Rule to a styleSheet you are
  314. // currently iterating on, otherwise the browser will be stuck
  315. // in a infinite loop…
  316. for (const mediaRule of mediaRules) {
  317. styleSheet.insertRule(mediaRule.cssText)
  318. hasDarkRules = true
  319. }
  320. }
  321. if (hasDarkRules) {
  322. loadThemeForm('#theme-selector')
  323. }
  324. })
  325. </script>
  326. </body>
  327. </html>