chore: update github.com/go-ap/activitypub to 902f6cf (#11301)

Picks the update commit from https://codeberg.org/forgejo/forgejo/pulls/11200 and fixes the new incompatibilities.

I ran full end-to-end tests against Forgejo and basic end-to-end tests against GoToSocial which appear to be working.

Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11301
Reviewed-by: elle <0xllx0@noreply.codeberg.org>
Co-authored-by: famfo <famfo@famfo.xyz>
Co-committed-by: famfo <famfo@famfo.xyz>
This commit is contained in:
famfo 2026-04-02 23:57:13 +02:00 committed by Gusted
parent 4121d5ec85
commit 2fc3144de4
19 changed files with 46 additions and 53 deletions

4
go.mod
View file

@ -43,7 +43,7 @@ require (
github.com/felixge/fgprof v0.9.5
github.com/fsnotify/fsnotify v1.9.0
github.com/gliderlabs/ssh v0.3.8
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9
github.com/go-ap/activitypub v0.0.0-20260208110334-902f6cf8c2cc
github.com/go-ap/jsonld v0.0.0-20251216162253-e38fa664ea77
github.com/go-chi/chi/v5 v5.2.5
github.com/go-chi/cors v1.2.2
@ -168,7 +168,7 @@ require (
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 // indirect
github.com/go-ap/errors v0.0.0-20260208110149-e1b309365966 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
github.com/go-enry/go-oniguruma v1.2.1 // indirect
github.com/go-errors/errors v1.4.2 // indirect

10
go.sum
View file

@ -253,11 +253,10 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9 h1:j2TrkUG/NATGi/EQS+MvEoF79CxiRUmT16ErFroNcKI=
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9/go.mod h1:cJ9Ye0ZNSMN7RzZDBRY3E+8M3Bpf/R1JX22Ir9yX6WI=
github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 h1:I2nuhyVI/48VXoRCCZR2hYBgnSXa+EuDJf/VyX06TC0=
github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7/go.mod h1:5x8a6P/dhmMGFxWLcyYlyOuJ2lRNaHGhRv+yu8BaTSI=
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73/go.mod h1:jyveZeGw5LaADntW+UEsMjl3IlIwk+DxlYNsbofQkGA=
github.com/go-ap/activitypub v0.0.0-20260208110334-902f6cf8c2cc h1:yLe7YJhK+XNjNV4SqDxAjpWAgft+KU+XwKZS4AKEUV0=
github.com/go-ap/activitypub v0.0.0-20260208110334-902f6cf8c2cc/go.mod h1:jUs8eczo1EAT4ByRpZ4mQmNvjarw9eNf7Nm5udpMRhY=
github.com/go-ap/errors v0.0.0-20260208110149-e1b309365966 h1:tV+3kZgqFMKVUf+JPKBV400ISM8440+6y/SQCS0WZwQ=
github.com/go-ap/errors v0.0.0-20260208110149-e1b309365966/go.mod h1:zkp58Q5yXpCxZbh3d0GDvwqiYclfVuHEHjc9SZKAj6I=
github.com/go-ap/jsonld v0.0.0-20251216162253-e38fa664ea77 h1:yHAmoR6avNy84PlLmjHt1z9flAp2Qs2ens5QDE/CNWk=
github.com/go-ap/jsonld v0.0.0-20251216162253-e38fa664ea77/go.mod h1:4h93IBxgfnE/DEleMLgJ/XCeu/RtQ+MUh3ucANseeXA=
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
@ -664,7 +663,6 @@ github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY=
github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli/v3 v3.8.0 h1:XqKPrm0q4P0q5JpoclYoCAv0/MIvH/jZ2umzuf8pNTI=
github.com/urfave/cli/v3 v3.8.0/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/valyala/fastjson v1.6.10 h1:/yjJg8jaVQdYR3arGxPE2X5z89xrlhS0eGXdv+ADTh4=
github.com/valyala/fastjson v1.6.10/go.mod h1:e6FubmQouUNP73jtMLmcbxS6ydWIpOfhz34TSfO3JaE=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=

View file

@ -48,8 +48,8 @@ func (follow *ForgeFollow) UnmarshalJSON(data []byte) error {
func (follow ForgeFollow) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(string(follow.Type), "type")...)
result = append(result, validation.ValidateOneOf(string(follow.Type), []any{"Follow"}, "type")...)
result = append(result, validation.ValidateNotEmpty(follow.Type, "type")...)
result = append(result, validation.ValidateOneOf(follow.Type, []any{ap.FollowType}, "type")...)
result = append(result, validation.ValidateIDExists(follow.Actor, "actor")...)
result = append(result, validation.ValidateIDExists(follow.Object, "object")...)

View file

@ -15,7 +15,7 @@ import (
func Test_NewForgeFollowValidation(t *testing.T) {
sut := forgefed.ForgeFollow{}
sut.Type = "Follow"
sut.Type = ap.FollowType
sut.Actor = ap.IRI("example.org/alice")
sut.Object = ap.IRI("example.org/bob")

View file

@ -44,8 +44,8 @@ func (like ForgeLike) IsNewer(compareTo time.Time) bool {
func (like ForgeLike) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(string(like.Type), "type")...)
result = append(result, validation.ValidateOneOf(string(like.Type), []any{"Like"}, "type")...)
result = append(result, validation.ValidateNotEmpty(like.Type, "type")...)
result = append(result, validation.ValidateOneOf(like.Type, []any{ap.LikeType}, "type")...)
if like.Actor == nil {
result = append(result, "Actor should not be nil.")

View file

@ -51,7 +51,7 @@ func Test_LikeMarshalJSON(t *testing.T) {
item: forgefed.ForgeLike{
Activity: ap.Activity{
Actor: ap.IRI("https://repo.prod.meissa.de/api/v1/activitypub/user-id/1"),
Type: "Like",
Type: ap.LikeType,
Object: ap.IRI("https://codeberg.org/api/v1/activitypub/repository-id/1"),
},
},
@ -80,7 +80,7 @@ func Test_LikeUnmarshalJSON(t *testing.T) {
item: []byte(`{"type":"Like","actor":"https://repo.prod.meissa.de/api/activitypub/user-id/1","object":"https://codeberg.org/api/activitypub/repository-id/1"}`),
want: &forgefed.ForgeLike{
Activity: ap.Activity{
Type: "Like",
Type: ap.LikeType,
Actor: ap.IRI("https://repo.prod.meissa.de/api/activitypub/user-id/1"),
Object: ap.IRI("https://codeberg.org/api/activitypub/repository-id/1"),
},
@ -124,7 +124,7 @@ func Test_ForgeLikeValidation(t *testing.T) {
validate := sut.Validate()
assert.Len(t, validate, 2)
assert.Equal(t,
"Field type contains the value , which is not in allowed subset [Like]",
"Field type contains the value <nil>, which is not in allowed subset [Like]",
validate[1])
sut.UnmarshalJSON([]byte(`{"type":"bad-type",

View file

@ -42,8 +42,8 @@ func (undo *ForgeUndoLike) UnmarshalJSON(data []byte) error {
func (undo ForgeUndoLike) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(string(undo.Type), "type")...)
result = append(result, validation.ValidateOneOf(string(undo.Type), []any{"Undo"}, "type")...)
result = append(result, validation.ValidateNotEmpty(undo.Type, "type")...)
result = append(result, validation.ValidateOneOf(undo.Type, []any{ap.UndoType}, "type")...)
if undo.Actor == nil {
result = append(result, "Actor should not be nil.")
@ -61,8 +61,8 @@ func (undo ForgeUndoLike) Validate() []string {
} else if activity, ok := undo.Object.(*ap.Activity); !ok {
result = append(result, "object is not of type Activity")
} else {
result = append(result, validation.ValidateNotEmpty(string(activity.Type), "type")...)
result = append(result, validation.ValidateOneOf(string(activity.Type), []any{"Like"}, "type")...)
result = append(result, validation.ValidateNotEmpty(activity.Type, "type")...)
result = append(result, validation.ValidateOneOf(activity.Type, []any{ap.LikeType}, "type")...)
if activity.Actor == nil {
result = append(result, "Object.Actor should not be nil.")

View file

@ -64,7 +64,7 @@ func Test_UndoLikeMarshalJSON(t *testing.T) {
Activity: ap.Activity{
StartTime: startTime,
Actor: ap.IRI("https://repo.prod.meissa.de/api/v1/activitypub/user-id/1"),
Type: "Undo",
Type: ap.UndoType,
Object: like,
},
},
@ -117,7 +117,7 @@ func Test_UndoLikeUnmarshalJSON(t *testing.T) {
Activity: ap.Activity{
StartTime: startTime,
Actor: ap.IRI("https://repo.prod.meissa.de/api/v1/activitypub/user-id/1"),
Type: "Undo",
Type: ap.UndoType,
Object: like,
},
},

View file

@ -60,8 +60,8 @@ func NewForgeUserActivity(doer *user_model.User, actionID int64, content string)
func (userActivity ForgeUserActivity) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(string(userActivity.Type), "type")...)
result = append(result, validation.ValidateOneOf(string(userActivity.Type), []any{"Create"}, "type")...)
result = append(result, validation.ValidateNotEmpty(userActivity.Type, "type")...)
result = append(result, validation.ValidateOneOf(userActivity.Type, []any{ap.CreateType}, "type")...)
result = append(result, validation.ValidateIDExists(userActivity.Actor, "actor")...)
if len(userActivity.To) == 0 {

View file

@ -15,17 +15,14 @@ import (
func Test_ForgeUserActivityValidation(t *testing.T) {
note := forgefed.ForgeUserActivityNote{}
note.Type = "Note"
note.Type = ap.NoteType
note.Content = ap.NaturalLanguageValues{
{
Ref: ap.NilLangRef,
Value: ap.Content("Any Content!"),
},
ap.NilLangRef: ap.Content("Any Content!"),
}
note.URL = ap.IRI("example.org/user-id/57")
sut := forgefed.ForgeUserActivity{}
sut.Type = "Create"
sut.Type = ap.CreateType
sut.Actor = ap.IRI("example.org/user-id/23")
sut.CC = ap.ItemCollection{
ap.IRI("example.org/registration/public#2nd"),

View file

@ -115,8 +115,8 @@ func (s *ForgePerson) UnmarshalJSON(data []byte) error {
func (s ForgePerson) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(string(s.Type), "Type")...)
result = append(result, validation.ValidateOneOf(string(s.Type), []any{string(ap.PersonType)}, "Type")...)
result = append(result, validation.ValidateNotEmpty(s.Type, "Type")...)
result = append(result, validation.ValidateOneOf(s.Type, []any{ap.PersonType}, "Type")...)
result = append(result, validation.ValidateNotEmpty(s.PreferredUsername.String(), "PreferredUsername")...)
return result

View file

@ -194,9 +194,9 @@ func TestShouldThrowErrorOnInvalidInput(t *testing.T) {
func Test_PersonMarshalJSON(t *testing.T) {
sut := forgefed.ForgePerson{}
sut.Type = "Person"
sut.Type = ap.PersonType
sut.PreferredUsername = ap.NaturalLanguageValuesNew()
sut.PreferredUsername.Set("en", ap.Content("MaxMuster"))
sut.PreferredUsername.Set(ap.English, ap.Content("MaxMuster"))
result, _ := sut.MarshalJSON()
assert.JSONEq(t, `{"type":"Person","preferredUsername":"MaxMuster"}`, string(result), "Expected string is not equal")
}
@ -204,9 +204,9 @@ func Test_PersonMarshalJSON(t *testing.T) {
func Test_PersonUnmarshalJSON(t *testing.T) {
expected := &forgefed.ForgePerson{
Actor: ap.Actor{
Type: "Person",
Type: ap.PersonType,
PreferredUsername: ap.NaturalLanguageValues{
ap.LangRefValue{Ref: "en", Value: []byte("MaxMuster")},
ap.English: []byte("MaxMuster"),
},
},
}

View file

@ -35,10 +35,7 @@ func newNote(doer *user_model.User, content, id string, published time.Time) (Fo
note.Type = ap.NoteType
note.AttributedTo = ap.IRI(doer.APActorID())
note.Content = ap.NaturalLanguageValues{
{
Ref: ap.NilLangRef,
Value: ap.Content(content),
},
ap.NilLangRef: ap.Content(content),
}
note.ID = ap.IRI(id)
note.Published = published
@ -59,8 +56,8 @@ func newNote(doer *user_model.User, content, id string, published time.Time) (Fo
func (note ForgeUserActivityNote) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(string(note.Type), "type")...)
result = append(result, validation.ValidateOneOf(string(note.Type), []any{"Note"}, "type")...)
result = append(result, validation.ValidateNotEmpty(note.Type, "type")...)
result = append(result, validation.ValidateOneOf(note.Type, []any{ap.NoteType}, "type")...)
result = append(result, validation.ValidateNotEmpty(note.Content.String(), "content")...)
result = append(result, validation.ValidateIDExists(note.URL, "url")...)

View file

@ -15,12 +15,9 @@ import (
func Test_UserActivityNoteValidation(t *testing.T) {
sut := forgefed.ForgeUserActivityNote{}
sut.Type = "Note"
sut.Type = ap.NoteType
sut.Content = ap.NaturalLanguageValues{
{
Ref: ap.NilLangRef,
Value: ap.Content("Any Content!"),
},
ap.NilLangRef: ap.Content("Any Content!"),
}
sut.URL = ap.IRI("example.org/user-id/57")

View file

@ -70,6 +70,8 @@ func ValidateNotEmpty(value any, name string) []string {
if v == 0 {
isValid = false
}
case ap.Typer:
isValid = len(value.(ap.Typer).AsTypes()) > 0
default:
isValid = false
}

View file

@ -32,7 +32,7 @@ func Actor(ctx *context.APIContext) {
actor := ap.ActorNew(ap.IRI(link), ap.ApplicationType)
actor.PreferredUsername = ap.NaturalLanguageValuesNew()
err := actor.PreferredUsername.Set("en", ap.Content("ghost"))
err := actor.PreferredUsername.Set(ap.NilLangRef, ap.Content("ghost"))
if err != nil {
ctx.ServerError("PreferredUsername.Set", err)
return

View file

@ -45,7 +45,7 @@ func Repository(ctx *context.APIContext) {
repo.Outbox = ap.IRI(link + "/outbox")
repo.Name = ap.NaturalLanguageValuesNew()
err := repo.Name.Set("en", ap.Content(ctx.Repo.Repository.Name))
err := repo.Name.Set(ap.NilLangRef, ap.Content(ctx.Repo.Repository.Name))
if err != nil {
ctx.Error(http.StatusInternalServerError, "Set Name", err)
return

View file

@ -16,7 +16,7 @@ import (
func ToActivityPubPersonFeedItem(item *activities.FederatedUserActivity) ap.Note {
return ap.Note{
AttributedTo: ap.IRI(item.ActorURI),
Content: ap.NaturalLanguageValues{{Value: ap.Content(item.NoteContent), Ref: ap.NilLangRef}},
Content: ap.NaturalLanguageValues{ap.NilLangRef: ap.Content(item.NoteContent)},
ID: ap.IRI(item.NoteURL),
URL: ap.IRI(item.OriginalNote),
}
@ -27,13 +27,13 @@ func ToActivityPubPerson(ctx context.Context, user *user_model.User) (*ap.Person
person := ap.PersonNew(ap.IRI(link))
person.Name = ap.NaturalLanguageValuesNew()
err := person.Name.Set("en", ap.Content(user.FullName))
err := person.Name.Set(ap.NilLangRef, ap.Content(user.FullName))
if err != nil {
return nil, err
}
person.PreferredUsername = ap.NaturalLanguageValuesNew()
err = person.PreferredUsername.Set("en", ap.Content(user.Name))
err = person.PreferredUsername.Set(ap.NilLangRef, ap.Content(user.Name))
if err != nil {
return nil, err
}

View file

@ -18,6 +18,8 @@ import (
"forgejo.org/modules/test"
"forgejo.org/modules/validation"
"forgejo.org/tests"
ap "github.com/go-ap/activitypub"
)
func TestActivityPubRepoFollowing(t *testing.T) {
@ -69,7 +71,7 @@ func TestActivityPubRepoFollowing(t *testing.T) {
}
activityType := like.Type
object := like.Object.GetLink().String()
isLikeType := activityType == "Like"
isLikeType := activityType == ap.LikeType
isCorrectObject := strings.HasSuffix(object, "/api/v1/activitypub/repository-id/1")
if !isLikeType || !isCorrectObject {
t.Error("Activity is not a like for this repo")