1 line
8 KiB
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'll upload small json\nobjects called "events". 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 "hello world", 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{{ "blobs": Vec<String> }}.",{"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 << 0} get things"],["~code{1 << 1} enumerate things"],["~code{1 << 2} create things"],["~code{1 << 3} remove things (x.redact event specifically)"],["~code{1 << 4} manage shares"],["~code{1 << 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 -> 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"}
|