From 64400c3faf62e42d314eff17b7c0468f151689ee Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Thu, 28 Mar 2024 14:22:47 -1000 Subject: [PATCH 1/8] Begin work on new Microblogging extension --- docs/extensions/microblogging.md | 66 +++++++++++++++++++++++++++++++ docs/objects/announce.md | 45 +-------------------- docs/public/assets/boosting.png | Bin 0 -> 43568 bytes docs/spec.md | 6 ++- 4 files changed, 72 insertions(+), 45 deletions(-) create mode 100644 docs/extensions/microblogging.md create mode 100644 docs/public/assets/boosting.png diff --git a/docs/extensions/microblogging.md b/docs/extensions/microblogging.md new file mode 100644 index 0000000..4c50ccc --- /dev/null +++ b/docs/extensions/microblogging.md @@ -0,0 +1,66 @@ +# Microblogging + +> [!WARNING] +> +> Before Lysand 3.0, microblogging was directly integrated into the core spec. As of Lysand 3.0, microblogging has been moved to an extension, as part of a larger effort to modularization. This document describes the new microblogging extension. + +The Microblogging extension allows users to perform certain tasks related to microblogging, such as "boosting" (reposting) posts. + +## Announce + +The `Announce` action signifies a user's intent to broadcast or share an object with their followers. This action is analogous to the "retweet" function on Twitter. + + +`Announce`s can of course be deleted ("unboosting") with a classic [Undo](../objects/undo) object. + +Here's an example of an `Announce` action: + +```json5 +{ + "id": "3e7e4750-afd4-4d99-a256-02f0710a0520", + "type": "Extension", + "extension_type": "org.lysand:microblogging/Announce", + "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", + "uri": "https://example.com/actions/3e7e4750-afd4-4d99-a256-02f0710a0520", + "created_at": "2021-01-01T00:00:00.000Z", + "object": "https://example.com/publications/f08a124e-fe90-439e-8be4-15a428a72a19" +} +``` + +### Fields + +#### Author + +| Name | Type | Required | +| :----- | :----- | :------- | +| author | String | Yes | + +URI of the [Actor](../objects/actors) who initiated the action. + +#### Object + +| Name | Type | Required | +| :----- | :----- | :------- | +| object | String | Yes | + +URI of the object being announced. Must be of type [Note](../objects/note) + +### Implementation + +When a [Note](../objects/note) object is announced, the client **SHOULD** display the original note with an indicator that it has been announced. The client **SHOULD** also display the number of times the note has been announced, such as a number next to a small icon like such on [Mastodon](https://joinmastodon.org/): + +![Bottom graphics of a Mastodon post, including a "boosting" icon with numbers next to it](/assets/boosting.png) + +Furthermore, users should be notified when their notes are announced by other users. + + +## Types + +```typescript +interface Announce extends Entity { + type: "Announce"; + author: string; + object: string; +} +``` + diff --git a/docs/objects/announce.md b/docs/objects/announce.md index 3d7da0a..8c31fdb 100644 --- a/docs/objects/announce.md +++ b/docs/objects/announce.md @@ -1,44 +1 @@ -# Announce - -The `Announce` action signifies a user's intent to broadcast or share an object with their followers. This action is analogous to the "retweet" function on Twitter. - -Here's an example of an `Announce` action: - -```json5 -{ - "type": "Announce", - "id": "3e7e4750-afd4-4d99-a256-02f0710a0520", - "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", - "uri": "https://example.com/actions/3e7e4750-afd4-4d99-a256-02f0710a0520", - "created_at": "2021-01-01T00:00:00.000Z", - "object": "https://example.com/publications/f08a124e-fe90-439e-8be4-15a428a72a19" -} -``` - -## Fields - -### Author - -| Name | Type | Required | -| :----- | :----- | :------- | -| author | String | Yes | - -URI of the [Actor](./actors) who initiated the action. - -### Object - -| Name | Type | Required | -| :----- | :----- | :------- | -| object | String | Yes | - -URI of the object being announced. Must be of type [Note](./note) - -## Types - -```typescript -interface Announce extends Entity { - type: "Announce"; - author: string; - object: string; -} -``` \ No newline at end of file +This page has been moved to the [Microblogging Extension](../extensions/microblogging#announce). \ No newline at end of file diff --git a/docs/public/assets/boosting.png b/docs/public/assets/boosting.png new file mode 100644 index 0000000000000000000000000000000000000000..94fd6e8f63f850d5b73229179820784f7b684c78 GIT binary patch literal 43568 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 G`2H90hN5Z! literal 0 HcmV?d00001 diff --git a/docs/spec.md b/docs/spec.md index f8e172a..c09ae5e 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -1,7 +1,11 @@ # Introduction > [!NOTE] -> You are looking at the documentation for `Lysand 2.0`, released in March 2024 after revision of the original `Lysand 1.0` specification published in September 2023. +> You are looking at the documentation for `Lysand 3.0`, currently in development. +> +> Previous versions: +> - `Lysand 2.0`, released in March 2024. +> - `Lysand 1.0`, published in September 2023. The Lysand Protocol is designed as a communication medium for federated applications, leveraging the HTTP stack. Its simplicity ensures ease of implementation and comprehension. From e14cc8589036a25dd740f4d2e190bf0d08f5f19c Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Mon, 22 Apr 2024 13:55:10 -1000 Subject: [PATCH 2/8] docs: :sparkles: Add new Groups system --- .vitepress/config.mts | 233 +++++++++++++++++-------------- biome.json | 20 +++ bun.lockb | Bin 61216 -> 64788 bytes docs/extensions/microblogging.md | 12 +- docs/groups.md | 69 +++++++++ package.json | 20 +-- 6 files changed, 237 insertions(+), 117 deletions(-) create mode 100644 biome.json create mode 100644 docs/groups.md diff --git a/.vitepress/config.mts b/.vitepress/config.mts index eb7d8c4..10e6e43 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -1,108 +1,137 @@ -import { defineConfig } from 'vitepress' +import { defineConfig } from "vitepress"; // https://vitepress.dev/reference/site-config export default defineConfig({ - title: "Lysand Documentation", - description: "Documentation for Lysand, a new federated protocol", - srcDir: 'docs', - themeConfig: { - // https://vitepress.dev/reference/default-theme-config - nav: [ - { text: 'Home', link: '/' }, - { text: 'Specification', link: '/spec' }, - ], + title: "Lysand Documentation", + description: "Documentation for Lysand, a new federated protocol", + srcDir: "docs", + themeConfig: { + // https://vitepress.dev/reference/default-theme-config + nav: [ + { text: "Home", link: "/" }, + { text: "Specification", link: "/spec" }, + ], - sidebar: [ - { - text: 'Spec Details', - items: [ - { text: 'Spec', link: '/spec' }, - ] - }, - { - text: "Structures", - items: [ - { text: "Content Format", link: '/structures/content-format' }, - { text: "Custom Emoji", link: '/structures/custom-emoji' }, - { text: "Collection", link: '/structures/collection' }, - ] - }, - { - text: "Cryptography", - items: [ - { text: "Keys", link: "/cryptography/keys" }, - { text: "Signing", link: "/cryptography/signing" }, - ] - }, - { - text: "Objects", - link: "/objects", - items: [ - { - text: "Publications", link: "/objects/publications", items: [ - { text: "Note", link: "/objects/note" }, - { text: "Patch", link: "/objects/patch" }, - ] - }, - { - text: "Actors", link: "/objects/actors", items: [ - { text: "User", link: "/objects/user" }, - ] - }, - { - text: "Actions", link: "/objects/actions", items: [ - { text: "Like", link: "/objects/like" }, - { text: "Dislike", link: "/objects/dislike" }, - { text: "Follow", link: "/objects/follow" }, - { text: "FollowAccept", link: "/objects/follow-accept" }, - { text: "FollowReject", link: "/objects/follow-reject" }, - { text: "Announce", link: "/objects/announce" }, - { text: "Undo", link: "/objects/undo" }, - ] - }, - { text: "Server Metadata", link: "/objects/server-metadata" } - ] - }, - { - text: "Federation", - items: [ - { text: "Endpoints", link: "/federation/endpoints" }, - { text: "User Discovery", link: "/federation/user-discovery" }, - { text: "Server Actors", link: "/federation/server-actor" }, - ] - }, - { - text: "Extensions", - link: "/extensions", - items: [ - { text: "Custom Emojis", link: "/extensions/custom-emojis" }, - { text: "Reactions", link: "/extensions/reactions" }, - { text: "Polls", link: "/extensions/polls" }, - { text: "Is Cat", link: "/extensions/is-cat" }, - { text: "Server Endorsements", link: "/extensions/server-endorsement" }, - { text: "Events", link: "/extensions/events" }, - { text: "Reports", link: "/extensions/reports" }, - { text: "Vanity", link: "/extensions/vanity" }, - ] - } - ], + sidebar: [ + { + text: "Spec Details", + items: [{ text: "Spec", link: "/spec" }], + }, + { + text: "Structures", + items: [ + { + text: "Content Format", + link: "/structures/content-format", + }, + { text: "Custom Emoji", link: "/structures/custom-emoji" }, + { text: "Collection", link: "/structures/collection" }, + ], + }, + { + text: "Groups", + link: "/groups", + }, + { + text: "Cryptography", + items: [ + { text: "Keys", link: "/cryptography/keys" }, + { text: "Signing", link: "/cryptography/signing" }, + ], + }, + { + text: "Objects", + link: "/objects", + items: [ + { + text: "Publications", + link: "/objects/publications", + items: [ + { text: "Note", link: "/objects/note" }, + { text: "Patch", link: "/objects/patch" }, + ], + }, + { + text: "Actors", + link: "/objects/actors", + items: [{ text: "User", link: "/objects/user" }], + }, + { + text: "Actions", + link: "/objects/actions", + items: [ + { text: "Like", link: "/objects/like" }, + { text: "Dislike", link: "/objects/dislike" }, + { text: "Follow", link: "/objects/follow" }, + { + text: "FollowAccept", + link: "/objects/follow-accept", + }, + { + text: "FollowReject", + link: "/objects/follow-reject", + }, + { text: "Announce", link: "/objects/announce" }, + { text: "Undo", link: "/objects/undo" }, + ], + }, + { + text: "Server Metadata", + link: "/objects/server-metadata", + }, + ], + }, + { + text: "Federation", + items: [ + { text: "Endpoints", link: "/federation/endpoints" }, + { + text: "User Discovery", + link: "/federation/user-discovery", + }, + { text: "Server Actors", link: "/federation/server-actor" }, + ], + }, + { + text: "Extensions", + link: "/extensions", + items: [ + { + text: "Custom Emojis", + link: "/extensions/custom-emojis", + }, + { + text: "Microblogging", + link: "/extensions/microblogging", + }, + { text: "Reactions", link: "/extensions/reactions" }, + { text: "Polls", link: "/extensions/polls" }, + { text: "Is Cat", link: "/extensions/is-cat" }, + { + text: "Server Endorsements", + link: "/extensions/server-endorsement", + }, + { text: "Events", link: "/extensions/events" }, + { text: "Reports", link: "/extensions/reports" }, + { text: "Vanity", link: "/extensions/vanity" }, + ], + }, + ], - socialLinks: [ - { icon: 'github', link: 'https://github.com/lysand-org/' } - ], - search: { - provider: "local", + socialLinks: [ + { icon: "github", link: "https://github.com/lysand-org/" }, + ], + search: { + provider: "local", + }, + editLink: { + pattern: "https://github.com/lysand-org/docs/edit/main/docs/:path", + }, + logo: "/logo.png", }, - editLink: { - pattern: "https://github.com/lysand-org/docs/edit/main/docs/:path" - }, - logo: "/logo.png", - }, - lastUpdated: true, - cleanUrls: true, - titleTemplate: ":title · Lysand 2.0 Docs", - head: [ - ['link', { rel: 'icon', href: '/favicon.png', type: 'image/png' }] - ], - lang: 'en-US', -}) + lastUpdated: true, + cleanUrls: true, + titleTemplate: ":title · Lysand 2.0 Docs", + head: [["link", { rel: "icon", href: "/favicon.png", type: "image/png" }]], + lang: "en-US", +}); diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..ef6b12d --- /dev/null +++ b/biome.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.6.4/schema.json", + "organizeImports": { + "enabled": true, + "ignore": ["node_modules", "dist", "cache"] + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + }, + "ignore": ["node_modules", "dist", "cache"] + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 4, + "ignore": ["node_modules", "dist", "cache"] + } +} diff --git a/bun.lockb b/bun.lockb index d8a9601a4d7f8b8520656d09f55ebb38307a192a..e9a9c040931ce6de1da67bca355faa9c84b0aa52 100755 GIT binary patch delta 10469 zcmeHNcU)9g+P)VU1QAe*I1WY#MG>h(5kW@O#1e&Au^Uv-K@fq#STlphh^vX3qcLCu z6BVo|8e1%=F=mYg{cv5Q5VMM60xCw0in`Bx3j={~cazPxzweK|zj^QTp0}NIPkC=S zlUruG;+g3(U$0e%(*3XBIo*Eq#&aX5FYmGP$xVJy^A&cMGyDB8)UoE1weQz*!tvSi z*!JG5^2CDiYy;Mk;|$YM(sdKk)49<+$62F1XnCHKex(V=IiT2% z3ot^Gw*|hA@^cH0YY)68;SnJDtryCA&M+SgRWKQd78ynX>56{cUGeGTGqgz)xoC6? z^-MTU_P`E6>On_I&P(NLbSLSr0US(W0m4fan5W0QKl)Lvmc&6yL;j z?jZzJ*2RqtLO^c74fS%3r7CX9cXHl;56$hlk zM_fazfizPdLQnp$Pi>tj1NQ?3mkOCJ1sl}^+RIvd_ z6;GD*gGgUAKyk^e&xSQg`Kc#7cMM(Hecq0KKe!#tiEq<;MdAsKPk}|^)z|Lbda9ms z)6LZ6@U}i0=h!amZ6B`sq(%@9!JmBjNNv%b#U?H=o04Aybs@jX`5?!6)R}2 zQD~7rd$8o@;TBuLMWA+=__N%OmP~7<;k{Ual}1s7eAl0Cw+dIZM237*;D*(4JHYi3 zwaBMkiR1e*FKdnE5|n!&qzMbK4&~3W0&A+a(psa4MMmu<_-q3wM&yxAdkEe=S*49e zF%xA$!=GVVTMe3Bfb#-YiE}ygYN_EpnYN`y;f-ZJiY2!US9}0&gus>8$+}{Z4i;n| zf*T`ncfn}|Zg2~Zixap#;6!aJYmSQ-WYfWo6S&ekE(jwk+ARksYVU&+>+Oqyk0lR2 zmuVd|{CBJXXFFDj^El?^s8PIwIp2%Pm$SyQ8k#PG=7B>f#vS zFBc8(%(OW7X9X@Ag#o!>B-`#1uDA+rxWEOv$g(Bi1_`n?I{=*Mx)K~_5o9-H8Kn^~jbaHhd>Bi12)FzSTu)&nQXN7S7Rc;< zX|nJGSwSZa|0%2Nq*0uM6qBG+IKPBxy)_CyU#cP5J6!QDxIqH<4LDpKWR8B+65_^z z8!mABz>O9-dklNDz{P>Y@kyTI)PhgpfH z-Ct@*k!hsEh)PkLm4rnB;g|uJ*aV}Amj_-XbO?M=}A4HQ(-G7yc; zYLGQ3A4JC=k7E5oV4A5%glhhSDAoUORZKm0Olo+2q^>Upk^TgT4nhmi8ITP~|5u!7 zwp|0!(G*gk>mb513Cn@x_XCJ3xG9xy18HvjD3z;$DE=z}kl ztNxOEqabg^gzJkF9|aZUWDn`}M#T(tEsw<960zv6Dj#O^Tz{_Ze5T9#!W6p)@2<#O zcO+FG^>SQWUCHpmva->Cn>_aPrlD!N3-8bTIC zb2Jn`3ktkOjtVsU#;xa`Uy}SBgTMP&;XEziy_{y|*)48w?eggxW#Na-6Rs$y_}#hO z-s0^?^G3WJQEif&o^?NSe#YRT-Sl5=I$hR!sEH6*Z1LLqfdjbm+r0PE;h9Hb1FYO~ zN@iuhQ{LM1P{Az7)y6z>rBhR1Ds4o4Hcd{za zsn_6j_2ZUX&MTZ`a&41-#>Ss-u1zgJeZph(L)XklrF`*$wj)cPcKyPAvf)IO!#9@~ zZ#tRTYM=Q}OM2hAvtnY85l^zYZ;mZAlNwBSzxDM47u5XdVwm~huP%$0KKg<`IM*f9 zJ9%mR=UMtqw~8yG3a4%e?D%sx>v13vh%IKgD)^#kqSb2keKA0{=}fS7s4xO&d4#?CY`s#C(;*MF?4t(n!v>#{E4 zpkIvTy?~eto1a;3s51YlXKBXlg0QNNr`+u_>~*8|J+t(yS#tl=0|Sd%Ox=1>>S7AK z!5Ek`yPh(!?8dWJJ63jGX7@ztZZc$#Pv~u>MTKkkb(!n!Y%YEgVv=D{-P@w;YwmH_ zV{iV{!Xal%TlD=)^mTQio#{mfJA8n0!t0WmB|W>~UTJV*15;x7+bl2TsKOlY4UTMA z+A6a6IMu>rRx`FEt*u}$e{FXv3P_#J^FxZZr_DFzXR(0k_Pi4dNPWU`(^?4PaVA9< z(w6b$Wj$V-k{pkkZ18esiO83VCeQBI4*COp^Y5iD>$QP>`Du5$kH35+9(2XCKr~@Nif?U$Iv)GL6 zHm}j6(lgL=P%Y>M=q2bCh~wEu*4Ens=mXF^(0tJQpamd$9iX?Q zuAp$n=h*wS1xGJ<_^w3XQH5N65_k$k5B*u7MW8={7PF|FQHo@6Jy~8(_#1=4(G}5C zjvvS$g!f?KMGvq1!t>u_-~$jnoqh{C3pxin54r#5FpXg?yZF+&#|H z)^~~_7Sqije`mEYAqgGwBz!+3bM2_bk>f1*u>rmTzPPeDQERA}Z#831kRi&1AFK8a zAx#Q9yI!fHVaAJ%;qJ!VkZs>ZIzb=c8|aJvSj6~TCBKfTa+Rt=SYfaXf3ZK+A^Pm$ z^{@)|^(U+2EGAbOd_bm&K0GCq8cV z$w3od?HlA97{GDzmRk1xp+k2*xVg!wDPY~;FUESsQa7j@#1-Xh*bUV5m|1_OR>_-f z$Mw-SQpyjFMRNmjp%_SNl>KAAQzVkso^Q z?H1<1?_~uWUHMDw%*IT96dSNf%}-{To0R-~mb%lP?bu|l61V0!!@!*C>h8HEFU|NM z-vIouEZO-@%3ygbugJq}jQ^bl_C~$D+1KU%>=>Jt3rmcewyfP|rApp9s)+Kic+|7k zNuz!w8@O4C#5V<2^48*zvZHwmf6i=cwEB{*hgB(yDztYMTO@B!+Wt@y(7EZ8qxVO`$f= zo&^m0b4a{VQ^5}BD^>D#pns2?ar?||O^kXQ_5c&vommwqRq|${_CQ2_ka=>2(W)QQ z6exq`&BqM|?Z)(S+X*#SiY8J8&5n0&J#MZ956ElPe4+qy-Kc~=fTg*^p7m-%c}<5OuI&JWqjt?J-a z$mGp&4OcJQ%-S&Q)Eoz%QZOBPlBV*tcShORx^y#Ywz3!S-@^j7DfuJpt!+x5VJb1p zJej1}lHK;(s}B5Ikl@1&?W79PQbV5qG{55E7cKcjwtSnbv%G_vFz}pbnqBf4EOdWb z=>D9!Gds7fjnv@VOtpPLu)KZxWo*sai4!JGq9g`mBvE;T^-uj<_MY*2Ipqt?Qh%(R z5p3=D%73sJ5A9ejEJOQd!IWM&T8v75JzKm}sgifh&2<+iCY^hTi5284T3usDcPfLM zT6Cgb-h*Gf^u?NeZmsSbJtLTPp;9I9i2A0MjHv0r=I(BK$%y)Bwre*n zlQTFQ*sa}aK8q=f)FxJ)S#(hwmAs#OytUQGe5rnb2_Jy_s~Qt0j%5}p`Mzv*ky1Mu zPat$3ZtLjLD${N7w+{R;Na)Tj?N4*dZeJ-=E<3rxsL{cK9$;s;34f+tI3&TSk@tw7 zewSf3rYbVTfsgFw65tZyqCU^s?NMR{Z{4R<$ve=yBc7-35Am)w!DK~##o};bQ}!rT z@{VCa`<+|zQ!u17g7O~-ZqBXVQj;BV z-l+LKKCUcozmgZ~l+JV6&izWguz8Q#zPvYY)X0ATkazEm8u>2* z^8UV2Bmarumh=w*Nizx+$^SEu|0G~^lK+Vy|Bb+?k^ie8|Ixsx=^}l!nQ?+$+~2F; zIow02H)lWU)yDPizAaZ#wnus3%2iV@v>O##g|aQmKU6Z_YHtImHy zlGf*4?NoK3&y0|uCZus`$-k0Mj7x(!Rd z2ZA=Rr%EJiag?NPtKXrLLw%9#<6XZ7gWYY<1i{x#H-$Tjq>Uqjtokt(Pw qlQmxSFt@OjghMwdW3cXxUK0)U-i_n^T6*U+$M+BXJBJmgE&Ds~c75Lf delta 8443 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 [!WARNING] > -> Before Lysand 3.0, microblogging was directly integrated into the core spec. As of Lysand 3.0, microblogging has been moved to an extension, as part of a larger effort to modularization. This document describes the new microblogging extension. +> Before Lysand 3.0, microblogging was directly integrated into the core spec. As of Lysand 3.0, microblogging has been moved to an extension, as part of a larger modularization effort. This document describes the new microblogging extension. The Microblogging extension allows users to perform certain tasks related to microblogging, such as "boosting" (reposting) posts. @@ -35,7 +35,7 @@ Here's an example of an `Announce` action: | :----- | :----- | :------- | | author | String | Yes | -URI of the [Actor](../objects/actors) who initiated the action. +URI of the [Actor](./actors) who initiated the action. #### Object @@ -43,9 +43,9 @@ URI of the [Actor](../objects/actors) who initiated the action. | :----- | :----- | :------- | | object | String | Yes | -URI of the object being announced. Must be of type [Note](../objects/note) +URI of the object being announced. Must be of type [Note](./note) -### Implementation +#### Implementation When a [Note](../objects/note) object is announced, the client **SHOULD** display the original note with an indicator that it has been announced. The client **SHOULD** also display the number of times the note has been announced, such as a number next to a small icon like such on [Mastodon](https://joinmastodon.org/): @@ -57,8 +57,8 @@ Furthermore, users should be notified when their notes are announced by other us ## Types ```typescript -interface Announce extends Entity { - type: "Announce"; +interface Announce extends Extension { + extension_type: "org.lysand:microblogging/Announce"; author: string; object: string; } diff --git a/docs/groups.md b/docs/groups.md new file mode 100644 index 0000000..f212bdb --- /dev/null +++ b/docs/groups.md @@ -0,0 +1,69 @@ +# Groups + +Groups are a way to organize the visibility of objects on the server. Groups can be thought of as something similar to a Matrix room or a Discord channel, while also being similar to a Mastodon list. + +> [!NOTE] +> Groups replace the old "visibility" system for Notes, which was designed for a microblogging context. Groups are more flexible and can be used for any application. +> +> Notes can still use visibility in cases where groups are not needed with the `followers` and `public` group URIs. + +# Group Entity + +The group entity encapsulates the details of a group. It adheres to the following structure: + +```json5 +{ + "type": "Group", + "id": "ed480922-b095-4f09-9da5-c995be8f5960", + "uri": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960", + "name": { + "text/html": { + "content": "The Woozy fan club" + } + }, + "description": { + "text/plain": { + "content": "A group for fans of the Woozy emoji." + } + }, + "members": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960/members", +} +``` + +## Fields + +### Name + +| Name | Type | Required | +| :--- | :------------ | :------- | +| name | ContentFormat | No | + +The name of the group. This field is optional. Can contain custom emojis, like most other text fields. + +### Description + +| Name | Type | Required | +| :---------- | :------------ | :------- | +| description | ContentFormat | No | + +A description of the group. This field is optional. Can contain custom emojis, like most other text fields. + +### Members + +| Name | Type | Required | +| :------ | :----- | :------- | +| members | String | Yes | + +The URI of the group's members list. This field is required. Resolves to a [Collection](./structures/collection) of [User](./objects/user) objects. + +## Implementation + +`Note` objects can be posted to groups by setting the `group` field to the URI of the group. If there is no `group` field, the note is posted to whoever is mentioned in the `to` field. + +Other values for `group` are: +- `public` for public notes, which can be seen by anyone. +- `followers` for notes that can be seen by the author's followers only. + +If the `group` field is empty, and nobody is mentioned in the `to` field, the note is only visible to the author. + +--> To finish \ No newline at end of file diff --git a/package.json b/package.json index 1e5ec50..952c10e 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,12 @@ { - "scripts": { - "docs:dev": "vitepress dev", - "docs:build": "vitepress build", - "docs:preview": "vitepress preview" - }, - "devDependencies": { - "vitepress": "^1.1.0" - } -} \ No newline at end of file + "scripts": { + "docs:dev": "vitepress dev", + "docs:build": "vitepress build", + "docs:preview": "vitepress preview" + }, + "devDependencies": { + "@biomejs/biome": "^1.7.1", + "vitepress": "^1.1.0" + }, + "trustedDependencies": ["@biomejs/biome"] +} From 33b862e82d60ae6fde476f43009576a83f1145cc Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Mon, 29 Apr 2024 11:58:47 -1000 Subject: [PATCH 3/8] refactor: :art: Refactor docs more, add new security section --- .vitepress/config.mts | 20 ++- docs/cryptography/signing.md | 195 ------------------------ docs/groups.md | 4 +- docs/index.md | 10 +- docs/objects.md | 16 +- docs/objects/user.md | 4 +- docs/public/favicon.png | Bin 13649 -> 4744 bytes docs/public/logo.png | Bin 44108 -> 0 bytes docs/security/api.md | 116 ++++++++++++++ docs/{cryptography => security}/keys.md | 12 +- docs/security/signing.md | 184 ++++++++++++++++++++++ docs/spec.md | 52 +++---- 12 files changed, 354 insertions(+), 259 deletions(-) delete mode 100644 docs/cryptography/signing.md delete mode 100644 docs/public/logo.png create mode 100644 docs/security/api.md rename docs/{cryptography => security}/keys.md (78%) create mode 100644 docs/security/signing.md diff --git a/.vitepress/config.mts b/.vitepress/config.mts index 10e6e43..a3d3c55 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -10,12 +10,16 @@ export default defineConfig({ nav: [ { text: "Home", link: "/" }, { text: "Specification", link: "/spec" }, + { text: "Objects", link: "/objects" }, ], sidebar: [ { - text: "Spec Details", - items: [{ text: "Spec", link: "/spec" }], + text: "Specification", + items: [ + { text: "Spec", link: "/spec" }, + { text: "Objects", link: "/objects" }, + ], }, { text: "Structures", @@ -30,18 +34,18 @@ export default defineConfig({ }, { text: "Groups", - link: "/groups", + items: [{ text: "Groups", link: "/groups" }], }, { - text: "Cryptography", + text: "Security", items: [ - { text: "Keys", link: "/cryptography/keys" }, - { text: "Signing", link: "/cryptography/signing" }, + { text: "API", link: "/security/api" }, + { text: "Keys", link: "/security/keys" }, + { text: "Signing", link: "/security/signing" }, ], }, { text: "Objects", - link: "/objects", items: [ { text: "Publications", @@ -127,7 +131,7 @@ export default defineConfig({ editLink: { pattern: "https://github.com/lysand-org/docs/edit/main/docs/:path", }, - logo: "/logo.png", + logo: "https://cdn.lysand.org/logo.svg", }, lastUpdated: true, cleanUrls: true, diff --git a/docs/cryptography/signing.md b/docs/cryptography/signing.md deleted file mode 100644 index d3191f4..0000000 --- a/docs/cryptography/signing.md +++ /dev/null @@ -1,195 +0,0 @@ -# Cryptography in Lysand - -Lysand employs cryptography to safeguard objects from being altered during transit. This is achieved by signing objects using a private key, and then verifying the signature with a corresponding public key. - -> [!NOTE] -> The 'author' of the object refers to the entity (usually an [Actor](../objects/actors)) that created the object. This is indicated by the `author` property on the object body. - -All HTTP requests **MUST** be sent over HTTPS for security reasons. Servers **MUST NOT** accept HTTP requests, unless it is for development purposes. - -HTTP requests **MUST** be signed with the public key of the object's author. This is done by adding a `Signature` header to the request. - -The `Signature` header is too be formatted as follows: -``` -Signature: keyId="https://example.com/users/uuid",algorithm="ed25519",headers="(request-target) host date digest",signature="base64_signature" -``` - -Here, the `keyId` field **MUST** be the URI of the user that is sending the request. - -The `algorithm` field **MUST** be `ed25519`. - -The `headers` field **MUST** be `(request-target) host date digest`. - -The `signature` field **MUST** be the base64-encoded signature of the request. - -The signature is calculated as follows: - -1. Create a string that contains the following, replacing the placeholders with the actual values of the request: -``` -(request-target): post /users/uuid/inbox -host: example.com -date: 2024-04-10T01:27:24.880Z -digest: SHA-256=base64_digest -``` - -1. Sign the string with the user's private key. - -2. Base64-encode the signature. - -The `digest` field **MUST** be the SHA-256 digest of the request body, base64-encoded. - -The `date` field **MUST** be the date and time that the request was sent, formatted as follows (ISO 8601): -``` -2024-04-10T01:27:24.880Z -``` - -The `host` field **MUST** be the host of the server that is receiving the request. - -The `request-target` field **MUST** be the request target of the request, formatted as follows: -``` -post /users/uuid/inbox -``` - -Where `/users/uuid/inbox` is the path of the request (this will depend on implementations). - -Let's imagine a user at `example.com` wants to send something to a user at `receiver.com`'s inbox. - -Here is an example of signing a request using TypeScript and the WebCrypto API (replace `status_author_private_key`, `full_lysand_object_as_string` and sample text appropriate): - -```typescript -const privateKey = await crypto.subtle.importKey( - "pkcs8", - Uint8Array.from(atob(status_author_private_key), (c) => - c.charCodeAt(0), - ), - "Ed25519", - false, - ["sign"], -); - -const digest = await crypto.subtle.digest( - "SHA-256", - new TextEncoder().encode(full_lysand_object_as_string), -); - -const userInbox = new URL( - "https://receiver.com/users/22a56612-9909-48ca-84af-548b28db6fd5/inbox" -); - -const date = new Date(); - -const signature = await crypto.subtle.sign( - "Ed25519", - privateKey, - new TextEncoder().encode( - `(request-target): post ${userInbox.pathname}\n` + - `host: ${userInbox.host}\n` + - `date: ${date.toISOString()}\n` + - `digest: SHA-256=${btoa( - String.fromCharCode(...new Uint8Array(digest)), - )}\n`, - ), -); - -const signatureBase64 = btoa( - String.fromCharCode(...new Uint8Array(signature)), -); -``` - -> [!WARNING] -> Support for Ed25519 in the WebCrypto API is recent and may not be available in some older runtimes, such as Node.js or older browsers. - -The request can then be sent with the `Signature`, `Origin` and `Date` headers as follows: -```ts -await fetch("https://receiver.com/users/22a56612-9909-48ca-84af-548b28db6fd5/inbox", { - method: "POST", - headers: { - "Content-Type": "application/json", - Date: date.toISOString(), - Origin: "example.com", - Signature: `keyId="https://example.com/users/caf18716-800d-4c88-843d-4947ab39ca0f",algorithm="ed25519",headers="(request-target) host date digest",signature="${signatureBase64}"`, - }, - body: full_lysand_object_as_string, -}); -``` - -Example of validation on the server side: - -```typescript -// req is a Request object -const signatureHeader = req.headers.get("Signature"); -const origin = req.headers.get("Origin"); -const date = req.headers.get("Date"); - -if (!signatureHeader) { - return errorResponse("Missing Signature header", 400); -} - -if (!origin) { - return errorResponse("Missing Origin header", 400); -} - -if (!date) { - return errorResponse("Missing Date header", 400); -} - -const signature = signatureHeader - .split("signature=")[1] - .replace(/"/g, ""); - -const digest = await crypto.subtle.digest( - "SHA-256", - new TextEncoder().encode(JSON.stringify(body)), -); - -const keyId = signatureHeader - .split("keyId=")[1] - .split(",")[0] - .replace(/"/g, ""); - -// TODO: Fetch sender using WebFinger if not found -const sender = ... // Get sender from your database via its URI (inside the keyId variable) - -const public_key = await crypto.subtle.importKey( - "spki", - Uint8Array.from(atob(sender.publicKey), (c) => c.charCodeAt(0)), - "Ed25519", - false, - ["verify"], -); - -const expectedSignedString = - `(request-target): ${req.method.toLowerCase()} ${ - new URL(req.url).pathname - }\n` + - `host: ${new URL(req.url).host}\n` + - `date: ${date}\n` + - `digest: SHA-256=${btoa( - String.fromCharCode(...new Uint8Array(digest)), - )}\n`; - -// Check if signed string is valid -const isValid = await crypto.subtle.verify( - "Ed25519", - public_key, - Uint8Array.from(atob(signature), (c) => c.charCodeAt(0)), - new TextEncoder().encode(expectedSignedString), -); - -if (!isValid) { - throw new Error("Invalid signature"); -} -``` - -Signature is **REQUIRED** on **ALL** outbound requests. If the request is not signed, the server **MUST** respond with a `401 Unauthorized` response code. However, the receiving server is not required to validate the signature, it just must be provided. - -If a request is made by the server and not by a server actor, the [Server Actor](/federation/server-actor) **MUST** be used in the `author` field. - -## Security Considerations - -When implementing cryptography in Lysand, it is important to consider the following security considerations: -- **Key Management**: Ensure that private keys are stored securely and are not exposed to unauthorized parties. -- **Key Export**: Do not export private keys to untrusted environments, but allow users to export their private keys to secure locations. -- **Key Import**: Allow users to import private keys when creating new account, but ensure that the keys are not exposed to unauthorized parties. - -Most implementations should not roll their own cryptography, but instead use well-established libraries such as the WebCrypto API. (See the [WebCrypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) documentation for more information). Libraries written in unsafe languages, such as C, or that are a frequent source of security issues (e.g., OpenSSL) should be avoided. diff --git a/docs/groups.md b/docs/groups.md index f212bdb..f02c892 100644 --- a/docs/groups.md +++ b/docs/groups.md @@ -64,6 +64,4 @@ Other values for `group` are: - `public` for public notes, which can be seen by anyone. - `followers` for notes that can be seen by the author's followers only. -If the `group` field is empty, and nobody is mentioned in the `to` field, the note is only visible to the author. - ---> To finish \ No newline at end of file +If the `group` field is empty, and nobody is mentioned in the `to` field, the note is only visible to the author. \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index 513d9e3..34da42e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -7,7 +7,7 @@ hero: text: "Federation, simpler" tagline: A simple to implement and complete federation protocol image: - src: /logo.png + src: https://cdn.lysand.org/logo.svg alt: Lysand Logo actions: - theme: brand @@ -25,7 +25,7 @@ features: - title: Easy to implement details: The protocol is simple to implement, and can be used with any language - title: Secure by default - details: All requests are signed with the latest cryptography algorithms + details: All requests are signed with the latest cryptographic algorithms - title: No vendor-specific implementations details: Everything is heavily standardized to ensure compatibility - title: TypeScript types @@ -35,11 +35,9 @@ features: --- > [!INFO] -> The latest version of Lysand is **2.0**, released on **March 19th 2024** by [**CPlusPatch**](https://cpluspatch.dev). +> The latest version of Lysand is **3.0**, released on **(beta site)** by [**CPlusPatch**](https://cpluspatch.com). > -> Lysand 2.0 features **more standardization**, **simpler object structures**, and **documentation rewrite**. -> -> [See the full Git diff here](https://github.com/lysand-org/docs/compare/158ec6e...f11d51c) +> Lysand 3.0 features **stricter security** and **more modularizarion**. \ No newline at end of file + \ No newline at end of file diff --git a/docs/objects/publications.md b/docs/objects/publications.md index 7e2242c..36b3f20 100644 --- a/docs/objects/publications.md +++ b/docs/objects/publications.md @@ -12,13 +12,28 @@ Here is an example publication: "created_at": "2021-01-01T00:00:00.000Z", "content": { "text/plain": { - "content": "Hello, world!" + "content": "Hello, world! I own this website: https://google.com" }, "text/html": { - "content": "Hello, world!" + "content": "Hello, world! I own this website! https://google.com" } }, - "visibility": "public", + "category": "microblog", + "device": { + "name": "Megalodon for Android", + "version": "1.3.89", + "url": "https://sk22.github.io/megalodon" + }, + "previews": [ + { + "link": "https://google.com", + "title": "Google", + "description": "The world's most popular search engine", + "image": "https://cdn.example.com/previews/6e0204a2-746c-4972-8602-c4f37fc63bbe.png", + "icon": "https://google.com/favicon.ico" + } + ], + "group": "public", "attachments": [ { "image/png": { @@ -85,9 +100,55 @@ An example value for the `content` field would be: > > Lysand also recommends that servers always include a `text/plain` version of each object, as it is the most basic content type that is supported by all clients, such as command line clients. +> [!WARNING] +> Servers should not trust the `text/html` content type, as it could contain malicious code. Servers should always sanitize the content before displaying it to the user. +> +> Additionally, frontends should warn users before clicking on links that do not match the link text, such as `https://google.com` + It is up to the client to choose which content format to display to the user. The client may choose to display the first content format that it supports, or it may choose to display the content format that it thinks is the most appropriate. -Lysand recommends that clients display the richest content format that they support, such as HTML or more exotic formats such as MFM. +Clients should display the richest content format that they support, such as HTML or more exotic formats such as MFM. + +### Category + +| Name | Type | Required | +| :------- | :----------- | :------- | +| category | CategoryType | No | + +Category of the publication. Used for clients to possibly display notes in different ways, for example a note with the `microblog` category could be displayed in a timeline, while a note with the `forum` category could be displayed Reddit-style. + +See [the Types section](#types) for more information on the `CategoryType` enum. + +### Device + +| Name | Type | Required | +| :----- | :----- | :------- | +| device | Device | No | + +Device that the publication was created on. If it is not provided, it is assumed that the publication was created on a generic device. + +Servers should avoid collecting any information that could be used to identify the user, such as IP addresses or user agents. A simple name is recommended. + +### Previews + +| Name | Type | Required | +| :------- | :------------------- | :------- | +| previews | Array of LinkPreview | No | + +Previews for links in the publication. Optional. This is to avoid the [stampeding mastodon problem](https://github.com/mastodon/mastodon/issues/23662) where a link preview is fetched by every server that sees the publication, creating an accidental DDOS attack. + +> [!WARNING] +> Servers should make sure not to trust the previews, as they could be faked by remote servers. This is not a very good attack vector, but it is still possible to redirect users to malicious links. + +### Group + +| Name | Type | Required | +| :---- | :----- | :------- | +| group | String | No | + +URI of a [Group](../groups.md), or `public` or `followers`. + +Refer to the [Groups](../groups.md) page for more information on groups, their implementation and what to do if this value is not provided. ### Attachments @@ -216,6 +277,10 @@ interface Publication extends Entity { type: "Note" | "Patch"; author: string; content?: ContentFormat; + category?: CategoryType; + device?: Device; + previews?: LinkPreview[]; + group?: string | "public" | "followers"; attachments?: ContentFormat[]; replies_to?: string; quotes?: string; @@ -246,4 +311,34 @@ enum Visibility { Followers = "followers", Direct = "direct" } +``` + +```typescript +interface LinkPreview { + link: string; + title: string; + description?: string; + image?: string; + icon?: string; +} +``` + +```typescript +interface Device { + name: string; + version?: string; + url?: string; +} +``` + +```typescript +/* + * microblog -> Twitter, Mastodon-style + * forum -> Reddit-style + * blog -> Wordpress, WriteFreely-style + * image -> Instagram-style + * video -> YouTube-style + * audio -> SoundCloud, Spotify-style + */ +type CategoryType = "microblog" | "forum" | "blog" | "image" | "video" | "audio" ``` \ No newline at end of file diff --git a/docs/public/assets/discord-buttons.webp b/docs/public/assets/discord-buttons.webp new file mode 100644 index 0000000000000000000000000000000000000000..593b25a212b0223005a147e5da0d474db7a07320 GIT binary patch literal 31498 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 Date: Wed, 1 May 2024 17:42:07 -1000 Subject: [PATCH 7/8] chore: :bookmark: Update versions in code --- docs/spec.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/spec.md b/docs/spec.md index 4f03c5a..337681a 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -1,7 +1,8 @@ # Introduction > [!NOTE] -> You are looking at the documentation for `Lysand 3.0`, currently in development. +> You are looking at the documentation for `Lysand 3.0-beta1`, released in May 2024 +> Small changes may still be made before the final release. > > Previous versions: > - `Lysand 2.0`, released in March 2024. From 6a512684c5f67da8f7abfc665f2bdbc555e22b4a Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Wed, 1 May 2024 17:44:05 -1000 Subject: [PATCH 8/8] fix: :bug: Fix build crashing because of dead links --- bun.lockb | Bin 75332 -> 87140 bytes docs/extensions/microblogging.md | 4 ++-- docs/spec.md | 2 +- package.json | 30 +++++++++++++++--------------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/bun.lockb b/bun.lockb index 76e1389514e3468069671ef0c02b8e9671667f78..53f4bbf46f0dc4e89ab06990635a5e582a0dd198 100755 GIT binary patch delta 14648 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 T!oRTK6G$|0MvGISPj31z6zVrL delta 9459 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 diff --git a/docs/extensions/microblogging.md b/docs/extensions/microblogging.md index 6dcaba0..4f894ed 100644 --- a/docs/extensions/microblogging.md +++ b/docs/extensions/microblogging.md @@ -35,7 +35,7 @@ Here's an example of an `Announce` action: | :----- | :----- | :------- | | author | String | Yes | -URI of the [Actor](./actors) who initiated the action. +URI of the [Actor](../objects/actors) who initiated the action. #### Object @@ -43,7 +43,7 @@ URI of the [Actor](./actors) who initiated the action. | :----- | :----- | :------- | | object | String | Yes | -URI of the object being announced. Must be of type [Note](./note) +URI of the object being announced. Must be of type [Note](../objects/note) #### Implementation diff --git a/docs/spec.md b/docs/spec.md index 337681a..17abcc6 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -28,7 +28,7 @@ The words **MUST**, **MUST NOT**, **SHOULD**, **SHOULD NOT**, and **MAY** are us - **Actor**: An individual or entity utilizing the Lysand protocol, analogous to ActivityPub's `Actor` objects. An actor could be a [Server Actor](federation/server-actor), representing a server, or a [User Actor](objects/actors). - **Server**: A server that deploys the Lysand protocol, referred to as an **implementation**. Servers are also known as **instances** when referring to the deployed form. -- **Entity**: A generic term for any object in the Lysand protocol, such as an [Actor](objects/actors), [Note](objects/publications), or [Attachment](objects/attachments). +- **Entity**: A generic term for any object in the Lysand protocol, such as an [Actor](objects/actors), [Note](objects/publications), or [Like](objects/like). # Implementation Requirements diff --git a/package.json b/package.json index 3ea6396..aa9a4cf 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,17 @@ { - "scripts": { - "docs:dev": "vitepress dev", - "docs:build": "vitepress build", - "docs:preview": "vitepress preview" - }, - "devDependencies": { - "@biomejs/biome": "^1.7.1", - "vitepress": "^1.1.0" - }, - "trustedDependencies": ["@biomejs/biome"], - "dependencies": { - "@tailwindcss/vite": "^4.0.0-alpha.14", - "iconify-icon": "^2.1.0", - "tailwindcss": "^4.0.0-alpha.14" - } + "scripts": { + "docs:dev": "vitepress dev", + "docs:build": "vitepress build", + "docs:preview": "vitepress preview" + }, + "devDependencies": { + "@biomejs/biome": "^1.7.1", + "vitepress": "^1.1.0" + }, + "trustedDependencies": ["@biomejs/biome"], + "dependencies": { + "@tailwindcss/vite": "^4.0.0-alpha.14", + "iconify-icon": "^2.1.0", + "tailwindcss": "^4.0.0-alpha.14" + } }