[feature] Use hidesToPublicFromUnauthedWeb and hidesCcPublicFromUnauthedWeb properties for web visibility of statuses (#4315)

This pull request implements two new properties on ActivityPub actors: `hidesToPublicFromUnauthedWeb` and `hidesCcPublicFromUnauthedWeb`.

As documented, these properties allow actors to signal their preference for whether or not their posts should be hidden from unauthenticated web views (ie., web pages like the GtS frontend, web apps like the Mastodon frontend, web APIs like the Mastodon public timeline API, etc). This allows remote accounts to *opt in* to having their unlisted visibility posts shown in (for example) the replies section of the web view of a GtS thread. In future, we can also use these properties to determine whether we should show boosts of a remote actor's post on a GtS profile, and that sort of thing.

In keeping with our stance around privacy by default, GtS assumes `true` for `hidesCcPublicFromUnauthedWeb` if the property is not set on a remote actor, ie., hide unlisted/unlocked posts by default. `hidesToPublicFromUnauthedWeb` is assumed to be `false` if the property is not set on a remote actor, ie., show public posts by default.

~~WIP as I still want to work on the documentation for this a bit.~~

New props are already in the namespace document: https://gotosocial.org/ns

Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4315
Reviewed-by: kim <gruf@noreply.codeberg.org>
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
This commit is contained in:
tobi 2025-07-09 16:50:25 +02:00 committed by kim
commit dcfc9b7885
159 changed files with 10900 additions and 2918 deletions

View file

@ -248,6 +248,90 @@ Another difference between GoToSocial and other server implementations is that G
Instead, to build a view of a GoToSocial user's pinned posts, it is recommended that remote instances simply poll a GoToSocial Actor's `featured` collection every so often, and add/remove posts in their cached representation as appropriate.
## `hidesToPublicFromUnauthedWeb` and `hidesCcPublicFromUnauthedWeb`
GoToSocial uses the properties `hidesToPublicFromUnauthedWeb` and `hidesCcPublicFromUnauthedWeb` to indicate whether an actor prefers to hide posts addressed `to` or `cc` public from unauthenticated (ie., logged-out) visitors to web pages, web apps, and web APIs.
Some background for this: many ActivityPub server softwares allow unauthenticated visitors to the profile web page of an actor to see a list of posts that an actor has created that are addressed either `to` or `cc` public. These are often called "public" posts, and "unlisted", "unlocked", or "quiet public" posts, respectively. GoToSocial provides [a settings flag](../user_guide/settings.md#visibility-level-of-posts-to-show-on-your-profile) that allows GtS accounts to hide posts from the web view of their profile, as one layer of protection to make it more of a nuisance to scrape/stalk someone with a GtS account.
While this setting works for hiding posts of an actor *on their own instance*, prior to GoToSocial v0.20.0, this preference was not federated out to other instances, nor was it federated in from other instances. This leads to two problems:
1. Many other fedi server softwares permit logged-out visitors, via a web app, to look up profiles of *remote* accounts, and to see public and unlisted posts created by those accounts. This means that it is trivial to work around the ability of GtS users to hide their posts from the web. For example, say a GtS user at `@someone@gts.example.org` locks down their profile by setting the visibility of posts on their profile to "none"; this prevents visitors to `gts.example.org` from seeing posts, but one could visit eg. `mastodon.example.org` and, while logged out, look up `@someone@gts.example.org`, and see all the posts there that have been sent to, or dereferenced by, actors on `mastodon.example.org`. This makes the GtS user's choice to hide their posts significantly less meaningful.
2. In an effort to support this extra layer of privacy, by default GoToSocial instances do not show posts from remote instances unless they are addressed `to` public. For example, if someone from `mastodon.example.org` were to reply to a post by `@someone@gts.example.org`, and the reply was only addressed `cc` public instead of `to` public, the GtS instance `gts.example.org` would *not* show that reply in the web view, as it could not determine the preferences of the user from `mastodon.example.org` with regard to showing the "quiet public" post to logged-out visitors to the web page. This could be frustrating for the GtS user, as they might want to show a more complete picture of the thread that they started, right there on their instance; this could also frustrate the Mastodon user, as are used to their "quiet public" posts being visible on the web even when logged out.
The actor properties `hidesToPublicFromUnauthedWeb` and `hidesCcPublicFromUnauthedWeb` are a move towards solving these issues, by allowing actors to signal their preferences for hiding or showing `to`- and/or `cc`-public posts to unauthenticated visitors via the web.
For example, the following actor representation indicates that the actor is happy to show both "unlisted" and "public" posts via unauthed web view (this represents the de-facto default for actors on Mastodon and most other server softwares):
```json
{
"@context": [
"https://gotosocial.org/ns",
"https://www.w3.org/ns/activitystreams"
],
"type": "Person",
[... other properties here ...]
"hidesToPublicFromUnauthedWeb": false,
"hidesCcPublicFromUnauthedWeb": false,
[... other properties here ...]
}
```
By contrast, the following indicates that the actor hides "unlisted" posts but is happy to show "public" posts unauthed (this is the default for actors on GtS instances):
```json
{
"@context": [
"https://gotosocial.org/ns",
"https://www.w3.org/ns/activitystreams"
],
"type": "Person",
[... other properties here ...]
"hidesToPublicFromUnauthedWeb": false,
"hidesCcPublicFromUnauthedWeb": true,
[... other properties here ...]
}
```
And the following shows that the actor wants to show no posts unauthed at all:
```json
{
"@context": [
"https://gotosocial.org/ns",
"https://www.w3.org/ns/activitystreams"
],
"type": "Person",
[... other properties here ...]
"hidesToPublicFromUnauthedWeb": true,
"hidesCcPublicFromUnauthedWeb": true,
[... other properties here ...]
}
```
Both `hidesToPublicFromUnauthedWeb` and `hidesCcPublicFromUnauthedWeb` are defined in [the GoToSocial json-ld `@context` document](https://gotosocial.org/ns).
In line with its emphasis on having people opt-in to greater visibility rather than opt-out, when receiving a post from a remote actor that does not set these flags, GoToSocial assumes `hidesToPublicFromUnauthedWeb` = `false`, and `hidesCcPublicFromUnauthedWeb` = `true`. That is, the pre-v0.20.x behavior of GoToSocial is still the default for remote servers that don't (yet) use these flags.
!!! note
While unusual, it's possible for an actor to also specify that they want to show "unlisted" posts but hide "public" ones:
```json
{
"@context": [
"https://gotosocial.org/ns",
"https://www.w3.org/ns/activitystreams"
],
"type": "Person",
[... other properties here ...]
"hidesToPublicFromUnauthedWeb": true,
"hidesCcPublicFromUnauthedWeb": false,
[... other properties here ...]
}
```
GoToSocial respects these flags for incoming posts, but it does not let accounts set this combination of flags for outgoing posts. It may be desirable for other implementers to also prevent users from being able to set this state, as it doesn't make a lot of sense.
## Actor Migration / Aliasing
GoToSocial supports account migration from one instance/server to another through a combination of the `Move` activity, and the Actor Object properties `alsoKnownAs` and `movedTo`.