diff --git a/go.mod b/go.mod
index 9bead0a364..3d5662d9a8 100644
--- a/go.mod
+++ b/go.mod
@@ -119,7 +119,7 @@ require (
 	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
 	gopkg.in/ini.v1 v1.67.0
 	gopkg.in/yaml.v3 v3.0.1
-	lab.forgefriends.org/friendlyforgeformat/gof3 v0.0.0-20230427084437-fabab01062d0
+	lab.forgefriends.org/friendlyforgeformat/gof3 v0.0.0-20230601123105-50a6e740ac04
 	mvdan.cc/xurls/v2 v2.4.0
 	strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
 	xorm.io/builder v0.3.12
diff --git a/go.sum b/go.sum
index 5a07d44d0a..42f139601e 100644
--- a/go.sum
+++ b/go.sum
@@ -1806,8 +1806,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
 honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-lab.forgefriends.org/friendlyforgeformat/gof3 v0.0.0-20230427084437-fabab01062d0 h1:5y3hSNZGWNUpyRpEGWAQVc1Y9BdHzMh9HSkklnXTAgM=
-lab.forgefriends.org/friendlyforgeformat/gof3 v0.0.0-20230427084437-fabab01062d0/go.mod h1:hHO78jzN6POY88iXr2+kJFl7IHOaBsVS22bBbRCBwRQ=
+lab.forgefriends.org/friendlyforgeformat/gof3 v0.0.0-20230601123105-50a6e740ac04 h1:JdNHyMEVNixsOvNw3XqrkWi/RqVLN+wjrdeL6NVk2jE=
+lab.forgefriends.org/friendlyforgeformat/gof3 v0.0.0-20230601123105-50a6e740ac04/go.mod h1:yIlQydnn+pym6OH20iQ7fbe2TjLfnlOTtEOqvjFaC70=
 lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU=
 lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
 modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
diff --git a/services/f3/driver/asset.go b/services/f3/driver/asset.go
index 6b73ee2342..9463d2e20a 100644
--- a/services/f3/driver/asset.go
+++ b/services/f3/driver/asset.go
@@ -32,10 +32,18 @@ func (o Asset) GetID() int64 {
 	return o.ID
 }
 
+func (o Asset) GetIDString() string {
+	return fmt.Sprintf("%d", o.GetID())
+}
+
 func (o *Asset) SetID(id int64) {
 	o.ID = id
 }
 
+func (o *Asset) SetIDString(id string) {
+	o.SetID(util.ParseInt(id))
+}
+
 func (o *Asset) IsNil() bool {
 	return o.ID == 0
 }
@@ -44,6 +52,10 @@ func (o *Asset) Equals(other *Asset) bool {
 	return o.Name == other.Name
 }
 
+func (o *Asset) ToFormatInterface() format.Interface {
+	return o.ToFormat()
+}
+
 func (o *Asset) ToFormat() *format.ReleaseAsset {
 	return &format.ReleaseAsset{
 		Common:        format.NewCommon(o.ID),
diff --git a/services/f3/driver/comment.go b/services/f3/driver/comment.go
index 5380f468af..1ba740cc47 100644
--- a/services/f3/driver/comment.go
+++ b/services/f3/driver/comment.go
@@ -31,10 +31,18 @@ func (o Comment) GetID() int64 {
 	return o.Comment.ID
 }
 
+func (o Comment) GetIDString() string {
+	return fmt.Sprintf("%d", o.GetID())
+}
+
 func (o *Comment) SetID(id int64) {
 	o.Comment.ID = id
 }
 
+func (o *Comment) SetIDString(id string) {
+	o.SetID(util.ParseInt(id))
+}
+
 func (o *Comment) IsNil() bool {
 	return o.ID == 0
 }
@@ -43,6 +51,10 @@ func (o *Comment) Equals(other *Comment) bool {
 	return o.Comment.ID == other.Comment.ID
 }
 
+func (o *Comment) ToFormatInterface() format.Interface {
+	return o.ToFormat()
+}
+
 func (o *Comment) ToFormat() *format.Comment {
 	return &format.Comment{
 		IssueIndex: o.Comment.IssueID,
diff --git a/services/f3/driver/issue.go b/services/f3/driver/issue.go
index 3dc97b59ba..180b8de044 100644
--- a/services/f3/driver/issue.go
+++ b/services/f3/driver/issue.go
@@ -32,10 +32,18 @@ func (o Issue) GetID() int64 {
 	return o.Index
 }
 
+func (o Issue) GetIDString() string {
+	return fmt.Sprintf("%d", o.GetID())
+}
+
 func (o *Issue) SetID(id int64) {
 	o.Index = id
 }
 
+func (o *Issue) SetIDString(id string) {
+	o.SetID(util.ParseInt(id))
+}
+
 func (o *Issue) IsNil() bool {
 	return o.Index == 0
 }
@@ -44,6 +52,10 @@ func (o *Issue) Equals(other *Issue) bool {
 	return o.Index == other.Index
 }
 
+func (o *Issue) ToFormatInterface() format.Interface {
+	return o.ToFormat()
+}
+
 func (o *Issue) ToFormat() *format.Issue {
 	var milestone string
 	if o.Milestone != nil {
diff --git a/services/f3/driver/label.go b/services/f3/driver/label.go
index 3790b39c0c..cd511b4418 100644
--- a/services/f3/driver/label.go
+++ b/services/f3/driver/label.go
@@ -27,6 +27,10 @@ func (o Label) GetID() int64 {
 	return o.ID
 }
 
+func (o Label) GetIDString() string {
+	return fmt.Sprintf("%d", o.GetID())
+}
+
 func (o Label) GetName() string {
 	return o.Name
 }
@@ -35,6 +39,10 @@ func (o *Label) SetID(id int64) {
 	o.ID = id
 }
 
+func (o *Label) SetIDString(id string) {
+	o.SetID(util.ParseInt(id))
+}
+
 func (o *Label) IsNil() bool {
 	return o.ID == 0
 }
@@ -43,6 +51,10 @@ func (o *Label) Equals(other *Label) bool {
 	return o.Name == other.Name
 }
 
+func (o *Label) ToFormatInterface() format.Interface {
+	return o.ToFormat()
+}
+
 func (o *Label) ToFormat() *format.Label {
 	return &format.Label{
 		Common:      format.NewCommon(o.ID),
diff --git a/services/f3/driver/milestone.go b/services/f3/driver/milestone.go
index 4ef2ec964c..30e22f3db0 100644
--- a/services/f3/driver/milestone.go
+++ b/services/f3/driver/milestone.go
@@ -31,6 +31,10 @@ func (o Milestone) GetID() int64 {
 	return o.ID
 }
 
+func (o Milestone) GetIDString() string {
+	return fmt.Sprintf("%d", o.GetID())
+}
+
 func (o Milestone) GetName() string {
 	return o.Name
 }
@@ -39,6 +43,10 @@ func (o *Milestone) SetID(id int64) {
 	o.ID = id
 }
 
+func (o *Milestone) SetIDString(id string) {
+	o.SetID(util.ParseInt(id))
+}
+
 func (o *Milestone) IsNil() bool {
 	return o.ID == 0
 }
@@ -47,6 +55,10 @@ func (o *Milestone) Equals(other *Milestone) bool {
 	return o.Name == other.Name
 }
 
+func (o *Milestone) ToFormatInterface() format.Interface {
+	return o.ToFormat()
+}
+
 func (o *Milestone) ToFormat() *format.Milestone {
 	milestone := &format.Milestone{
 		Common:      format.NewCommon(o.ID),
diff --git a/services/f3/driver/project.go b/services/f3/driver/project.go
index e31b2dbb79..3e94e05e0e 100644
--- a/services/f3/driver/project.go
+++ b/services/f3/driver/project.go
@@ -30,10 +30,18 @@ func (o Project) GetID() int64 {
 	return o.ID
 }
 
+func (o Project) GetIDString() string {
+	return fmt.Sprintf("%d", o.GetID())
+}
+
 func (o *Project) SetID(id int64) {
 	o.ID = id
 }
 
+func (o *Project) SetIDString(id string) {
+	o.SetID(f3_util.ParseInt(id))
+}
+
 func (o *Project) IsNil() bool {
 	return o.ID == 0
 }
@@ -42,6 +50,10 @@ func (o *Project) Equals(other *Project) bool {
 	return (o.Name == other.Name)
 }
 
+func (o *Project) ToFormatInterface() format.Interface {
+	return o.ToFormat()
+}
+
 func (o *Project) ToFormat() *format.Project {
 	return &format.Project{
 		Common:        format.NewCommon(o.ID),
diff --git a/services/f3/driver/pull_request.go b/services/f3/driver/pull_request.go
index a84002396b..63e040d67b 100644
--- a/services/f3/driver/pull_request.go
+++ b/services/f3/driver/pull_request.go
@@ -35,10 +35,18 @@ func (o PullRequest) GetID() int64 {
 	return o.Index
 }
 
+func (o PullRequest) GetIDString() string {
+	return fmt.Sprintf("%d", o.GetID())
+}
+
 func (o *PullRequest) SetID(id int64) {
 	o.Index = id
 }
 
+func (o *PullRequest) SetIDString(id string) {
+	o.SetID(util.ParseInt(id))
+}
+
 func (o *PullRequest) IsNil() bool {
 	return o.Index == 0
 }
@@ -51,6 +59,10 @@ func (o PullRequest) IsForkPullRequest() bool {
 	return o.HeadRepoID != o.BaseRepoID
 }
 
+func (o *PullRequest) ToFormatInterface() format.Interface {
+	return o.ToFormat()
+}
+
 func (o *PullRequest) ToFormat() *format.PullRequest {
 	var milestone string
 	if o.Issue.Milestone != nil {
diff --git a/services/f3/driver/reaction.go b/services/f3/driver/reaction.go
index e9c70064ba..75f356a814 100644
--- a/services/f3/driver/reaction.go
+++ b/services/f3/driver/reaction.go
@@ -30,10 +30,18 @@ func (o Reaction) GetID() int64 {
 	return o.ID
 }
 
+func (o Reaction) GetIDString() string {
+	return fmt.Sprintf("%d", o.GetID())
+}
+
 func (o *Reaction) SetID(id int64) {
 	o.ID = id
 }
 
+func (o *Reaction) SetIDString(id string) {
+	o.SetID(util.ParseInt(id))
+}
+
 func (o *Reaction) IsNil() bool {
 	return o.ID == 0
 }
@@ -42,6 +50,10 @@ func (o *Reaction) Equals(other *Reaction) bool {
 	return o.UserID == other.UserID && o.Type == other.Type
 }
 
+func (o *Reaction) ToFormatInterface() format.Interface {
+	return o.ToFormat()
+}
+
 func (o *Reaction) ToFormat() *format.Reaction {
 	return &format.Reaction{
 		Common:  format.NewCommon(o.ID),
diff --git a/services/f3/driver/release.go b/services/f3/driver/release.go
index 21749fe3b6..1d0f8b370e 100644
--- a/services/f3/driver/release.go
+++ b/services/f3/driver/release.go
@@ -33,10 +33,18 @@ func (o Release) GetID() int64 {
 	return o.ID
 }
 
+func (o Release) GetIDString() string {
+	return fmt.Sprintf("%d", o.GetID())
+}
+
 func (o *Release) SetID(id int64) {
 	o.ID = id
 }
 
+func (o *Release) SetIDString(id string) {
+	o.SetID(util.ParseInt(id))
+}
+
 func (o *Release) IsNil() bool {
 	return o.ID == 0
 }
@@ -45,6 +53,10 @@ func (o *Release) Equals(other *Release) bool {
 	return o.ID == other.ID
 }
 
+func (o *Release) ToFormatInterface() format.Interface {
+	return o.ToFormat()
+}
+
 func (o *Release) ToFormat() *format.Release {
 	return &format.Release{
 		Common:          format.NewCommon(o.ID),
diff --git a/services/f3/driver/repository.go b/services/f3/driver/repository.go
index 68cd3a3b8c..6874ea0a8e 100644
--- a/services/f3/driver/repository.go
+++ b/services/f3/driver/repository.go
@@ -22,6 +22,10 @@ func (o *Repository) Equals(other *Repository) bool {
 	return false // it is costly to figure that out, mirroring is as fast
 }
 
+func (o *Repository) ToFormatInterface() format.Interface {
+	return o.ToFormat()
+}
+
 func (o *Repository) ToFormat() *format.Repository {
 	return &o.Repository
 }
diff --git a/services/f3/driver/review.go b/services/f3/driver/review.go
index bc4877c762..1df9346283 100644
--- a/services/f3/driver/review.go
+++ b/services/f3/driver/review.go
@@ -30,10 +30,18 @@ func (o Review) GetID() int64 {
 	return o.ID
 }
 
+func (o Review) GetIDString() string {
+	return fmt.Sprintf("%d", o.GetID())
+}
+
 func (o *Review) SetID(id int64) {
 	o.ID = id
 }
 
+func (o *Review) SetIDString(id string) {
+	o.SetID(util.ParseInt(id))
+}
+
 func (o *Review) IsNil() bool {
 	return o.ID == 0
 }
@@ -42,6 +50,10 @@ func (o *Review) Equals(other *Review) bool {
 	return o.Content == other.Content
 }
 
+func (o *Review) ToFormatInterface() format.Interface {
+	return o.ToFormat()
+}
+
 func (o *Review) ToFormat() *format.Review {
 	comments := make([]*format.ReviewComment, 0, len(o.Comments))
 	for _, comment := range o.Comments {
diff --git a/services/f3/driver/topic.go b/services/f3/driver/topic.go
index f91f455433..8b2ffcca36 100644
--- a/services/f3/driver/topic.go
+++ b/services/f3/driver/topic.go
@@ -4,6 +4,7 @@ package driver
 
 import (
 	"context"
+	"fmt"
 
 	"code.gitea.io/gitea/models/db"
 	repo_model "code.gitea.io/gitea/models/repo"
@@ -26,10 +27,18 @@ func (o Topic) GetID() int64 {
 	return o.ID
 }
 
+func (o Topic) GetIDString() string {
+	return fmt.Sprintf("%d", o.GetID())
+}
+
 func (o *Topic) SetID(id int64) {
 	o.ID = id
 }
 
+func (o *Topic) SetIDString(id string) {
+	o.SetID(util.ParseInt(id))
+}
+
 func (o *Topic) IsNil() bool {
 	return o.ID == 0
 }
@@ -38,6 +47,10 @@ func (o *Topic) Equals(other *Topic) bool {
 	return o.Name == other.Name
 }
 
+func (o *Topic) ToFormatInterface() format.Interface {
+	return o.ToFormat()
+}
+
 func (o *Topic) ToFormat() *format.Topic {
 	return &format.Topic{
 		Common: format.NewCommon(o.ID),
diff --git a/services/f3/driver/user.go b/services/f3/driver/user.go
index c71eadd36a..5ab94864ee 100644
--- a/services/f3/driver/user.go
+++ b/services/f3/driver/user.go
@@ -29,10 +29,18 @@ func (o User) GetID() int64 {
 	return o.ID
 }
 
+func (o User) GetIDString() string {
+	return fmt.Sprintf("%d", o.GetID())
+}
+
 func (o *User) SetID(id int64) {
 	o.ID = id
 }
 
+func (o *User) SetIDString(id string) {
+	o.SetID(f3_util.ParseInt(id))
+}
+
 func (o *User) IsNil() bool {
 	return o.ID == 0
 }
@@ -41,6 +49,10 @@ func (o *User) Equals(other *User) bool {
 	return (o.Name == other.Name)
 }
 
+func (o *User) ToFormatInterface() format.Interface {
+	return o.ToFormat()
+}
+
 func (o *User) ToFormat() *format.User {
 	return &format.User{
 		Common:   format.NewCommon(o.ID),
diff --git a/tests/integration/f3_test.go b/tests/integration/f3_test.go
index 3c213fef5c..2a179d9d9f 100644
--- a/tests/integration/f3_test.go
+++ b/tests/integration/f3_test.go
@@ -24,6 +24,7 @@ import (
 	f3_common "lab.forgefriends.org/friendlyforgeformat/gof3/forges/common"
 	f3_f3 "lab.forgefriends.org/friendlyforgeformat/gof3/forges/f3"
 	f3_forgejo "lab.forgefriends.org/friendlyforgeformat/gof3/forges/forgejo"
+	f3_tests "lab.forgefriends.org/friendlyforgeformat/gof3/forges/tests"
 	"lab.forgefriends.org/friendlyforgeformat/gof3/format"
 	f3_util "lab.forgefriends.org/friendlyforgeformat/gof3/util"
 )
@@ -44,7 +45,7 @@ func TestF3(t *testing.T) {
 		//
 		// Step 1: create a fixture
 		//
-		fixtureNewF3Forge := func(t *testing.T, user *format.User, tmpDir string) *f3_forges.ForgeRoot {
+		fixtureNewF3Forge := func(t f3_tests.TestingT, user *format.User, tmpDir string) *f3_forges.ForgeRoot {
 			root := f3_forges.NewForgeRoot(&f3_f3.Options{
 				Options: gof3.Options{
 					Configuration: gof3.Configuration{