This commit is contained in:
a 2024-09-29 20:32:51 -05:00
parent e7b9116b86
commit 9984b60738
159 changed files with 261 additions and 154 deletions

View file

@ -11,7 +11,8 @@ const WORD_REGEX = /\b(\w*)[\W|\s|\b]?/gm
async function initSearch() {
try {
const response = await fetch("/index.json");
const indexJsonUrl = document.getElementById("base-url").dataset["baseUrl"] + "/index.json";
const response = await fetch(indexJsonUrl);
pagesIndex = await response.json();
searchIndex = lunr(function () {
this.field("title");

View file

@ -0,0 +1,56 @@
+++
title = "re: starting to investigate other protocols"
summary = "The main thing I'm trying to formulate right now is a generic understanding of what is a protocol and what makes up a protocol."
date = "2023-01-02T21:00:00-06:00"
source = "https://socialhub.activitypub.rocks/t/socialwebfoundation-what-do-people-think/4564/13"
inReplyTo = "https://socialhub.activitypub.rocks/t/socialwebfoundation-what-do-people-think/4564/12"
+++
<blockquote cite="https://socialhub.activitypub.rocks/t/socialwebfoundation-what-do-people-think/4564/12">
<p>And from an activist perspective, Id be very loud about starting to investigate other protocols and why youre doing it.</p>
</blockquote>
If anything, the recent developments have definitely gotten me to more seriously revisit some ideas I had a few years back about a multi-protocol approach[^multi-proto-approach] and how best to synthesize several different protocols that have similar or different approaches to certain things. The main thing I'm trying to formulate right now is a generic understanding of what is a protocol and what makes up a protocol. To give an example limited to just 3 "protocols" that mostly work off of from/to semantics, we can look at SMTP, XMPP, and ActivityPub.
- Data format: SMTP is more or less plaintext, XMPP is XML, and ActivityPub is JSON.
- Message payload format: SMTP uses RFC 822 messages, XMPP uses stanzas, and ActivityPub uses AS2 Activities.
- Message semantics: SMTP messages have headers and body content. XMPP stanzas can be message, presence, or information query. ActivityPub activities... are activities. That's it.
So before you even get to the part where you can do anything interesting, you find that ActivityPub is really not much of a protocol. All three of these protocols let you "send and receive", but there's more to communication than just sending and receiving. So, given that, what does ActivityPub *actually* provide?
The best I can describe it right now, ActivityPub provides the following "protocols" layered on top of LDN:
- A protocol for "following". You send a `Follow`, it can trigger an `Accept` or `Reject`, you can `Undo` it later, and there are side effects of being added to `followers`/`following`.
- A protocol for "liking". You send a `Like`, there are side effects of being added to the `likes` collection.
- A protocol for "(re)sharing". You send an `Announce`, there are side effects of being added to the `shares` collection.
Everything else is far too undefined or under-defined to constitute much of a "protocol". Things like Create have "surprisingly few side effects" according to the ActivityPub TR, because they were intended for the C2S API to be able to do basic CRUD and Collection management. But in the fediverse, Create actually has a lot more to it! So if we were to define a basic "social media post" application protocol for the lowest common denominator of most of the current fediverse, then we need to define more than what the ActivityPub spec concerns itself with, just to get to "hello world" levels of functionality. We need to explicitly define the following additional things to get from "AP Create notification" to "social media post" in its most limited form:
- You send a `Create` where the `object` is a `Note`.
- The object MUST have `content` whose value is a string.
- The content MUST conform to some sanitized subset of HTML.
- The object MUST have a `published` whose value is a string containing a timestamp.
- The object MUST have an `attributedTo` whose value is exactly one actor.
- The actor MUST be of type `Person`.
- The actor MUST have a `name` whose value is a string.
- The name MUST be plain text, and will be interpreted as plain text.
- The actor MUST have an `icon` whose value is the URL to a 1:1 image file.
- The actor MUST have a `preferredUsername` whose value is a string.
- The username MUST be unique on the domain.
- The username MUST link back to the actor when querying that actor's domain's WebFinger endpoint for an `acct:` URI formed of the username and the domain.
- The object MUST have `to` or `cc` or both, whose value is an array which contains at least `https://www.w3.org/ns/activitystreams#Public`.
Now, I'm simplifying a bit, so the above has the following caveats:
- Requirements can be relaxed or willfully violated as various needs arise. For example, if an actor is missing an `icon`, the protocol can be modified such that a "default avatar" is assumed instead.
- Requirements can also be added or extended as the protocol matures and develops. For example, support for `inReplyTo`, `attachment`, `tag` can be added over time.
- Protocols may require other protocols or specifications. For example, WebFinger in the above "social media post" protocol.
- Additional protocols would be need to be defined for each use case. For example, a similar protocol for "making a blog post" could be defined using `Create Article`.
- Specifications ideally ought to be followed, but ultimately the real protocol is what implementers end up doing, and the above protocol codifies some mistakes and errors into itself. For example, hard assumptions of actor and object types, hard requirements on the maximum cardinality of properties like `attributedTo`, soft requirements for specifically `https://www.w3.org/ns/activitystreams#Public` instead of `as:Public`. (All of these things represent real incorrect assumptions by real implementers.)
When you put it like this, it becomes clear that if the fediverse wants to continue to make use of ActivityPub, then there are a *lot* of things that need to be explicitly defined as protocols layered[^protocol-layering] on top of ActivityPub. The "implicit protocol of the fediverse" is not sufficiently described by "the ActivityPub specification". We need to standardize and align on common patterns and common protocols for those patterns.
And the challenge here, the issue is, that if we don't do this work at a grassroots level, then Meta will do it for us. (Can you imagine a "developer portal" for "interoperating with Threads"?) Things like the FEP process allow writing up these "micro-protocols", and then after that, the difficult task of cat-herding begins, as you need to get implementers onboard with adhering to these specifications. And of course, we're all mostly doing this in our free time and without access to the resources that larger organizations have or can gain access to. So it's going to be an uphill battle. But whichever "protocol building blocks" we can agree and align upon, let's go for it.
[^multi-proto-approach]: I was specifically looking at a "unified communication" project, which mapped abstract forms of communication like "messaging", "publishing", "discussing", "reading" onto existing protocols like SMTP, XMPP, ActivityPub, IRC, RSS, ATOM, HTTP. There's a risk of ending up with something like Pidgin here, but maybe that's not the worst thing.
[^protocol-layering]: And of course, other protocols and other layerings are possible. Libervia (formerly Salut a Toi) does AS2 with PubSub over XMPP, but offers an "ActivityPub gateway". You could, if you wanted to, send AS2 over an SMTP transport.

View file

@ -156,4 +156,4 @@ the thing is, though, that its really seeming like if we use “syndication
## current thoughts
i wrote a whole thing abt this [here]({{< relref "note-vs-article" >}})
i wrote a whole thing abt this [here](https://trwnh.com/wiki/tech/spec/activitypub/confusion/note-vs-article/)

View file

@ -0,0 +1,7 @@
+++
layout = "search"
url = "search"
name = "Search results"
[_build]
list = "never"
+++

View file

@ -0,0 +1,6 @@
+++
title = "some of my threads out of context"
summary = "mostly a compilation of times i replied to myself on social media or in chat"
+++
[[rejected outtakes]](misc.md)

9
blog.hugo/hugo.toml Normal file
View file

@ -0,0 +1,9 @@
baseURL = 'https://trwnh.com/blog/'
languageCode = 'en-us'
title = '~a blog'
markup.goldmark.renderer.unsafe = true
pagination.pagerSize = 100
[outputs]
home = ["HTML", "JSON"]

View file

@ -1,8 +1,13 @@
{{ define "head" }}
{{ partial "search/search-index.html" . }}
{{ end }}
{{ define "main" }}
<main>
<div class="search-results section">
<header>
<div class="container">
{{ partial "search/search-form.html" . }}
<h2 class="search-results__title"><span id="results-count"></span> <span id="results-count-text"></span> for "<span id="results-query"></span>"</h2>
</div>
</header>
@ -18,5 +23,4 @@
<style>
a[href="#top"] {display: none;}
</style>
{{ partial "search/search-index.html" . }}
{{ end }}

View file

@ -0,0 +1,4 @@
<script src="https://unpkg.com/lunr/lunr.js"></script>
{{ $js := resources.Get "scripts/search.js" | minify | fingerprint }}
<script defer type="text/javascript" src="{{ $js.Permalink }}" integrity="{{ $js.Data.Integrity }}"></script>
<div id="base-url" data-base-url="{{.Site.BaseURL}}"></div>

View file

@ -0,0 +1,153 @@
{{- $title := or .Title $.File.ContentBaseName }}
{{- $cover := ($.Resources.ByType "image").GetMatch "{*opengraph*}" -}}
{{ $icon := resources.GetMatch (default "" .Site.Params.icon) -}}
{{/*=== title ===*/}}
{{ "<!-- text -->" | safeHTML }}
{{- with .Site.Title }}
<meta name="application-name" property="og:site_name" content="{{ . }}" />
{{- end -}}
{{- if .IsHome}}
{{- with or .Params.name .Site.Title }}
<title>{{ . }}</title>
<meta property="og:title" name="twitter:title" itemprop="name" content="{{ . }}" />
{{- end }}
{{- else }}
<title>{{ or .Params.name (print $title " • " .Site.Title) }}</title>
<meta property="og:title" name="twitter:title" itemprop="name" content="{{ or .Params.name $title }}" />
{{- end -}}
{{/*=== description ===*/}}
{{- with or .Description .Summary .Site.Params.description }}
<meta name="description" itemprop="description" property="og:description" content="{{ . }}" />
<meta name="twitter:description" content="{{ . }}" />
{{- end }}
{{ "<!-- url -->" | safeHTML }}
{{- with .Permalink | absURL}}
<base href="{{ . }}" />
<link rel="canonical" href="{{ or $.Params.canonical . }}" />
<meta name="url" property="og:url" itemprop="url" content="{{ . }}" />
<meta name="twitter:url" content="{{ . }}" />
{{- end -}}
{{/*=== image ===*/}}
{{- $staticIcon := "icon.png" | absURL -}}
{{- with or $cover $icon }}
{{ "<!-- image -->" | safeHTML }}
<meta property="og:image" itemprop="image" content="{{ .Permalink | absURL }}" />
{{- with .Width }}
<meta property="og:image:width" content="{{ . }}" />
{{- end }}
{{- with .Height }}
<meta property="og:image:height" content="{{ . }}" />
{{- end }}
<meta name="twitter:image" content="{{ .Permalink | absURL }}" />
<meta name="twitter:image:src" content="{{ .Permalink | absURL }}" />
{{- else }}
{{ "<!-- image -->" | safeHTML }}
<meta property="og:image" itemprop="image" content="{{ $staticIcon }}" />
<meta name="twitter:image" content="{{ $staticIcon }}" />
<meta name="twitter:image:src" content="{{ $staticIcon }}" />
{{- end -}}
{{/*=== extra params? ===*/}}
{{- with .Params.audio }}<meta property="og:audio" content="{{ . }}" />{{ end }}
{{- with .Params.locale }}<meta property="og:locale" content="{{ . }}" />{{ end }}
{{- with .Params.videos }}{{- range . }}
<meta property="og:video" content="{{ . | absURL }}" />
{{ end }}{{ end }}
{{/*=== article ===*/}}
{{ with or .Params.author .Site.Params.author -}}
{{ "<!-- author -->" | safeHTML }}
<meta name="author" property="article:author" content="{{ . }}" />
{{- end }}
<meta property="article:publisher" content="{{ .Site.BaseURL }}" />
{{ "<!-- time -->" | safeHTML }}
{{ with .Date -}}
<meta property="article:published_time" itemprop="datePublished" content={{ .Format "2006-01-02T03:04:05Z" | safeHTML }} />
{{ end -}}
{{ with .Lastmod -}}
<meta property="article:modified_time" itemprop="dateModified" content={{ .Format "2006-01-02T03:04:05Z" | safeHTML }} />
{{ end -}}
{{/*=== section and keywords ===*/}}
{{- "<!-- keywords -->" | safeHTML }}
{{ with.Params.category -}}
<meta property="article:section" content="{{ . }}" />
{{- end -}}
{{- with .Params.tags }}
<meta property="article:tag" itemprop="keywords" name="keywords" content='{{ delimit . " "}}' />
{{- end -}}
{{- if isset .Params "date" }}
{{ "<!-- article metadata -->" | safeHTML }}
<meta property="og:type" content="article" />
<meta itemprop="wordCount" content="{{ .WordCount }}" />
<script defer type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "Article",
"headline": {{ $title }},
"author": {
"@type": "Person",
"name": {{ or .Params.author .Site.Params.author }},
"url": {{ .Site.BaseURL }}
},
"datePublished": {{ .Date.UTC.Format "2006-01-02T03:04:05Z" }},
"description": {{ (or .Description .Summary) | plainify }},
"wordCount": {{ .WordCount }},
"mainEntityOfPage": {{.Permalink}},
"dateModified": "{{ .Lastmod.UTC.Format "2006-01-02T03:04:05Z" }}",
"image": {
"@type": "ImageObject",
"url": {{ with or $cover $icon }}{{ .Permalink | absURL }}{{ end }}
},
"publisher": {
"@type": "WebSite",
"name": {{ .Site.Title }},
"url": {{ .Site.BaseURL }},
"image": {
"@type": "ImageObject",
"url": {{with $icon}}{{.Permalink}}{{else}}{{$staticIcon}}{{end}}
}
}
}
</script>
{{- else }}
{{ "<!-- webpage metadata -->" | safeHTML }}
<meta property="og:type" content="website" />
<script defer type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "WebPage",
"name": {{ .Title }},
"url": {{ .Permalink }},
"description": {{ (or .Description .Summary) | plainify }},
"image": {
"@type": "ImageObject",
"url": {{with $icon}}{{.Permalink}}{{else}}{{$staticIcon}}{{end}}
}
}
</script>
{{- end -}}
{{/* auxiliary info */}}
{{ "<!-- site presentation -->" | safeHTML }}
{{ with $icon }}
<link rel="shortcut icon" href='{{ .Permalink }}' sizes="{{.Width}}x{{.Height}}" />
{{- else -}}
<link rel="shortcut icon" href='{{ $staticIcon }}' sizes="512x512" />
{{- end }}
<meta name="theme-color" content="#ffffff" />
<meta name="msapplication-TileColor" content="#ffffff" />
<link rel="sitemap" type="application/xml" title="Sitemap" href="{{ .Site.BaseURL }}sitemap.xml" />
{{ with .OutputFormats.Get "RSS" -}}
<link href="{{ .Permalink }}" rel="feed alternate" type="application/rss+xml" title="{{ $.Site.Title }}" />
{{- end -}}
{{/* robots */}}
{{ "<!-- robots -->" | safeHTML }}
<meta name="robots" content="index,follow" />
<meta name="googlebot" content="index,follow" />

View file

@ -1,7 +1,7 @@
<header class="site-header">
<div class="container">
<div class='hang-left'>
<a href="/" class="site-masthead">
<a href="{{.Site.BaseURL}}" class="site-masthead">
{{ with .Site.Params.masthead.image }}
<img class="site-masthead__image" height="32" src="{{.}}">
{{ end }}

View file

@ -0,0 +1,6 @@
<aside class="toc section">
<details open>
<summary class="toc-title">Contents</summary>
{{ .Page.TableOfContents }}
</details>
</aside>

Some files were not shown because too many files have changed in this diff Show more