R1 cleanup: collAnon and dead code gone, docs current, every peer's scenario in one sweep
Build / Build (push) Successful in 1m7s
Build / Build (push) Successful in 1m7s
Starts the completion program (docs/ROADMAP.md, "Owner decisions on finishing everything", 2026-10-17). - Dead code: the commented-out collAnon blocks (discussions, seeding, admin user lists, HTTP/3, the old signature middleware), the empty PrivaPubWorkersConfiguration, PublicAvatarUsersService and UserPolicyType, unused helpers, the second IPasswordHasher registration, the PasswordGenerator package, SignUpAsync/LoginAsync's unused invitation parameters. "Starting PrivaPub"; a signed-in login is sent to "/", not to "/discussions". - Stored fields nothing read: RootUser.Contacts and ResetPasswordToken*, the local Avatar.AvatarServer, EmailRecovery.RecoveryCode/RequestIP/CreationDate, MongoSettings.LogsDatabase, and AppConfiguration's upload/discussion keys, RequiresFirstTimeSetup and Version (old documents still load: MongoDB.Entities ignores extra elements). DmPost's indexes are no longer made. 49 collAnon keys leave FieldsNameResource in every language. - /clientapi/data/current-version answers the build's ref. UsersIds is a list that can't throw, and the admin routes leave the administrator out without mutating the request. - deploy.yml checks SecureMode on a name no persona can have, and the browser redirect on the directory's first local persona: @thepra is the administrator's own now. - Town: decePub's e2e remnants (expect, client.jsonl, the decePub column) and town/tests go; the dead gaps/load commands too. Mobilizon no longer keeps an event for a deleted test. - tools/pasture/sweep.sh runs every peer's scenario, batch by batch, as CLAUDE.md asks before a change to what PrivaPub sends. - Docs: CLAUDE.md's repo map, route table (every frozen route) and stale lines; ROADMAP's status (setup, v1.25.0, v1.26.0, the program C), the 2026-10-17 decisions, and dated notes where earlier text no longer holds; FEDERATION.md's FEP list (7888, f228, 7628, ae0c and 8967 supported) and the deploy's persona. Verified: dotnet build PrivaPub.sln -c Release (0 errors, no new warnings); bash -n on the touched scripts; py_compile on the town; the pasture's gts, mastodon and lemmy scenarios on this build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WpVCoDeM1qUTRp4fXQdfof
This commit is contained in:
1 parent
6727e1817a
commit
ff5e635dda
71 files changed
+238
-4767
No files matched your search
@@ -18,7 +18,7 @@ Its defining idea: **one private login owns several public personas.**
|
||||
Root and avatar are linked only through `RootToAvatar`.
|
||||
- **Personas must stay unlinkable** to other users and servers; only the instance admin can see the link.
|
||||
- **`Group` is an ActivityPub Group actor.** It has members, an invitation code and an optional password. Groups are
|
||||
becoming two kinds: a public **community** (FEP-1b12, Lemmy-compatible) and a private, invitation-only **circle**.
|
||||
of two kinds: a public **community** (FEP-1b12, Lemmy-compatible) and a private, invitation-only **circle**.
|
||||
- **`DmGroup` is a direct-message conversation.**
|
||||
- **`privapub` is the instance actor** (type Application). It signs fetches no persona should be tied to.
|
||||
- **`privapub_reports` is the reporter** (type Service, `LocalActorKind.Reporter`). It carries reports to Lemmy, which
|
||||
@@ -30,9 +30,9 @@ Its defining idea: **one private login owns several public personas.**
|
||||
shown as accounts.
|
||||
|
||||
Privacy features in the model:
|
||||
- location-ranged posts (`Post.Location`, `RangeKm`), to become local-only and never federated;
|
||||
- contacts a persona can share (`Avatar.SharedPersonalContacts`);
|
||||
- private notes (`RootUserNote`, `PersonalNote`).
|
||||
- location-ranged posts (`Post.Location`, `RangeKm`), local-only and never federated;
|
||||
- contacts a persona can share (`Avatar.SharedPersonalContacts`) and private notes (`RootUserNote`, `PersonalNote`)
|
||||
exist only as model classes, with no endpoint.
|
||||
|
||||
The intended client is the Mastodon client API (Tusky, Elk, Phanpy, Ivory), where each avatar logs in as its own
|
||||
account. The private `/clientapi` covers what Mastodon can't express. `thepra/decePubClient`
|
||||
@@ -56,10 +56,17 @@ actor-scoped route gets a name in the same spirit, agreed with the owner, and a
|
||||
| Activities | `/peasants/{name}/grunts/{id}` (`create-{postId}` resolves) |
|
||||
| DM context | `/peasants/{name}/whispers/{id}` |
|
||||
| Quote permission (FEP-044f `QuoteAuthorization`) | `/peasants/{name}/parrot-licences/{id}` |
|
||||
| Featured (pinned posts) | `/peasants/{name}/trophies` |
|
||||
| Featured tags | `/peasants/{name}/tattoos` |
|
||||
| Wall (FEP-400e) | `/peasants/{name}/graffiti` |
|
||||
| Followers synchronisation (FEP-8fcf) | `/peasants/{name}/groupies/roll-call` |
|
||||
| A group's members and moderators | `/peasants/{name}/flock`, `/peasants/{name}/wardens` |
|
||||
| A post's replies and thread | `/peasants/{name}/scribbles/{id}/replies`, `/peasants/{name}/scribbles/{id}/context` |
|
||||
| Token refresh | `/clientapi/user/sniff/again` |
|
||||
|
||||
Agreed for later phases: `/gossip`, `/drool`, `/echoes` (replies, likes, shares), `/trophies` (featured), `/tattoos`
|
||||
(featured tags), `/flock` and `/wardens` (group members and moderators).
|
||||
All of these have federated, so they are frozen. Agreed for later: `/drool` and `/echoes` (likes, shares). `/gossip` was
|
||||
agreed for replies before they were served at `…/scribbles/{id}/replies` (2026-10-06); whether it is still wanted is
|
||||
asked in the completion program's R10.
|
||||
|
||||
Routes other software looks up by name stay conventional:
|
||||
- `/.well-known/*` and `/nodeinfo/*`;
|
||||
@@ -74,15 +81,21 @@ PrivaPub.sln
|
||||
PrivaPub/ ASP.NET Core Web API, net10.0
|
||||
Program.cs host, Mongo init (GUIDs Standard), pipeline, /build.json
|
||||
Middleware/SocialPubConfigurations.cs every DI registration (auth, federation, services, swagger, CORS)
|
||||
Controllers/ClientToServer/ /clientapi/*: RootUser (signup/login/invitations/recovery), PrivateAvatar,
|
||||
Group, Post (posts + DMs), Admin, Data
|
||||
Controllers/ClientToServer/ /clientapi/*: RootUser (signup, setup, login, invitations, recovery), PrivateAvatar,
|
||||
Group, Post (posts + DMs), Social, Timeline, Data, PersonaArchive, Moderator (reports),
|
||||
Admin (logins), DomainBlock, Statistics, Backup
|
||||
Infrastructure/
|
||||
Http/ FederationHttp + SafeHttpHandlerFactory + IpRangeGuard: the only way out
|
||||
Jobs/ JobQueue (leases), JobWorker, Backoff, HostCircuitBreaker
|
||||
Ids/ PrivacyIds (day-only ids for personas and groups, arrival-ordered ids for remote posts)
|
||||
Data/ Indexes (created at start), EntityMaps.Warm, Migrations/_NNN_*.cs
|
||||
Cli/ AdminCommands (`PrivaPub admin promote|demote <root>`)
|
||||
Cli/ AdminCommands (`PrivaPub admin promote|demote|create-root|move-persona|delete-root`,
|
||||
`media audit`, `backup`, `backups`, `restore`)
|
||||
Backup/ ServerBackup, ServerRestore, ProtectiveMerge, MaintenanceLock, TransferStore
|
||||
Geo/ GeoLocator, GeoUpdater (DB-IP Lite), CdnCatalog, CdnUpdater
|
||||
Statistics/ InteractionLedger, Rollup, TrafficMeter, StatisticsOptions
|
||||
RateLimiting.cs accounts (per client address) and inbox (per sending origin) policies
|
||||
RegistrationOptions.cs who may make a login (`Registrations:Mode`)
|
||||
Federation/
|
||||
Controllers/ PeasantsController (actor, outbox, followers, following, posts, inboxes),
|
||||
WellKnownController (webfinger, nodeinfo), UsersController (redirect)
|
||||
@@ -100,13 +113,17 @@ PrivaPub/ ASP.NET Core Web API, net10.0
|
||||
ReplyRelay (third-party replies to a persona's posts passed on to its followers)
|
||||
Outbox/ OutboxPublisher (who a post goes to), DeliveryService (queues jobs) + DeliveryJobHandler
|
||||
Rendering/ ActivityPubRenderer (Mastodon @context, actors, notes, collections)
|
||||
Crawler/ Crawler, PeerHosts, RobotsTxt (the opt-in crawler behind `/stargazing`)
|
||||
Relays/ Relays (the instance actor's relay subscriptions)
|
||||
Domain/
|
||||
Content/ ContentRenderer (Markdown or plain text → HTML with h-card mentions and hashtags)
|
||||
Social/ FollowService (local in-process, remote Follow/Accept), Notifications
|
||||
Timelines/ Fanout (TimelineEntry rows, Mastodon's home rules), TimelineService
|
||||
Privacy/ VisibilityPolicy (IsPublic expression, CanSee)
|
||||
Relationships/ RelationshipService (blocks, mutes, account domain blocks; Hidden), ReportService
|
||||
Media/ MediaService (libvips, ffmpeg remux, blurhash), MediaProxy, MediaJanitor
|
||||
Media/ MediaService (libvips, ffmpeg, blurhash), MediaProxy, MediaJanitor
|
||||
Portability/ persona archives exported and imported (Mastodon's layout)
|
||||
Statistics/ StatisticsQueries, PublicGeo, ServerPlaces, SelfLocation
|
||||
Domain/Statuses/ StatusService: publish, edit, remove, favourite, reblog, for a persona (both client APIs use it);
|
||||
InteractionApprovals: GoToSocial's canReply/canLike/canAnnounce, judged, asked and answered;
|
||||
Participations: a persona's Join and Leave of a remote event, and the organiser's answer
|
||||
@@ -114,7 +131,9 @@ PrivaPub/ ASP.NET Core Web API, net10.0
|
||||
Auth/ OpenIddict setup (keys in Mongo), MastodonScopes, TokenController, OAuthPruner
|
||||
Infrastructure/ MastodonController (avatar context, scopes, errors, Link), MastodonParams, MastodonJson, Page
|
||||
Entities/ Mappers/ Mastodon entities; MastodonMapper (Account, Status), AccountSearch
|
||||
Controllers/ apps, instance, accounts, statuses, timelines, notifications, search, stubs
|
||||
Controllers/ apps, instance, accounts, statuses, timelines, notifications, search, lists, filters,
|
||||
media, polls, reactions, reports, scheduled statuses, streaming, tags, trends, cdns,
|
||||
provenance; the stubs are `StubsController` in `SearchController.cs`
|
||||
Web/Pages/ Razor: /@{user}, /@{user}/{id} (public posts only, strict CSP, noindex);
|
||||
OAuth/: /oauth/login (root password), /oauth/authorize (choose persona, consent)
|
||||
Services/ RootUsersService, GroupUsersService, PostsService, AppConfigurationService, …
|
||||
@@ -127,8 +146,8 @@ deploy/ nginx vhost, systemd units (privapub, privapub
|
||||
docs/ROADMAP.md decisions + phased plan
|
||||
```
|
||||
|
||||
The roadmap moves code towards `Infrastructure/`, `Federation/`, `Domain/`, `Api/{ClientApi,Mastodon}` and `Web/`,
|
||||
one pure-move commit at a time.
|
||||
The planned move of `/clientapi` into `Api/ClientApi` was dropped (2026-10-17): it stays in `Controllers/ClientToServer/`
|
||||
and `Services/`.
|
||||
|
||||
## Commands
|
||||
|
||||
@@ -607,11 +626,12 @@ Interop is checked against real servers, starting with the workstation's own pas
|
||||
```bash
|
||||
DOTNET=~/.dotnet/dotnet tools/pasture/run.sh up [gts mastodon ...] # podman: PrivaPub + the named peers (default gts) + Mongo, behind Caddy
|
||||
tools/pasture/interop.sh [gts mastodon ...] # each peer's scenario, then what PrivaPub's statistics saw of it
|
||||
tools/pasture/sweep.sh [A|B|C|D ...] # every peer's scenario, batch by batch (up, interop, down); out/sweep-<batch>.log
|
||||
tools/pasture/run.sh down # removes every pasture container and volume
|
||||
```
|
||||
|
||||
- **A change to what PrivaPub sends** (the `@context`, an actor's properties, an activity's shape, a delivery's headers)
|
||||
is run against every peer's scenario before it is committed, not only the peers it was written for. One reader
|
||||
is run against every peer's scenario before it is committed, not only the peers it was written for (`sweep.sh`). One reader
|
||||
stricter than the rest fails on it alone: the 2026-10-06 `proof` term passed every peer but Smithereen, whose JSON-LD
|
||||
1.0 reader refused every document carrying it.
|
||||
- **Layout:** `lib/pasture.sh` (network, Caddy, Mongo, PrivaPub), `peers/<name>.sh` (`<name>_up`, plus `peers/shared.sh`
|
||||
@@ -664,7 +684,7 @@ tools/pasture/run.sh down # removes e
|
||||
read from its `user_relationships`. `akkoma_token <user>` signs one of its users in. 45 checks.
|
||||
- **Lemmy (1.0.0-beta.2):** the backend alone on the shared Postgres, its admin made by `setup` in the generated
|
||||
`config.hjson`. It trusts Caddy's CA through `SSL_CERT_FILE` and reaches the network through
|
||||
`DANGER_FEDERATION_ALLOW_LOCAL_IP=1`; 0.19 cannot join (its rustls trusts only its bundled roots). Its API is
|
||||
`DANGER_FEDERATION_ALLOW_LOCAL_IP=1`; 0.19's release can't join as it is, so it runs as its own build (`lemmy19`, below). Its API is
|
||||
`/api/v4/<path>` with a bearer token (`lm` in the scenario), and `sort` values are lowercase. It logs no refused
|
||||
activity at `warn` (`LEMMY_LOG` sets `RUST_LOG`); the reason is in the 400's body. It answers our community's echo of
|
||||
its own activity and every bare `Announce{object}` 400 by design, and the echo is still needed (see
|
||||
|
||||
Reference in new issue
Block a user