From 60bf21b019b4e843c66747403edd1cf9cf1a13d8 Mon Sep 17 00:00:00 2001 From: thepra Date: Thu, 1 Oct 2026 11:28:37 +0200 Subject: [PATCH] CLAUDE.md describes the code after P1.1 The route table lists the themed names now in use, the repo map gains Jobs, Ids, Moderation, Domain and Web, and the invariants add the job queue, VisibilityPolicy and the rule for which remote posts are stored. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012CzABvBkbcFqoHdmi8b9WB --- CLAUDE.md | 51 ++++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 4a86513..79024e2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -37,26 +37,19 @@ actor-scoped route gets a name in the same spirit, agreed with the owner, and a | Thing | Route | |---|---| -| Actor | `/peasants/{name}` (`/users/{name}` 301-redirects here) | +| Actor | `/peasants/{name}` (`/users/{name}` 301-redirects here; browsers are sent to `/@{name}`) | | Inbox | `/peasants/{name}/mouth` | -| Outbox | `/peasants/{name}/anus` | +| Outbox | `/peasants/{name}/anus` (`?page=true[&max_id=]` for pages) | | Shared inbox | `/human-centipede` (also `/peasants/{name}/human-centipede`) | +| Followers | `/peasants/{name}/groupies` | +| Following | `/peasants/{name}/stalking` | +| Notes | `/peasants/{name}/scribbles/{id}` | +| Activities | `/peasants/{name}/grunts/{id}` (`create-{postId}` resolves) | +| DM context | `/peasants/{name}/whispers/{id}` | | Token refresh | `/clientapi/user/sniff/again` | -These are agreed for the roadmap and replace the conventional names still in the code today: - -| Thing | Route | Replaces | -|---|---|---| -| Followers | `/groupies` | `/followers` | -| Following | `/stalking` | `/following` | -| Notes | `/scribbles/{id}` | `/posts/{id}` | -| Activities | `/grunts/{id}` | `/activities/{id}` | -| Replies, likes, shares | `/gossip`, `/drool`, `/echoes` | | -| Featured | `/trophies` | | -| Featured tags | `/tattoos` | | -| Group members | `/flock` | | -| Group moderators | `/wardens` | | -| DM context | `/whispers/{id}` | | +Agreed for later phases: `/gossip`, `/drool`, `/echoes` (replies, likes, shares), `/trophies` (featured), `/tattoos` +(featured tags), `/flock` and `/wardens` (group members and moderators). Routes other software looks up by name stay conventional: - `/.well-known/*` and `/nodeinfo/*`; @@ -75,6 +68,8 @@ PrivaPub/ ASP.NET Core Web API, net10.0 Group, Post (posts + DMs), Admin, Data Infrastructure/ Http/ FederationHttp + SafeHttpHandlerFactory + IpRangeGuard: the only way out + Jobs/ JobQueue (leases), JobWorker, Backoff, HostCircuitBreaker + Ids/ PrivacyIds (day-only ids for personas and groups, published-time ids for remote posts) Data/ Indexes (created at start), EntityMaps.Warm, Migrations/_NNN_*.cs Cli/ AdminCommands (`PrivaPub admin promote|demote `) RateLimiting.cs accounts (per client address) and inbox (per sending origin) policies @@ -83,13 +78,18 @@ PrivaPub/ ASP.NET Core Web API, net10.0 WellKnownController (webfinger, nodeinfo), UsersController (redirect) Actors/ LocalActorService (LocalActor, Keys, ReservedName), RemoteActorService (authoritative fetch, key verification, WebFinger), ActorDocument (parser) - Objects/ Origin (same-origin rules), ContentSanitizer (HtmlSanitizer, Mastodon allowlist) + Objects/ Origin, ActivityJson, NoteParser, Addressing, ContentSanitizer + Moderation/ DomainBlocks (suspend / silence / reject media) Signing/ HttpSignatures (draft-cavage sign/verify) - Inbox/ InboxService (Follow/Undo/Create/Delete/Update) - Outbox/ DeliveryService + DeliveryWorker - Rendering/ ActivityPubRenderer (JsonObject builders) + Inbox/ InboxReceiver (verify, queue, 202) → InboxProcessor (job) → Handlers/{Follow,Undo,Create,Update,Delete} + Outbox/ DeliveryService (queues jobs) + DeliveryJobHandler + Rendering/ ActivityPubRenderer (Mastodon @context, actors, notes, collections) + Domain/ + Content/ ContentRenderer (Markdown or plain text → HTML with h-card mentions and hashtags) + Privacy/ VisibilityPolicy (IsPublic expression, CanSee) + Web/Pages/ Razor: /@{user}, /@{user}/{id} (public posts only, strict CSP, noindex) Services/ RootUsersService, GroupUsersService, PostsService, AppConfigurationService, … - Models/ Mongo entities: User/, Group/, Post/, Federation/, AppConfiguration + Models/ Mongo entities: User/, Group/, Post/, Federation/, Jobs/, AppConfiguration StaticServices/ DbEntities (Find accessors), AuthTokenManager (JWT), PasswordHasher Data/InitDb.cs first-run seeding (languages) PrivaPub.ClientModels/ DTOs + validation resources shared with clients @@ -157,8 +157,13 @@ cd /var/www/privapub.thepra.dev && sudo -u www-data ASPNETCORE_ENVIRONMENT=Produ 8. **Circles never federate.** A circle's actor, collections, WebFinger and inbox answer 404, and its posts are `IsLocalOnly`. Only communities are Group actors. 9. **A DM joins a conversation only by `DmGroup.ParticipantsKey`**, the exact set of its participants; a remote - `context` decides nothing. -10. **Durable delivery:** activities go out through the delivery queue, never inline in a request. + `context` decides nothing. DMs are `Post`s with `Visibility = Direct` and a `ConversationId` (`DmPost` is legacy). +10. **Nothing slow happens inside a request.** Deliveries and inbox processing are `Job`s (`Infrastructure/Jobs`): + leased, retried on Mastodon's curve, at most two per host, paused per host by `RemoteInstance`. The inbox answers + 202 once it has verified and queued; a handler must be idempotent (unique `ObjectURI`, job `DedupeKey`). +11. **Every "may anyone see this" goes through `VisibilityPolicy.IsPublic`;** a persona-specific read uses `CanSee`. +12. **Remote content is stored only when someone here asked for it:** a local persona addressed or mentioned, a reply to + a local post, or a community the author follows. Followers-only is detected by the author's stored `followers` URL. ## Privacy invariants