I was using release so I went ahead and performed a source install on an Arch VM. Everything seems to be up and running. I generated and added this no longer valid generated code to my runtime.exs…
config :web_push_encryption, :vapid_details,
subject: "mailto:noreply@mydomain.tld",
public_key: "BBG17BHw2bLbK-iZFl7sbD5ySt-4u8L-S86Y4hhxTpD7RxGxM8uu1bRTuThGi5Ii5D90k6tdEGzUA2KZvXdnbHM",
private_key: "JRyFLZPMaF5XpWzsgyBBqvhkhJRIqtE-0CVr4WilxoA"
« Activate browser push notifications » then becomes an available option in my user preferences. Which, if there isn’t, it feels like there should be an initial « Notifications Enabled! » notification. Anyway, I’m not sure I can see any notifications being attempted in my logs. I enabled debug logs and have push notifications enabled for « A member requested to join one of my groups » wherein email notifications work perfectly fine. Here is the log when another user then requests to join my group.
Jan 25 16:21:23 Arch-Mobilizon mobilizon[2987]: [info] POST /api
Jan 25 16:21:23 Arch-Mobilizon mobilizon[2987]: [info] {"args":{"author_id":5,"group_id":4,"inserted_at":"2024-01-25T21:21:23.406432Z","object_id":"0036cb3a-7fa5-4bbc-9c33-748725fac833","object_type":"member","op":"build_activity","subject":"member_request","subject_params":{"member_actor_federated_username":"notkj","member_actor_name":"NotKJ","member_role":"NOT_APPROVED"},"type":"member"},"id":25,"meta":{},"system_time":1706217683418861613,"max_attempts":1,"queue":"activity","worker":"Mobilizon.Service.Workers.ActivityBuilder","source":"oban","tags":[],"event":"job:start","attempt":1}
Jan 25 16:21:23 Arch-Mobilizon mobilizon[2987]: [info] {"args":{"author_id":5,"group_id":4,"inserted_at":"2024-01-25T21:21:23.406432Z","object_id":"0036cb3a-7fa5-4bbc-9c33-748725fac833","object_type":"member","op":"build_activity","subject":"member_request","subject_params":{"member_actor_federated_username":"notkj","member_actor_name":"NotKJ","member_role":"NOT_APPROVED"},"type":"member"},"id":25,"meta":{},"state":"success","max_attempts":1,"queue":"activity","worker":"Mobilizon.Service.Workers.ActivityBuilder","source":"oban","tags":[],"event":"job:stop","attempt":1,"duration":14181,"queue_time":8358}
Jan 25 16:21:23 Arch-Mobilizon mobilizon[2987]: [error] no function clause matching in Absinthe.Middleware.Telemetry.on_complete/2
Jan 25 16:21:23 Arch-Mobilizon mobilizon[2987]: (absinthe 1.7.6) lib/absinthe/middleware/telemetry.ex:37: Absinthe.Middleware.Telemetry.on_complete(#Absinthe.Resolution<[private: %{}, value: nil, state: :unresolved, path: [%Absinthe.Blueprint.Document.Field{name: "groupMembershipChanged", alias: nil, selections: [%Absinthe.Blueprint.Document.Field{name: "id", alias: nil, selections: [], arguments: [], argument_data: %{}, directives: [], flags: %{}, errors: [], source_location: %Absinthe.Blueprint.SourceLocation{line: 3, column: 5}, type_conditions: [], schema_node: %Absinthe.Type.Field{identifier: :id, name: "id", description: "Internal ID for this person", type: :id, deprecation: nil, args: %{}, config: nil, triggers: %{}, middleware: [{{Rajska.FieldAuthorization, :call}, [object: %Absinthe.Type.Object{identifier: :person, name: "Person", description: "Represents a person identity", fields: %{id: %Absinthe.Type.Field{identifier: :id, name: "id", description: "Internal ID for this person", type: :id, deprecation: nil, args: %{}, config: {:ref, Mobilizon.GraphQL.Schema.Actors.PersonType, {Absinthe.Blueprint.Schema.FieldDefinition, {...}}}, triggers: {:ref, Mobilizon.GraphQL.Schema.Actors.PersonType, {Absinthe.Blueprint.Schema.FieldDefinition, ...}}, middleware: [{:ref, Mobilizon.GraphQL.Schema.Actors.PersonType, ...}], complexity: {:ref, Mobilizon.GraphQL.Schema.Actors.PersonType, ...}, default_value: nil, __private__: [], ...}, local: %Absinthe.Type.Field{identifier: :local, name: "local", description: "If the actor is from this instance", type: :boolean, deprecation: nil, args: %{}, config: {:ref, Mobilizon.GraphQL.Schema.Actors.PersonType, {Absinthe.Blueprint.Schema.FieldDefinition, ...}}, triggers: {:ref, Mobilizon.GraphQL.Schema.Actors.PersonType, {...}}, middleware: [{:ref, ...}], complexity: {:ref, ...}, default_value: nil, ...}, name: %Absinthe.Type.Field{identifier: :name, name: "name", description: "The actor's displayed name", type: :string, deprecation: nil, args: %{}, config: {:ref, Mobilizon.GraphQL.Schema.Actors.PersonType, {...}}, triggers: {:ref, Mobilizon.GraphQL.Schema.Actors.PersonType, ...}, middleware: [{...}], complexity: {...}, ...}, suspended: %Absinthe.Type.Field{identifier: :suspended, name: "suspended", description: "If the actor is suspended", type: :boolean, deprecation: nil, args: %{}, config: {:ref, Mobilizon.GraphQL.Schema.Actors.PersonType, ...}, triggers: {:ref, ...}, middleware: [...], ...}, type: %Absinthe.Type.Field{identifier: :type, name: "type", description: "The type of Actor (Person, Group,…)", type: :actor_type, deprecation: nil, args: %{}, config: {:ref, ...}, triggers: {...}, ...}, user: %Absinthe.Type.Field{identifier: :user, name: "user", description: "The user this actor is associated to", type: :user, deprecation: nil, args: %{}, config: {...}, ...}, domain: %Absinthe.Type.Field{identifier: :domain, name: "domain", description: "The actor's domain if (null if it's this instance)", type: :string, deprecation: nil, args: %{}, ...}, url: %Absinthe.Type.Field{identifier: :url, name: "url", description: "The ActivityPub actor's URL", type: :string, deprecation: nil, ...}, preferred_username: %Absinthe.Type.Field{identifier: :preferred_username, name: "preferred_username", description: "The actor's preferred username", type: :string, ...}, banner: %Absinthe.Type.Field{identifier: :banner, name: "banner", description: "The actor's banner media", ...}, avatar: %Absinthe.Type.Field{identifier: :avatar, name: "avatar", ...}, participations: %Absinthe.Type.Field{identifier: :participations, ...}, summary: %Absinthe.Type.Field{...}, ...}, interfaces: [:action_log_object, :actor], __private__: [__absinthe_referenced__: true, meta: [authorize: :all, scope_field?: true]], definition: Mobilizon.GraphQL.Schema.Actors.PersonType, __reference__: %{module: Mobilizon.GraphQL.Schema.Actors.PersonType, location: %{line: 18, file: "/home/mobilizon/live/lib/graphql/schema/actors/person.ex"}}, is_type_of: nil}, field: :id]}, {Absinthe.Middleware.MapGet, :id}], complexity: nil, default_value: nil, __private__: [], definition: Mobilizon.GraphQL.Schema.Actors.PersonType, __reference__: %{module: Mobilizon.GraphQL.Schema.Actors.PersonType, location: %{line: 22, file: "/home/mobilizon/live/lib/graphql/schema/actors/person.ex"}}}, complexity: nil, parent_type: nil}, %Absinthe.Blueprint.Document.Field{name: "memberships", alias: nil, selections: [%Absinthe.Blueprint.Document.Field{name: "total", alias: nil, selections: [], arguments: [], argument_data: %{}, directives: [], flags: %{}, errors: [], source_location: %Absinthe.Blueprint.SourceLocation{line: 5, column: 7}, type_conditions: [], schema_node: %Absinthe.Type.Field{identifier: :total, name: "total", description: "The total number of elements in the list", type: :integer, deprecation: nil, args: %{}, config: nil, triggers: %{}, middleware: [{{Rajska.FieldAuthorization, :call}, [object: %Absinthe.Type.Object{identifier: :paginated_member_list, name: "PaginatedMemberList", description: "A paginated list of members", fields: %{total: %Absinthe.Type.Field{identifier: :total, name: "total", description: "The total number of elements in the list", type: :integer, deprecation: nil, args: %{}, config: {...}, ...}, elements: %Absinthe.Type.Field{identifier: :elements, name: "elements", description: "A list of members", type: %Absinthe.Type.List{of_type: :member}, deprecation: nil, args: %{}, ...}, __typename: %Absinthe.Type.Field{identifier: :__typename, name: "__typename", description: "The name of the object type currently being queried.", type: :string, deprecation: nil, ...}}, interfaces: [], __private__: [__absinthe_referenced__: true, meta: [authorize: :all]], definition: Mobilizon.GraphQL.Schema.Actors.MemberType, __reference__: %{module: Mobilizon.GraphQL.Schema.Actors.MemberType, location: %{line: 40, file: "/home/mobilizon/live/lib/graphql/schema/actors/member.ex"}}, is_type_of: nil}, field: :total]}, {Absinthe.Middleware.MapGet, :total}], complexity: nil, default_value: nil, __private__: [], definition: Mobilizon.GraphQL.Schema.Actors.MemberType, __reference__: %{module: Mobilizon.GraphQL.Schema.Actors.MemberType, location: %{line: 43, file: "/home/mobilizon/live/lib/graphql/schema/actors/member.ex"}}}, complexity: nil, parent_type: nil}, %Absinthe.Blueprint.Document.Field{name: "elements", alias: nil, selections: [%Absinthe.Blueprint.Document.Field{name: "id", alias: nil, selections: [], arguments: [], argument_data: %{}, directives: [], flags: %{}, errors: [], source_location: %Absinthe.Blueprint.SourceLocation{line: 7, column: 9}, type_conditions: [], schema_node: %Absinthe.Type.Field{identifier: :id, name: "id", description: "The member's ID", type: :id, deprecation: nil, args: %{}, config: nil, triggers: %{}, middleware: [{{Rajska.FieldAuthorization, :call}, [object: %Absinthe.Type.Object{identifier: :member, name: "Member", description: "Represents a member of a group", fields: %{id: %Absinthe.Type.Field{identifier: :id, name: "id", ...}, parent: %Absinthe.Type.Field{identifier: :parent, ...}, role: %Absinthe.Type.Field{...}, ...}, interfaces: [:activity_object], __private__: [__absinthe_referenced__: true, ...], definition: Mobilizon.GraphQL.Schema.Actors.MemberType, ...}, field: :id]}, {Absinthe.Middleware.MapGet, :id}], complexity: nil, default_value: nil, __private__: [], definition: Mobilizon.GraphQL.Schema.Actors.MemberType, __reference__: %{module: Mobilizon.GraphQL.Schema.Actors.MemberType, location: %{line: 15, file: "/home/mobilizon/live/lib/graphql/schema/actors/member.ex"}}}, complexity: nil, parent_type: nil}, %Absinthe.Blueprint.Document.Field{name: "role", alias: nil, selections: [], arguments: [], argument_data: %{}, directives: [], flags: %{}, errors: [], source_location: %Absinthe.Blueprint.SourceLocation{line: 8, column: 9}, type_conditions: [], schema_node: %Absinthe.Type.Field{identifier: :role, name: "role", description: "The role of this membership", type: :member_role_enum, deprecation: nil, args: %{}, con (truncated)
Jan 25 16:21:23 Arch-Mobilizon mobilizon[2987]: [info] Sent 200 in 124ms
Jan 25 16:21:23 Arch-Mobilizon mobilizon[2987]: [info] Sending https://mydomain.tld/member/0036cb3a-7fa5-4bbc-9c33-748725fac833 out via AP
Jan 25 16:21:23 Arch-Mobilizon mobilizon[2987]: [info] POST /api
Jan 25 16:21:23 Arch-Mobilizon mobilizon[2987]: [info] Sent 200 in 9ms
Now I’m not sure if any of that even means anything as I see the same exact logging whether notifications are enabled on the instance or not. This would be my first attempt at using any kind of Elixir based app so I’m just not sure if I’m missing something or the documentation page is.