Anahita Services
The server, one service at a time. Each does one thing, all are reached through one gateway, and the optional ones can be left out.
Signing in
Signing in and signing up, for Anahita’s own apps and anybody else’s.
- OAuth 2.0 and OpenID Connect
- A complete provider: discovery, keys, UserInfo, refresh tokens, introspection and revocation; PKCE for apps that hold no secret, client credentials for services.
- No tokens in the browser
- A backend for frontend (BFF): Anahita Web holds only an HttpOnly, SameSite session cookie, and the tokens stay on the server, traded for the cookie on each request.
- Passkeys
- WebAuthn, with Face ID, Touch ID, Windows Hello or a security key. A passkey is both factors.
- Two-factor
- Codes from any authenticator app, their secrets encrypted at rest.
- OTP by email
- A one-time password by email: signing in without a password.
- Signing keys
- Rotated every 90 days, and sealed with a key of your own or AWS KMS: reading the database is not enough to make a token.
- Who may join
- Invitations, applications to join, and the agreements a member accepts.
- Guarded
- Limits on guessing codes and passwords, and a one-time token on every form.
Profiles and the graph
actor-service
Every kind of profile, in one service.
- People
- A profile at a username, made when somebody signs up.
- Groups
- Made by members, with administrators and followers; a group can host events.
- Events
- A start and an end in their own time zone, how many may go, and where to join online; going or maybe, calling it off, and a calendar file.
- Websites
- A website’s feed, followed like a profile.
- Every kind
- An avatar and a cover, followers, invitations, who may see and do what, and the same life from enabled to archived to deleted.
Who follows, blocks and subscribes to whom.
- Follow requests
- A profile can ask to approve its followers, and shows strangers only its name and picture.
- Invitations
- Up to 50 followers invited to a group or event at once; unanswered ones lapse after 30 days.
- Blocks that hold
- A block ends follows both ways, and is sent on to the fediverse.
- Each person’s say
- Who may mention them, and who may tag them in photos, or approve each first.
- Group rules
- A group or event with rules is followed only once each rule is agreed to.
identity-image-service
The avatars and covers of profiles and posts.
- Safe images
- Each upload is judged by its bytes, turned upright and encoded afresh; nothing is kept as it arrived.
- Addresses that stay
- A public profile’s pictures keep one address, so other servers can link to them for good.
graph-grpc-service
The graph every other service reads: profiles and posts are its nodes, and the ties between them its edges.
- One gate
- Feeds, search, notifications and recommendations all ask one check of who may see what.
- Identifiers for good
- Every node has a random UUID that never changes, used in every address other servers are given.
- Threads in one go
- Up to ten notes written as a thread are saved together, all or none.
- Purges that finish
- Deleting a profile’s posts goes in batches it can resume, and keeps its handle from being taken.
Posts and media
Notes, articles and topics.
- Drafts
- Articles and topics can be kept as drafts and published when ready.
- Embeds and citations
- An address on a line of its own shows the post or a card for the page; citations are counted and listed as “Cited by”.
- Quotes by consent
- Authors choose who may quote them, and can take their post out of any quote.
- Who may reply
- Anyone, nobody, followers, people they follow or people mentioned; and replies can be hidden.
- Private saves
- What somebody saves is seen by them alone: nothing is counted, and the author is never told.
Photo posts.
- Up to twenty images
- In one post, with one caption and one audience.
- Alt text
- A description of up to 2,000 characters for each image.
- Nothing hidden in the file
- Each image is encoded afresh at six sizes, never enlarged, so only the picture is kept.
- Downloads by consent
- Full size only if the author allows it, and never counted.
Video posts. A worker makes each video ready for every screen.
- Straight to storage
- The browser sends a video in parts directly to object storage.
- Several sizes
- MP4 at 1080, 720 and 360 by default, up to 4K, with a poster frame.
- Nothing hidden in the file
- Every file shown is encoded afresh, and the original is deleted.
- GIFs as loops
- Animated GIFs become silent looping videos, a fraction of the size.
- Checked on every play
- Each play checks again that the viewer may see the post.
Hashtags.
- Any language
- Letters of any script, digits and emoji, whatever their case.
- Fair trending
- Each profile counts once, only public posts count, and the window is the operator’s.
- Suggestions while writing
- Offered as you type, or from the title (“open science” finds #OpenScience).
- From elsewhere too
- A hashtag in a post from another server leads to this instance’s own page for it.
location-service
The locations posts are tagged with, and finding them on a map.
- Open maps
- Addresses found with OpenStreetMap’s Photon and Nominatim, which can be run yourself.
- The operator decides
- Who may add a location: administrators, anyone signed in, or super administrators.
- Understood elsewhere
- Up to five per post, sent to other servers in the form Pixelfed reads.
- Nearby and trending
- Locations within a distance of a point, and those used most lately.
like-service
Likes.
- With permissions
- Each profile chooses who may like what it posts: followers by default.
- Lists that respect privacy
- Who liked a post shows only the people its reader may see.
- Across networks
- Likes cross to and from the fediverse and Bluesky.
Feeds, search and notifications
The chronological feed, reposts, and the custom feeds people make.
- Chronological first
- The first tab is always who you follow, newest first, and it cannot be removed.
- Custom feeds
- Made from sources, filtered by hashtag, keyword, location, language and kind of post.
- Near me
- Posts within 1 to 500 km, with the reader’s position never kept.
- Never wider
- A shared feed shows each reader only what they could already see.
- Share, copy, pin
- Feeds can be shared, found, copied and kept on the home page.
Search for people, groups, events, posts and shared feeds; the most relevant first, or the newest.
- Old and useful
- How fast interest fades is the operator’s to set: a year by default, or never.
- Each person’s weights
- Six signals each person can turn down or up, kept wherever they sign in.
- Any script
- “Montréal” and “東京” are found as typed.
Recommendations of who to follow.
- Reasons, not a model
- Worked out from the graph by written rules, and shown with their reasons.
- In each person’s hands
- Weights for each reason, “Not interested”, and not being suggested at all.
- Replaceable
- Leave it out, or run another service that answers the same way.
Notifications in the app.
- Never emailed
- Notifications stay in the app; a test fails if a service starts sending mail.
- Gone with their cause
- A deleted post or a like taken back takes its notification with it.
- Grouped
- “Worf and 2 others liked your post”.
- Act in place
- Accept a follow request, approve a tag or follow back, right from the notification.
The open social web
Makes the instance a server of the fediverse, for the people who choose to be found there.
- Both ways
- Follows, notes, photos, videos, articles, replies, likes and reposts, with Mastodon, Pixelfed, GoToSocial and others.
- Signed and checked
- Each person has their own signing keys, kept encrypted; every message in is checked against its sender.
- Delivered
- Sending is retried for two days, and what goes missing is found and sent again.
- Refusing servers
- Super administrators can refuse a domain and everything under it.
Bluesky: following profiles there, and posting there for whoever connects their own Bluesky account.
- For everyone
- Anybody can follow Bluesky profiles from here, without a Bluesky account.
- Post as yourself
- Connect your Bluesky account to post, reply, like, repost and follow there.
- Password never kept
- The app password is traded once for a token, which is kept encrypted.
- Bring your follows
- Follow here the people you already follow on Bluesky.
Follow a website’s feed like a profile. A worker reads every feed and posts what is new.
- Any feed
- RSS, Atom or JSON Feed, from WordPress, a static site or a podcast; followed here and from the fediverse.
- Proven domains
- A DNS record or a file on the site, checked again every day.
- Polite
- Feeds are read every 30 minutes, or at once through WebSub, and less often when they fail.
- Replies as the site
- Its administrators can answer readers as the website.
The card under a note that links to a page: its title and picture.
- Safe fetching
- Web addresses only; private and internal addresses are refused, and every redirect is checked again.
- Private reading
- The picture is served from this instance, so reading a note tells the linked site nothing.
- Cards that last
- The card is kept with the note, and reads the same if the page changes or goes.
Safety and your data
Reports of people and posts, and the cases administrators decide.
- Cases, not piles
- Everyone who reports the same thing joins one case.
- Your own reasons
- The list of reasons can be replaced with your own, in your languages.
- Rules
- A report can name a site’s, group’s or event’s rule; group administrators see those without the reporters’ names.
- Reporters protected
- The person reported is never told who reported them.
A copy of your own data, made by a worker and kept for a while to download.
- Everything
- Every post, private ones too, full-size photos and videos, follows, followers, blocks, likes and saves.
- Readable anywhere
- A web page in the archive works with no connection and no scripts.
- Portable
- ActivityStreams files that other fediverse software reads.
- Asked for in person
- Each copy needs a fresh proof of who you are, and is kept for 7 days.
Upkeep by the clock.
- Grace, then gone
- A deleted profile is purged when its 30 days of grace are over.
- Resumable
- A purge that was interrupted carries on where it stopped.
- Events
- A reminder the day before, and archived 30 days after.
- Tidying
- Photos uploaded but never posted, and invitations nobody answered, are removed.
Storage, mail and upkeep
Files, on any S3-compatible object storage.
- Any store
- AWS, Garage or any other S3-compatible store, with a test to check a new one.
- Judged by its bytes
- What a file says it is counts for nothing: an HTML file named photo.png is refused.
- Private by default
- The store stays private, and every link to a file is signed and short-lived.
Email, over SMTP.
- Any provider
- Any SMTP server or relay, with TLS.
- Account mail only
- Signing in and account messages; nothing else is ever mailed.
- Safe while developing
- In development, every message goes to the developer instead.
Serves Anahita Web, with each page’s own title and picture, so a shared link shows as itself.
- The same for all
- Crawlers and people are sent the same page; nobody is told apart.
- Public only
- A page is described only if its post and profile are public.
- Handles on your domain
- The fediverse finds @name@your-domain at the main address.
migration-job
Brings the database up to date at each upgrade.
- Three paths
- A fresh database, an upgrade in place from the PHP Anahita, or the newest changes.
- Proven the same
- A test compares a fresh database and an upgraded one, column by column.
Underneath
What the services keep their data in. Each can be run by you, or bought as a managed service.
MySQL
Everything that is kept.
Redis
Sessions.
RabbitMQ
Events between the services.
Object storage
Photos, videos and files, on any S3-compatible store: Garage on your own machine, your own or your cloud’s live.