This action will delete this post on this instance and on all federated instances, and it cannot be undone. Are you certain you want to delete this post?
This action will delete this post on this instance and on all federated instances, and it cannot be undone. Are you certain you want to delete this post?
This action will block this actor and hide all of their past and future posts. Are you certain you want to block this actor?
This action will block this object. Are you certain you want to block this object?
Are you sure you want to delete the OAuth client [Client Name]? This action cannot be undone and will revoke all access tokens for this client.
Are you sure you want to revoke the OAuth token [Token ID]? This action cannot be undone and will immediately revoke access for this token.
#fediverse 71 hashtags

This release continues my focus on security instead of new features. As I wrote earlier this week, I rebuilt the template framework Ktistec uses with type safety as a central principle. What does that mean?
Imagine that you have an instance of a String that holds federated data. Where can you safely render that in a browser, and what operations (sanitization, escaping, etc.) do you need to do first?
The only way to answer that is to look carefully at the lineage of that data: where it came from, how it was stored, how it was transformed, and where it's rendered. A name holds text; an href or src attribute holds a URL. If you want to render a name inside an HTML element you should HTML escape it. You should escape href and src, too, but the escaping rules for URLs are slightly different from the HTML rules. It's easy to make mistakes.
Ktistec uses four "safe" types to express the contracts:
SafeHTML: A String wrapper marking HTML markup safe to emit raw into HTML data slots (text content, between tags).
SafeAttrValue: A String wrapper marking a value safe to emit raw inside a double-quoted HTML attribute (attr="..."), other than URL or event-handler slots.
SafeURI: A String wrapper marking a URL safe to emit raw into a URL attribute slot (href, src, action, etc.).
SafeJSON: A String wrapper marking JSON output safe to emit raw into the body of a <script type="application/json"> block.
Using the wrong type at a call site is either a compile-time error, or it triggers automatic sanitization of the underlying string value.
Here's the full changelog:
Added
WebFinger and HostMeta client shards.Fixed
I have at least one more cleanup pass to do, and then I'll turn my attention back to the Mastodon-compatible API and a few features I've been looking forward to—like scheduled posts.

Release v3.3.7 of Ktistec fixes several bugs and introduces two enhancements.
Security is a focus in this release. Every gap in input sanitization or escaping is a potential vulnerability, and I've been systematically closing them. I am also carefully, and maybe conservatively, restricting things like supported URL schemes and uploaded file types.
The two enhancements improve compatibility with Mastodon-compatible clients. Mastodon's OAuth tokens don't expire, and Mastodon clients don't know how to handle tokens that do. Sliding expiration ensures that tokens in active use stay alive, while unused tokens eventually expire.
Here's the full changelog:
Added
/api/v1/accounts/update_credentials endpoint.Fixed
href attributes with unsafe schemes from sanitized HTML.X-Content-Type-Options: nosniff.publicKey and scrub Tag.href.I'm working on performance improvements for the next release. A rewrite of the Slang template library looks like it will cut both build time and executable size by around 10%!
📡 Stay tuned!

This release is a maintenance update: a few bug fixes, a security mitigation worth paying attention to, and some performance improvements for users on slow connections.
It's worth updating to pick up the SSRF (Server-Side Request Forgery) mitigation.
Fixed
Changed

The Mastodon-compatible API is at a stable stopping point, so I have removed the gating with_mastodon_api build flag and made it generally available.
I use the API daily via a couple different client apps. What works, works. There are known limitations, most of them rooted in architectural differences between Mastodon and Ktistec. For example, Mastodon and Ktistec manage media differently. In Ktistec, there is no simple way to upload and manage media apart from creating a post. That difference will take some work to bridge.
Here's the full changelog for this release:
Added
/api/v1/accounts/api/v1/accounts/lookup/api/v1/accounts/:id/api/v1/accounts/:id/statuses/api/v1/accounts/:id/following/api/v1/accounts/:id/followers/api/v1/accounts/relationships/api/v1/follow_requests/api/v1/polls/:id/votes/api/v1/preferencesFixed
keyId from Signature header for inbox verification.Changed
Credit goes to this thread for inspiring me to review my signature verification. There is now one more correct implementation. 😉
The next release will focus on cleaning up the internals. Ktistec is just under 100,000 lines of code, 307 source files, and 195 spec files (7030 tests). With one maintainer, the only way to stay sane is by ruthlessly refactoring and paying down the debt!

Release v3.3.4 of Ktistec is available.
This release adds Mastodon-compatible client support for publishing posts. Just like the previous release, however, all Mastodon API support is behind a build flag (-Dwith_mastodon_api). It's still experimental, so opt in only if you're happy to work with rough edges.
Beyond that, I focused on cleanup and refactoring throughout the codebase. Here's the full changelog:
Added
/api/v1/statuses endpoint for status posting./api/v1/timelines/public endpoint.Fixed
Changed
npm audit, test, and caching.npm ci in Dockerfile for reproducible builds.🏋️ Mastodon API support is coming along—more in the next release!

I have started work on a Mastodon-compatible API layer intended to support the many Mastodon front-ends available. It is incomplete and requires an explicit build flag to enable, but what's there (the main timeline) already works with the official Mastodon app, Tusky, and Phanpy.
Here's the full changelog:
Fixed
Changed
As always, check out the full diff for the complete details.

This small release focused on two big deliverables: support for the latest version of Crystal and fixes for a few delivery issues.
Previous releases supported a wide range of Crystal Language versions, but ran into problems with version 1.17.x and beyond due to breaking changes in the standard library. This release works on 1.19.1 but also requires at least 1.19.1.
This release also fixes a bug, present since mid-2020 when HTTP signatures were first added, that resulted in signatures some fediverse servers wouldn't accept. Mastodon did, but with the proliferation of new ActivityPub servers, I increasingly encountered servers that did not.
Here's the full changelog:
Fixed
keyId now includes #main-key fragment.Changed
It's always good to stay up-to-date on releases. But if your platform doesn't yet support 1.19.1, I've also released a parallel branch that still runs on 1.16.3 and earlier. I'll maintain that branch for the next few releases to give everyone time to upgrade.

The latest release of Ktistec addresses the shortcomings of the previous release that became apparent after using quote posts in production for a few days. So far, there have been no major bugs, but there was room for improvement.
Here's the full changelog.
Added
Changed
siteName to more standard nodeName.Fixed
I added a FEDERATION.md document to the project. This is documentation required by FEP-67ff on "information necessary for achieving interoperability with a federated service". The document describes, at a high level, what federation protocols and standards Ktistec currently supports.

working on writing FEDERATION.md i already found one easily fixable deviation (siteName instead of nodeName in nodeinfo).

Before creating and publishing FEDERATION.md for #ktistec I wanted to understand what existing practice looked like across the Fediverse.
FEP-67ff describes the requirements of the FEDERATION.md file in loose terms and provides a non-normative template. I scraped the URLs of FEDERATION.md files from FEP-67ff itself and confirmed I could fetch them. The FEP listed 30 accessible projects (31 total, but one project—FIRM—does not appear to exist).
If a file had a section with the heading "Supported FEPs" per the non-normative template, I only looked there for supported FEPs. Otherwise I scanned the entire document.
Implemented FEPs, ranked by the number of implementations that attest support, are:
FEP Name # ---- --------------------------------------------------------- -- 67ff FEDERATION.md 18 f1d5 NodeInfo in Fediverse Software 16 8b32 Object Integrity Proofs 7 044f Consent-respecting quote posts 7 2677 Identifying the Application Actor 7 e232 Object Links 6 1b12 Group federation 6 3b86 Activity Intents 6 521a Representing actor's public keys 5 2c59 Discovery of a Webfinger address from an ActivityPub actor 5 7888 Demystifying the context property 5 5feb Search indexing consent for actors 5 4adb Dereferencing identifiers with webfinger 4 d556 Server-Level Actor Discovery Using WebFinger 4 fb2a Actor metadata 4 ef61 Portable Objects 4 8fcf Followers collection synchronization across servers 4 844e Capability discovery 4 7628 Move actor 3 61cf The OpenWebAuth Protocol 3 c390 Identity Proofs 3 400e Publicly-appendable ActivityPub collections 3 c0e0 Emoji reactions 3 0151 NodeInfo in Fediverse Software (2025 edition) 3 fffd Proxy Objects 2 f228 Backfilling conversations 2 fe34 Origin-based security model 2 eb48 Hashtags 2 171b Conversation Containers 2 a5c5 Web Syndication Methods 2
There are obvious flaws in the methodology. Or maybe in the data. Only 18 out of the 30 projects I could access had a FEDERATION.md that attested FEDERATION.md support. Only 19 mentioned "FEDERATION.md". Only 21 mentioned "67ff". The remaining projects clearly did support FEP-67ff—the file itself was evidence. (FEDERATION.md is not meant to be machine readable—there's an issue about that).
It was more difficult to rank implemented federation protocols. I extracted keywords from documents with a "Supported federation protocols and standards" section and created a dictionary of terms. If a file had a section with the heading "Supported federation protocols and standards", I only looked there. Otherwise I scanned the entire document.
Feature # ---------------- -- activitypub 26 webfinger 24 http_signatures 21 nodeinfo 19 json_ld 2 ld_signatures 2 ostatus 2 authorized_fetch 1 atproto 1
If time allows, I'm going to try to rank these documents by "utility", though I haven't yet determined the exact metric. These documents clearly provide valuable information, but their lack of standardization makes them harder to analyze systematically.