ufh/docs/test.json

1 line
8 KiB
JSON

{"doc":[{"type":"header","level":1,"content":"notes"},"Takes ideas from ipfs, perkeep, and matrix.","Theoretically, you only need 3 api endpoints for this to work.",{"type":"ul","items":[["~code{POST /things} Upload a blob"],["~code{GET /things/:hash} Get a blob by hash"],["~code{GET /things} Enumerate blobs"]]},"You can upload media, but most of the time you&#39;ll upload small json\nobjects called &quot;events&quot;. Events can relate to each other. You can specify\naccess control around event types and relations.","To read events, you upload a json query via the upload endpoint and use\nit with the enumerate endpoint.","This is a fairly minimal example.",{"type":"header","level":2,"content":"stages"},{"type":"ol","items":[["i have a content addressed blob store, blobs can be uploaded then retrieved from its hash (eg. put &quot;hello world&quot;, later retrieve by hash)"],["i can store specific json objects called events (eg. a url event with a href, title, description)"],["events can relate to each other (eg. url eventswith relations to a rss feed event)"],["events can be queried based on thing types and relations (eg. query url events that relate to a rss feed event)"],["access control can be specified based on things and relations (eg. comment things that relate to this rss feed thing can only be made by certain people)"]]},"For implementation",{"type":"ol","items":[["i have a content addressed blob store"],["i can query events"],["i can query relations/structure"],["servers can synchronize with each other"],["i can specify access control on events"]]},"This project is working on impl stage 4/5, currently.","TODO: work out a proper api spec for blob servers and index servers",{"type":"header","level":2,"content":"blob servers"},"Blob servers have only one goal: store blobs, somewhere. You can have a\nblob server that stores on the local filesystem, s3, over sftp, or so\non. Blob servers are content-addressed.",{"type":"header","level":3,"content":"rough api"},{"type":"table","headers":["method","path","description"],"rows":[["POST","/blobs","upload a new blob"],["GET","/blobs/:hash","get a blob by hash"],["DELETE","/blobs/:hash","delete a blob by hash"],["GET","/blobs","get new blobs, or via long polling"]]},"POST uploads raw bytes directly, GET blob returns the raw bytes, DELETE\nreturns nothing","GET /blobs takes in a few query paramaters: limit, to limit the number of\nblobs returned; after, to paginate blobs; and timeout, to long poll new\nblobs. It returns a json object in the form ~code{{ &quot;blobs&quot;: Vec&lt;String&gt; }}.",{"type":"header","level":2,"content":"index servers"},"Index servers take events/blobs and index them.",{"type":"header","level":3,"content":"core api"},"intentionally uses ~code{/things/} instead of ~code{/blobs/}",{"type":"ul","items":[["~code{GET /things/:hash/blob} get a thing as a blob"],["~code{GET /things/:hash} get a thing"],["~code{POST /things} uploads a thing"]]},"there are also extensions",{"type":"ul","items":[["accounts",{"type":"ul","items":[["~code{POST /accounts}"],["~code{GET /accounts/:id}"],["~code{DELETE /accounts/:id}"]]}],["sessions",{"type":"ul","items":[["~code{POST /sessions}"],["~code{DELETE /sessions}"],["~code{GET /sessions}"],["~code{GET /sessions/:id}"],["~code{DELETE /sessions/:id}"],["~code{PATCH /sessions/:id}"]]}],["thumbnails",{"type":"ul","items":[["~code{GET /things/:hash/thumbnail}"]]}]]},{"type":"header","level":2,"content":"queries"},"You can query events",{"type":"code","lang":"ts","content":"interface Query {\n ids: Array<string>,\n types: Array<string>,\n relations: Array<Array<string>>,\n}"},{"type":"header","level":2,"content":"derived"},"The server can derive data for you",{"type":"code","lang":"ts","content":"const ev = {\n type: \"x.file\",\n content: {\n parts: [\"ref:sha224-1234\"],\n },\n derived: {\n // tbd\n \"x.file\": {\n size: 1234,\n type: \"image/png\",\n width: 12,\n height: 34,\n }\n },\n};"},"It is excluded from hash calculations/signatures. Here are some example derives:",{"type":"code","lang":"ts","content":"{\n file: {\n size: 1234,\n name: \"filename.ext\",\n type: \"mime/type\",\n },\n media: {\n width: 1234,\n height: 1234,\n duration: 1234,\n },\n keys: {\n reaction: {\n \"foo\": 1,\n \"bar\": 2,\n \"baz\": 3,\n },\n }\n}"},{"type":"code","lang":"ts","content":"// playing around with different possible event formats...\nconst userEvent = {\n type: \"x.user\",\n sender: \"ed25519-pubkey\",\n signature: \"ed25519-sig\",\n};\n\nconst roomEvent = {\n type: \"x.nexus\",\n content: {\n type: \"room\", // or space, or forum, or torment (please don't)\n },\n sender: \"ed25519-pubkey\",\n signature: \"ed25519-sig\",\n};\n\nconst messageEvent = {\n type: \"l.chat.message\",\n content: {\n body: \"hello\",\n },\n relations: {\n \"ref:sha224-1234abcd\": { type: \"prev_event\" },\n \"ref:sha224-5678wxyz\": { type: \"reply\" },\n },\n sender: \"ed25519-pubkey\",\n signature: \"ed25519-sig\",\n};\n\nconst fileEvent = {\n type: \"x.file\",\n content: {},\n sender: \"ed25519-pubkey\",\n signature: \"ed25519-sig\",\n};\n\nconst aclEvent = {\n type: \"x.acl\",\n content: {\n roles: {\n \"roleid\": [\n [\"l.chat.message\", \"room\", \"this\"],\n [\"l.chat.message\", \"reply\", \"l.chat.message\"],\n ],\n \"roleid2\": [\n [\"l.chat.message\", \"room\", \"this\"],\n [\"l.chat.message\", \"reply\", \"l.chat.message\"],\n [\"x.file\", \"attach\", \"l.chat.message\"],\n ],\n \"default\": [],\n },\n admins: [\"sha224-userid\"],\n inherit: \"ref:sha224-asdf\", // another x.acl event\n },\n sender: \"ed25519-pubkey\",\n signature: \"ed25519-sig\",\n};"},{"type":"header","level":2,"content":"core events"},"Summary of core event types",{"type":"ul","items":[["~code{x.user}: creates a user"],["~code{x.file}: creates a file (also the only event able to reference blobs)"],["~code{x.redact}: removes another event"],["~code{x.acl}: TODO"],["~code{x.annotate}: TODO"],["~code{x.annotate.local}: TODO"],["~code{x.tag}: TODO"]]},{"type":"header","level":2,"content":"access tokens"},"todo in the future, things will change a lot",{"type":"ul","items":[["~code{1 &lt;&lt; 0} get things"],["~code{1 &lt;&lt; 1} enumerate things"],["~code{1 &lt;&lt; 2} create things"],["~code{1 &lt;&lt; 3} remove things (x.redact event specifically)"],["~code{1 &lt;&lt; 4} manage shares"],["~code{1 &lt;&lt; 5} manage sessions"]]},{"type":"header","level":2,"content":"acls"},{"type":"ul","items":[["you specify an acl on an event"],["it determines how events can relate to that event"],["it determines how events which relate to that event can relate to each other"]]},"Example of an acl:",{"type":"code","lang":"js","content":"{\n roles: {\n \"send\": [\n [\"l.chat.message\", \"chat\", \"l.chat.room\"],\n ],\n \"react\": [\n [\"l.chat.react\", \"chat\", \"l.chat.message\"],\n ],\n },\n users: {\n \"%bar\": [\"send\", \"react\"],\n \"%baz\": [\"send\"],\n },\n admins: [\"%foobar\"],\n}"},{"type":"header","level":2,"content":"features"},"Different servers can have different features. Here are the official\nones so far:",{"type":"ul","items":[["~code{core}: supports the core api (~code{/things/...})"],["~code{aliase}: server name -&gt; hash mappings"],["~code{thumbnail}: generates small images/icons for x.file events"],["~code{account}: users can manage accounts"],["~code{session}: users can manage sessions"],["~code{search}: has full text search"],["~code{share}: deprecated"]]},{"type":"header","level":2,"content":"searching"},"see ~link{https://docs.rs/tantivy/latest/tantivy/query/struct.QueryParser.html}{https://docs.rs/tantivy/latest/tantivy/query/struct.QueryParser.html}","deriving takes a lot of dependencies, which might not be desierable"],"name":"notes.md"}