nfnitloop / feoblog Goto Github PK
View Code? Open in Web Editor NEWA distributed, cryptographically-verifiable blog / social network
License: Other
A distributed, cryptographically-verifiable blog / social network
License: Other
As a server admin, I should be able to use the CLI to:
In the meantime you have to make DB calls yourself.
Right now, FeoBlog uses an SQLite database. This simplifies maintenance, and should scale enough for individual use, or use among a small group of friends. But SQLite does have limitations with high write loads.
Currently, database operations are all abstracted through the Backend
type. It should be easy to add a new implementation, but I'd need to plan for a few things.
The UI of the JS and plain HTML versions of the site has diverged a bit, and TBH the JS version is much nicer. For a better initial experience, redirect browsers that have JavaScript enabled to the corresponding URL in the client.
Right now, user administration is performed via the CLI. That's not terrible for a server run by a programmer for a few of his friends. But others might prefer a web-based UI.
How do we do this?
FeoBlog "blogs" are organized as an unordered¹ collection of Item
s so that an individual server may deny storing certain Items. However, this means that, when looking at data stored on a single server, it's not possible to determine whether any of a user's data is missing. To do so, one would have to find a list of Item
on some other server and compare it to the one in question.
To enable this type of checking against a single server, we could add optional metadata to the Item type which lists previous Item IDs published by this user ID. Like the rest of the Item, this data would be cryptographically signed by the user's key, so unable to be modified by servers. Clients could walk that DAG and report on any missing items.
IMO, server sync is going to be enough to detect censored Items. During sync, the client compares lists of Item IDs from two servers and copies over missing Items. If a server denies POSTing an item, the client will notify the user, and the user can detect the censorship.
To control spam, objectional content, and abuse, and to comply with legal requirements, server admins should be able to:
Blocking one of those should:
Additionally, we should have commands to find out the reason that blocked content showed up on our instance in the first place:
Currently, URLs to posts on here are incredibly long, and it would be nice to have "shortcuts" (ex. t.co/XJK98Y)
I should compose a list of servers running FeoBlog, once there are some.
Right now, AFAIK, this is just https://blog.nfnitloop.com/. If you're running another server, please do comment and let me know! :)
I added Luxon, and it seems to be a smaller/better library. But because moment is scattered around the code I keep accidentally using more of it. :p
See:
Line 84 in ccb906c
Right now I'm just using the webbrowser
crate to open a browser, but on Linux that might open a blocking browser, which will block the server from actually starting.
There's an open issue for that here:
amodm/webbrowser-rs#18
--open
still might work for a user, depending on what they have set up as their default browser, and which launcher it can find, so it's not necessarily fully broken, but it would be nice if this were consistent with Windows & MacOS behavior.
One of the first people I shared FeoBlog with asked "Does it support ActivityPub?" and I had to say no.
I should create a FAQ or somewhere to document these kinds of things, and this question in particular.
Until then, here's why FeoBlog doesn't support ActivityPub:
See https://www.w3.org/TR/activitypub/#security-considerations for some of the unanswered security concerns.
In particular, I don't see there how servers or clients can validate that data they received is actually from the supposedly originating user.
Meanwhile, FeoBlog only accepts signed data. As a result, its data model doesn't need an "inbox". Being passed data for a user operates the same whether it's from that user, or from some other service on their behalf.
I had fun implementing them. But it's not immediately obvious how to use them. Just do a JS confirmation dialog instead.
If I'm writing a post and navigate away from that page then return to it, it should restore my previous post. Losing long posts this way would be pretty annoying.
Browsers try to save form data for you these days, but I think because I'm running a single-page webapp which just removes the element when you navigate away, the browser doesn't know how to save/restore that state. (Plus I think my Svelte code is explicitly starting out with empty state.)
Advanced, possibly future features:
Users should be able to comment on any Item (including other comments).
Clients should have a way to query for comments in response to an Item.
By default, the displayed comments should be limited to:
Comments should not be rendered on the main HTML-only home page.
Comments may optionally be rendered in clients' feeds (chronologically, detached, but linking to the Item they respond to.)
Comments should be rendered when viewing an individual item.
Comments are not Posts. In particular, they lack:
Right now the server makes users' posts and feeds available as plain HTML, and as data accessible via the FeoBlog REST API.
However, to allow consuming a FeoBlog blog from third party systems like feed readers, we should also expose the feeds as RSS, and/or Atom, and/or JsonFeed.
When I visit blog.nfnitloop.com, the thing I usually want to see is the feed of all my follows' (and my) posts. But it currently takes me to the "Home" view by default:
This is just because we redirect to the client from /, and I'm trying to mirror the URL structure from the web site in the client. However, I think we can make an exception for the home page, give it an explicit /client/#/home
URL, and redirect /client/#/
to the user's feed.
Users should be able to attach files to a post. This would make sharing images, PDFs, etc. possible.
Rough plans are:
Additional work:
If I write a post or otherwise create an Item that's larger than accepted by the server, the client could/should warn me before I hit submit.
This project reminds me a lot of tumblr, so it would be cool if you could bring back some of tumblrs features into this.
Out of the box, FeoBlog uses its embedded styles.css
and client.css
files to render the plain HTML view and client view.
Users will probably want a way to provide their own styles for their own sites.
FeoBlog should include a robots.txt
Immediately after sharing a link to a live server for the first time, it got hit by several bots, and they generally requested a robots.txt
.
I should read up on the modern format of robots.txt and include an appropriate one.
Can they do wildcard matching? Do I want to allow/deny specific sections? (Maybe deny /client/*
?)
Support audio recording in the client.
https://blog.addpipe.com/recording-audio-in-the-browser-using-pure-html5-and-minimal-javascript/ has some example code for reference.
Depends on File attachments working: (#4)
I'll probably also need to add some Item metadata to say that "this attachment is audio meant to be played inline", since unfortunately .ogg and .webm file extensions are not exactly unambiguous there.
I just posted minutes ago, but somehow the post is backdated 18 hours. !?!?
I think I figured out what happened. Since the drafts feature was introduced, if there was something in the text field (and there was in this case), we load the text and the timestamp associated w/ that text.
I cleared the text, wrote a new post, and posted it without even looking at the timestamp. So it ended up getting posted w/ an old timestamp. Oops.
I think the common case is going to be posting with the current timestamp, so I should probably make that the default behavior for both new posts and saved drafts.
Maybe I can just allow the timestamp to be blank to mean "now" and leave it blank by default?
Since there's there are raw (/u/_/i/_/
) links and client (/client/#/u/_/...
) links, it ends up being easier to share the client link, though the other one would likely result in better SEO and discoverability. Add a share button. It could:
Currently, servers are pretty simple.
All of the sync logic is written in the client.
It would be nice if I as a user could run a command from the CLI to sync posts. That way I could easily make a copy to bootstrap a new server, or create a backup, or just grab stuff before I go offline for a while.
I thought I'd need support for this in rust-embed, but as I wrote up pyrossh/rust-embed#140 I realized a workaround would be simple:
Create some wrapper that calculates an ETag (and also Last-Modified date?) on server startup or lazily on the first request. Then serve static files w/ that ETag so browsers will cache them longer.
Use the keyboard to navigate through items in the client.
ex: j/k for next/previous items.
Right now you have to drag/drop attachments into the web UI to add them. This doesn't work on iOS (and probably not Android?)
I suppose I should add some UI element that's more discoverable than drag & drop to enable that.
Related to #20 -- maybe allow attaching multiple versions of an image with different sizes?
Hmm, this might be a bit complicated.
First thought: Add some "metadata" to the Attachment protobuf message that allows alternative sizes.
But ... wouldn't I want all attachments listed in the top-level repeated Attachments.file
? Maybe there should be an Attachments.meta
? But then clients that naively copy all Attachments may get redundant copies of images? Hmm. I'll need to think about this one a bit more.
Right now the client has you "Log In" as a user. But you don't provide any password to do so. Really you're just configuring the client to act as if you are logged in.
It feels a bit like a kludge. Is there some better language / UI to represent this?
I recently implemented filtering for the user's feed.
Eventually, when there are many users on a server, a user might want to filter which comments are shown in reply to posts. For example:
I'm not going to bother with this until I get some more users, though, and this actually becomes an issue.
I wrote in the v0.1.0 README.md:
Reblogging [is an unplanned feature]. I [believe] there should be a higher barrier to sharing others' content. You'll need to comment, post, or "Reply" post to share content to your followers.
But, the more I think about it having a lot of posts like
⬆️ OMG This
is probably even more annoying. If I implement a reblog functionality, I could limit it to the feed, and add an option to not display reblogs for people that don't want to see that.
I really want to use this service, but right now there seems to be only one user and one website, with the UI being not the best. Is there a detailed guide on how to set up your own instance?
What are the obligations servers have under GDPR?
My layman's understanding is that under GDPR users must be able to:
The REST API can already list all of a user's Items, so that may take care of point 1.
And eventually I'll implement #5 -- is that enough to handle point 2?
If folks know other GDPR obligations, please leave comments, IANAL.
Maybe just think about branding in general? In particular "blog" is not quite accurate. And "Feo" was a funny pun for a while but may not really attract new users.
Example names: Disapora, Mastodon, Scuttlebutt. Single word, unique, not necessarily related to what it is.
I'm writing a new rss->feoblog client for Deno. I was getting a 500 "Server Error" from the server. That's not super helpful. Should expose what failed validation.
I saw this on my actix web console:
[2021-07-04T02:05:33Z ERROR actix_http::response] Internal Server Error: Error { inner: ValidationError { message: "Timestamp is required" } }
Make sure that gets returned via HTTP.
When Snowpack generates files via snowpack build
, it ends up generating files that have colons in the name.
Initially, these seem to work when I'm running the rust server in dev. mode, which passes through file requests to the underlying file system. However, when I attempt to do a release build, which bundles files up into the executable, the required files do not exist.
This also breaks the ability for rollup to do a release build. It itself can't find the files it generated. 😣
cd feoblog/web-client
npm install
npm run build
Take a look in build/web_modules/common
__node-resolve:empty-1777c4cc.js
__node-resolve
. It will be 0 bytes.This is because file names can't have a colon in them on Windows. However, file paths can have a colon in them, which causes the bit after the colon to be interpreted as a stream when using NTFS file systems. You can see this in this output:
C:\Users\Cody\code\feoblog\web-client\build\web_modules\common>dir /r __node-resolve
Volume in drive C has no label.
Volume Serial Number is 3894-D9B7
Directory of C:\Users\Cody\code\feoblog\web-client\build\web_modules\common
02/20/2021 09:41 PM 0 __node-resolve
358 __node-resolve:empty-1777c4cc.js:$DATA
1 File(s) 0 bytes
0 Dir(s) 357,425,332,224 bytes free
This issue still exists even if I upgrade to Snowpack v3.
I'm not sure if this is a Snowpack bug or a Rollup bug, so I've just reported it here against my own code until I find the culprit. :)
This seems to work in dev mode because the expected file name is directly requested via the browser. RustEmbed then asks the filesystem for that file path, which also ends up opening the NTFS data stream.
However, bundling the files likely just lists files on disk and tries to include them in the binary. Likewise, copying or zipping the files would probably break this functionality. Right now this is a blocker to having a working feoblog web client on Windows. 😢
See:
To do:
Now that I've got some "blogs" with lots of "posts", the initial sync can be a bit slow.
For example:
There's probably room to parallelize the sync more than it is already.
I think I can also walk down the list of items instead of fetching the full list then doing set comparisons. Though I doubt that's the slow part, it's probably just the latency overhead of copying items from and to a server one-by-one.
Right now, profiles only contain an identicon based on their public ID.
My current thinking is that profile photos will just be attachments to the Profile object. Since those are backed by a content-addressable store, editing profiles won't require re-uploading new photos.
This is like a comment (#1) , but is a fully-fledged post. It would appear on a feed or the home page like other posts.
However, it also has additional metadata that marks it as a reply to some other Item.
Having that metadata available would allow some nice UI features:
When you attach a very large image, or paste an image (which seems to always paste as a PNG), the file size can be quite large.
Offer an option to re-encode the image as a smaller jpeg (or webp) image to save space.
If a userID is compromised, or its private key is lost, there should be some tool(s) for migrating content to a new userID (pub/priv key pair).
Optional features:
When a UserID becomes compromised, or a user just wants to delete their account, they should be able to create a revocation Item. Servers should honor this item by:
The server should also delete the content for that user, but may do so asynchronously. (ex: via a clean
command at some later time.) This could allow someone whose key has been compromised a chance to recover their content and publish it under a new key.
/u/:userID/proto3
endpoint should list 1 Item, which is the revocation item, so that other servers that sync from this one will learn of the revocation.There's a TODO here:
https://github.com/NfNitLoop/feoblog/blob/develop/protobufs/feoblog.proto#L114
... but the more I think about it, the more I think a Revocation should be its own item_type
. I don't want the option of specifying a Profile.display_name, about, servers, or follows.
Need to get some automated builds and releases on this.
develop
branch. I don't care about warnings at this stage. OMG Rust has so many warnings.release
stage. OK I should probably clean up warnings for that.Oh, right, also, some tests. 😬
Once there's a release for protoc-gen-ts that contains thesayyn/protoc-gen-ts#20 it should have better support for oneof fields. Update to it and remove any hacky workarounds I made in the meantime.
Right now, following a user, and knowing whether you already follow a user, is a bit error-prone. You've got to copy/paste the userID into your Edit Profile page.
The UI should:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.