Owner decisions of 2026-10-06; personas' public posts go to relays

The owner decided four gated questions, now in ROADMAP: personas publish a wall (G-0009), their public posts go to the
relays PrivaPub subscribes to, public threads publish their replies and context, and FEP-8fcf follower digests are sent.

The first is in: a persona's own public post outside any group, its edit and its deletion also go to the relays that
accepted us, as Mastodon sends them; nothing less public, and no boost. Checked live (scenarios/relay.sh, 15 checks):
the post reaches Activity-Relay, and Mastodon through aode-relay's announce. Mastodon drops what Activity-Relay forwards
without an LD signature or FEP-8b32 proof, which PrivaPub does not add yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
This commit is contained in:
thepraandClaude Opus 5.5 committed 2026-10-06 07:08:37 +02:00
1 parent b45321f28d
commit 93e13e5563
8 files changed
+70 -21

No files matched your search

@@ -28,9 +28,11 @@ namespace PrivaPub.Federation.Outbox
readonly DbEntities _dbEntities;
readonly ILocalActorService _localActors;
readonly IDeliveryService _delivery;
readonly Relays.IRelays _relays;
public OutboxPublisher(DbEntities dbEntities, ILocalActorService localActors, IDeliveryService delivery)
public OutboxPublisher(DbEntities dbEntities, ILocalActorService localActors, IDeliveryService delivery, Relays.IRelays relays = default)
{
_relays = relays;
_dbEntities = dbEntities;
_localActors = localActors;
_delivery = delivery;
@@ -79,6 +81,12 @@ namespace PrivaPub.Federation.Outbox
inboxes.Add(inbox);
}
// a persona's own public post, outside any group, also goes to the relays we subscribe to (owner decision
// 2026-10-06), its edits and deletion with it
if (_relays != default && post.Visibility == PostVisibility.Public && author.Kind == LocalActorKind.Person
&& string.IsNullOrEmpty(post.ReblogOfPostId) && string.IsNullOrEmpty(post.GroupId))
inboxes.AddRange(await _relays.Inboxes(token));
return inboxes.Where(i => !string.IsNullOrEmpty(i)).Distinct(StringComparer.Ordinal).ToList();
}
+8 -1
View File
@@ -21,11 +21,13 @@ namespace PrivaPub.Federation.Relays
Task Reconcile(CancellationToken token);
Task<bool> Answered(JsonNode activity, ForeignAvatar actor, bool accepted, CancellationToken token);
Task<bool> Passes(string actorUri, CancellationToken token);
Task<IReadOnlyList<string>> Inboxes(CancellationToken token);
}
// Relays (Activity-Relay, aode-relay, pub-relay): the instance actor follows Public at each relay the configuration
// names, as Mastodon subscribes, and takes what they pass on: public posts, forwarded as their authors sent them (read
// again from their origin, as any forwarded post) or announced by the relay. Nothing of a persona's is sent to a relay.
// again from their origin, as any forwarded post) or announced by the relay. A persona's public posts go to the relays
// that accepted us (owner decision 2026-10-06), as Mastodon sends them; nothing else of a persona's does.
public class Relays : IRelays
{
static readonly TimeSpan AskAgain = TimeSpan.FromDays(1);
@@ -108,6 +110,11 @@ namespace PrivaPub.Federation.Relays
return accepted.Contains(actorUri);
}
// the inboxes of the relays that accepted our subscription, where a persona's public posts also go
public async Task<IReadOnlyList<string>> Inboxes(CancellationToken token) =>
(await DB.Default.Find<RelaySubscription>().Match(s => s.State == RelayState.Accepted).ExecuteAsync(token))
.Select(s => s.InboxURL).Where(i => !string.IsNullOrEmpty(i)).Distinct(StringComparer.Ordinal).ToList();
// the relay's actor, from its address or, for a relay named by its inbox, from the /actor beside it
async Task<ForeignAvatar> Resolve(string address, CancellationToken token)
{