diff --git a/go.mod b/go.mod
index 4fcdbe30c5..ce1718c0a3 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.24
 toolchain go1.24.1
 
 require (
-	code.forgejo.org/f3/gof3/v3 v3.10.4
+	code.forgejo.org/f3/gof3/v3 v3.10.6
 	code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251
 	code.forgejo.org/forgejo/levelqueue v1.0.0
 	code.forgejo.org/forgejo/reply v1.0.2
diff --git a/go.sum b/go.sum
index 2d1587ec93..3c3733c219 100644
--- a/go.sum
+++ b/go.sum
@@ -610,8 +610,8 @@ cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoIS
 cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M=
 cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA=
 cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw=
-code.forgejo.org/f3/gof3/v3 v3.10.4 h1:NOkw8lG3PhgYykdR5pJ19KFLdYmRFVII43YBSNKtpvk=
-code.forgejo.org/f3/gof3/v3 v3.10.4/go.mod h1:aQSlSGpISIf016g1dBrmm16h53WUKjCR7nSCuoO8dq8=
+code.forgejo.org/f3/gof3/v3 v3.10.6 h1:Ru/Iz+pqM8IPi7atUHE7+q7v3O3DRbYgMFqrFTsO1m8=
+code.forgejo.org/f3/gof3/v3 v3.10.6/go.mod h1:K6lQCWQIyN/5rjP/OJL9fMA6fd++satndE20w/I6Kss=
 code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251 h1:HTZl3CBk3ABNYtFI6TPLvJgGKFIhKT5CBk0sbOtkDKU=
 code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:PphB88CPbx601QrWPMZATeorACeVmQlyv3u+uUMbSaM=
 code.forgejo.org/forgejo/act v1.23.1 h1:4LU7u3FE380DicHz1oZ4ohsWU9I527OHeslVHnr9eP4=
diff --git a/services/f3/driver/asset.go b/services/f3/driver/asset.go
index 6759cc645c..61e571d1b6 100644
--- a/services/f3/driver/asset.go
+++ b/services/f3/driver/asset.go
@@ -20,6 +20,7 @@ import (
 	"code.gitea.io/gitea/services/attachment"
 
 	"code.forgejo.org/f3/gof3/v3/f3"
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 	f3_util "code.forgejo.org/f3/gof3/v3/util"
@@ -131,7 +132,7 @@ func (o *asset) Patch(ctx context.Context) {
 	}
 }
 
-func (o *asset) Put(ctx context.Context) generic.NodeID {
+func (o *asset) Put(ctx context.Context) f3_id.NodeID {
 	node := o.GetNode()
 	o.Trace("%s", node.GetID())
 
@@ -154,7 +155,7 @@ func (o *asset) Put(ctx context.Context) generic.NodeID {
 	}
 
 	o.Trace("asset created %d", o.forgejoAsset.ID)
-	return generic.NewNodeID(o.forgejoAsset.ID)
+	return f3_id.NewNodeID(o.forgejoAsset.ID)
 }
 
 func (o *asset) Delete(ctx context.Context) {
diff --git a/services/f3/driver/comment.go b/services/f3/driver/comment.go
index 0c10fd744d..166bfcd328 100644
--- a/services/f3/driver/comment.go
+++ b/services/f3/driver/comment.go
@@ -14,6 +14,7 @@ import (
 	"code.gitea.io/gitea/modules/timeutil"
 
 	"code.forgejo.org/f3/gof3/v3/f3"
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 	f3_util "code.forgejo.org/f3/gof3/v3/util"
@@ -95,7 +96,7 @@ func (o *comment) Patch(ctx context.Context) {
 	}
 }
 
-func (o *comment) Put(ctx context.Context) generic.NodeID {
+func (o *comment) Put(ctx context.Context) f3_id.NodeID {
 	node := o.GetNode()
 	o.Trace("%s", node.GetID())
 
@@ -105,7 +106,7 @@ func (o *comment) Put(ctx context.Context) generic.NodeID {
 		panic(err)
 	}
 	o.Trace("comment created %d", o.forgejoComment.ID)
-	return generic.NewNodeID(o.forgejoComment.ID)
+	return f3_id.NewNodeID(o.forgejoComment.ID)
 }
 
 func (o *comment) Delete(ctx context.Context) {
diff --git a/services/f3/driver/common.go b/services/f3/driver/common.go
index 104f91c977..4c5dfd8b1a 100644
--- a/services/f3/driver/common.go
+++ b/services/f3/driver/common.go
@@ -7,6 +7,7 @@ package driver
 import (
 	"context"
 
+	f3_kind "code.forgejo.org/f3/gof3/v3/kind"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 )
 
@@ -37,7 +38,7 @@ func (o *common) getPageSize() int {
 	return o.getTreeDriver().GetPageSize()
 }
 
-func (o *common) getKind() generic.Kind {
+func (o *common) getKind() f3_kind.Kind {
 	return o.GetNode().GetKind()
 }
 
diff --git a/services/f3/driver/container.go b/services/f3/driver/container.go
index 153044416e..1ca47ef285 100644
--- a/services/f3/driver/container.go
+++ b/services/f3/driver/container.go
@@ -8,8 +8,8 @@ import (
 	"context"
 
 	"code.forgejo.org/f3/gof3/v3/f3"
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
-	"code.forgejo.org/f3/gof3/v3/tree/generic"
 )
 
 type container struct {
@@ -30,7 +30,7 @@ func (o *container) FromFormat(content f3.Interface) {
 
 func (o *container) Get(context.Context) bool { return true }
 
-func (o *container) Put(ctx context.Context) generic.NodeID {
+func (o *container) Put(ctx context.Context) f3_id.NodeID {
 	return o.upsert(ctx)
 }
 
@@ -38,6 +38,6 @@ func (o *container) Patch(ctx context.Context) {
 	o.upsert(ctx)
 }
 
-func (o *container) upsert(context.Context) generic.NodeID {
-	return generic.NewNodeID(o.getKind())
+func (o *container) upsert(context.Context) f3_id.NodeID {
+	return f3_id.NewNodeID(o.getKind())
 }
diff --git a/services/f3/driver/forge.go b/services/f3/driver/forge.go
index a4bcf61231..c232882753 100644
--- a/services/f3/driver/forge.go
+++ b/services/f3/driver/forge.go
@@ -11,6 +11,8 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 
 	"code.forgejo.org/f3/gof3/v3/f3"
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
+	f3_kind "code.forgejo.org/f3/gof3/v3/kind"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 	"code.forgejo.org/f3/gof3/v3/util"
@@ -19,16 +21,16 @@ import (
 type forge struct {
 	generic.NullDriver
 
-	ownersKind map[string]generic.Kind
+	ownersKind map[string]f3_kind.Kind
 }
 
 func newForge() generic.NodeDriverInterface {
 	return &forge{
-		ownersKind: make(map[string]generic.Kind),
+		ownersKind: make(map[string]f3_kind.Kind),
 	}
 }
 
-func (o *forge) getOwnersKind(ctx context.Context, id string) generic.Kind {
+func (o *forge) getOwnersKind(ctx context.Context, id string) f3_kind.Kind {
 	kind, ok := o.ownersKind[id]
 	if !ok {
 		user, err := user_model.GetUserByID(ctx, util.ParseInt(id))
@@ -50,7 +52,7 @@ func (o *forge) getOwnersPath(ctx context.Context, id string) f3_tree.Path {
 
 func (o *forge) Equals(context.Context, generic.NodeInterface) bool { return true }
 func (o *forge) Get(context.Context) bool                           { return true }
-func (o *forge) Put(context.Context) generic.NodeID                 { return generic.NewNodeID("forge") }
+func (o *forge) Put(context.Context) f3_id.NodeID                   { return f3_id.NewNodeID("forge") }
 func (o *forge) Patch(context.Context)                              {}
 func (o *forge) Delete(context.Context)                             {}
 func (o *forge) NewFormat() f3.Interface                            { return &f3.Forge{} }
diff --git a/services/f3/driver/issue.go b/services/f3/driver/issue.go
index 371ff9d45a..7e10f3a9db 100644
--- a/services/f3/driver/issue.go
+++ b/services/f3/driver/issue.go
@@ -17,6 +17,7 @@ import (
 	issue_service "code.gitea.io/gitea/services/issue"
 
 	"code.forgejo.org/f3/gof3/v3/f3"
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 	f3_util "code.forgejo.org/f3/gof3/v3/util"
@@ -210,7 +211,7 @@ func updateIssueLabels(ctx context.Context, issueID int64, labels []*issues_mode
 	}
 }
 
-func (o *issue) Put(ctx context.Context) generic.NodeID {
+func (o *issue) Put(ctx context.Context) f3_id.NodeID {
 	node := o.GetNode()
 	o.Trace("%s", node.GetID())
 
@@ -232,7 +233,7 @@ func (o *issue) Put(ctx context.Context) generic.NodeID {
 	updateIssueLabels(ctx, o.forgejoIssue.ID, o.forgejoIssue.Labels)
 
 	o.Trace("issue created %d/%d", o.forgejoIssue.ID, o.forgejoIssue.Index)
-	return generic.NewNodeID(o.forgejoIssue.Index)
+	return f3_id.NewNodeID(o.forgejoIssue.Index)
 }
 
 func (o *issue) Delete(ctx context.Context) {
diff --git a/services/f3/driver/label.go b/services/f3/driver/label.go
index aef0d0256d..509a69cf71 100644
--- a/services/f3/driver/label.go
+++ b/services/f3/driver/label.go
@@ -13,6 +13,7 @@ import (
 	issues_model "code.gitea.io/gitea/models/issues"
 
 	"code.forgejo.org/f3/gof3/v3/f3"
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 	f3_util "code.forgejo.org/f3/gof3/v3/util"
@@ -86,7 +87,7 @@ func (o *label) Patch(ctx context.Context) {
 	}
 }
 
-func (o *label) Put(ctx context.Context) generic.NodeID {
+func (o *label) Put(ctx context.Context) f3_id.NodeID {
 	node := o.GetNode()
 	o.Trace("%s", node.GetID())
 
@@ -95,7 +96,7 @@ func (o *label) Put(ctx context.Context) generic.NodeID {
 		panic(err)
 	}
 	o.Trace("label created %d", o.forgejoLabel.ID)
-	return generic.NewNodeID(o.forgejoLabel.ID)
+	return f3_id.NewNodeID(o.forgejoLabel.ID)
 }
 
 func (o *label) Delete(ctx context.Context) {
diff --git a/services/f3/driver/milestone.go b/services/f3/driver/milestone.go
index f133d37f7a..e57fee95a7 100644
--- a/services/f3/driver/milestone.go
+++ b/services/f3/driver/milestone.go
@@ -15,6 +15,7 @@ import (
 	"code.gitea.io/gitea/modules/timeutil"
 
 	"code.forgejo.org/f3/gof3/v3/f3"
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 	f3_util "code.forgejo.org/f3/gof3/v3/util"
@@ -122,7 +123,7 @@ func (o *milestone) Patch(ctx context.Context) {
 	}
 }
 
-func (o *milestone) Put(ctx context.Context) generic.NodeID {
+func (o *milestone) Put(ctx context.Context) f3_id.NodeID {
 	node := o.GetNode()
 	o.Trace("%s", node.GetID())
 
@@ -131,7 +132,7 @@ func (o *milestone) Put(ctx context.Context) generic.NodeID {
 		panic(err)
 	}
 	o.Trace("milestone created %d", o.forgejoMilestone.ID)
-	return generic.NewNodeID(o.forgejoMilestone.ID)
+	return f3_id.NewNodeID(o.forgejoMilestone.ID)
 }
 
 func (o *milestone) Delete(ctx context.Context) {
diff --git a/services/f3/driver/organization.go b/services/f3/driver/organization.go
index 76b240068d..8e818a231a 100644
--- a/services/f3/driver/organization.go
+++ b/services/f3/driver/organization.go
@@ -13,6 +13,7 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 
 	"code.forgejo.org/f3/gof3/v3/f3"
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 	f3_util "code.forgejo.org/f3/gof3/v3/util"
@@ -81,7 +82,7 @@ func (o *organization) Patch(ctx context.Context) {
 	}
 }
 
-func (o *organization) Put(ctx context.Context) generic.NodeID {
+func (o *organization) Put(ctx context.Context) f3_id.NodeID {
 	node := o.GetNode()
 	o.Trace("%s", node.GetID())
 
@@ -94,7 +95,7 @@ func (o *organization) Put(ctx context.Context) generic.NodeID {
 		panic(err)
 	}
 
-	return generic.NewNodeID(o.forgejoOrganization.ID)
+	return f3_id.NewNodeID(o.forgejoOrganization.ID)
 }
 
 func (o *organization) Delete(ctx context.Context) {
diff --git a/services/f3/driver/organizations.go b/services/f3/driver/organizations.go
index 98c4c1497d..adebdbbe95 100644
--- a/services/f3/driver/organizations.go
+++ b/services/f3/driver/organizations.go
@@ -12,6 +12,7 @@ import (
 	org_model "code.gitea.io/gitea/models/organization"
 	user_model "code.gitea.io/gitea/models/user"
 
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 )
@@ -36,13 +37,13 @@ func (o *organizations) ListPage(ctx context.Context, page int) generic.Children
 	return f3_tree.ConvertListed(ctx, o.GetNode(), f3_tree.ConvertToAny(organizations...)...)
 }
 
-func (o *organizations) GetIDFromName(ctx context.Context, name string) generic.NodeID {
+func (o *organizations) GetIDFromName(ctx context.Context, name string) f3_id.NodeID {
 	organization, err := org_model.GetOrgByName(ctx, name)
 	if err != nil {
 		panic(fmt.Errorf("GetOrganizationByName: %v", err))
 	}
 
-	return generic.NewNodeID(organization.ID)
+	return f3_id.NewNodeID(organization.ID)
 }
 
 func newOrganizations() generic.NodeDriverInterface {
diff --git a/services/f3/driver/project.go b/services/f3/driver/project.go
index c2a2df38c4..2400663426 100644
--- a/services/f3/driver/project.go
+++ b/services/f3/driver/project.go
@@ -14,6 +14,7 @@ import (
 	repo_service "code.gitea.io/gitea/services/repository"
 
 	"code.forgejo.org/f3/gof3/v3/f3"
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 	f3_util "code.forgejo.org/f3/gof3/v3/util"
@@ -121,7 +122,7 @@ func (o *project) Patch(ctx context.Context) {
 	}
 }
 
-func (o *project) Put(ctx context.Context) generic.NodeID {
+func (o *project) Put(ctx context.Context) f3_id.NodeID {
 	node := o.GetNode()
 	o.Trace("%s", node.GetID())
 
@@ -166,7 +167,7 @@ func (o *project) Put(ctx context.Context) generic.NodeID {
 		o.forgejoProject = repo
 		o.Trace("project created %d", o.forgejoProject.ID)
 	}
-	return generic.NewNodeID(o.forgejoProject.ID)
+	return f3_id.NewNodeID(o.forgejoProject.ID)
 }
 
 func (o *project) Delete(ctx context.Context) {
diff --git a/services/f3/driver/projects.go b/services/f3/driver/projects.go
index a2dabc3f95..fb447f3f01 100644
--- a/services/f3/driver/projects.go
+++ b/services/f3/driver/projects.go
@@ -11,6 +11,7 @@ import (
 	"code.gitea.io/gitea/models/db"
 	repo_model "code.gitea.io/gitea/models/repo"
 
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 )
@@ -19,18 +20,18 @@ type projects struct {
 	container
 }
 
-func (o *projects) GetIDFromName(ctx context.Context, name string) generic.NodeID {
+func (o *projects) GetIDFromName(ctx context.Context, name string) f3_id.NodeID {
 	owner := f3_tree.GetOwnerName(o.GetNode())
 	forgejoProject, err := repo_model.GetRepositoryByOwnerAndName(ctx, owner, name)
 	if repo_model.IsErrRepoNotExist(err) {
-		return generic.NilID
+		return f3_id.NilID
 	}
 
 	if err != nil {
 		panic(fmt.Errorf("error GetRepositoryByOwnerAndName(%s, %s): %v", owner, name, err))
 	}
 
-	return generic.NewNodeID(forgejoProject.ID)
+	return f3_id.NewNodeID(forgejoProject.ID)
 }
 
 func (o *projects) ListPage(ctx context.Context, page int) generic.ChildrenSlice {
diff --git a/services/f3/driver/pullrequest.go b/services/f3/driver/pullrequest.go
index 466b4bd576..b8cb06c4d5 100644
--- a/services/f3/driver/pullrequest.go
+++ b/services/f3/driver/pullrequest.go
@@ -18,6 +18,8 @@ import (
 	issue_service "code.gitea.io/gitea/services/issue"
 
 	"code.forgejo.org/f3/gof3/v3/f3"
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
+	f3_path "code.forgejo.org/f3/gof3/v3/path"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 	f3_util "code.forgejo.org/f3/gof3/v3/util"
@@ -51,7 +53,7 @@ func (o *pullRequest) repositoryToReference(ctx context.Context, repository *rep
 	if repository == nil {
 		panic("unexpected nil repository")
 	}
-	forge := o.getTree().GetRoot().GetChild(generic.NewNodeID(f3_tree.KindForge)).GetDriver().(*forge)
+	forge := o.getTree().GetRoot().GetChild(f3_id.NewNodeID(f3_tree.KindForge)).GetDriver().(*forge)
 	owners := forge.getOwnersPath(ctx, fmt.Sprintf("%d", repository.OwnerID))
 	return f3_tree.NewRepositoryReference(owners.String(), repository.OwnerID, repository.ID)
 }
@@ -61,7 +63,7 @@ func (o *pullRequest) referenceToRepository(reference *f3.Reference) int64 {
 	if reference.Get() == "../../repository/vcs" {
 		project = f3_tree.GetProjectID(o.GetNode())
 	} else {
-		p := f3_tree.ToPath(generic.PathAbsolute(o.GetNode().GetCurrentPath().String(), reference.Get()))
+		p := f3_tree.ToPath(f3_path.PathAbsolute(generic.NewElementNode, o.GetNode().GetCurrentPath().String(), reference.Get()))
 		o.Trace("%v %v", o.GetNode().GetCurrentPath().String(), p)
 		_, project = p.OwnerAndProjectID()
 	}
@@ -237,7 +239,7 @@ func (o *pullRequest) GetPullRequestRef() string {
 	return fmt.Sprintf("refs/pull/%s/head", o.GetNativeID())
 }
 
-func (o *pullRequest) Put(ctx context.Context) generic.NodeID {
+func (o *pullRequest) Put(ctx context.Context) f3_id.NodeID {
 	node := o.GetNode()
 	o.Trace("%s", node.GetID())
 
@@ -289,7 +291,7 @@ func (o *pullRequest) Put(ctx context.Context) generic.NodeID {
 	}
 
 	o.Trace("pullRequest created %d/%d", o.forgejoPullRequest.ID, o.forgejoPullRequest.Index)
-	return generic.NewNodeID(o.forgejoPullRequest.Index)
+	return f3_id.NewNodeID(o.forgejoPullRequest.Index)
 }
 
 func (o *pullRequest) Delete(ctx context.Context) {
diff --git a/services/f3/driver/reaction.go b/services/f3/driver/reaction.go
index 0dc486c729..4f12fa41db 100644
--- a/services/f3/driver/reaction.go
+++ b/services/f3/driver/reaction.go
@@ -13,6 +13,7 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 
 	"code.forgejo.org/f3/gof3/v3/f3"
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 	f3_util "code.forgejo.org/f3/gof3/v3/util"
@@ -87,7 +88,7 @@ func (o *reaction) Patch(ctx context.Context) {
 	}
 }
 
-func (o *reaction) Put(ctx context.Context) generic.NodeID {
+func (o *reaction) Put(ctx context.Context) f3_id.NodeID {
 	o.Error("%v", o.forgejoReaction.User)
 
 	sess := db.GetEngine(ctx)
@@ -115,7 +116,7 @@ func (o *reaction) Put(ctx context.Context) generic.NodeID {
 		panic(err)
 	}
 	o.Trace("reaction created %d", o.forgejoReaction.ID)
-	return generic.NewNodeID(o.forgejoReaction.ID)
+	return f3_id.NewNodeID(o.forgejoReaction.ID)
 }
 
 func (o *reaction) Delete(ctx context.Context) {
diff --git a/services/f3/driver/release.go b/services/f3/driver/release.go
index e937f84d05..86490e8b02 100644
--- a/services/f3/driver/release.go
+++ b/services/f3/driver/release.go
@@ -17,6 +17,7 @@ import (
 	release_service "code.gitea.io/gitea/services/release"
 
 	"code.forgejo.org/f3/gof3/v3/f3"
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 	f3_util "code.forgejo.org/f3/gof3/v3/util"
@@ -115,7 +116,7 @@ func (o *release) Patch(ctx context.Context) {
 	}
 }
 
-func (o *release) Put(ctx context.Context) generic.NodeID {
+func (o *release) Put(ctx context.Context) f3_id.NodeID {
 	node := o.GetNode()
 	o.Trace("%s", node.GetID())
 
@@ -133,7 +134,7 @@ func (o *release) Put(ctx context.Context) generic.NodeID {
 		panic(err)
 	}
 	o.Trace("release created %d", o.forgejoRelease.ID)
-	return generic.NewNodeID(o.forgejoRelease.ID)
+	return f3_id.NewNodeID(o.forgejoRelease.ID)
 }
 
 func (o *release) Delete(ctx context.Context) {
diff --git a/services/f3/driver/repository.go b/services/f3/driver/repository.go
index 21f826e551..118d5f2f2a 100644
--- a/services/f3/driver/repository.go
+++ b/services/f3/driver/repository.go
@@ -11,6 +11,7 @@ import (
 
 	"code.forgejo.org/f3/gof3/v3/f3"
 	helpers_repository "code.forgejo.org/f3/gof3/v3/forges/helpers/repository"
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 )
@@ -57,7 +58,7 @@ func (o *repository) Get(ctx context.Context) bool {
 	return o.h.Get(ctx)
 }
 
-func (o *repository) Put(ctx context.Context) generic.NodeID {
+func (o *repository) Put(ctx context.Context) f3_id.NodeID {
 	return o.upsert(ctx)
 }
 
@@ -65,10 +66,10 @@ func (o *repository) Patch(ctx context.Context) {
 	o.upsert(ctx)
 }
 
-func (o *repository) upsert(ctx context.Context) generic.NodeID {
+func (o *repository) upsert(ctx context.Context) f3_id.NodeID {
 	o.Trace("%s", o.GetNativeID())
 	o.h.Upsert(ctx, o.f)
-	return generic.NewNodeID(o.f.Name)
+	return f3_id.NewNodeID(o.f.Name)
 }
 
 func (o *repository) SetFetchFunc(fetchFunc func(ctx context.Context, destination string, internalRefs []string)) {
diff --git a/services/f3/driver/review.go b/services/f3/driver/review.go
index a3c074bd63..d180ea96be 100644
--- a/services/f3/driver/review.go
+++ b/services/f3/driver/review.go
@@ -14,6 +14,7 @@ import (
 	"code.gitea.io/gitea/modules/timeutil"
 
 	"code.forgejo.org/f3/gof3/v3/f3"
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 	f3_util "code.forgejo.org/f3/gof3/v3/util"
@@ -134,7 +135,7 @@ func (o *review) Patch(ctx context.Context) {
 	}
 }
 
-func (o *review) Put(ctx context.Context) generic.NodeID {
+func (o *review) Put(ctx context.Context) f3_id.NodeID {
 	node := o.GetNode()
 	o.Trace("%s", node.GetID())
 
@@ -153,7 +154,7 @@ func (o *review) Put(ctx context.Context) generic.NodeID {
 		panic(err)
 	}
 	o.Trace("review created %d", o.forgejoReview.ID)
-	return generic.NewNodeID(o.forgejoReview.ID)
+	return f3_id.NewNodeID(o.forgejoReview.ID)
 }
 
 func (o *review) Delete(ctx context.Context) {
diff --git a/services/f3/driver/reviewcomment.go b/services/f3/driver/reviewcomment.go
index 8e13d86b63..7ba0e15802 100644
--- a/services/f3/driver/reviewcomment.go
+++ b/services/f3/driver/reviewcomment.go
@@ -15,6 +15,7 @@ import (
 	"code.gitea.io/gitea/modules/timeutil"
 
 	"code.forgejo.org/f3/gof3/v3/f3"
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 	f3_util "code.forgejo.org/f3/gof3/v3/util"
@@ -115,7 +116,7 @@ func (o *reviewComment) Patch(ctx context.Context) {
 	}
 }
 
-func (o *reviewComment) Put(ctx context.Context) generic.NodeID {
+func (o *reviewComment) Put(ctx context.Context) f3_id.NodeID {
 	node := o.GetNode()
 	o.Trace("%s", node.GetID())
 
@@ -125,7 +126,7 @@ func (o *reviewComment) Put(ctx context.Context) generic.NodeID {
 		panic(err)
 	}
 	o.Trace("reviewComment created %d", o.forgejoReviewComment.ID)
-	return generic.NewNodeID(o.forgejoReviewComment.ID)
+	return f3_id.NewNodeID(o.forgejoReviewComment.ID)
 }
 
 func (o *reviewComment) Delete(ctx context.Context) {
diff --git a/services/f3/driver/root.go b/services/f3/driver/root.go
index 0e8a67faf3..f4a6e6a7ca 100644
--- a/services/f3/driver/root.go
+++ b/services/f3/driver/root.go
@@ -8,6 +8,7 @@ import (
 	"context"
 
 	"code.forgejo.org/f3/gof3/v3/f3"
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 )
 
@@ -33,8 +34,8 @@ func (o *root) ToFormat() f3.Interface {
 
 func (o *root) Get(context.Context) bool { return true }
 
-func (o *root) Put(context.Context) generic.NodeID {
-	return generic.NilID
+func (o *root) Put(context.Context) f3_id.NodeID {
+	return f3_id.NilID
 }
 
 func (o *root) Patch(context.Context) {
diff --git a/services/f3/driver/tests/new.go b/services/f3/driver/tests/new.go
index 2e3dfc3c95..dc6ac437e6 100644
--- a/services/f3/driver/tests/new.go
+++ b/services/f3/driver/tests/new.go
@@ -9,8 +9,8 @@ import (
 
 	driver_options "code.gitea.io/gitea/services/f3/driver/options"
 
+	f3_kind "code.forgejo.org/f3/gof3/v3/kind"
 	"code.forgejo.org/f3/gof3/v3/options"
-	"code.forgejo.org/f3/gof3/v3/tree/generic"
 	forge_test "code.forgejo.org/f3/gof3/v3/tree/tests/f3/forge"
 )
 
@@ -22,8 +22,8 @@ func (o *forgeTest) NewOptions(t *testing.T) options.Interface {
 	return newTestOptions(t)
 }
 
-func (o *forgeTest) GetExceptions() []generic.Kind {
-	return []generic.Kind{}
+func (o *forgeTest) GetExceptions() []f3_kind.Kind {
+	return []f3_kind.Kind{}
 }
 
 func (o *forgeTest) GetNonTestUsers() []string {
diff --git a/services/f3/driver/topic.go b/services/f3/driver/topic.go
index 16b2eb3142..eeb387cf93 100644
--- a/services/f3/driver/topic.go
+++ b/services/f3/driver/topic.go
@@ -12,6 +12,7 @@ import (
 	repo_model "code.gitea.io/gitea/models/repo"
 
 	"code.forgejo.org/f3/gof3/v3/f3"
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 	f3_util "code.forgejo.org/f3/gof3/v3/util"
@@ -79,14 +80,14 @@ func (o *topic) Patch(ctx context.Context) {
 	}
 }
 
-func (o *topic) Put(ctx context.Context) generic.NodeID {
+func (o *topic) Put(ctx context.Context) f3_id.NodeID {
 	sess := db.GetEngine(ctx)
 
 	if _, err := sess.Insert(o.forgejoTopic); err != nil {
 		panic(err)
 	}
 	o.Trace("topic created %d", o.forgejoTopic.ID)
-	return generic.NewNodeID(o.forgejoTopic.ID)
+	return f3_id.NewNodeID(o.forgejoTopic.ID)
 }
 
 func (o *topic) Delete(ctx context.Context) {
diff --git a/services/f3/driver/tree.go b/services/f3/driver/tree.go
index 0302ed74ae..2377d3794d 100644
--- a/services/f3/driver/tree.go
+++ b/services/f3/driver/tree.go
@@ -10,6 +10,7 @@ import (
 
 	forgejo_options "code.gitea.io/gitea/services/f3/driver/options"
 
+	f3_kind "code.forgejo.org/f3/gof3/v3/kind"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 )
@@ -24,7 +25,7 @@ func (o *treeDriver) Init() {
 	o.NullTreeDriver.Init()
 }
 
-func (o *treeDriver) Factory(ctx context.Context, kind generic.Kind) generic.NodeDriverInterface {
+func (o *treeDriver) Factory(ctx context.Context, kind f3_kind.Kind) generic.NodeDriverInterface {
 	switch kind {
 	case f3_tree.KindForge:
 		return newForge()
@@ -88,7 +89,7 @@ func (o *treeDriver) Factory(ctx context.Context, kind generic.Kind) generic.Nod
 		return newRepositories()
 	case f3_tree.KindRepository:
 		return newRepository(ctx)
-	case generic.KindRoot:
+	case f3_kind.KindRoot:
 		return newRoot(o.GetTree().(f3_tree.TreeInterface).NewFormat(kind))
 	default:
 		panic(fmt.Errorf("unexpected kind %s", kind))
diff --git a/services/f3/driver/user.go b/services/f3/driver/user.go
index 221b06e834..0ba6cbb7c6 100644
--- a/services/f3/driver/user.go
+++ b/services/f3/driver/user.go
@@ -14,6 +14,7 @@ import (
 	user_service "code.gitea.io/gitea/services/user"
 
 	"code.forgejo.org/f3/gof3/v3/f3"
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 	f3_util "code.forgejo.org/f3/gof3/v3/util"
@@ -96,9 +97,9 @@ func (o *user) Get(ctx context.Context) bool {
 func (o *user) Patch(context.Context) {
 }
 
-func (o *user) Put(ctx context.Context) generic.NodeID {
+func (o *user) Put(ctx context.Context) f3_id.NodeID {
 	if user := getSystemUserByName(o.forgejoUser.Name); user != nil {
-		return generic.NewNodeID(user.ID)
+		return f3_id.NewNodeID(user.ID)
 	}
 
 	o.forgejoUser.LowerName = strings.ToLower(o.forgejoUser.Name)
@@ -111,7 +112,7 @@ func (o *user) Put(ctx context.Context) generic.NodeID {
 		panic(err)
 	}
 
-	return generic.NewNodeID(o.forgejoUser.ID)
+	return f3_id.NewNodeID(o.forgejoUser.ID)
 }
 
 func (o *user) Delete(ctx context.Context) {
diff --git a/services/f3/driver/users.go b/services/f3/driver/users.go
index 92ed0bcbc5..59b10fc51d 100644
--- a/services/f3/driver/users.go
+++ b/services/f3/driver/users.go
@@ -11,6 +11,7 @@ import (
 	"code.gitea.io/gitea/models/db"
 	user_model "code.gitea.io/gitea/models/user"
 
+	f3_id "code.forgejo.org/f3/gof3/v3/id"
 	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
 	"code.forgejo.org/f3/gof3/v3/tree/generic"
 )
@@ -34,13 +35,13 @@ func (o *users) ListPage(ctx context.Context, page int) generic.ChildrenSlice {
 	return f3_tree.ConvertListed(ctx, o.GetNode(), f3_tree.ConvertToAny(users...)...)
 }
 
-func (o *users) GetIDFromName(ctx context.Context, name string) generic.NodeID {
+func (o *users) GetIDFromName(ctx context.Context, name string) f3_id.NodeID {
 	user, err := user_model.GetUserByName(ctx, name)
 	if err != nil {
 		panic(fmt.Errorf("GetUserByName: %v", err))
 	}
 
-	return generic.NewNodeID(user.ID)
+	return f3_id.NewNodeID(user.ID)
 }
 
 func newUsers() generic.NodeDriverInterface {