All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- LitePub mutual follow support: relay sends Follow back to instances that follow the relay actor directly, and handles Accept/Reject responses
- Relay support for Move, Add, Remove, and Undo (non-Follow) activity types
- Relay support for Like and EmojiReact activity types
- Periodic instance info fetching for subscriber instances with software name/version, registration status, staff accounts, reachability, and favicon displayed on the homepage
INSTANCE_INFO_CHECK_INTERVALenvironment variable to configure instance info check frequency (default: 60 seconds, minimum: 60)DEFAULT_QUEUE_WORKER_COUNT,DELIVERY_QUEUE_WORKER_COUNT, andINSTANCE_INFO_QUEUE_WORKER_COUNTenvironment variables for configurable queue worker countsSOURCE_REPOSITORY_URLandSOURCE_REPOSITORY_COMMIT_PATHenvironment variables for configurable source repository links
- Homepage instance list now displays subscribers in join order instead of alphabetical order
- Prometheus metrics endpoint moved to a dedicated server controlled by
METRICS_BINDenvironment variable - Delivery jobs now run on a dedicated queue separate from the default job queue
- Instance info checks now run on a dedicated
instanceInfoqueue separate from the default job queue, and double as a reachability heartbeat at a default 60-second interval - Failed instance info checks preserve last-known software/version/staff/favicon metadata while marking the instance unreachable, and back off exponentially (base 60s doubling per failure, capped at 30 minutes) with equal jitter before the next attempt
- Delivery retries now back off exponentially (base 60s doubling per attempt, capped at 30 minutes) with equal jitter instead of retrying immediately
DeliveryError.isRetryableclassification removed; retries are uniformly governed bymaxRetryCountand the new backoff- Instance info cache TTL is now a fixed 1 hour, decoupled from the check interval
- Japanese locale: use 登録 (registration) instead of 購読 (subscription) for more natural relay terminology
- NodeInfo response now includes required
servicesfield and uses free-formmetadataper NodeInfo 2.1 schema - InstanceInfoFetchJob error logs now include the failing domain name for diagnosis
- Large ActivityPub payloads (e.g. long posts, many mentions) now accepted instead of returning 413 Payload Too Large
- Unified HTTP signature verification error responses on
/inboxto prevent oracle/fingerprinting attacks; all failure modes (missing/malformed Signature, stale Date, Digest mismatch, actor fetch error, invalid signature) now return identical401 Unauthorized "Signature verification failed"with server-side warning logs for operator debugging - Rejected subscriber state is now sticky: a repeat Follow from a rejected domain no longer silently reinstates the subscriber (previously auto-accept mode reset
.rejected→.accepted, making admin rejections effectively one-time deletes) - HTTP signatures on
/inboxnow requiredatein the signed headers list, and additionallydigeston POST, following Mastodon's enforcement. Without these, Date freshness and body integrity checks are not cryptographically bound to the signature; Misskey, Pleroma, and Akkoma senders already include both in practice
- ActivityPub relay server with HTTP Signature verification (draft-cavage-http-signatures-06)
- Inbox controller handling Follow, Undo, Create, Announce, Delete, and Update activities
- Pleroma/Akkoma compatibility: accept Follow with relay actor URL as object
- Signed HTTP GET requests for remote actor fetching, enabling compatibility with Mastodon Authorized Fetch (Secure Mode) and Pleroma
authorized_fetch_mode - Actor-signer domain validation to prevent activity forgery
- Digest header requirement and conditional Date header validation for POST requests
- Key ID resolution for both fragment-based (
#main-key) and path-based (/publickey) formats - Shared inbox (
endpoints.sharedInbox) support for efficient delivery - Flexible JSON-LD
@contextdecoding for mixed arrays (Pleroma format) - Flexible
actorfield decoding (string or object withid) - Activity deduplication via Redis with atomic SET NX EX and automatic TTL expiration
- Subscriber management with pending/accepted/rejected states and manual accept mode
- Domain blocking and restricted mode (allowlist) support
- Admin REST API with Bearer token authentication
- Admin CLI commands under
APRelay admin: list-subscribers, accept, reject, block, unblock, list-blocked-domains - Delivery system with Vapor Queues for reliable activity delivery with exponential backoff retry and smart error classification
- WebFinger, NodeInfo 2.1, and actor endpoint for federation discovery
- RSA-4096 key pair generation and storage
- Prometheus metrics for inbox activities and delivery performance
- Multi-language homepage with English, Korean, and Japanese translations, auto-selected via
Accept-Languageheader Localizeri18n system with JSON translation files and Accept-Language quality factor parsing- Dark mode support and responsive homepage with status badges, instance grid, and subscriber join dates
VersionGeneratorPluginbuild plugin for automatic version and commit detection from git at build timeUser-Agentheader on outgoing HTTP requests andServerresponse header with relay version info- Environment variables:
RELAY_URL,REDIS_URL,ADMIN_TOKEN,RELAY_NAME,RELAY_DESCRIPTION,RELAY_FOOTER,MANUAL_ACCEPT,RESTRICTED_MODE,AP_RELAY_VERSION,SOURCE_COMMIT,LOG_LEVEL - Per-locale environment variable overrides for
RELAY_NAME,RELAY_DESCRIPTION, andRELAY_FOOTER(e.g.RELAY_NAME__KO) - GitHub Actions CI/CD: test workflow with swiftly-based Swift toolchain on Ubuntu and macOS, deploy workflow for multi-platform Docker images (amd64/arm64) to GitHub Container Registry
- Docker multi-stage build with jemalloc, static Swift stdlib linking, and non-root user execution
- Docker Compose with Valkey (Redis-compatible) service
- Strict memory safety checking (SE-0458) enabled for all targets
- Comprehensive test suite: inbox integration, signature middleware, admin API, and localization tests
- Constant-time comparison for admin token authentication via HMAC-based equality
- Unified admin API authentication error responses to prevent configuration state disclosure; all failure cases return identical
401 Unauthorizedwith server-side warning logs for operator debugging