Hi, I am playing with making an event sourcing database. Its super alpha but I thought I would share since others are talking about databases and such.
Itâs super basic. Using tidwall/wal as the disk backing. The first use case I am playing with is an implementation of msgbus. I can post events to it and read them back in reverse order.

I plan to expand it to handle other event sourcing type things like aggregates and projections.
Find it here: sour-is/ev
@prologic@twtxt.net @movq@www.uninformativ.de @lyse@lyse.isobeef.org
@prologic@twtxt.net Oh.. reading comprehension is strong today.. you went to US and now back.
A read-only, finger(1)-based social network, maybe? http://txtpunk.com/fingers/
#!/bin/sh
# Validate environment
if ! command -v msgbus > /dev/null; then
printf "missing msgbus command. Use: go install git.mills.io/prologic/msgbus/cmd/msgbus@latest"
exit 1
fi
if ! command -v salty > /dev/null; then
printf "missing salty command. Use: go install go.mills.io/salty/cmd/salty@latest"
exit 1
fi
if ! command -v salty-keygen > /dev/null; then
printf "missing salty-keygen command. Use: go install go.mills.io/salty/cmd/salty-keygen@latest"
exit 1
fi
if [ -z "$SALTY_IDENTITY" ]; then
export SALTY_IDENTITY="$HOME/.config/salty/$USER.key"
fi
get_user () {
user=$(grep user: "$SALTY_IDENTITY" | awk '{print $3}')
if [ -z "$user" ]; then
user="$USER"
fi
echo "$user"
}
stream () {
if [ -z "$SALTY_IDENTITY" ]; then
echo "SALTY_IDENTITY not set"
exit 2
fi
jq -r '.payload' | base64 -d | salty -i "$SALTY_IDENTITY" -d
}
lookup () {
if [ $# -lt 1 ]; then
printf "Usage: %s nick@domain\n" "$(basename "$0")"
exit 1
fi
user="$1"
nick="$(echo "$user" | awk -F@ '{ print $1 }')"
domain="$(echo "$user" | awk -F@ '{ print $2 }')"
curl -qsSL "https://$domain/.well-known/salty/${nick}.json"
}
readmsgs () {
topic="$1"
if [ -z "$topic" ]; then
topic=$(get_user)
fi
export SALTY_IDENTITY="$HOME/.config/salty/$topic.key"
if [ ! -f "$SALTY_IDENTITY" ]; then
echo "identity file missing for user $topic" >&2
exit 1
fi
msgbus sub "$topic" "$0"
}
sendmsg () {
if [ $# -lt 2 ]; then
printf "Usage: %s nick@domain.tld <message>\n" "$(basename "$0")"
exit 0
fi
if [ -z "$SALTY_IDENTITY" ]; then
echo "SALTY_IDENTITY not set"
exit 2
fi
user="$1"
message="$2"
salty_json="$(mktemp /tmp/salty.XXXXXX)"
lookup "$user" > "$salty_json"
endpoint="$(jq -r '.endpoint' < "$salty_json")"
topic="$(jq -r '.topic' < "$salty_json")"
key="$(jq -r '.key' < "$salty_json")"
rm "$salty_json"
message="[$(date +%FT%TZ)] <$(get_user)> $message"
echo "$message" \
| salty -i "$SALTY_IDENTITY" -r "$key" \
| msgbus -u "$endpoint" pub "$topic"
}
make_user () {
mkdir -p "$HOME/.config/salty"
if [ $# -lt 1 ]; then
user=$USER
else
user=$1
fi
identity_file="$HOME/.config/salty/$user.key"
if [ -f "$identity_file" ]; then
printf "user key exists!"
exit 1
fi
# Check for msgbus env.. probably can make it fallback to looking for a config file?
if [ -z "$MSGBUS_URI" ]; then
printf "missing MSGBUS_URI in environment"
exit 1
fi
salty-keygen -o "$identity_file"
echo "# user: $user" >> "$identity_file"
pubkey=$(grep key: "$identity_file" | awk '{print $4}')
cat <<- EOF
Create this file in your webserver well-known folder. https://hostname.tld/.well-known/salty/$user.json
{
"endpoint": "$MSGBUS_URI",
"topic": "$user",
"key": "$pubkey"
}
EOF
}
# check if streaming
if [ ! -t 1 ]; then
stream
exit 0
fi
# Show Help
if [ $# -lt 1 ]; then
printf "Commands: send read lookup"
exit 0
fi
CMD=$1
shift
case $CMD in
send)
sendmsg "$@"
;;
read)
readmsgs "$@"
;;
lookup)
lookup "$@"
;;
make-user)
make_user "$@"
;;
esac
I would HIGHLY recommend reading up on the keybase architecture. They designed device key system for real time chat that is e2e secure. https://book.keybase.io/security
A property of ec keys is deriving new keys that can be determined to be âon curve.â bitcoin has some BIPs that derive single use keys for every transaction connected to a wallet. And be derived as either public or private chains. https://qvault.io/security/bip-32-watch-only-wallets/
The rise of tags on online articles saying how many minutes it takes to read them says, to me, a lot about our breakneck-speed culture.
@benk@kwiecien.us I am using jenny (we chatted a bit on IRC earlier today). I have been using it for over five months now, I think. It is truly a joy to use, specially because you can use the power of Mutt/NeoMutt to read your twts.
Nominally, my seen/read list for 2021, but I missed a lot of short readings. I may try to write more about these things this year. http://a.9srv.net/media/2021
@lyse@lyse.isobeef.org I thought it was just me. I drives me nuts to try reading on that page. I guess I am no longer capable to look at old CRT monitors without side effects.
@movq@www.uninformativ.de, is removing the hash from the body of the twt on the TODO? I read it, but I am unsure if it is there already, or not. đ Sorry if it is, and I failed to spot it!
@movq@www.uninformativ.de i believe the delete of any twt was a tech limitation with retwt parser not knowing where in the file a twt came from. lextwt tracks the bytes in file where a twt was read from. which could be used to delete a twt from file.. in theory.
I think something has caused my feed to be in a bad state and is now unpardableđ„
I can read this on jenny, but the twt isnât making it to my own pod. Something has gone really wrong, me thinks.
If
Subjectcontains the full twt, then you can skim over conversations just by reading those lines in muttâs index pager
Yes, I do the same, true.
So I decided: Okay, letâs have mutt do it.
And Mutt does it well. I agree it was/is a good idea.
The subject lines are already âcompressedâ
I noticed, yes.
I am not sure why I asked to begin with; in retrospect, in was a silly request. Perhaps the OCD in me got triggered while viewing rich headers, on a specific twt, when I saw the huge subject line that is, otherwise, always hidden.
Anyway, donât mind me, move along. đ
@adi@f.adi.onl
Just like your highschool girlfriend in Afghanistan âdoesnât need savingâ, right? I think it is a language issue you are having, as English isnât your mother tongue.
QAnon followers are cultist nuts. Some of them wanting out are finding that it is a hard thing to do (did you read the article?). Saying that âthey donât need to escapeâ is a silly thing to say, at the very least. To me, it just doesnât make sense.
Third generation of AirPods. So, new AirPods. Read more at Apple. đ
@laz@tt.vltra.plus
Are all minimum requirements met? All pre-install checks performed? Install steps carefully read, and checked, one more time?
@eldersnake@yarn.andrewjvpowell.com There isnât an equivalent for those because:
Markdown is not a replacement for HTML, or even close to it. Its syntax is very small, corresponding only to a very small subset of HTML tags.
You can read more of its philosophy at Daring Fireball. There are enhancements to Markdown (CommonMark, for example), that add extra to it.
I wonder how can I set, on Mutt, a shorter subject (elipsed) on the status bar, while reading a email (or a twt).
Anyone (preferably in the PDX area) have a way to read QIC-80 tapes?
Bookmarking this to read over a few more times. https://dave.cheney.net/practical-go/presentations/qcon-china.html #practical #GO
I was reading dd(1), where it is mentioned in passing, obliquely. Then stty(1) has more info.
I want read-only iOS client that just does the simplest model: pull a list of feeds, make a timeline.
@lyse@lyse.isobeef.org Yes, I often read the raw messages. But more to the point, the simplicity of the format is the bulk of the appeal.
@prologic@twtxt.net the meta info on the top I added manually. itâs following what I have seen from some other twtxt feeds. the new parser will read them.
@prologic@twtxt.net yeah it reads a seed file. Iâm using mine. it scans for any mention links and then scans them recursively. it reads from http/s or gopher. i donât have much of a db yet.. it just writes to disk the feed and checks modified dates.. but I will add a db that has hashs/mentions/subjects and such.
i am guessing you are using some form of webmention to notify the target of the DM? which loads it into a store for the user to read?