Status with "limited" visibility not visible to recipient in Mastodon Web

So, after HTTP signature claimed to be invalid, I can now send activities to my test Mastodon instance. Here is what I send:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://vocatadev.pagekite.me/testcreate-priv-to-admin-5",
  "summary": "Tester left a note",
  "type": "Create",
  "actor": "https://vocatadev.pagekite.me/users/clitest3",
  "to": [ "https://masto.vocata.one/users/admin" ],
  "object": {
    "id": "https://vocatadev.pagekite.me/testnote-priv-to-admin-5",
    "summary": "Dangerous software test",
    "type": "Note",
    "content": "<p><span class=\"h-card\"><a href=\"https://vocatadev.pagekite.me/users/clitest3\" class=\"u-url mention\">@<span>clitest3</span></a></span></p>",
    "published": "2023-04-15T14:10:30Z",
    "attributedTo": "https://vocatadev.pagekite.me/users/clitest3",
    "to": [ "https://masto.vocata.one/users/admin" ]
  }
}

I can see it show up in the database entirely correctly, except for one detail:

The visibility column in the statuses table is set to 4. Funnily, according to [Mastodon docs on the field](https://Mastodon’s docs on the field), it is an Enum with 4 entries, and I can see in the database that it has values from 0 to 3, and “direct” messages sent from another Mastodon instance get assigned a 3. (EDIT: Reading the code, I see there is indeed a fifth visbility named limited, which is undocumented).

The consequence is that my post remains inivisble. Once I manually set visibility to 3 in the database, I can see it in the frontend and interact with it :joy_cat: !

Why does Mastodon assign a visibility of 4 to my post?

That’s actually in my tutorial, you need to mention yourself in order to interact with it. The other option is to follow the sending account. This behavior is actually captured really well in how people talk about Mastodon. They don’t have “an inbox” but “mentions”.

Also I just rewrote that tutorial to explain more what is going on, there should be a new version tomorrow.

What do you mean by “mention yourself”?

If I am sending a DM from A to B, do I need to mention A, B, or both?

I tried adding a Mention of B, but that did not help:

{'id': 'https://vocatadev.pagekite.me/testcreate-priv-to-admin-7',
 'type': 'Create',
 'actor': 'https://vocatadev.pagekite.me/users/clitest3',
 'object': {'id': 'https://vocatadev.pagekite.me/testnote-priv-to-admin-7',
  'type': 'Note',
  'attributedTo': 'https://vocatadev.pagekite.me/users/clitest3',
  'content': '<p><span class="h-card"><a href="https://vocatadev.pagekite.me/users/clitest3" class="u-url mention">@<span>clitest3</span></a></span> This is a test!</p>',
  'published': '2023-04-15T15:42:30+00:00',
  'summary': 'Dangerous software test',
  'tag': [{'type': 'Mention',
    'href': 'https://masto.vocata.one/users/admin',
    'name': '@admin@masto.vocata.one'}],
  'to': ['https://masto.vocata.one/users/admin']},
 'summary': 'Tester left a note',
 'to': ['https://masto.vocata.one/users/admin'],
 '@context': ['https://www.w3.org/ns/activitystreams',
  'https://w3id.org/security/v1']}

Not sure then. The summary properties shouldn’t be a problem. Can you lookup your actor from Mastodon?

A working create - note is

    {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "Create",
        "actor": "https://your_uuid.your_region.ngrok.io/milkdrinker",
        "to": [
            "https://mas.to/users/themilkman"
        ],
        "id": "https://your_uuid.your_region.ngrok.io/h12C6ybY",
        "object": {
            "@context": "https://www.w3.org/ns/activitystreams",
            "type": "Note",
            "attributedTo": "https://your_uuid.your_region.ngrok.io/milkdrinker",
            "to": ["https://mas.to/users/themilkman"],
            "id": "https://your_uuid.your_region.ngrok.io/Jj90godf",
            "content": "Hello. I'm doing the bovine tutorial on ActivityPub",
            "tag": {
                "type": "Mention",
                "href": "https://mas.to/users/themilkman",
                "name": "name"
            }
        }
    }

Yes, as stated: Everything works, except for that one database value.

Heck, I can even see the mention in the mentions table…

Is the “silent” column set to a true value?

Are you posting to the actor-specific inbox or the shared inbox?

You probably have seen this in the Mastodon code already, but if not, it gives a hint about one reason why the visibility would be set to “limited”.

      # If there is at least one silent mention, then the status can be considered
      # as a limited-audience status, and not strictly a direct message, but only
      # if we considered a direct message in the first place
      @params[:visibility] = :limited if @params[:visibility] == :direct

I see a few “limited” visibility statuses in my self-hosted Mastodon. One that I spot-checked had 3 mentions in the database. Two were non-silent and one was silent (consistent with limited visibility). The one that was silent did not have a corresponding mention of the account in the Status text. I haven’t been able to determine if that’s the cause of the silent mention or not.

I know this doesn’t answer your question but maybe it gives a few ideas to investigate.

Mastodon uses mentions for addressing, not just as mentions. limited visibility in Mastodon is basically an activity that was addressed to more people than it explicitly mentions. It’s a consequence of Improve support for aspects/circles by Gargron · Pull Request #8950 · mastodon/mastodon · GitHub which added limited support for “circles” or custom audiences / arbitrary addressing.

You may also want to see use `audience` and `discoverable` instead of `to`/`cc` "magic semantics" to determine scope/privacy level · Issue #18212 · mastodon/mastodon · GitHub for a breakdown of how visibility is currently calculated (see also: status_parser)

Basically, for everyone who is addressed but not mentioned, a “silent mention” is created for visibility purposes, and the visibility is changed from “direct” to “limited”. However, in the API, limited is presented as direct, since they carry similar semantics and there isn’t a user-facing difference yet.

Your interpretation of the consequences is a little misleading—direct and limited posts use the same calculation for determining who is allowed to interact with them. You can see this in the code:

def show?
  return false if author.suspended?

  if requires_mention?
    owned? || mention_exists?
  elsif private?
    owned? || following_author? || mention_exists?
  else
    current_account.nil? || (!author_blocking? && !author_blocking_domain?)
  end
end

where requires_mention? is defined as

def requires_mention?
  record.direct_visibility? || record.limited_visibility?
end

This is to say: limited and direct visibility are almost identical, except in the way that they’re messaged to the user in the UI. direct posts are posts where Mastodon is reasonably certain that the only recipients are the ones that are visible and mentioned in the post’s text, so it adds an indication of this in the UI, limited posts are posts where Mastodon cannot determine the underlying logic to how they’re distributed (so it displays a generic message about the post being non-public).

Except for, well, the message not being shown anywhere at all in Mastodon’s own web frontend, unless I set the visibility from limited to direct in the database.

Except that I can’t.

Is that a bug in Mastodon’s frontend, then?