1 Commits

Author SHA1 Message Date
mr 83f8de0439 oclib 2025-02-13 10:22:42 +01:00
26 changed files with 673 additions and 2713 deletions
-27
View File
@@ -1,27 +0,0 @@
kind: pipeline
type: docker
name: build-and-push
trigger:
branch:
- main
steps:
- name: docker-login-build-push
image: docker:26
volumes:
- name: docker_sock
path: /var/run/docker.sock
environment:
DOCKER_USERNAME:
from_secret: docker-user
DOCKER_PASSWORD:
from_secret: docker_password
commands:
- echo "$DOCKER_PASSWORD" | docker login opencloudregistry -u "$DOCKER_USERNAME" --password-stdin
- make ci
volumes:
- name: docker_sock
host:
path: /var/run/docker.sock
-3
View File
@@ -1,3 +0,0 @@
# Force Go as the main language
*.go linguist-detectable=true
* linguist-language=Go
+19 -33
View File
@@ -1,44 +1,30 @@
FROM golang:alpine AS deps
WORKDIR /app
COPY go.mod go.sum ./
RUN sed -i '/replace/d' go.mod
RUN apk add --no-cache git
RUN git config --global url."https://cloud.o-forge.io/".insteadOf "http://cloud.o-forge.io/"
RUN go mod download
#----------------------------------------------------------------------------------------------
FROM golang:alpine AS builder
WORKDIR /app
RUN go install github.com/beego/bee/v2@latest
WORKDIR /oc-peer
COPY --from=deps /go/pkg /go/pkg
COPY --from=deps /app/go.mod /app/go.sum ./
RUN export CGO_ENABLED=0 && \
export GOOS=linux && \
export GOARCH=amd64 && \
export BUILD_FLAGS="-ldflags='-w -s'"
COPY . .
RUN sed -i '/replace/d' go.mod
RUN bee pack
RUN mkdir -p /app/extracted && tar -zxvf oc-peer.tar.gz -C /app/extracted
#----------------------------------------------------------------------------------------------
RUN apk add git
FROM golang:alpine
RUN go get github.com/beego/bee/v2 && go install github.com/beego/bee/v2@master
RUN timeout 15 bee run -gendoc=true -downdoc=true -runmode=dev || :
RUN sed -i 's/http:\/\/127.0.0.1:8080\/swagger\/swagger.json/swagger.json/g' swagger/index.html
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o setup .
RUN ls /app
FROM scratch
WORKDIR /app
COPY --from=builder /app/extracted/oc-peer /usr/bin/
COPY --from=builder /app/extracted/swagger /app/swagger
COPY --from=builder /app/extracted/docker_conf.json /etc/oc/peer.json
EXPOSE 8080
COPY --from=builder /app/setup /usr/bin/
COPY --from=builder /app/swagger /app/swagger
ENTRYPOINT ["oc-peer"]
COPY docker_conf.json /etc/oc/peer.json
EXPOSE $PORT
ENTRYPOINT ["setup"]
-49
View File
@@ -1,49 +0,0 @@
.DEFAULT_GOAL := all
build: clean
bee pack
run:
bee run -gendoc=true -downdoc=true
purge:
lsof -t -i:8093 | xargs kill | true
run-dev:
bee generate routers && bee run -gendoc=true -downdoc=true -runmode=prod
dev: purge run-dev
debug:
bee run -downdebug -gendebug
clean:
rm -rf oc-peer.tar.gz
docker:
DOCKER_BUILDKIT=1 docker build -t oc-peer -f Dockerfile . --build-arg=HOST=$(HOST)
docker tag oc-peer opencloudregistry/oc-peer:latest
publish-kind:
kind load docker-image opencloudregistry/oc-monitord:latest --name $(CLUSTER_NAME) | true
publish-registry:
docker push opencloudregistry/oc-peer:latest
docker-deploy:
docker compose up -d
run-docker: docker publish-kind publish-registry docker-deploy
prepare-multiarch:
docker buildx create --name multiarch --driver docker-container --use | true
docker run --privileged --rm tonistiigi/binfmt --install all | true
docker-multiarch:
DOCKER_BUILDKIT=1 docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t opencloudregistry/oc-peer:latest --push .
ci: docker publish-registry
all: docker publish-kind
.PHONY: build run clean docker publish-kind publish-registry
-2
View File
@@ -6,8 +6,6 @@ To build :
bee generate routers
bee run -gendoc=true -downdoc=true
OR
make dev
If default Swagger page is displayed instead of tyour api, change url in swagger/index.html file to :
+1 -1
View File
@@ -1,5 +1,5 @@
appname = oc-peer
httpport = 8093
httpport = 8080
runmode = dev
autorender = false
copyrequestbody = true
+31 -663
View File
@@ -1,20 +1,11 @@
package controllers
import (
ctx "context"
"encoding/json"
"fmt"
"oc-peer/infrastructure"
"strconv"
oclib "cloud.o-forge.io/core/oc-lib"
"cloud.o-forge.io/core/oc-lib/config"
"cloud.o-forge.io/core/oc-lib/dbs"
"cloud.o-forge.io/core/oc-lib/models/organization"
"cloud.o-forge.io/core/oc-lib/models/peer"
"cloud.o-forge.io/core/oc-lib/tools"
beego "github.com/beego/beego/v2/server/web"
"github.com/gorilla/websocket"
)
// Operations about workflow
@@ -24,65 +15,32 @@ type PeerController struct {
// @Title Search
// @Description search workspace
// @Param type path string true "the type you want to get"
// @Param search path string true "the word search you want to get"
// @Param is_draft query string false
// @Param offset query string false
// @Param limit query string false
// @Success 200 {workspace} models.workspace
// @router /:type/search/:search [get]
// @router /search/:search [get]
func (o *PeerController) Search() {
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
// store and return Id or post with UUIDLibDataEnum
search := o.Ctx.Input.Param(":search")
typ := o.Ctx.Input.Param(":type")
isDraft := o.Ctx.Input.Query("is_draft")
offset, _ := strconv.Atoi(o.Ctx.Input.Query("offset"))
limit, _ := strconv.Atoi(o.Ctx.Input.Query("limit"))
var filter *dbs.Filters
fmt.Println("TYP", typ)
relation := peer.GetRelationPath(typ)
if relation != -1 {
filter = &dbs.Filters{
And: map[string][]dbs.Filter{ // search by name if no filters are provided
"relation": {{Operator: dbs.EQUAL.String(), Value: relation}},
},
Or: map[string][]dbs.Filter{ // search by name if no filters are providedz
"abstractobject.name": {{Operator: dbs.LIKE.String(), Value: search}},
"url": {{Operator: dbs.LIKE.String(), Value: search}},
"peer_id": {{Operator: dbs.LIKE.String(), Value: search}},
},
}
search = ""
}
fmt.Println(filter, relation, "<", search, ">")
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), user, peerID, groups, nil).Search(
filter, search, isDraft == "true", int64(offset), int64(limit))
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), user, peerID, groups, nil).Search(nil, search, isDraft == "true")
o.ServeJSON()
}
// @Title Search
// @Description search workspace
// @Param is_draft query string false
// @Param offset query string false
// @Param limit query string false
// @Param data body json true "body for data content (Json format)"
// @Success 200 {workspace} models.workspace
// @router /:type/extended/search [post]
func (o *PeerController) SearchExtended() {
// @Title Update
// @Description create peers
// @Param id path string true "the peer id you want to get"
// @Param body body models.peer true "The peer content"
// @Success 200 {object} models.peer
// @router /:id [put]
func (o *PeerController) Put() {
// store and return Id or post with UUID
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
// store and return Id or post with UUIDLibDataEnum
isDraft := o.Ctx.Input.Query("is_draft")
typ := o.Ctx.Input.Param(":type")
offset, _ := strconv.Atoi(o.Ctx.Input.Query("offset"))
limit, _ := strconv.Atoi(o.Ctx.Input.Query("limit"))
var res map[string]interface{}
json.Unmarshal(o.Ctx.Input.CopyBody(100000), &res)
fmt.Println(res, oclib.FiltersFromFlatMap(res, &peer.Peer{}))
relation := peer.GetRelationPath(typ)
res["relation"] = relation
data := oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), user, peerID, groups, nil).Search(
oclib.FiltersFromFlatMap(res, &peer.Peer{}), "", isDraft == "true", int64(offset), int64(limit))
id := o.Ctx.Input.Param(":id")
json.Unmarshal(o.Ctx.Input.CopyBody(10000), &res)
data := oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), user, peerID, groups, nil).UpdateOne(res, id)
o.Data["json"] = data
o.ServeJSON()
}
@@ -90,25 +48,12 @@ func (o *PeerController) SearchExtended() {
// @Title GetAll
// @Description find all peer
// @Param is_draft query string false
// @Param offset query string false
// @Param limit query string false
// @Success 200 {peer} models.peer
// @router / [get]
func (o *PeerController) GetAll() {
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
isDraft := o.Ctx.Input.Query("is_draft")
offset, _ := strconv.Atoi(o.Ctx.Input.Query("offset"))
limit, _ := strconv.Atoi(o.Ctx.Input.Query("limit"))
verify := o.Ctx.Input.Query("verify")
if verify == "true" {
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), user, peerID, groups, nil).Search(&dbs.Filters{
And: map[string][]dbs.Filter{
"verify": {{Operator: dbs.EQUAL.String(), Value: true}},
},
}, "", false, int64(offset), int64(limit))
} else {
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), user, peerID, groups, nil).LoadAll(isDraft == "true", int64(offset), int64(limit))
}
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), user, peerID, groups, nil).LoadAll(isDraft == "true")
o.ServeJSON()
}
@@ -124,621 +69,44 @@ func (o *PeerController) Get() {
o.ServeJSON()
}
// @Title Valid
// @Description find peer by peerid
// @Param id path string true "the peer id you want to get"
// @Success 200 {peer} models.peer
// @router /valid/:id [get]
func (o *PeerController) Valid() {
user, _, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
id := o.Ctx.Input.Param(":id")
if ok, _ := oclib.IsMySelf(id); ok {
o.Data["json"] = map[string]interface{}{
"data": nil,
"code": 400,
"error": "can't validate a link relation for ourself",
}
o.ServeJSON()
return
}
fmt.Println(id)
req := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
l := req.LoadOne(id)
if l.Data != nil && l.ToPeer().Verify && (l.ToPeer().Relation == peer.PARTNER || l.ToPeer().Relation == peer.PENDING_PARTNER) {
data := req.UpdateOne(map[string]interface{}{
"verify": false,
"relation": peer.PARTNER,
}, l.ToPeer().GetID())
fmt.Println(l.Data, data.Data)
if data.Data != nil {
b, _ := json.Marshal(data.Data)
go infrastructure.EmitNATS(user, groups, tools.PropalgationMessage{
DataType: tools.PEER.EnumIndex(),
Action: tools.PB_CREATE,
Payload: b,
})
}
o.Data["json"] = data
o.ServeJSON()
return
} else if l.Data != nil && l.ToPeer().Verify && (l.ToPeer().Relation == peer.MASTER || l.ToPeer().Relation == peer.PENDING_MASTER) {
masterPeerID := l.ToPeer().PeerID
data := req.UpdateOne(map[string]interface{}{
"verify": false,
"relation": peer.MASTER,
}, l.ToPeer().GetID())
fmt.Println(l.Data, data.Data)
data.Data.(*peer.Peer).MasterID = masterPeerID
data.Data.(*peer.Peer).Relation = peer.NANO // dest is a nano
if data.Data != nil {
b, _ := json.Marshal(data.Data)
go infrastructure.EmitNATS(user, groups, tools.PropalgationMessage{
DataType: tools.PEER.EnumIndex(),
Action: tools.PB_CREATE,
Payload: b,
})
}
// This node is now a NANO of the confirmed master: stamp its libp2p PeerID on self.
if self, serr := oclib.GetMySelf(); serr == nil && self != nil {
oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil).UpdateOne(map[string]interface{}{
"master_id": masterPeerID,
}, self.GetID())
}
o.Data["json"] = data
o.ServeJSON()
return
} else if l.Data != nil && l.ToPeer().Verify && (l.ToPeer().Relation == peer.NANO || l.ToPeer().Relation == peer.PENDING_NANO) {
masterPeerID, err := oclib.GetMySelf()
if err == nil {
data := req.UpdateOne(map[string]interface{}{
"verify": false,
"relation": peer.NANO,
}, l.ToPeer().GetID())
fmt.Println(l.Data, data.Data)
data.Data.(*peer.Peer).MasterID = masterPeerID.GetID()
data.Data.(*peer.Peer).Relation = peer.MASTER // dest is a nano
if data.Data != nil {
b, _ := json.Marshal(data.Data)
go infrastructure.EmitNATS(user, groups, tools.PropalgationMessage{
DataType: tools.PEER.EnumIndex(),
Action: tools.PB_CREATE,
Payload: b,
})
}
// This node is now a NANO of the confirmed master: stamp its libp2p PeerID on self.
if self, serr := oclib.GetMySelf(); serr == nil && self != nil {
oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil).UpdateOne(map[string]interface{}{
"master_id": masterPeerID.GetID(),
}, self.GetID())
}
o.Data["json"] = data
o.ServeJSON()
return
}
} else if l.Data != nil && l.ToPeer().Verify && (l.ToPeer().Relation == peer.ORGANIZATION_MASTER || l.ToPeer().Relation == peer.ORGANIZATION_MASTER_PENDING) {
// The remote peer asked us to be their organization master.
// We confirm: they become our ORGANIZATION_MEMBER, we become their ORGANIZATION_MASTER.
self, serr := oclib.GetMySelf()
if serr == nil && self != nil {
data := req.UpdateOne(map[string]interface{}{
"verify": false,
"relation": peer.ORGANIZATION_MEMBER,
}, l.ToPeer().GetID())
// Stamp our peer ID as their OrganizationMasterID.
oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil).UpdateOne(map[string]interface{}{
"organization_master_id": self.GetID(),
}, l.ToPeer().GetID())
if data.Data != nil {
b, _ := json.Marshal(data.Data)
go infrastructure.EmitNATS(user, groups, tools.PropalgationMessage{
DataType: tools.PEER.EnumIndex(),
Action: tools.PB_CREATE,
Payload: b,
})
}
o.Data["json"] = data
o.ServeJSON()
return
}
} else if l.Data != nil && l.ToPeer().Verify && (l.ToPeer().Relation == peer.ORGANIZATION_MEMBER || l.ToPeer().Relation == peer.ORGANIZATION_MEMBER_PENDING) {
// The remote peer asked to join our organization as a member.
// We confirm: they are our ORGANIZATION_MEMBER, we are their ORGANIZATION_MASTER.
self, serr := oclib.GetMySelf()
if serr == nil && self != nil {
data := req.UpdateOne(map[string]interface{}{
"verify": false,
"relation": peer.ORGANIZATION_MEMBER,
}, l.ToPeer().GetID())
// Stamp our ID as the OrganizationMasterID on the new member.
oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil).UpdateOne(map[string]interface{}{
"organization_master_id": self.GetID(),
}, l.ToPeer().GetID())
// Set our own OrganizationMasterID on self (we are the master).
if self2, _ := oclib.GetMySelf(); self2 != nil && self2.OrganizationMasterID == "" {
oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil).UpdateOne(map[string]interface{}{
"organization_master_id": self.GetID(),
}, self2.GetID())
}
if data.Data != nil {
b, _ := json.Marshal(data.Data)
go infrastructure.EmitNATS(user, groups, tools.PropalgationMessage{
DataType: tools.PEER.EnumIndex(),
Action: tools.PB_CREATE,
Payload: b,
})
}
o.Data["json"] = data
o.ServeJSON()
return
}
} else if l.Data != nil && l.ToPeer().Verify && l.ToPeer().Relation == peer.ORGANIZATION_PARTNER {
data := req.UpdateOne(map[string]interface{}{
"verify": false,
"relation": peer.ORGANIZATION_PARTNER,
}, l.ToPeer().GetID())
if data.Data != nil {
b, _ := json.Marshal(data.Data)
go infrastructure.EmitNATS(user, groups, tools.PropalgationMessage{
DataType: tools.PEER.EnumIndex(),
Action: tools.PB_CREATE,
Payload: b,
})
}
o.Data["json"] = data
o.ServeJSON()
return
}
o.Data["json"] = map[string]interface{}{
"data": nil,
"code": 404,
"error": "peer to verify not found",
}
o.ServeJSON()
}
// @Title add
// @Description add peer by peerid
// @Param id path string true "the peer id you want to blacklist"
// @Success 200 {peer} models.peer
// @router /add/:id [post]
func (o *PeerController) Add() {
user, _, _ := oclib.ExtractTokenInfo(*o.Ctx.Request)
id := o.Ctx.Input.Param(":id")
infrastructure.SearchMu.Lock()
defer infrastructure.SearchMu.Unlock()
fmt.Println("qdqqds", infrastructure.SearchStreamAction)
if infrastructure.SearchStreamAction[user] != nil {
for _, p := range infrastructure.SearchStreamAction[user] {
if p.GetID() == id {
req := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
p.NotInCatalog = false
o.Data["json"] = req.StoreOne(p.Serialize(p))
o.ServeJSON()
return
}
}
}
o.Data["json"] = map[string]interface{}{
"data": nil,
"code": 404,
"error": "peer not received found",
}
o.ServeJSON()
}
// @Title Master
// @Description add master peer by peerid
// @Param id path string true "the peer id you want to blacklist"
// @Success 200 {peer} models.peer
// @router /master/:id [post]
func (o *PeerController) Master() {
if !config.GetConfig().IsNano {
o.Data["json"] = map[string]interface{}{
"data": nil,
"code": 409,
"error": "not nano built can't ask for master",
}
}
user, _, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
id := o.Ctx.Input.Param(":id")
req := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
data := req.LoadOne(id)
p := data.ToPeer()
if p.IsNano {
o.Data["json"] = map[string]interface{}{
"data": nil,
"code": 409,
"error": "is not Master built can't ask for master",
}
}
o.changeRelation(id, p, user, groups, peer.MASTER, req)
}
// @Title Nano
// @Description add Nano peer by peerid
// @Param id path string true "the peer id you want to blacklist"
// @Success 200 {peer} models.peer
// @router /nano/:id [post]
func (o *PeerController) Nano() {
if config.GetConfig().IsNano {
o.Data["json"] = map[string]interface{}{
"data": nil,
"code": 409,
"error": "nano built can't ask for nano",
}
}
user, _, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
id := o.Ctx.Input.Param(":id")
req := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
data := req.LoadOne(id)
p := data.ToPeer()
if !p.IsNano {
o.Data["json"] = map[string]interface{}{
"data": nil,
"code": 409,
"error": "is not Nano built can't ask for nano",
}
}
o.changeRelation(id, p, user, groups, peer.NANO, req)
}
// @Title known
// @Description add kwown peer by peerid
// @Param id path string true "the peer id you want to blacklist"
// @Success 200 {peer} models.peer
// @router /known/:id [post]
func (o *PeerController) Known() {
user, _, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
id := o.Ctx.Input.Param(":id")
req := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
data := req.LoadOne(id)
o.changeRelation(id, data.ToPeer(), user, groups, peer.NONE, req)
}
// @Title Partner
// @Description add partner peer by peerid
// @Param id path string true "the peer id you want to blacklist"
// @Param id path string true "the peer id you want to partner"
// @Success 200 {peer} models.peer
// @router /partner/:id [post]
// @router /:id/partner [post]
func (o *PeerController) Partner() {
if config.GetConfig().IsNano {
o.Data["json"] = map[string]interface{}{
"data": nil,
"code": 409,
"error": "nano built can't ask for partner",
}
}
user, _, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
id := o.Ctx.Input.Param(":id")
req := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
data := req.LoadOne(id)
o.changeRelation(id, data.ToPeer(), user, groups, peer.PARTNER, req)
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), user, peerID, groups, nil).UpdateOne(map[string]interface{}{
"state": peer.PARTNER,
}, id)
o.ServeJSON()
}
// @Title Blacklist
// @Description add blacklist peer by peerid
// @Param id path string true "the peer id you want to blacklist"
// @Success 200 {peer} models.peer
// @router /blacklist/:id [post]
// @router /:id/blacklist [post]
func (o *PeerController) Blacklist() {
user, _, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
id := o.Ctx.Input.Param(":id")
req := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
data := req.LoadOne(id)
o.changeRelation(id, data.ToPeer(), user, groups, peer.BLACKLIST, req)
}
// used from : peer ask, or response, only from peer origin is authorized to change...
func (o *PeerController) changeRelation(id string, dest *peer.Peer, user string, groups []string, relation peer.PeerRelation, request *oclib.Request) {
if dest.IsNano && relation != peer.NANO {
o.Data["json"] = map[string]interface{}{
"data": nil,
"code": 409,
"error": "can't change relation on nano",
}
o.ServeJSON()
return
}
infrastructure.SearchMu.Lock()
if dest == nil && infrastructure.SearchStreamAction[user] != nil { // add auto in base if not existing
req := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
for _, pp := range infrastructure.SearchStreamAction[user] {
if pp.GetID() == id {
data := req.StoreOne(pp.Serialize(pp))
dest = data.ToPeer()
break
}
}
}
infrastructure.SearchMu.Unlock()
// store and return Id or post with UUID
if dest != nil {
if ok, _ := oclib.IsMySelf(dest.GetID()); ok {
o.Data["json"] = map[string]interface{}{
"data": nil,
"code": 400,
"error": "can't change ourself",
}
o.ServeJSON()
return
}
rRelation := relation
if !dest.Verify {
switch relation {
case peer.PARTNER:
relation = peer.PENDING_PARTNER
case peer.NANO:
relation = peer.PENDING_NANO
case peer.BLACKLIST:
relation = peer.NONE
case peer.ORGANIZATION_MASTER:
relation = peer.ORGANIZATION_MASTER_PENDING
case peer.ORGANIZATION_MEMBER:
relation = peer.ORGANIZATION_MEMBER_PENDING
}
}
if dest.Verify && relation == peer.PENDING_PARTNER {
relation = peer.PARTNER
}
if dest.Verify && relation == peer.PENDING_NANO {
relation = peer.NANO
}
if dest.Verify && relation == peer.ORGANIZATION_MASTER_PENDING {
relation = peer.ORGANIZATION_MASTER
}
if dest.Verify && relation == peer.ORGANIZATION_MEMBER_PENDING {
relation = peer.ORGANIZATION_MEMBER
}
wasMaster := dest.Relation == peer.MASTER
data := request.UpdateOne(map[string]interface{}{
"relation": relation,
}, dest.GetID())
fmt.Println(data.Err, data.Data)
if data.Err == "" && data.Data != nil {
b, _ := json.Marshal(data.Data)
go infrastructure.EmitNATS(user, groups, tools.PropalgationMessage{
DataType: tools.PEER.EnumIndex(),
Action: tools.PB_CREATE,
Payload: b,
})
}
// The peer was our master and is no longer — clear the MasterID on self.
if wasMaster {
if self, serr := oclib.GetMySelf(); serr == nil && self != nil {
oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil).UpdateOne(map[string]interface{}{
"master_id": "",
}, self.GetID())
}
}
if rRelation == peer.BLACKLIST {
request.UpdateOne(map[string]interface{}{
"relation": rRelation,
}, dest.GetID())
}
o.Data["json"] = data
o.ServeJSON()
return
}
o.Data["json"] = map[string]interface{}{
"data": nil,
"code": 404,
"error": "peer not found.",
}
o.ServeJSON()
}
// @Title SetOrganization
// @Description set organization data on self peer (only allowed when peer has no OrganizationMasterID)
// @Param data body json true "organization data"
// @Success 200 {peer} models.peer
// @router /organization [put]
func (o *PeerController) SetOrganization() {
self, err := oclib.GetMySelf()
if err != nil || self == nil {
o.Data["json"] = map[string]interface{}{"data": nil, "code": 404, "error": "self peer not found"}
o.ServeJSON()
return
}
if self.OrganizationMasterID != "" {
o.Data["json"] = map[string]interface{}{"data": nil, "code": 409, "error": "cannot set organization: peer already has an organization master"}
o.ServeJSON()
return
}
var org organization.Organization
if err := json.Unmarshal(o.Ctx.Input.CopyBody(100000), &org); err != nil {
o.Data["json"] = map[string]interface{}{"data": nil, "code": 400, "error": "invalid organization payload: " + err.Error()}
o.ServeJSON()
return
}
req := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
data := req.UpdateOne(map[string]interface{}{"organization": org}, self.GetID())
o.Data["json"] = data
o.ServeJSON()
}
// @Title OrganizationMasterRequest
// @Description request to become the organization master of a peer (send them an ORGANIZATION_MEMBER relation)
// @Param id path string true "the peer id to become member of our org"
// @Success 200 {peer} models.peer
// @router /organization_master/:id [post]
func (o *PeerController) OrganizationMasterRequest() {
user, _, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
id := o.Ctx.Input.Param(":id")
self, err := oclib.GetMySelf()
if err != nil || self == nil {
o.Data["json"] = map[string]interface{}{"data": nil, "code": 404, "error": "self peer not found"}
o.ServeJSON()
return
}
req := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
data := req.LoadOne(id)
p := data.ToPeer()
if p == nil {
o.Data["json"] = map[string]interface{}{"data": nil, "code": 404, "error": "peer not found"}
o.ServeJSON()
return
}
// Send the target peer an ORGANIZATION_MEMBER relation request (they receive us as their master).
o.changeRelation(id, p, user, groups, peer.ORGANIZATION_MEMBER, req)
}
// @Title OrganizationMemberRequest
// @Description request to join a peer's organization as a member (send them an ORGANIZATION_MASTER relation)
// @Param id path string true "the peer id whose org we want to join"
// @Success 200 {peer} models.peer
// @router /organization_member/:id [post]
func (o *PeerController) OrganizationMemberRequest() {
user, _, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
id := o.Ctx.Input.Param(":id")
self, err := oclib.GetMySelf()
if err != nil || self == nil {
o.Data["json"] = map[string]interface{}{"data": nil, "code": 404, "error": "self peer not found"}
o.ServeJSON()
return
}
if self.OrganizationMasterID != "" {
o.Data["json"] = map[string]interface{}{"data": nil, "code": 409, "error": "cannot request master: peer already has an organization master"}
o.ServeJSON()
return
}
req := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
data := req.LoadOne(id)
p := data.ToPeer()
if p == nil {
o.Data["json"] = map[string]interface{}{"data": nil, "code": 404, "error": "peer not found"}
o.ServeJSON()
return
}
// Send the target peer an ORGANIZATION_MASTER relation request (they receive us as a member candidate).
o.changeRelation(id, p, user, groups, peer.ORGANIZATION_MASTER, req)
}
// @Title OrganizationPartner
// @Description request organization partner relation with a peer
// @Param id path string true "the peer id to set as organization partner"
// @Success 200 {peer} models.peer
// @router /organization_partner/:id [post]
func (o *PeerController) OrganizationPartner() {
user, _, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
id := o.Ctx.Input.Param(":id")
req := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
data := req.LoadOne(id)
p := data.ToPeer()
if p == nil {
o.Data["json"] = map[string]interface{}{"data": nil, "code": 404, "error": "peer not found"}
o.ServeJSON()
return
}
o.changeRelation(id, p, user, groups, peer.ORGANIZATION_PARTNER, req)
}
// @Title SetPolicy
// @Description assign or clear a policy on a peer
// @Param id path string true "the peer id"
// @Param data body json true "body with policy_id field"
// @Success 200 {peer} models.peer
// @router /:id/policy [put]
func (o *PeerController) SetPolicy() {
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
id := o.Ctx.Input.Param(":id")
var body map[string]interface{}
json.Unmarshal(o.Ctx.Input.CopyBody(100000), &body)
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), user, peerID, groups, nil).UpdateOne(map[string]interface{}{
"policy_id": body["policy_id"],
"state": peer.BLACKLIST,
}, id)
o.ServeJSON()
}
// @Title Delete
// @Description delete peer by peerid
// @Title DeleteState
// @Description delete state peer by peerid
// @Param id path string true "the peer id you want to delete state"
// @Success 200 {peer} models.peer
// @router /:id [delete]
func (o *PeerController) Delete() {
id := o.Ctx.Input.Param(":id")
if ok, _ := oclib.IsMySelf(id); ok {
o.Data["json"] = map[string]interface{}{
"data": nil,
"code": 400,
"error": "can't remove myself",
}
o.ServeJSON()
return
}
// @router /:id/undo_state [post]
func (o *PeerController) DeleteState() {
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), user, peerID, groups, nil).DeleteOne(id)
fmt.Println(o.Data["json"])
id := o.Ctx.Input.Param(":id")
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), user, peerID, groups, nil).UpdateOne(map[string]interface{}{
"state": peer.NONE,
}, id)
o.ServeJSON()
}
func Websocket(c ctx.Context, user string, conn *websocket.Conn) {
defer conn.Close()
done := make(chan struct{})
go func() {
var discard interface{}
for {
if conn.ReadJSON(&discard) != nil {
close(done)
return
}
}
}()
defer func() {
if ch, ok := infrastructure.SearchStream[user]; ok {
close(ch)
infrastructure.SearchMu.Lock()
delete(infrastructure.SearchStream, user)
delete(infrastructure.SearchStreamAction, user)
fmt.Println("DEFER")
infrastructure.SearchMu.Unlock()
}
infrastructure.EmitNATS(user, nil, tools.PropalgationMessage{
Action: tools.PB_CLOSE_SEARCH,
DataType: tools.PEER.EnumIndex(),
})
}()
for {
select {
case msg, ok := <-infrastructure.SearchStream[user]:
if !ok {
continue
}
// Only accumulate peers in the action list (not online-change events).
if msg.Peer != nil {
fmt.Println("AAADDD")
infrastructure.SearchMu.Lock()
infrastructure.SearchStreamAction[user] = append(infrastructure.SearchStreamAction[user], msg.Peer)
infrastructure.SearchMu.Unlock()
fmt.Println("AAADDD", infrastructure.SearchStreamAction[user])
}
if conn.WriteJSON(msg) != nil {
continue
}
case <-done:
return
case <-c.Done():
return
}
}
}
/*
Un pair change le statut d'un autre pair, alors ce dernier est joins automatiquement, on ne peut pas s'auto lié seul un externe peut faire ce processus de demande.
On change le pair pour pouvoir le mettre à jour, alors, le lien se met à jour automatiquement. p1 -> update status -> link (p2) -> p2 response -> update status -> link (p1)
Que définit le partnership de type : Partner, Blacklist et None.
BlackList : implique qu'on ne peut pas "voir" un pair et ses ressources, d'un coté comme de l'autre. Il suffit qu'un pair définisse la Blacklist, le pair opposant ne peut plus le voir.
(DHT allons plus loin)
Partner : Donne accès à des ressources non publique duquel un partnership à été modélisé, de type * ou dédié.
None : Est visible, et ne donne accès qu'au ressources publique et aux profiles all. Les profiles dédiés ne s'appliquent que si on est dans une situation de partenariat.
Note: L'état PENDING revient à dire qu'une relation est à l'état None,... si il y a une vérification on considère tout status à None. C'est une vérification importante.
*/
-81
View File
@@ -1,81 +0,0 @@
package controllers
import (
"encoding/json"
"strconv"
oclib "cloud.o-forge.io/core/oc-lib"
beego "github.com/beego/beego/v2/server/web"
)
type PolicyController struct {
beego.Controller
}
// @Title GetAll
// @Description get all policies
// @Param is_draft query string false
// @Param offset query string false
// @Param limit query string false
// @Success 200 {policy} policy.Policy
// @router / [get]
func (o *PolicyController) GetAll() {
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
isDraft := o.Ctx.Input.Query("is_draft")
offset, _ := strconv.Atoi(o.Ctx.Input.Query("offset"))
limit, _ := strconv.Atoi(o.Ctx.Input.Query("limit"))
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.POLICY), user, peerID, groups, nil).LoadAll(isDraft == "true", int64(offset), int64(limit))
o.ServeJSON()
}
// @Title Get
// @Description get policy by id
// @Param id path string true "the policy id"
// @Success 200 {policy} policy.Policy
// @router /:id [get]
func (o *PolicyController) Get() {
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
id := o.Ctx.Input.Param(":id")
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.POLICY), user, peerID, groups, nil).LoadOne(id)
o.ServeJSON()
}
// @Title Post
// @Description create a policy
// @Param data body json true "policy body"
// @Success 200 {policy} policy.Policy
// @router / [post]
func (o *PolicyController) Post() {
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
var body map[string]interface{}
json.Unmarshal(o.Ctx.Input.CopyBody(100000), &body)
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.POLICY), user, peerID, groups, nil).StoreOne(body)
o.ServeJSON()
}
// @Title Put
// @Description update a policy
// @Param id path string true "the policy id"
// @Param data body json true "policy body"
// @Success 200 {policy} policy.Policy
// @router /:id [put]
func (o *PolicyController) Put() {
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
id := o.Ctx.Input.Param(":id")
var body map[string]interface{}
json.Unmarshal(o.Ctx.Input.CopyBody(100000), &body)
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.POLICY), user, peerID, groups, nil).UpdateOne(body, id)
o.ServeJSON()
}
// @Title Delete
// @Description delete a policy
// @Param id path string true "the policy id"
// @Success 200 {policy} policy.Policy
// @router /:id [delete]
func (o *PolicyController) Delete() {
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
id := o.Ctx.Input.Param(":id")
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.POLICY), user, peerID, groups, nil).DeleteOne(id)
o.ServeJSON()
}
+1 -2
View File
@@ -34,8 +34,7 @@ func (o *StatusController) Status() {
var address map[string]string
json.Unmarshal(o.Ctx.Input.CopyBody(10000), &address)
api := tools.API{}
state, services, err := api.CheckRemoteAPIs([]tools.DataType{
tools.BOOKING, tools.WORKFLOW, tools.WORKSPACE,
state, services, err := api.CheckRemoteAPIs([]tools.DataType{tools.BOOKING, tools.WORKFLOW, tools.WORKSPACE,
tools.COLLABORATIVE_AREA, tools.DATA_RESOURCE}) // check if the services are alive
errSTR := ""
if err != nil {
+1 -4
View File
@@ -14,9 +14,6 @@ type VersionController struct {
// @Success 200
// @router / [get]
func (c *VersionController) GetAll() {
c.Data["json"] = map[string]string{
"service": "oc-peer",
"version": "1",
}
c.Data["json"] = map[string]string{"version": "1"}
c.ServeJSON()
}
+33
View File
@@ -0,0 +1,33 @@
version: '3.4'
services:
mongo:
image: 'mongo:latest'
networks:
- catalog
ports:
- 27017:27017
container_name: mongo
volumes:
- oc-catalog-data:/data/db
- oc-catalog-data:/data/configdb
mongo-express:
image: "mongo-express:latest"
restart: always
depends_on:
- mongo
networks:
- catalog
ports:
- 8081:8081
environment:
- ME_CONFIG_BASICAUTH_USERNAME=test
- ME_CONFIG_BASICAUTH_PASSWORD=test
volumes:
oc-catalog-data:
networks:
catalog:
# name: catalog
+6 -11
View File
@@ -8,21 +8,16 @@ services:
labels:
- "traefik.enable=true"
- "traefik.http.routers.peer.entrypoints=web"
- "traefik.http.routers.peer.rule=PathPrefix(`/peer`)"
- "traefik.http.middlewares.peer-rewrite.replacepathregex.regex=^/peer(.*)"
- "traefik.http.middlewares.peer-rewrite.replacepathregex.replacement=/oc$$1"
- "traefik.http.routers.peer.middlewares=peer-rewrite,auth-peer"
- "traefik.http.services.peer.loadbalancer.server.port=8080"
- "traefik.http.middlewares.auth-peer.forwardauth.address=http://oc-auth:8080/oc/forward"
- "traefik.http.middlewares.auth-peer.forwardauth.trustForwardHeader=true"
- "traefik.http.middlewares.auth-peer.forwardauth.authResponseHeaders=X-Auth-Request-User,X-Auth-Request-Email"
- "traefik.http.middlewares.auth.forwardauth.address=http://oc-auth:8080/oc/forward"
- "traefik.http.routers.workflow.rule=PathPrefix(/peer)"
- "traefik.http.routers.peer.tls=false"
- "traefik.http.routers.peer.middlewares=auth"
ports:
- 8093:8080
container_name: oc-peer
networks:
- oc
- catalog
networks:
oc:
catalog:
external: true
+2 -1
View File
@@ -1,5 +1,6 @@
{
"MONGO_URL":"mongodb://mongo:27017/",
"MONGO_DATABASE":"DC_myDC",
"NATS_URL": "nats://nats:4222"
"NATS_URL": "nats://nats:4222",
"PORT" : 8080
}
-4
View File
@@ -1,4 +0,0 @@
KUBERNETES_SERVICE_HOST=192.168.1.169
KUBE_CA="LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUzTnpReU56STVNVEF3SGhjTk1qWXdNekl6TVRNek5URXdXaGNOTXpZd016SXdNVE16TlRFdwpXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUzTnpReU56STVNVEF3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFSSGpYRDVpbnRIYWZWSk5VaDFlRnIxcXBKdFlkUmc5NStKVENEa0tadTIKYjUxRXlKaG1zanRIY3BDUndGL1VGMzlvdzY4TFBUcjBxaUorUHlhQTBLZUtvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVTdWQkNzZVN3ajJ2cmczMFE5UG8vCnV6ZzAvMjR3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUloQUlEOVY2aFlUSS83ZW1hRzU0dDdDWVU3TXFSdDdESUkKNlgvSUwrQ0RLbzlNQWlCdlFEMGJmT0tVWDc4UmRGdUplcEhEdWFUMUExaGkxcWdIUGduM1dZdDBxUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
KUBE_CERT="LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrVENDQVRlZ0F3SUJBZ0lJUU5KbFNJQUJPMDR3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOemMwTWpjeU9URXdNQjRYRFRJMk1ETXlNekV6TXpVeE1Gb1hEVEkzTURNeQpNekV6TXpVeE1Gb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJMY3Uwb2pUbVg4RFhTQkYKSHZwZDZNVEoyTHdXc1lRTmdZVURXRDhTVERIUWlCczlMZ0x5ZTdOMEFvZk85RkNZVW1HamhiaVd3WFVHR3dGTgpUdlRMU2lXalNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCUlJhRW9wQzc5NGJyTHlnR0g5SVhvbDZTSmlFREFLQmdncWhrak9QUVFEQWdOSUFEQkYKQWlFQWhaRUlrSWV3Y1loL1NmTFVCVjE5MW1CYTNRK0J5S2J5eTVlQmpwL3kzeWtDSUIxWTJicTVOZTNLUUU4RAprNnNzeFJrbjJmN0VoWWVRQU1pUlJ2MjIweDNLCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdFkyeHAKWlc1MExXTmhRREUzTnpReU56STVNVEF3SGhjTk1qWXdNekl6TVRNek5URXdXaGNOTXpZd016SXdNVE16TlRFdwpXakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwWlc1MExXTmhRREUzTnpReU56STVNVEF3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFTcTdVTC85MEc1ZmVTaE95NjI3eGFZWlM5dHhFdWFoWFQ3Vk5wZkpQSnMKaEdXd2UxOXdtbXZzdlp6dlNPUWFRSzJaMmttN0hSb1IrNlA1YjIyamczbHVvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVVVXaEtLUXUvZUc2eThvQmgvU0Y2Ckpla2lZaEF3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUloQUk3cGxHczFtV20ySDErbjRobDBNTk13RmZzd0o5ZXIKTzRGVkM0QzhwRG44QWlCN3NZMVFwd2M5VkRUeGNZaGxuZzZNUzRXai85K0lHWjJxcy94UStrMjdTQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
KUBE_DATA="LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUROZDRnWXd6aVRhK1hwNnFtNVc3SHFzc1JJNkREaUJTbUV2ZHoxZzk3VGxvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFdHk3U2lOT1pmd05kSUVVZStsM294TW5ZdkJheGhBMkJoUU5ZUHhKTU1kQ0lHejB1QXZKNwpzM1FDaDg3MFVKaFNZYU9GdUpiQmRRWWJBVTFPOU10S0pRPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo="
+30 -59
View File
@@ -1,92 +1,63 @@
module oc-peer
go 1.25.0
go 1.22.0
toolchain go1.22.4
require (
cloud.o-forge.io/core/oc-lib v0.0.0-20260605135650-1425a3149455
github.com/beego/beego/v2 v2.3.8
cloud.o-forge.io/core/oc-lib v0.0.0-20250211081618-d82ae166a1e5
github.com/beego/beego/v2 v2.3.1
github.com/smartystreets/goconvey v1.7.2
)
require (
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/google/gnostic-models v0.7.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/libp2p/go-libp2p/core v0.43.0-rc2 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/x448/float16 v0.8.4 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/term v0.37.0 // indirect
golang.org/x/time v0.9.0 // indirect
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
k8s.io/api v0.35.1 // indirect
k8s.io/apimachinery v0.35.1 // indirect
k8s.io/client-go v0.35.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
)
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/biter777/countries v1.7.5 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/gabriel-vasile/mimetype v1.4.10 // indirect
github.com/gabriel-vasile/mimetype v1.4.6 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.27.0 // indirect
github.com/golang/snappy v1.0.0 // indirect
github.com/go-playground/validator/v10 v10.22.1 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c // indirect
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
github.com/goraz/onion v0.1.3 // indirect
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/jtolds/gls v4.20.0+incompatible // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/marcinwyszynski/geopoint v0.0.0-20140302213024-cf2a6f750c5b // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/montanaflynn/stats v0.7.1 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nats-io/nats.go v1.44.0 // indirect
github.com/nats-io/nkeys v0.4.11 // indirect
github.com/nats-io/nats.go v1.37.0 // indirect
github.com/nats-io/nkeys v0.4.7 // indirect
github.com/nats-io/nuid v1.0.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.23.2 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.66.1 // indirect
github.com/prometheus/procfs v0.17.0 // indirect
github.com/rs/zerolog v1.34.0 // indirect
github.com/prometheus/client_golang v1.20.5 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.60.1 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/robfig/cron v1.2.0 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/rs/zerolog v1.33.0 // indirect
github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02 // indirect
github.com/smartystreets/assertions v1.2.0 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
go.mongodb.org/mongo-driver v1.17.4 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
golang.org/x/crypto v0.45.0 // indirect
golang.org/x/net v0.47.0 // indirect
golang.org/x/sync v0.18.0 // indirect
golang.org/x/sys v0.38.0 // indirect
golang.org/x/text v0.31.0 // indirect
google.golang.org/protobuf v1.36.10 // indirect
go.mongodb.org/mongo-driver v1.17.1 // indirect
golang.org/x/crypto v0.28.0 // indirect
golang.org/x/net v0.30.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/text v0.19.0 // indirect
google.golang.org/protobuf v1.35.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
+340 -184
View File
@@ -1,14 +1,263 @@
cloud.o-forge.io/core/oc-lib v0.0.0-20260528142936-26948da3c1ff h1:Pqjt/IBv+AajJkvwqPCUpYunm6ZfXapT1pIXej1iQuc=
cloud.o-forge.io/core/oc-lib v0.0.0-20260528142936-26948da3c1ff/go.mod h1:JynnOb3eMr9VZW1mHq+Vsl3tzx6gPhPsGKpQD/dtEBc=
cloud.o-forge.io/core/oc-lib v0.0.0-20260604070031-d19ff1f8b206 h1:HRbUR9H9CIblNC0Z8obgp2J3jW4d9nO0MLNw/aiZRRs=
cloud.o-forge.io/core/oc-lib v0.0.0-20260604070031-d19ff1f8b206/go.mod h1:JynnOb3eMr9VZW1mHq+Vsl3tzx6gPhPsGKpQD/dtEBc=
cloud.o-forge.io/core/oc-lib v0.0.0-20260605135650-1425a3149455 h1:hDsqGw1EUY2b4mB+aUFSuQO75t+l+Ow9vZgjHZDK3uw=
cloud.o-forge.io/core/oc-lib v0.0.0-20260605135650-1425a3149455/go.mod h1:JynnOb3eMr9VZW1mHq+Vsl3tzx6gPhPsGKpQD/dtEBc=
cloud.o-forge.io/core/oc-lib v0.0.0-20240904135449-4f0ab6a3760f h1:v9mw3uNg/DJswOvHooMu8/BMedA+vIXbma+8iUwsjUI=
cloud.o-forge.io/core/oc-lib v0.0.0-20240904135449-4f0ab6a3760f/go.mod h1:FIJD0taWLJ5pjQLJ6sfE2KlTkvbmk5SMcyrxdjsaVz0=
cloud.o-forge.io/core/oc-lib v0.0.0-20241002120813-a09a04e1a71e h1:77QHk5JSf0q13B/Ai3xjcsGSS7nX+9AfxcsYz5oDo/A=
cloud.o-forge.io/core/oc-lib v0.0.0-20241002120813-a09a04e1a71e/go.mod h1:t+zpCTVKVdHH/BImwtMYY2QIWLMXKgY4n/JhFm3Vpu8=
cloud.o-forge.io/core/oc-lib v0.0.0-20241015082307-62705cc9b93e h1:auncAXo/J15Dc5NVeyZRtyt6OJ602GNO+UhaBDeCAYc=
cloud.o-forge.io/core/oc-lib v0.0.0-20241015082307-62705cc9b93e/go.mod h1:t+zpCTVKVdHH/BImwtMYY2QIWLMXKgY4n/JhFm3Vpu8=
cloud.o-forge.io/core/oc-lib v0.0.0-20241015083538-9f5e6d60185a h1:2mBMc36WKh1/Dpomktx9dVXGxK0agFr7RdgvHTtyn2w=
cloud.o-forge.io/core/oc-lib v0.0.0-20241015083538-9f5e6d60185a/go.mod h1:t+zpCTVKVdHH/BImwtMYY2QIWLMXKgY4n/JhFm3Vpu8=
cloud.o-forge.io/core/oc-lib v0.0.0-20241015143718-73602b6c3dad h1:XkuDc4v2XpTS+w6N9ovbzJdXs/78y2sH36tkQf4LW+E=
cloud.o-forge.io/core/oc-lib v0.0.0-20241015143718-73602b6c3dad/go.mod h1:t+zpCTVKVdHH/BImwtMYY2QIWLMXKgY4n/JhFm3Vpu8=
cloud.o-forge.io/core/oc-lib v0.0.0-20241018065112-59a1b52242b3 h1:IH0kY/aDvaxQAYDHuxpG82vf40P4QygIxf7mAxm7epU=
cloud.o-forge.io/core/oc-lib v0.0.0-20241018065112-59a1b52242b3/go.mod h1:t+zpCTVKVdHH/BImwtMYY2QIWLMXKgY4n/JhFm3Vpu8=
cloud.o-forge.io/core/oc-lib v0.0.0-20241030091613-1a5521237800 h1:uZ4Qrxk/KEpOfDq8QHjZankW7aZGLlDYLoM3CZowlR8=
cloud.o-forge.io/core/oc-lib v0.0.0-20241030091613-1a5521237800/go.mod h1:t+zpCTVKVdHH/BImwtMYY2QIWLMXKgY4n/JhFm3Vpu8=
cloud.o-forge.io/core/oc-lib v0.0.0-20241030105814-5f05b73366ab h1:hYUf9xXpqhp9w0eBfOWVi7c17iWpN+FL2FbhsAkmQ2E=
cloud.o-forge.io/core/oc-lib v0.0.0-20241030105814-5f05b73366ab/go.mod h1:t+zpCTVKVdHH/BImwtMYY2QIWLMXKgY4n/JhFm3Vpu8=
cloud.o-forge.io/core/oc-lib v0.0.0-20241106093658-06e048165e2a h1:TmCuwF62bktK4EeJ6z74FNbBMBT8O7f4lqQqsNbr+uw=
cloud.o-forge.io/core/oc-lib v0.0.0-20241106093658-06e048165e2a/go.mod h1:ya7Q+zHhaKM+XF6sAJ+avqHEVzaMnFJQih2X3TlTlGo=
cloud.o-forge.io/core/oc-lib v0.0.0-20241106144206-66413e15bb68 h1:ubyaVojqPBS9Fljmx4dKFRGhvB1md25r4sZiJf/mnG0=
cloud.o-forge.io/core/oc-lib v0.0.0-20241106144206-66413e15bb68/go.mod h1:ya7Q+zHhaKM+XF6sAJ+avqHEVzaMnFJQih2X3TlTlGo=
cloud.o-forge.io/core/oc-lib v0.0.0-20241106150956-d249bcdf94ab h1:CFeyAJItGsPhLGD0WPLZ5Uq7okL/Z09e+LIU4AWK0BM=
cloud.o-forge.io/core/oc-lib v0.0.0-20241106150956-d249bcdf94ab/go.mod h1:ya7Q+zHhaKM+XF6sAJ+avqHEVzaMnFJQih2X3TlTlGo=
cloud.o-forge.io/core/oc-lib v0.0.0-20241107114600-4c0c75be9161 h1:so5V7C6kiJ9tpuxtgK/KcgjXQC2ythInAH8X2gohuaM=
cloud.o-forge.io/core/oc-lib v0.0.0-20241107114600-4c0c75be9161/go.mod h1:ya7Q+zHhaKM+XF6sAJ+avqHEVzaMnFJQih2X3TlTlGo=
cloud.o-forge.io/core/oc-lib v0.0.0-20241107122526-f3df1e42b9ba h1:MGd8N7bY1LWXMhAp7gibDNwMS2hsatLQ3rfayvy5rGs=
cloud.o-forge.io/core/oc-lib v0.0.0-20241107122526-f3df1e42b9ba/go.mod h1:ya7Q+zHhaKM+XF6sAJ+avqHEVzaMnFJQih2X3TlTlGo=
cloud.o-forge.io/core/oc-lib v0.0.0-20241108104423-7fd44a55cb28 h1:jekSPkD/b59kJ9Bp/trBWnahkdd1FkX4csQOcSaZa8I=
cloud.o-forge.io/core/oc-lib v0.0.0-20241108104423-7fd44a55cb28/go.mod h1:ya7Q+zHhaKM+XF6sAJ+avqHEVzaMnFJQih2X3TlTlGo=
cloud.o-forge.io/core/oc-lib v0.0.0-20241120085309-08e9ee67fe96 h1:1f2m8148/bOY19urpgtgShmGPDMnnjRqcEczrkVDJBA=
cloud.o-forge.io/core/oc-lib v0.0.0-20241120085309-08e9ee67fe96/go.mod h1:ya7Q+zHhaKM+XF6sAJ+avqHEVzaMnFJQih2X3TlTlGo=
cloud.o-forge.io/core/oc-lib v0.0.0-20241120093920-b49685aa8223 h1:LX04VfuXWxi+Q0lKhBBd7tfyLO3R4y8um3srRVlMbSY=
cloud.o-forge.io/core/oc-lib v0.0.0-20241120093920-b49685aa8223/go.mod h1:ya7Q+zHhaKM+XF6sAJ+avqHEVzaMnFJQih2X3TlTlGo=
cloud.o-forge.io/core/oc-lib v0.0.0-20241120150854-57f18b224443 h1:cqlL4/EsqYlQ6luPBC4+6+gWNwQqWVV8DPD8O7F6yM8=
cloud.o-forge.io/core/oc-lib v0.0.0-20241120150854-57f18b224443/go.mod h1:ya7Q+zHhaKM+XF6sAJ+avqHEVzaMnFJQih2X3TlTlGo=
cloud.o-forge.io/core/oc-lib v0.0.0-20241120153807-3b77c0da8352 h1:xNYjEiB/nrvXLbLcjSDfNZEPSR38/LKcsQKP/oWg5HI=
cloud.o-forge.io/core/oc-lib v0.0.0-20241120153807-3b77c0da8352/go.mod h1:ya7Q+zHhaKM+XF6sAJ+avqHEVzaMnFJQih2X3TlTlGo=
cloud.o-forge.io/core/oc-lib v0.0.0-20241120160521-ac49d3324d7b h1:5prB7K0iM284VmYdoRaBMZIOEXq5S0YgTrSp4+SnZyo=
cloud.o-forge.io/core/oc-lib v0.0.0-20241120160521-ac49d3324d7b/go.mod h1:ya7Q+zHhaKM+XF6sAJ+avqHEVzaMnFJQih2X3TlTlGo=
cloud.o-forge.io/core/oc-lib v0.0.0-20241121065159-d8fac883d260 h1:DSumHyw9XJQ/r+LjWa5GDkjS0ri/lFkU7oPr5vv8mws=
cloud.o-forge.io/core/oc-lib v0.0.0-20241121065159-d8fac883d260/go.mod h1:ya7Q+zHhaKM+XF6sAJ+avqHEVzaMnFJQih2X3TlTlGo=
cloud.o-forge.io/core/oc-lib v0.0.0-20241121071546-e9b3a65a0ec6 h1:AdUkzaX63VF3fdloWyyWT1jLM4M1pkDLErAdHyVbsKU=
cloud.o-forge.io/core/oc-lib v0.0.0-20241121071546-e9b3a65a0ec6/go.mod h1:ya7Q+zHhaKM+XF6sAJ+avqHEVzaMnFJQih2X3TlTlGo=
cloud.o-forge.io/core/oc-lib v0.0.0-20241121074503-15ca06aba883 h1:JdHJT8vuup4pJCC7rjiOe0/qD7at6400ml5zZHjEeUo=
cloud.o-forge.io/core/oc-lib v0.0.0-20241121074503-15ca06aba883/go.mod h1:ya7Q+zHhaKM+XF6sAJ+avqHEVzaMnFJQih2X3TlTlGo=
cloud.o-forge.io/core/oc-lib v0.0.0-20241202081145-cb21db672bb5 h1:qxXC6fkEa8bLTo0qn3VrB55tfxyjHQQa/0n97piJhNI=
cloud.o-forge.io/core/oc-lib v0.0.0-20241202081145-cb21db672bb5/go.mod h1:2IevepXviessA6m67fB6ZJhZSeEeoOYWbVqPS4dzkbg=
cloud.o-forge.io/core/oc-lib v0.0.0-20241202121923-2ec6899a1865 h1:BhGzhy6gsEA7vthuq6KWyABsRuF4KV5NqOvfkygytGg=
cloud.o-forge.io/core/oc-lib v0.0.0-20241202121923-2ec6899a1865/go.mod h1:2IevepXviessA6m67fB6ZJhZSeEeoOYWbVqPS4dzkbg=
cloud.o-forge.io/core/oc-lib v0.0.0-20241202134851-9a2ed2351d7e h1:3U5JBdQRti2OpALLPhev6lkUi1TlYHgo2ADidOAfEAs=
cloud.o-forge.io/core/oc-lib v0.0.0-20241202134851-9a2ed2351d7e/go.mod h1:2IevepXviessA6m67fB6ZJhZSeEeoOYWbVqPS4dzkbg=
cloud.o-forge.io/core/oc-lib v0.0.0-20241202152644-e2ddd7e4e6f9 h1:qUA6T5Pjq/pv6dZYH4PWktXmFiRnloDX84m1U5NhvLM=
cloud.o-forge.io/core/oc-lib v0.0.0-20241202152644-e2ddd7e4e6f9/go.mod h1:2IevepXviessA6m67fB6ZJhZSeEeoOYWbVqPS4dzkbg=
cloud.o-forge.io/core/oc-lib v0.0.0-20241202155908-599a6144803e h1:3xGLiTDTgWHIIPDZyTo/clMIj+gQxnIDSE78s9/0wNE=
cloud.o-forge.io/core/oc-lib v0.0.0-20241202155908-599a6144803e/go.mod h1:2IevepXviessA6m67fB6ZJhZSeEeoOYWbVqPS4dzkbg=
cloud.o-forge.io/core/oc-lib v0.0.0-20241203073336-6042d47700fd h1:iDryCORnODgAvBe1Yi+RnIGjYgUSkAv7ZCnm+CUV18w=
cloud.o-forge.io/core/oc-lib v0.0.0-20241203073336-6042d47700fd/go.mod h1:2IevepXviessA6m67fB6ZJhZSeEeoOYWbVqPS4dzkbg=
cloud.o-forge.io/core/oc-lib v0.0.0-20241203082527-2924ccd23b5c h1:3ghuxLEI3JXicDYoFx4YnkLauLl0Nq9UErjpL/2SqEU=
cloud.o-forge.io/core/oc-lib v0.0.0-20241203082527-2924ccd23b5c/go.mod h1:2IevepXviessA6m67fB6ZJhZSeEeoOYWbVqPS4dzkbg=
cloud.o-forge.io/core/oc-lib v0.0.0-20241203090110-471e0c9d9b48 h1:kVTpROPipS4YtROH9vAGZw21OMLNR48qbYedCngGThw=
cloud.o-forge.io/core/oc-lib v0.0.0-20241203090110-471e0c9d9b48/go.mod h1:2IevepXviessA6m67fB6ZJhZSeEeoOYWbVqPS4dzkbg=
cloud.o-forge.io/core/oc-lib v0.0.0-20241203095728-ea55c94c7328 h1:7iK2HzMm0EEEF60ajUVT/6jwqIirduww5Xa3191XS4I=
cloud.o-forge.io/core/oc-lib v0.0.0-20241203095728-ea55c94c7328/go.mod h1:2IevepXviessA6m67fB6ZJhZSeEeoOYWbVqPS4dzkbg=
cloud.o-forge.io/core/oc-lib v0.0.0-20241203105751-4b88da8ff66d h1:iIo+AMQ09MshkKKN8K8pd1ooLaigAYlnUUnQAaCidLo=
cloud.o-forge.io/core/oc-lib v0.0.0-20241203105751-4b88da8ff66d/go.mod h1:2IevepXviessA6m67fB6ZJhZSeEeoOYWbVqPS4dzkbg=
cloud.o-forge.io/core/oc-lib v0.0.0-20241203115141-6681c455d8e0 h1:RnHCONn0oYbEaTN1wDIeOAEM12cCZQRtvjBCVCb0b1Y=
cloud.o-forge.io/core/oc-lib v0.0.0-20241203115141-6681c455d8e0/go.mod h1:2IevepXviessA6m67fB6ZJhZSeEeoOYWbVqPS4dzkbg=
cloud.o-forge.io/core/oc-lib v0.0.0-20241204103308-fd01f535a131 h1:FdUY8b8xTdVzQ9wlphlo8TlbQif76V9oxGDYq26TsAs=
cloud.o-forge.io/core/oc-lib v0.0.0-20241204103308-fd01f535a131/go.mod h1:2IevepXviessA6m67fB6ZJhZSeEeoOYWbVqPS4dzkbg=
cloud.o-forge.io/core/oc-lib v0.0.0-20241204111455-1fcbc7c08ab0 h1:cBr4m2tcLf+dZufrjYvhvcsSqXcRDeyhnq5c5HY15po=
cloud.o-forge.io/core/oc-lib v0.0.0-20241204111455-1fcbc7c08ab0/go.mod h1:2IevepXviessA6m67fB6ZJhZSeEeoOYWbVqPS4dzkbg=
cloud.o-forge.io/core/oc-lib v0.0.0-20241205082103-fbbce7817b73 h1:g96KMOxdhvM7x6YFqJfd08wybRzCLEvol7HfhKJfxO4=
cloud.o-forge.io/core/oc-lib v0.0.0-20241205082103-fbbce7817b73/go.mod h1:2IevepXviessA6m67fB6ZJhZSeEeoOYWbVqPS4dzkbg=
cloud.o-forge.io/core/oc-lib v0.0.0-20250110164331-5255ffc2f728 h1:3p1G82xZmEAu2OEyY5HM42Cfbb1J887P9lSoRKNhgg8=
cloud.o-forge.io/core/oc-lib v0.0.0-20250110164331-5255ffc2f728/go.mod h1:2IevepXviessA6m67fB6ZJhZSeEeoOYWbVqPS4dzkbg=
cloud.o-forge.io/core/oc-lib v0.0.0-20250113102407-21a7ff90104a h1:rrLSuAHI/TGOTm5d7Bffu+qf4EnmPguOll5x5nG/3Tc=
cloud.o-forge.io/core/oc-lib v0.0.0-20250113102407-21a7ff90104a/go.mod h1:VgWEn23ddKySWXrwPMhqtiBjTJnbm5t7yWjzfvNxbbI=
cloud.o-forge.io/core/oc-lib v0.0.0-20250113114256-11905339bb24 h1:Kc51xKbnyfeafHpOJP7mWh9InNGqZUwcJR46008D+Eg=
cloud.o-forge.io/core/oc-lib v0.0.0-20250113114256-11905339bb24/go.mod h1:VgWEn23ddKySWXrwPMhqtiBjTJnbm5t7yWjzfvNxbbI=
cloud.o-forge.io/core/oc-lib v0.0.0-20250113124812-6e5c87379649 h1:dmtrmNDdTR/2R3HjaIbPdu5LZViPzigwSjU207NXCxI=
cloud.o-forge.io/core/oc-lib v0.0.0-20250113124812-6e5c87379649/go.mod h1:VgWEn23ddKySWXrwPMhqtiBjTJnbm5t7yWjzfvNxbbI=
cloud.o-forge.io/core/oc-lib v0.0.0-20250113135241-a0f436b3e162 h1:oGP40P/uUngU7stnsRdx0jwxZGc+pzLzrMlUjEBSy0M=
cloud.o-forge.io/core/oc-lib v0.0.0-20250113135241-a0f436b3e162/go.mod h1:VgWEn23ddKySWXrwPMhqtiBjTJnbm5t7yWjzfvNxbbI=
cloud.o-forge.io/core/oc-lib v0.0.0-20250114071722-1c32cd2d12df h1:T52jgXQddoxwe+embR26Fwmz4G2jkl4QpYVHGtiLUNI=
cloud.o-forge.io/core/oc-lib v0.0.0-20250114071722-1c32cd2d12df/go.mod h1:VgWEn23ddKySWXrwPMhqtiBjTJnbm5t7yWjzfvNxbbI=
cloud.o-forge.io/core/oc-lib v0.0.0-20250114081637-918006302bb4 h1:AwCbDHjvUz9iQaF7hgYWyabVF/EzSSSk5bCNgntNJ6c=
cloud.o-forge.io/core/oc-lib v0.0.0-20250114081637-918006302bb4/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250114105339-b782248da741 h1:akAQLlcAXDtUhbNHbona9xJrHCzK9jxlvsDsEpVP1fg=
cloud.o-forge.io/core/oc-lib v0.0.0-20250114105339-b782248da741/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250114135055-1a4694c8913a h1:AxnecA1YKOZ81OKb1akK2Qc/0UNDUxdjSww7ALyehas=
cloud.o-forge.io/core/oc-lib v0.0.0-20250114135055-1a4694c8913a/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250115082026-ad69c0495144 h1:MZ90rw4SKL0dqL/Lb+7E54vkk9fb8W6X0UJo9UW/XBk=
cloud.o-forge.io/core/oc-lib v0.0.0-20250115082026-ad69c0495144/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250115095644-be3803039583 h1:6My1sqjvqgHnC4TlE7RsZQHC8AVhad0gZl8uOvLTM9o=
cloud.o-forge.io/core/oc-lib v0.0.0-20250115095644-be3803039583/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250115102820-0e0540af43d0 h1:AcHC2WIeHOSjz5xe7OsjMi39EevxdY2O/9q0VMkDRz0=
cloud.o-forge.io/core/oc-lib v0.0.0-20250115102820-0e0540af43d0/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250116091455-68f418928395 h1:u4myLPGqBbzprWHg6713k5a++4yiq1ujlVy7yrMkZ9g=
cloud.o-forge.io/core/oc-lib v0.0.0-20250116091455-68f418928395/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250116142544-a4a249bab828 h1:yMDBDTs7LECyueUfh0iug502GN8GodVpQSl/gZchUjU=
cloud.o-forge.io/core/oc-lib v0.0.0-20250116142544-a4a249bab828/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250117081640-450fab437cb7 h1:SV9U48sR09cNRl48489lQHrrKJFtTMQoQcRhmtsLTYQ=
cloud.o-forge.io/core/oc-lib v0.0.0-20250117081640-450fab437cb7/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250117090737-b990fe42d375 h1:UsPWfbVgvUcOC3BtD8B9dUQfv/FnRF4IZGrYxUJr1iM=
cloud.o-forge.io/core/oc-lib v0.0.0-20250117090737-b990fe42d375/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250117100508-d44fb976e4ff h1:GaLrVn6ame6BV7pfUB2xeHCCJLBECRiCCpPj6zteL+s=
cloud.o-forge.io/core/oc-lib v0.0.0-20250117100508-d44fb976e4ff/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250117121920-ed787683f47b h1:3wap+dPPplJkDglE5toKfdFUmjobAeIJWdiRtCQ3xkQ=
cloud.o-forge.io/core/oc-lib v0.0.0-20250117121920-ed787683f47b/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250117124801-e5c7dbe4cb96 h1:opQ/Uku27DOKAqDcKC9k6J9H5Tj9bNyKdHnJnD3U850=
cloud.o-forge.io/core/oc-lib v0.0.0-20250117124801-e5c7dbe4cb96/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250117135417-c63a1fef6c48 h1:dEebv8ZV5rt6BYPkcK6HOts+OPqkSxkKp5zn1lCq1vs=
cloud.o-forge.io/core/oc-lib v0.0.0-20250117135417-c63a1fef6c48/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250117152246-b85ca8674b27 h1:QEIj90eIoYsjs1uekbI3Nu48KDWmzGV7ugcr9agJbYI=
cloud.o-forge.io/core/oc-lib v0.0.0-20250117152246-b85ca8674b27/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250120123706-58b36f282344 h1:MPt8BhrbMJiMa4KDWqBUvdrlone7UxgIgZ5PW4du0Ek=
cloud.o-forge.io/core/oc-lib v0.0.0-20250120123706-58b36f282344/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250120124939-67b8215adf79 h1:9Y+KJlzy5jHhrd4b44pNEBjSJKnIyvlSQ5Mbj1zcXbA=
cloud.o-forge.io/core/oc-lib v0.0.0-20250120124939-67b8215adf79/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250120143509-305f2605030d h1:f1tpLADIAbwTKxN62csH+v2Fe0q1eQ7dYIDhPl1GZ8I=
cloud.o-forge.io/core/oc-lib v0.0.0-20250120143509-305f2605030d/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250121080257-de585a723426 h1:49cuCsDsBE6ZrvqMh6d48ZynpPyEpkw1LtC0nMQnvEU=
cloud.o-forge.io/core/oc-lib v0.0.0-20250121080257-de585a723426/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250121083541-0d83885b9b5e h1:yh2tiTxuQbrdgCePREyMewPr8Btdacpw6vo7ymmqf7Y=
cloud.o-forge.io/core/oc-lib v0.0.0-20250121083541-0d83885b9b5e/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250121101118-bc12fb53be23 h1:oOSJA8w33aJ2TlMRuR7bU/rme/IYSBcVjrb6gE/jwSw=
cloud.o-forge.io/core/oc-lib v0.0.0-20250121101118-bc12fb53be23/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250121105544-bf5a16f41bea h1:X9YiXv2GSLT6jotS3C/JvvdYBLtxgKI8OV60ndJzjXk=
cloud.o-forge.io/core/oc-lib v0.0.0-20250121105544-bf5a16f41bea/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250121131007-745bb58c593e h1:rHbooeLrsMvIYj5nHc3MK8NVEh9v5edFBCkOxeRoYjs=
cloud.o-forge.io/core/oc-lib v0.0.0-20250121131007-745bb58c593e/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250121160438-67ebeca1f489 h1:XwPLFaKjP0o6ZuKnj5aDJ9hIBlX8giNS9BB78uIH0g0=
cloud.o-forge.io/core/oc-lib v0.0.0-20250121160438-67ebeca1f489/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250122080653-67940296d255 h1:VFlxjrbks8pDzoZ40lnyHD5qVyEMAIfEAmY2w4wBAE8=
cloud.o-forge.io/core/oc-lib v0.0.0-20250122080653-67940296d255/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250122090736-8ab313e6cbd8 h1:u7Rt0tQMCzylFPyMcO5uNQ8041K80cM0BQNbBDbjAj0=
cloud.o-forge.io/core/oc-lib v0.0.0-20250122090736-8ab313e6cbd8/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250122101635-2a93b17d71d8 h1:AvthXY1/mrB4aeQpoj84ewVCdIYYemwn9WydYJ+9hyw=
cloud.o-forge.io/core/oc-lib v0.0.0-20250122101635-2a93b17d71d8/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250122110438-062c1afe8568 h1:pk7Gqa1yEwl5ASc9wJNjxJ+1XfTXYSwDvsxB3KOHWoo=
cloud.o-forge.io/core/oc-lib v0.0.0-20250122110438-062c1afe8568/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250122121814-ed1e76105250 h1:TwCz7oXB7diECiM/kadwDZ78iM8E8ka2ShKs/PzdszA=
cloud.o-forge.io/core/oc-lib v0.0.0-20250122121814-ed1e76105250/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250122135342-4be954a6f359 h1:x5dGOGYgdDhSeYtAkWeNlWQLU24yv8BUpwx1Idc9+ME=
cloud.o-forge.io/core/oc-lib v0.0.0-20250122135342-4be954a6f359/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250122140340-9c71730d9cb7 h1:oAkv9IOuiP71VO/plOkPHaPk9X3ELfnGdSz2cctLnGw=
cloud.o-forge.io/core/oc-lib v0.0.0-20250122140340-9c71730d9cb7/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250122153005-0e798dac5081 h1:P/WDRzkAJHhPuZZbU2VmVqSJ6AcMN/ia/pPZ60MpRfo=
cloud.o-forge.io/core/oc-lib v0.0.0-20250122153005-0e798dac5081/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250123074822-df04133551e4 h1:ayV2U6VUUJXdBE2AGuRuwTKr7WqIycmVgEMv8v/KlGU=
cloud.o-forge.io/core/oc-lib v0.0.0-20250123074822-df04133551e4/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250123082727-8cba10c4fe29 h1:zt0AA0GddWtbgupsvFvNAozrGMP0FISHnjSmsp3Ihgc=
cloud.o-forge.io/core/oc-lib v0.0.0-20250123082727-8cba10c4fe29/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250123094950-d15fdac27bde h1:Yjr0WPiR3dMg+H8EIO4GzqohRZBvGh/h4ysx5n8wCZw=
cloud.o-forge.io/core/oc-lib v0.0.0-20250123094950-d15fdac27bde/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250123103535-2205ac9b5819 h1:y/opEsKeo7G5Os2RWd7zF5i5DU4neDLt6fUq2hSW66U=
cloud.o-forge.io/core/oc-lib v0.0.0-20250123103535-2205ac9b5819/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250123114959-49e495f062eb h1:9FDB2xUhO+PFkb1mhNq+vItyfW/Jb0KjBRDEDPqPcno=
cloud.o-forge.io/core/oc-lib v0.0.0-20250123114959-49e495f062eb/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250123134717-db6049bab345 h1:OW5TLnNhNxJCkhMXUy5d9VSOgEGNFc9+uA3thyPuRA4=
cloud.o-forge.io/core/oc-lib v0.0.0-20250123134717-db6049bab345/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250123140834-c1888f89218f h1:iNqXYlnTh4nnfuVN/NObIJO5g9Mu3Mi9yFGmNFwO1Jk=
cloud.o-forge.io/core/oc-lib v0.0.0-20250123140834-c1888f89218f/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250124095557-97d466818af0 h1:v8Fj897AF5l8icSm2FE0E2tkl96eJI43Zr4UHIUkL6Y=
cloud.o-forge.io/core/oc-lib v0.0.0-20250124095557-97d466818af0/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250127080547-fbb55e64dcf4 h1:s6+5sTIeR86N+9oK3uXItlP0L1SgKCwMNQFU6LERDU4=
cloud.o-forge.io/core/oc-lib v0.0.0-20250127080547-fbb55e64dcf4/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250127083756-68bacf5da410 h1:b+dzulgEl+a7BudsqCkgBg/1aEqo8/1WpGs+WGZHznE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250127083756-68bacf5da410/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250127110938-1ad9ce09cb35 h1:PWlFiCaAHTUDuwOf84hA4BDivEA3FU+DDH7dBg9IPho=
cloud.o-forge.io/core/oc-lib v0.0.0-20250127110938-1ad9ce09cb35/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250127131512-7ca360be6aa4 h1:8y8I+hmSuUPV2dt/qw6d2TY/YRLXvZp0zE9iSwR3qv4=
cloud.o-forge.io/core/oc-lib v0.0.0-20250127131512-7ca360be6aa4/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250127134257-8b03df7923bd h1:eylhA0MziFMzY+kfXy2tnZEHDWIXCh/kPDLyBG2OC5E=
cloud.o-forge.io/core/oc-lib v0.0.0-20250127134257-8b03df7923bd/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250127150345-db85d1a48b73 h1:SNwsmEyaHrnoN7/IBathlA/HI/y4D2IBJjZEdtUC7Ew=
cloud.o-forge.io/core/oc-lib v0.0.0-20250127150345-db85d1a48b73/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250128131916-598774b0b197 h1:tAi5pznkPDjCFO81EhvS8Djx1e7iz4D2e72lxegRVmQ=
cloud.o-forge.io/core/oc-lib v0.0.0-20250128131916-598774b0b197/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250129073743-74a1f66d26c2 h1:ScjLqkn82u+on8CXnfgi52UZqddR879WlUtiq9qQOdo=
cloud.o-forge.io/core/oc-lib v0.0.0-20250129073743-74a1f66d26c2/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250129100135-330768490a61 h1:afATt4OzRndXApO1Xqn9PeKohW5G2nhqvptZkE2pML8=
cloud.o-forge.io/core/oc-lib v0.0.0-20250129100135-330768490a61/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250129133324-ede2d5fd5322 h1:d0/n7kJZNG6QKdI5ySqYGe3nYYOKmko76ysjlZA30Dk=
cloud.o-forge.io/core/oc-lib v0.0.0-20250129133324-ede2d5fd5322/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250129143004-df2c38199cf0 h1:8cIJxCeVHbefpa7oBZPeFUAa7Mmtiw93Z1xMa9Qf/wk=
cloud.o-forge.io/core/oc-lib v0.0.0-20250129143004-df2c38199cf0/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250129154925-84d20c52fa1c h1:6+KdDssQyPZSCmtiBrlygHIAt2yhewx3rz/SPEfsYnI=
cloud.o-forge.io/core/oc-lib v0.0.0-20250129154925-84d20c52fa1c/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250130072403-826d7586b127 h1:wYLo29accEk0anP8eLjBKbDyYGLFKg4Qp41NvCb2JsQ=
cloud.o-forge.io/core/oc-lib v0.0.0-20250130072403-826d7586b127/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250130084513-787c01b4be1c h1:3TEloYSf4k1o9tkEo5T3sES+qZcJBsdR82o+T81SC3A=
cloud.o-forge.io/core/oc-lib v0.0.0-20250130084513-787c01b4be1c/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250130101134-107ce2580128 h1:AElHp4SeiVmMiyCta9r8JOpSYMAS0To/fLK6eaBz1PU=
cloud.o-forge.io/core/oc-lib v0.0.0-20250130101134-107ce2580128/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250130130847-976a5cedcb5f h1:0buFXek+V4E4rIGBEygLXpw34I50yAGqTIAOyTgZwsA=
cloud.o-forge.io/core/oc-lib v0.0.0-20250130130847-976a5cedcb5f/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250131073800-3ec0d554edad h1:Ey6yORB8TOa+PkMpNhH0tayZuZ6FwyJ59vZM4BRGHnY=
cloud.o-forge.io/core/oc-lib v0.0.0-20250131073800-3ec0d554edad/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250131082340-892bd93471aa h1:53a/yqBAVkNpeAaCqxHx3FWC0wV5XK/dhooR3f0Kp8g=
cloud.o-forge.io/core/oc-lib v0.0.0-20250131082340-892bd93471aa/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250131100142-b2113bff62fa h1:S7nsqFotIeXSPJqipNW6wB3VsfYhFrWcZIR8mX6aJg0=
cloud.o-forge.io/core/oc-lib v0.0.0-20250131100142-b2113bff62fa/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250131110730-a2f2d0ebef72 h1:0EUj84bzUWvaH8egQkjH1xQ+HoyX9EZqtokNosYywgU=
cloud.o-forge.io/core/oc-lib v0.0.0-20250131110730-a2f2d0ebef72/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250131153610-6807614ac86b h1:/SjZVsLeH8sXopUeR3xB7wygJvIyA2V2uS+GsfPFysE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250131153610-6807614ac86b/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250203105249-64bea2a66e35 h1:5Zkm2tPQ60l2oMdrf3/uC1mWOCU+ti77d0k9y/AW1z8=
cloud.o-forge.io/core/oc-lib v0.0.0-20250203105249-64bea2a66e35/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250203113830-275bd56fe64c h1:4EW1OEHuRjH9B3LhQEvOLp3qPxnU4kDBwgKzy7KNlS4=
cloud.o-forge.io/core/oc-lib v0.0.0-20250203113830-275bd56fe64c/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250203124514-14977c7b2c39 h1:XW7Hny4W/2ClAZR2Wi9KRvLTH/pjmwpgXiwM+fDsy50=
cloud.o-forge.io/core/oc-lib v0.0.0-20250203124514-14977c7b2c39/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250203143322-22d15fe395e8 h1:OWBLh52Ee4Txs0PY4bMlfRbaTbfNNR/ndj2J+RGrR6k=
cloud.o-forge.io/core/oc-lib v0.0.0-20250203143322-22d15fe395e8/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250204080055-bf114b39b7d5 h1:rsOMNER+ZIIt/as3bOU2lJe+MbCCR5x1iR/XyZYmuKU=
cloud.o-forge.io/core/oc-lib v0.0.0-20250204080055-bf114b39b7d5/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250204091410-2ccb57ffb050 h1:NdKJD+hbAyDaUfRkdtMUZLasR1d/BGyEfCvuozTso+Y=
cloud.o-forge.io/core/oc-lib v0.0.0-20250204091410-2ccb57ffb050/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250204110709-3061df4f13da h1:Mx3vR5r21H0zX+B0yaQOeOn3hvWJUrdy0DFLI+RAH1I=
cloud.o-forge.io/core/oc-lib v0.0.0-20250204110709-3061df4f13da/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250204134321-69bf9518661e h1:etAdc6jOnpm49RFs2Z8R7zzwfP/uGN6eQAmMGVqTEnc=
cloud.o-forge.io/core/oc-lib v0.0.0-20250204134321-69bf9518661e/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250204155113-a8e2445c103c h1:wNM/SweaGy+Wz4KV3+1wpLYgtDOSDK+WO6564TCGDjE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250204155113-a8e2445c103c/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250205154116-7201cabb438a h1:DAEI00i+r2MAlUqqRJfW5FiXsWppQW8y51kKRl39WFA=
cloud.o-forge.io/core/oc-lib v0.0.0-20250205154116-7201cabb438a/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250205160221-88b7cfe2fd0f h1:6V+Z81ywYoDYSVMnM4PVaJYXFgCN3xSG3ddiUPn4jL8=
cloud.o-forge.io/core/oc-lib v0.0.0-20250205160221-88b7cfe2fd0f/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250206080835-e646cfef0b46 h1:YnM9WwcijS+/OrpgML7y1O5c8hJ3Wt5iIPSSZYai+zw=
cloud.o-forge.io/core/oc-lib v0.0.0-20250206080835-e646cfef0b46/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250206085600-3ffff7d32cf1 h1:PZ6Z3PdgjmiXQlNA64rhZgPyuZugs/jJROEVDHZs9yg=
cloud.o-forge.io/core/oc-lib v0.0.0-20250206085600-3ffff7d32cf1/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250206101306-ad3293da9dbc h1:3X2bDl/ErUp+ahzROiscJTF6XyF81Swv4JXY2xqI6/o=
cloud.o-forge.io/core/oc-lib v0.0.0-20250206101306-ad3293da9dbc/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250206115651-940ef17f7b0c h1:T4NE8PQY0opcYREioh4V2eVvJkagn52jytg4S1ZtpGE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250206115651-940ef17f7b0c/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250207072957-31ec352b57b9 h1:lmzktnKiGDo6f1+a8kRAeXvbu/+CEPe/PLsqIOt8hsc=
cloud.o-forge.io/core/oc-lib v0.0.0-20250207072957-31ec352b57b9/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250207104112-3d1383357252 h1:zLU294Mc2bcxdeihG2K+wK2Zr2B/lTm+dJCMIEMUOKU=
cloud.o-forge.io/core/oc-lib v0.0.0-20250207104112-3d1383357252/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250210085846-4a178d01e3ee h1:SwWTxlaRAX5p24XwOTBVbAeTLiLFNlSqDZpU0yICrWc=
cloud.o-forge.io/core/oc-lib v0.0.0-20250210085846-4a178d01e3ee/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250210094237-e55727d9e273 h1:flQk8D7BAQNolfMRXehxZ5QcWuR3ytUvwJWt5GyFSbw=
cloud.o-forge.io/core/oc-lib v0.0.0-20250210094237-e55727d9e273/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250210103255-f663ec80f5dd h1:myQN5EugL+AvIy4Ugw+jlHEfzcVaQ1bZ+RbwTioaZqs=
cloud.o-forge.io/core/oc-lib v0.0.0-20250210103255-f663ec80f5dd/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250210121042-52d5a1fbf9b8 h1:LQpmqcx6b+RjfvYzyrgquLSIWdRqcJi2UXybB9wk9Vk=
cloud.o-forge.io/core/oc-lib v0.0.0-20250210121042-52d5a1fbf9b8/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250211065515-a573a4ce715e h1:00SdIMSwwSJpKVfdwplehHpFULrVvAoc0HxKQD06KEs=
cloud.o-forge.io/core/oc-lib v0.0.0-20250211065515-a573a4ce715e/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250211073038-ffaa67fb5dca h1:mZBcicJezYO7gY5SHMzyUusyLxYKwFptliiysqaGwD0=
cloud.o-forge.io/core/oc-lib v0.0.0-20250211073038-ffaa67fb5dca/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
cloud.o-forge.io/core/oc-lib v0.0.0-20250211081618-d82ae166a1e5 h1:S+vFupQoyTwa2QrtxmSChxzAYCrh6mLf7GXRNKU475g=
cloud.o-forge.io/core/oc-lib v0.0.0-20250211081618-d82ae166a1e5/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/beego/beego/v2 v2.3.8 h1:wplhB1pF4TxR+2SS4PUej8eDoH4xGfxuHfS7wAk9VBc=
github.com/beego/beego/v2 v2.3.8/go.mod h1:8vl9+RrXqvodrl9C8yivX1e6le6deCK6RWeq8R7gTTg=
github.com/beego/beego/v2 v2.3.0 h1:iECVwzm6egw6iw6tkWrEDqXG4NQtKLQ6QBSYqlM6T/I=
github.com/beego/beego/v2 v2.3.0/go.mod h1:Ob/5BJ9fIKZLd4s9ZV3o9J6odkkIyL83et+p98gyYXo=
github.com/beego/beego/v2 v2.3.1 h1:7MUKMpJYzOXtCUsTEoXOxsDV/UcHw6CPbaWMlthVNsc=
github.com/beego/beego/v2 v2.3.1/go.mod h1:5cqHsOHJIxkq44tBpRvtDe59GuVRVv/9/tyVDxd5ce4=
github.com/beego/beego/v2 v2.3.2/go.mod h1:5cqHsOHJIxkq44tBpRvtDe59GuVRVv/9/tyVDxd5ce4=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/biter777/countries v1.7.5 h1:MJ+n3+rSxWQdqVJU8eBy9RqcdH6ePPn4PJHocVWUa+Q=
@@ -23,162 +272,111 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8=
github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw=
github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/etcd-io/etcd v3.3.17+incompatible/go.mod h1:cdZ77EstHBwVtD6iTgzgvogwcjo9m4iOqoijouPJ4bs=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
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/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc=
github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4=
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/goraz/onion v0.1.3 h1:KhyvbDA2b70gcz/d5izfwTiOH8SmrvV43AsVzpng3n0=
github.com/goraz/onion v0.1.3/go.mod h1:XEmz1XoBz+wxTgWB8NwuvRm4RAu3vKxvrmYtzK+XCuQ=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg=
github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0=
github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
github.com/libp2p/go-libp2p/core v0.43.0-rc2 h1:1X1aDJNWhMfodJ/ynbaGLkgnC8f+hfBIqQDrzxFZOqI=
github.com/libp2p/go-libp2p/core v0.43.0-rc2/go.mod h1:NYeJ9lvyBv9nbDk2IuGb8gFKEOkIv/W5YRIy1pAJB2Q=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/marcinwyszynski/geopoint v0.0.0-20140302213024-cf2a6f750c5b h1:XBF8THPBy28s2ryI7+/Jf/847unLWxYMpJveX5Kox+0=
github.com/marcinwyszynski/geopoint v0.0.0-20140302213024-cf2a6f750c5b/go.mod h1:z1oqhOuuYpPHmUmAK2aNygKFlPdb4o3PppQnVTRFdrI=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE=
github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI=
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
github.com/multiformats/go-multiaddr v0.16.0 h1:oGWEVKioVQcdIOBlYM8BH1rZDWOGJSqr9/BKl6zQ4qc=
github.com/multiformats/go-multiaddr v0.16.0/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0=
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
github.com/multiformats/go-multicodec v0.9.1 h1:x/Fuxr7ZuR4jJV4Os5g444F7xC4XmyUaT/FWtE+9Zjo=
github.com/multiformats/go-multicodec v0.9.1/go.mod h1:LLWNMtyV5ithSBUo3vFIMaeDy+h3EbkMTek1m+Fybbo=
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/nats-io/nats.go v1.44.0 h1:ECKVrDLdh/kDPV1g0gAQ+2+m2KprqZK5O/eJAyAnH2M=
github.com/nats-io/nats.go v1.44.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0=
github.com/nats-io/nkeys v0.4.11/go.mod h1:szDimtgmfOi9n25JpfIdGw12tZFYXqhGxjhVxsatHVE=
github.com/nats-io/nats.go v1.37.0 h1:07rauXbVnnJvv1gfIyghFEo6lUcYRY0WXc3x7x0vUxE=
github.com/nats-io/nats.go v1.37.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8=
github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/ogier/pflag v0.0.1/go.mod h1:zkFki7tvTa0tafRvTBIZTvzYyAu6kQhPZFnshFFPE+g=
github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns=
github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo=
github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg=
github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.58.0 h1:N+N8vY4/23r6iYfD3UQZUoJPnUYAo7v6LG5XZxjZTXo=
github.com/prometheus/common v0.58.0/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0=
github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA=
github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc=
github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02 h1:v9ezJDHA1XGxViAUSIoO/Id7Fl63u6d0YmsAm+/p2hs=
github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02/go.mod h1:RF16/A3L0xSa0oSERcnhd8Pu3IXSDZSK2gmGIMsttFE=
github.com/skarademir/naturalsort v0.0.0-20150715044055-69a5d87bef62/go.mod h1:oIdVclZaltY1Nf7OQUkg1/2jImBJ+ZfKZuDIRSwk3p0=
@@ -188,23 +386,10 @@ github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYl
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
@@ -214,37 +399,35 @@ github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gi
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw=
go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
go.mongodb.org/mongo-driver v1.16.1 h1:rIVLL3q0IHM39dvE+z2ulZLp9ENZKThVfuvN/IiN4l8=
go.mongodb.org/mongo-driver v1.16.1/go.mod h1:oB6AhJQvFQL4LEHyXi6aJzQJtBiTQHiAd83l0GdFaiw=
go.mongodb.org/mongo-driver v1.17.1 h1:Wic5cJIwJgSpBhe3lx3+/RybR5PiYRMpVFgO7cOHyIM=
go.mongodb.org/mongo-driver v1.17.1/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476 h1:bsqhLWFR6G6xiQcb+JoGqdKdRU6WzPWmK8E0jxTjzo4=
golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -255,60 +438,33 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo=
gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.35.1 h1:0PO/1FhlK/EQNVK5+txc4FuhQibV25VLSdLMmGpDE/Q=
k8s.io/api v0.35.1/go.mod h1:28uR9xlXWml9eT0uaGo6y71xK86JBELShLy4wR1XtxM=
k8s.io/apimachinery v0.35.1 h1:yxO6gV555P1YV0SANtnTjXYfiivaTPvCTKX6w6qdDsU=
k8s.io/apimachinery v0.35.1/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns=
k8s.io/client-go v0.35.1 h1:+eSfZHwuo/I19PaSxqumjqZ9l5XiTEKbIaJ+j1wLcLM=
k8s.io/client-go v0.35.1/go.mod h1:1p1KxDt3a0ruRfc/pG4qT/3oHmUj1AhSHEcxNSGg+OA=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE=
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ=
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck=
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg=
lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco=
sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
-267
View File
@@ -1,267 +0,0 @@
package infrastructure
import (
"encoding/json"
"fmt"
"slices"
"sync"
"time"
oclib "cloud.o-forge.io/core/oc-lib"
"cloud.o-forge.io/core/oc-lib/config"
"cloud.o-forge.io/core/oc-lib/dbs"
"cloud.o-forge.io/core/oc-lib/models/peer"
"cloud.o-forge.io/core/oc-lib/tools"
)
var ressourceCols = []oclib.LibDataEnum{
oclib.LibDataEnum(oclib.PEER),
}
var SearchMu sync.RWMutex
var SearchStreamAction = map[string][]*peer.Peer{}
var SearchStream = map[string]chan WSMessage{}
func EmitNATS(user string, groups []string, message tools.PropalgationMessage) {
b, _ := json.Marshal(message)
if message.Action == tools.PB_SEARCH {
SearchMu.Lock()
SearchStream[user] = make(chan WSMessage, 128)
SearchStreamAction[user] = []*peer.Peer{}
fmt.Println("NEW PB")
SearchMu.Unlock()
}
tools.NewNATSCaller().SetNATSPub(tools.PROPALGATION_EVENT, tools.NATSResponse{
FromApp: "oc-peer",
Datatype: -1,
User: user,
Groups: groups,
Method: int(tools.PROPALGATION_EVENT),
Payload: b,
})
}
var self *peer.Peer
func ListenNATS() {
tools.NewNATSCaller().ListenNats(map[tools.NATSMethod]func(tools.NATSResponse){
// ORG_PARTNER_EVENT is delivered by our local oc-discovery after receiving a
// libp2p stream from the remote. The payload "type" field routes to one of two
// sub-flows:
// "check" — we are master: validate candidate, emit confirm via PROPALGATION
// "confirm" — we are requester: upgrade (or discard) the candidate's relation
tools.ORG_PARTNER_EVENT: func(resp tools.NATSResponse) {
if resp.FromApp == config.GetAppName() {
return
}
var msg struct {
Type string `json:"type"`
RequesterID string `json:"requester_id"`
RequesterPeerID string `json:"requester_peer_id"`
CandidateID string `json:"candidate_id"`
MasterID string `json:"master_id"`
Confirmed bool `json:"confirmed"`
}
if err := json.Unmarshal(resp.Payload, &msg); err != nil || msg.CandidateID == "" {
return
}
switch msg.Type {
case "check":
self, _ := oclib.GetMySelf()
if self == nil || self.GetID() != msg.MasterID {
return
}
access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
candidate := access.LoadOne(msg.CandidateID)
confirmed := candidate.Data != nil && candidate.ToPeer().Relation == peer.ORGANIZATION_MEMBER
confirmPayload, _ := json.Marshal(map[string]interface{}{
"type": "confirm",
"requester_peer_id": msg.RequesterPeerID,
"candidate_id": msg.CandidateID,
"confirmed": confirmed,
})
propMsg := tools.PropalgationMessage{
Action: tools.PB_ORG_PARTNER,
DataType: int(tools.PEER),
Payload: confirmPayload,
}
b, _ := json.Marshal(propMsg)
tools.NewNATSCaller().SetNATSPub(tools.PROPALGATION_EVENT, tools.NATSResponse{
FromApp: config.GetAppName(),
Datatype: tools.PEER,
User: resp.User,
Groups: resp.Groups,
Method: int(tools.PROPALGATION_EVENT),
Payload: b,
})
case "confirm":
access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
relation := peer.NONE
if msg.Confirmed {
relation = peer.ORGANIZATION_PARTNER
}
access.UpdateOne(map[string]interface{}{
"relation": relation,
"verify": false,
}, msg.CandidateID)
}
},
tools.CREATE_RESOURCE: func(resp tools.NATSResponse) {
if resp.FromApp == config.GetAppName() || !slices.Contains(ressourceCols, oclib.LibDataEnum(resp.Datatype)) {
return
}
self, _ := oclib.GetMySelf()
if self != nil && self.IsNano {
return
}
p := &peer.Peer{}
if err := json.Unmarshal(resp.Payload, &p); err == nil {
fmt.Println("CREATE_RESOURCE", p.GetID())
if self.GetID() == p.GetID() {
fmt.Println("it's ourselve !")
return
}
access := oclib.NewRequestAdmin(oclib.LibDataEnum(resp.Datatype), nil)
if data := access.LoadOne(p.GetID()); data.Data != nil {
if p.Relation == peer.PENDING_PARTNER || p.Relation == peer.PARTNER {
if data.ToPeer().Verify {
fmt.Println("UPDATE 2", p.GetID())
access.UpdateOne(map[string]interface{}{
"verify": false,
"relation": peer.PARTNER,
}, p.GetID())
} else {
access.UpdateOne(map[string]interface{}{
"verify": true,
"relation": peer.PENDING_PARTNER,
}, p.GetID())
}
} else if data.ToPeer().Relation == peer.NONE {
access.UpdateOne(map[string]interface{}{
"verify": false,
"relation": p.Relation,
}, p.GetID())
}
} else if p.Relation == peer.PENDING_NANO || p.Relation == peer.NANO {
if data.ToPeer().Verify {
access.UpdateOne(map[string]interface{}{
"verify": false,
"relation": peer.MASTER,
}, p.GetID())
} else {
access.UpdateOne(map[string]interface{}{
"verify": true,
"relation": peer.PENDING_MASTER,
}, p.GetID())
}
} else if p.Relation != peer.SELF && p.Relation != peer.BLACKLIST {
if p.Relation == peer.PARTNER || p.Relation == peer.PENDING_PARTNER {
p.Verify = true
p.Relation = peer.PENDING_PARTNER
}
p.IsNano = config.GetConfig().IsNano
// If the incoming peer shares our OrganizationMasterID, initiate org partner
// verification with our master before accepting them as org partner.
if self != nil && self.OrganizationMasterID != "" && p.OrganizationMasterID == self.OrganizationMasterID {
go requestOrgPartnerVerification(self, p, resp.User, resp.Groups)
return
}
access.StoreOne(p.Serialize(p))
}
}
},
tools.SEARCH_EVENT: func(resp tools.NATSResponse) {
if !slices.Contains(ressourceCols, oclib.LibDataEnum(resp.Datatype)) {
return
}
p := &peer.Peer{}
if err := json.Unmarshal(resp.Payload, p); err != nil {
return
}
access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
fmt.Println("ADD in SEARCH STREAM", p.GetID())
if s := access.Search(&dbs.Filters{
And: map[string][]dbs.Filter{
"peer_id": {{Operator: dbs.EQUAL.String(), Value: p.PeerID}},
},
}, "", false, 0, 1); len(s.Data) > 0 {
p.Relation = s.Data[0].(*peer.Peer).Relation
} else {
p.NotInCatalog = true
}
// Stamp volatile online state from cache.
p.Online = IsOnline(p.PeerID)
now := time.Now()
if p.Online {
p.LastHeartbeat = &now
}
SearchMu.RLock()
if ch, ok := SearchStream[resp.User]; ok {
select {
case ch <- WSMessage{Type: "peer", Peer: p}:
default:
}
}
SearchMu.RUnlock()
},
// PEER_OBSERVE_RESPONSE_EVENT is emitted by oc-discovery when it
// receives a heartbeat from an observed remote peer.
tools.PEER_OBSERVE_RESPONSE_EVENT: func(resp tools.NATSResponse) {
var batch struct {
PeerIDs []string `json:"peer_ids"`
Metrics map[string]*PeerConnectivityMetrics `json:"metrics"`
}
if err := json.Unmarshal(resp.Payload, &batch); err != nil {
return
}
if len(batch.PeerIDs) == 0 {
return
}
fmt.Println("METRICS", batch.Metrics)
HandleHeartbeatBatch(batch.PeerIDs, batch.Metrics)
},
})
}
// requestOrgPartnerVerification stores the candidate as KNOWN and asks our
// OrganizationMaster (via PROPALGATION_EVENT → oc-discovery → libp2p stream)
// whether the candidate is really one of its ORGANIZATION_MEMBERs.
// The ORG_PARTNER_EVENT "confirm" branch upgrades the relation once the master replies.
func requestOrgPartnerVerification(self *peer.Peer, candidate *peer.Peer, user string, groups []string) {
// Store candidate as NONE (path "known") — no privilege until master confirms.
access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
candidate.Relation = peer.NONE
candidate.Verify = false
access.StoreOne(candidate.Serialize(candidate))
checkPayload, _ := json.Marshal(map[string]interface{}{
"type": "check",
"requester_id": self.GetID(),
"requester_peer_id": self.PeerID,
"candidate_id": candidate.GetID(),
"master_id": self.OrganizationMasterID,
})
propMsg := tools.PropalgationMessage{
Action: tools.PB_ORG_PARTNER,
DataType: int(tools.PEER),
Payload: checkPayload,
}
b, _ := json.Marshal(propMsg)
tools.NewNATSCaller().SetNATSPub(tools.PROPALGATION_EVENT, tools.NATSResponse{
FromApp: config.GetAppName(),
Datatype: tools.PEER,
User: user,
Groups: groups,
Method: int(tools.PROPALGATION_EVENT),
Payload: b,
})
}
-326
View File
@@ -1,326 +0,0 @@
package infrastructure
import (
"encoding/json"
"fmt"
"sync"
"time"
"cloud.o-forge.io/core/oc-lib/models/peer"
"cloud.o-forge.io/core/oc-lib/tools"
)
const observeTimeout = 60 * time.Second
const offlineRetryInterval = 60 * time.Second
// PeerConnectivityMetrics is the quality snapshot received from oc-discovery
// via PEER_OBSERVE_RESPONSE_EVENT and forwarded to the frontend via WebSocket.
type PeerConnectivityMetrics struct {
LatencyMs float64 `json:"latency_ms"`
Speed string `json:"speed"` // "fast" | "slow"
Reliability string `json:"reliability"` // "reliable" | "watch"
TrustScore float64 `json:"trust_score"`
LastSeenAt time.Time `json:"last_seen_at"`
MissRate float64 `json:"miss_rate"`
}
// WSMessage is sent on every WebSocket endpoint (search and observe).
//
// Type == "peer" → Peer field is set
// Type == "connectivity" → PeerID + Online + Metrics are set
type WSMessage struct {
Type string `json:"type"`
Peer *peer.Peer `json:"peer,omitempty"`
PeerID string `json:"peer_id,omitempty"`
Online bool `json:"online,omitempty"`
Metrics *PeerConnectivityMetrics `json:"metrics,omitempty"`
}
// ShallowPeer is the minimal peer representation the frontend sends when
// requesting observation. oc-discovery uses Address/StreamAddress to reach it.
type ShallowPeer struct {
ID string `json:"id"`
PeerID string `json:"peer_id"`
Address string `json:"address"`
StreamAddress string `json:"stream_address"`
}
// peerObserveCmd is the NATS payload sent to oc-discovery.
//
// Observe → User + Peers populated
// Close → User + PeerIDs + Close=true
// CloseAll → User + CloseAll=true
type peerObserveCmd struct {
User string `json:"user"`
Peers []ShallowPeer `json:"peers,omitempty"`
PeerIDs []string `json:"peer_ids,omitempty"`
Close bool `json:"close,omitempty"`
CloseAll bool `json:"close_all,omitempty"`
}
// ── online cache ─────────────────────────────────────────────────────────────
type onlineState struct {
online bool
timer *time.Timer
metrics *PeerConnectivityMetrics
}
var (
onlineMu sync.Mutex
onlineCache = map[string]*onlineState{}
offlineMu sync.Mutex
offlineCache = map[string]struct{}{}
)
// IsOnline returns whether peerID is currently considered online.
func IsOnline(peerID string) bool {
onlineMu.Lock()
defer onlineMu.Unlock()
if s, ok := onlineCache[peerID]; ok {
return s.online
}
return false
}
// HandleHeartbeatBatch processes a batch of peer heartbeats with optional metrics.
// Called from the PEER_OBSERVE_RESPONSE_EVENT NATS listener.
func HandleHeartbeatBatch(peerIDs []string, metricsMap map[string]*PeerConnectivityMetrics) {
for _, id := range peerIDs {
var m *PeerConnectivityMetrics
if metricsMap != nil {
m = metricsMap[id]
}
setOnline(id, m)
}
}
func setOnline(peerID string, metrics *PeerConnectivityMetrics) {
fmt.Println("SET ONLINE ", peerID, metrics)
onlineMu.Lock()
s, exists := onlineCache[peerID]
if !exists {
s = &onlineState{}
onlineCache[peerID] = s
}
s.online = true
s.metrics = metrics
if s.timer != nil {
s.timer.Stop()
}
s.timer = time.AfterFunc(observeTimeout, func() { setOffline(peerID) })
onlineMu.Unlock()
offlineMu.Lock()
delete(offlineCache, peerID)
offlineMu.Unlock()
broadcastConnectivity(peerID, true, metrics)
}
func setOffline(peerID string) {
onlineMu.Lock()
s, ok := onlineCache[peerID]
if !ok || !s.online {
onlineMu.Unlock()
return
}
s.online = false
s.timer = nil
onlineMu.Unlock()
offlineMu.Lock()
offlineCache[peerID] = struct{}{}
offlineMu.Unlock()
broadcastConnectivity(peerID, false, nil)
}
// broadcastConnectivity fans out a connectivity change to all observe sessions
// watching peerID.
func broadcastConnectivity(peerID string, online bool, metrics *PeerConnectivityMetrics) {
fmt.Println("BORADCAST METRICS", metrics)
msg := WSMessage{Type: "connectivity", PeerID: peerID, Online: online, Metrics: metrics}
sessionsMu.RLock()
for _, s := range sessions {
for _, p := range s.peers {
if p.PeerID == peerID {
select {
case s.ch <- msg:
default:
}
break
}
}
}
sessionsMu.RUnlock()
}
// ── observe sessions ──────────────────────────────────────────────────────────
// observeSession holds per-WS-connection state (user, watched peers, output channel).
type observeSession struct {
user string
peers []ShallowPeer
ch chan WSMessage
}
var (
sessionsMu sync.RWMutex
sessions = map[string]*observeSession{}
)
// RegisterObserveSession creates an empty session for connID / user.
func RegisterObserveSession(connID, user string, ch chan WSMessage) {
sessionsMu.Lock()
sessions[connID] = &observeSession{user: user, ch: ch}
sessionsMu.Unlock()
}
// AddObservedPeers merges new peers into the session, emits a NATS observe
// command (user-scoped), and returns the current online state for each peer.
func AddObservedPeers(connID string, peers []ShallowPeer) []WSMessage {
fmt.Println("AddObservedPeers Concrete")
sessionsMu.Lock()
s, ok := sessions[connID]
if !ok {
sessionsMu.Unlock()
fmt.Println("sessions IS NOT")
return nil
}
existing := make(map[string]struct{}, len(s.peers))
for _, p := range s.peers {
existing[p.PeerID] = struct{}{}
}
var newPeers []ShallowPeer
for _, p := range peers {
if _, dup := existing[p.PeerID]; !dup {
s.peers = append(s.peers, p)
newPeers = append(newPeers, p)
}
}
user := s.user
sessionsMu.Unlock()
fmt.Println("newPeers", newPeers)
if len(newPeers) > 0 {
EmitObserve(user, newPeers)
}
return GetCurrentStates(peerIDsFrom(peers))
}
// CloseObserveSession emits NATS close for all peers in the session, then
// removes it. Call this on WS disconnect (normal or error).
func CloseObserveSession(connID string) {
sessionsMu.Lock()
s, ok := sessions[connID]
if !ok {
sessionsMu.Unlock()
return
}
delete(sessions, connID)
user := s.user
ids := peerIDsFrom(s.peers)
sessionsMu.Unlock()
if len(ids) > 0 {
EmitClose(user, ids)
}
}
// GetCurrentStates returns one WSMessage per peer ID from the online cache
// (defaults to offline for unknown peers).
func GetCurrentStates(peerIDs []string) []WSMessage {
onlineMu.Lock()
defer onlineMu.Unlock()
msgs := make([]WSMessage, 0, len(peerIDs))
for _, id := range peerIDs {
online := false
var metrics *PeerConnectivityMetrics
if s, ok := onlineCache[id]; ok {
online = s.online
metrics = s.metrics
}
msgs = append(msgs, WSMessage{Type: "connectivity", PeerID: id, Online: online, Metrics: metrics})
}
return msgs
}
func peerIDsFrom(peers []ShallowPeer) []string {
ids := make([]string, 0, len(peers))
for _, p := range peers {
ids = append(ids, p.PeerID)
}
return ids
}
// ── NATS emission ─────────────────────────────────────────────────────────────
// EmitObserve asks oc-discovery to start observing peers on behalf of user.
func EmitObserve(user string, peers []ShallowPeer) {
emitCmd(peerObserveCmd{User: user, Peers: peers})
}
// EmitClose asks oc-discovery to stop observing peerIDs for user.
func EmitClose(user string, peerIDs []string) {
emitCmd(peerObserveCmd{User: user, PeerIDs: peerIDs, Close: true})
}
// EmitCloseAll resets all observations for user in oc-discovery.
// Pass an empty user to clear everything (startup reset).
func EmitCloseAll(user string) {
emitCmd(peerObserveCmd{User: user, CloseAll: true})
}
func emitCmd(cmd peerObserveCmd) {
b, err := json.Marshal(cmd)
if err != nil {
return
}
tools.NewNATSCaller().SetNATSPub(tools.PEER_OBSERVE_EVENT, tools.NATSResponse{
FromApp: "oc-peer",
Datatype: tools.PEER,
Method: int(tools.PEER_OBSERVE_EVENT),
Payload: b,
})
}
// ── offline retry loop ────────────────────────────────────────────────────────
// StartOfflineRetryLoop re-requests observation for offline peers every
// offlineRetryInterval, scoped to each active session's user.
func StartOfflineRetryLoop() {
go func() {
ticker := time.NewTicker(offlineRetryInterval)
defer ticker.Stop()
for range ticker.C {
offlineMu.Lock()
offlineIDs := make(map[string]struct{}, len(offlineCache))
for id := range offlineCache {
offlineIDs[id] = struct{}{}
}
offlineMu.Unlock()
if len(offlineIDs) == 0 {
continue
}
sessionsMu.RLock()
for _, s := range sessions {
var retry []ShallowPeer
for _, p := range s.peers {
if _, off := offlineIDs[p.PeerID]; off {
retry = append(retry, p)
}
}
if len(retry) > 0 {
go EmitObserve(s.user, retry)
}
}
sessionsMu.RUnlock()
}
}()
}
+23 -27
View File
@@ -1,12 +1,9 @@
package main
import (
"encoding/json"
"oc-peer/infrastructure"
_ "oc-peer/routers"
oclib "cloud.o-forge.io/core/oc-lib"
"cloud.o-forge.io/core/oc-lib/config"
"cloud.o-forge.io/core/oc-lib/tools"
beego "github.com/beego/beego/v2/server/web"
)
@@ -14,29 +11,28 @@ import (
const appname = "oc-peer"
func main() {
oclib.InitAPI(appname, map[string][]string{
"/oc/decentralized/search/:search": {"GET"},
"/oc/decentralized/observe": {"GET"},
})
go infrastructure.ListenNATS()
// On startup: reset all ongoing observations in oc-discovery.
// If oc-peer crashed while oc-discovery was still running, oc-discovery may
// hold stale observe streams. Close-all clears them and enters drain mode.
go infrastructure.EmitCloseAll("")
// Init the oc-lib
oclib.Init(appname)
d := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil).LoadAll(false, 0, 100000)
for _, dd := range d.Data {
if b, err := json.Marshal(dd); err == nil {
go infrastructure.EmitNATS("root", []string{}, tools.PropalgationMessage{
DataType: tools.PEER.EnumIndex(),
Action: tools.PB_CREATE,
Payload: b,
})
}
}
// Retry observe for offline peers every minute.
infrastructure.StartOfflineRetryLoop()
if config.GetConfig().IsApi {
beego.Run()
}
// Load the right config file
o := oclib.GetConfLoader()
// feed the library with the loaded config
oclib.SetConfig(
o.GetStringDefault("MONGO_URL", "mongodb://127.0.0.1:27017"),
o.GetStringDefault("MONGO_DATABASE", "DC_myDC"),
o.GetStringDefault("NATS_URL", "nats://localhost:4222"),
o.GetStringDefault("LOKI_URL", ""),
o.GetStringDefault("LOG_LEVEL", "info"),
)
// Beego init
beego.BConfig.AppName = appname
beego.BConfig.Listen.HTTPPort = o.GetIntDefault("port", 8080)
beego.BConfig.WebConfig.DirectoryIndex = true
beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
api := &tools.API{}
api.Discovered(beego.BeeApp.Handlers.GetAllControllerInfo())
beego.Run()
}
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -1,5 +1,5 @@
{
"port" : 8093,
"port" : 8080,
"MONGO_URL":"mongodb://localhost:27017/",
"MONGO_DATABASE":"DC_myDC",
"NATS_URL": "nats://localhost:4222"
+17 -152
View File
@@ -16,6 +16,15 @@ func init() {
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
beego.ControllerComments{
Method: "Put",
Router: `/:id`,
AllowHTTPMethods: []string{"put"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
beego.ControllerComments{
Method: "Get",
@@ -25,118 +34,10 @@ func init() {
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
beego.ControllerComments{
Method: "SetPolicy",
Router: `/:id/policy`,
AllowHTTPMethods: []string{"put"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
beego.ControllerComments{
Method: "Delete",
Router: `/:id`,
AllowHTTPMethods: []string{"delete"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
beego.ControllerComments{
Method: "SearchExtended",
Router: `/:type/extended/search`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
beego.ControllerComments{
Method: "Search",
Router: `/:type/search/:search`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
beego.ControllerComments{
Method: "Add",
Router: `/add/:id`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
beego.ControllerComments{
Method: "Blacklist",
Router: `/blacklist/:id`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
beego.ControllerComments{
Method: "Known",
Router: `/known/:id`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
beego.ControllerComments{
Method: "Master",
Router: `/master/:id`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
beego.ControllerComments{
Method: "Nano",
Router: `/nano/:id`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
beego.ControllerComments{
Method: "SetOrganization",
Router: `/organization`,
AllowHTTPMethods: []string{"put"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
beego.ControllerComments{
Method: "OrganizationMasterRequest",
Router: `/organization_master/:id`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
beego.ControllerComments{
Method: "OrganizationMemberRequest",
Router: `/organization_member/:id`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
beego.ControllerComments{
Method: "OrganizationPartner",
Router: `/organization_partner/:id`,
Router: `/:id/blacklist`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
@@ -145,7 +46,7 @@ func init() {
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
beego.ControllerComments{
Method: "Partner",
Router: `/partner/:id`,
Router: `/:id/partner`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
@@ -153,54 +54,18 @@ func init() {
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
beego.ControllerComments{
Method: "Valid",
Router: `/valid/:id`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"],
beego.ControllerComments{
Method: "GetAll",
Router: `/`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"],
beego.ControllerComments{
Method: "Get",
Router: `/:id`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"],
beego.ControllerComments{
Method: "Post",
Router: `/`,
Method: "DeleteState",
Router: `/:id/undo_state`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"],
beego.GlobalControllerRouter["oc-peer/controllers:PeerController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PeerController"],
beego.ControllerComments{
Method: "Put",
Router: `/:id`,
AllowHTTPMethods: []string{"put"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"] = append(beego.GlobalControllerRouter["oc-peer/controllers:PolicyController"],
beego.ControllerComments{
Method: "Delete",
Router: `/:id`,
AllowHTTPMethods: []string{"delete"},
Method: "Search",
Router: `/search/:search`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
+1 -119
View File
@@ -8,28 +8,13 @@
package routers
import (
"encoding/json"
"fmt"
"net/http"
"oc-peer/controllers"
"oc-peer/infrastructure"
"strings"
"time"
oclib "cloud.o-forge.io/core/oc-lib"
"cloud.o-forge.io/core/oc-lib/tools"
beego "github.com/beego/beego/v2/server/web"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
func init() {
ns := beego.NewNamespace("/oc",
ns := beego.NewNamespace("/oc/",
beego.NSNamespace("/status",
beego.NSInclude(
&controllers.StatusController{},
@@ -38,11 +23,6 @@ func init() {
beego.NSInclude(
&controllers.PeerController{},
),
beego.NSNamespace("/policy",
beego.NSInclude(
&controllers.PolicyController{},
),
),
beego.NSNamespace("/version",
beego.NSInclude(
&controllers.VersionController{},
@@ -50,102 +30,4 @@ func init() {
),
)
beego.AddNamespace(ns)
// WebSocket — peer search (returns found peers + online/offline updates for them)
beego.Handler("/oc/decentralized/search/:search", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
return
}
defer conn.Close()
parts := strings.Split(strings.TrimSuffix(r.URL.Path, "/"), "/")
search := parts[len(parts)-1]
user, _, groups := oclib.ExtractTokenInfoWs(*r)
b, _ := json.Marshal(map[string]string{"search": search})
infrastructure.EmitNATS(user, groups, tools.PropalgationMessage{
Action: tools.PB_SEARCH,
DataType: tools.PEER.EnumIndex(),
Payload: b,
})
fmt.Println("SEARCH", search)
controllers.Websocket(r.Context(), user, conn)
}))
// WebSocket — dedicated online/offline feed, user-scoped.
//
// The frontend sends lists of ShallowPeer to watch; oc-peer forwards them
// to oc-discovery via NATS (with user identity). On any disconnect or error
// oc-peer emits NATS close for all peers watched in this session.
beego.Handler("/oc/decentralized/observe", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
return
}
user, _, _ := oclib.ExtractTokenInfoWs(*r)
connID := fmt.Sprintf("%p", conn)
ch := make(chan infrastructure.WSMessage, 64)
fmt.Println("SUBSCRIBED TO", connID)
infrastructure.RegisterObserveSession(connID, user, ch)
done := make(chan struct{})
defer func() {
infrastructure.CloseObserveSession(connID)
close(done)
conn.Close()
}()
const pongWait = 60 * time.Second
const pingPeriod = 50 * time.Second
const writeWait = 10 * time.Second
conn.SetReadDeadline(time.Now().Add(pongWait))
conn.SetPongHandler(func(string) error {
return conn.SetReadDeadline(time.Now().Add(pongWait))
})
// Write loop: forward state-change messages and send keepalive pings.
go func() {
ticker := time.NewTicker(pingPeriod)
defer ticker.Stop()
for {
select {
case msg := <-ch:
fmt.Println("ONLINE", msg)
conn.SetWriteDeadline(time.Now().Add(writeWait))
if conn.WriteJSON(msg) != nil {
infrastructure.CloseObserveSession(connID)
conn.Close()
return
}
case <-ticker.C:
conn.SetWriteDeadline(time.Now().Add(writeWait))
if conn.WriteMessage(websocket.PingMessage, nil) != nil {
infrastructure.CloseObserveSession(connID)
conn.Close()
return
}
case <-done:
return
}
}
}()
// Read loop: receive peer lists from the frontend.
var req struct {
Peers []infrastructure.ShallowPeer `json:"peers"`
}
for {
if err := conn.ReadJSON(&req); err != nil {
return
}
// AddObservedPeers deduplicates, emits NATS observe, returns snapshot.
for _, msg := range infrastructure.AddObservedPeers(connID, req.Peers) {
select {
case ch <- msg:
default:
}
}
}
}))
}
+112 -360
View File
@@ -13,7 +13,7 @@
"url": "https://www.gnu.org/licenses/agpl-3.0.html"
}
},
"basePath": "/oc",
"basePath": "/oc/",
"paths": {
"/": {
"get": {
@@ -28,255 +28,40 @@
"name": "is_draft",
"description": "false",
"type": "string"
},
}
],
"responses": {
"200": {
"description": "{peer} models.peer"
}
}
}
},
"/search/{search}": {
"get": {
"tags": [
"oc-peer/controllersPeerController"
],
"description": "search workspace\n\u003cbr\u003e",
"operationId": "PeerController.Search",
"parameters": [
{
"in": "query",
"name": "offset",
"description": "false",
"in": "path",
"name": "search",
"description": "the word search you want to get",
"required": true,
"type": "string"
},
{
"in": "query",
"name": "limit",
"name": "is_draft",
"description": "false",
"type": "string"
}
],
"responses": {
"200": {
"description": "{peer} models.peer"
}
}
}
},
"/add/{id}": {
"post": {
"tags": [
"oc-peer/controllersPeerController"
],
"description": "add peer by peerid\n\u003cbr\u003e",
"operationId": "PeerController.add",
"parameters": [
{
"in": "path",
"name": "id",
"description": "the peer id you want to blacklist",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "{peer} models.peer"
}
}
}
},
"/blacklist/{id}": {
"post": {
"tags": [
"oc-peer/controllersPeerController"
],
"description": "add blacklist peer by peerid\n\u003cbr\u003e",
"operationId": "PeerController.Blacklist",
"parameters": [
{
"in": "path",
"name": "id",
"description": "the peer id you want to blacklist",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "{peer} models.peer"
}
}
}
},
"/known/{id}": {
"post": {
"tags": [
"oc-peer/controllersPeerController"
],
"description": "add kwown peer by peerid\n\u003cbr\u003e",
"operationId": "PeerController.known",
"parameters": [
{
"in": "path",
"name": "id",
"description": "the peer id you want to blacklist",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "{peer} models.peer"
}
}
}
},
"/master/{id}": {
"post": {
"tags": [
"oc-peer/controllersPeerController"
],
"description": "add master peer by peerid\n\u003cbr\u003e",
"operationId": "PeerController.Master",
"parameters": [
{
"in": "path",
"name": "id",
"description": "the peer id you want to blacklist",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "{peer} models.peer"
}
}
}
},
"/nano/{id}": {
"post": {
"tags": [
"oc-peer/controllersPeerController"
],
"description": "add Nano peer by peerid\n\u003cbr\u003e",
"operationId": "PeerController.Nano",
"parameters": [
{
"in": "path",
"name": "id",
"description": "the peer id you want to blacklist",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "{peer} models.peer"
}
}
}
},
"/organization": {
"put": {
"tags": [
"oc-peer/controllersPeerController"
],
"description": "set organization data on self peer (only allowed when peer has no OrganizationMasterID)\n\u003cbr\u003e",
"operationId": "PeerController.SetOrganization",
"parameters": [
{
"in": "body",
"name": "data",
"description": "organization data",
"required": true,
"schema": {
"$ref": "#/definitions/json"
}
}
],
"responses": {
"200": {
"description": "{peer} models.peer"
}
}
}
},
"/organization_master/{id}": {
"post": {
"tags": [
"oc-peer/controllersPeerController"
],
"description": "request to become the organization master of a peer (send them an ORGANIZATION_MEMBER relation)\n\u003cbr\u003e",
"operationId": "PeerController.OrganizationMasterRequest",
"parameters": [
{
"in": "path",
"name": "id",
"description": "the peer id to become member of our org",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "{peer} models.peer"
}
}
}
},
"/organization_member/{id}": {
"post": {
"tags": [
"oc-peer/controllersPeerController"
],
"description": "request to join a peer's organization as a member (send them an ORGANIZATION_MASTER relation)\n\u003cbr\u003e",
"operationId": "PeerController.OrganizationMemberRequest",
"parameters": [
{
"in": "path",
"name": "id",
"description": "the peer id whose org we want to join",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "{peer} models.peer"
}
}
}
},
"/organization_partner/{id}": {
"post": {
"tags": [
"oc-peer/controllersPeerController"
],
"description": "request organization partner relation with a peer\n\u003cbr\u003e",
"operationId": "PeerController.OrganizationPartner",
"parameters": [
{
"in": "path",
"name": "id",
"description": "the peer id to set as organization partner",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "{peer} models.peer"
}
}
}
},
"/partner/{id}": {
"post": {
"tags": [
"oc-peer/controllersPeerController"
],
"description": "add partner peer by peerid\n\u003cbr\u003e",
"operationId": "PeerController.Partner",
"parameters": [
{
"in": "path",
"name": "id",
"description": "the peer id you want to blacklist",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "{peer} models.peer"
"description": "{workspace} models.workspace"
}
}
}
@@ -305,29 +90,6 @@
}
}
},
"/valid/{id}": {
"get": {
"tags": [
"oc-peer/controllersPeerController"
],
"description": "find peer by peerid\n\u003cbr\u003e",
"operationId": "PeerController.Valid",
"parameters": [
{
"in": "path",
"name": "id",
"description": "the peer id you want to get",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "{peer} models.peer"
}
}
}
},
"/version/": {
"get": {
"tags": [
@@ -364,12 +126,93 @@
}
}
},
"delete": {
"put": {
"tags": [
"oc-peer/controllersPeerController"
],
"description": "delete peer by peerid\n\u003cbr\u003e",
"operationId": "PeerController.Delete",
"description": "create peers\n\u003cbr\u003e",
"operationId": "PeerController.Update",
"parameters": [
{
"in": "path",
"name": "id",
"description": "the peer id you want to get",
"required": true,
"type": "string"
},
{
"in": "body",
"name": "body",
"description": "The peer content",
"required": true,
"schema": {
"$ref": "#/definitions/models.peer"
}
}
],
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/models.peer"
}
}
}
}
},
"/{id}/blacklist": {
"post": {
"tags": [
"oc-peer/controllersPeerController"
],
"description": "add blacklist peer by peerid\n\u003cbr\u003e",
"operationId": "PeerController.Blacklist",
"parameters": [
{
"in": "path",
"name": "id",
"description": "the peer id you want to blacklist",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "{peer} models.peer"
}
}
}
},
"/{id}/partner": {
"post": {
"tags": [
"oc-peer/controllersPeerController"
],
"description": "add partner peer by peerid\n\u003cbr\u003e",
"operationId": "PeerController.Partner",
"parameters": [
{
"in": "path",
"name": "id",
"description": "the peer id you want to partner",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "{peer} models.peer"
}
}
}
},
"/{id}/undo_state": {
"post": {
"tags": [
"oc-peer/controllersPeerController"
],
"description": "delete state peer by peerid\n\u003cbr\u003e",
"operationId": "PeerController.DeleteState",
"parameters": [
{
"in": "path",
@@ -385,107 +228,16 @@
}
}
}
},
"/{type}/extended/search": {
"post": {
"tags": [
"oc-peer/controllersPeerController"
],
"description": "search workspace\n\u003cbr\u003e",
"operationId": "PeerController.Search",
"parameters": [
{
"in": "query",
"name": "is_draft",
"description": "false",
"type": "string"
},
{
"in": "query",
"name": "offset",
"description": "false",
"type": "string"
},
{
"in": "query",
"name": "limit",
"description": "false",
"type": "string"
},
{
"in": "body",
"name": "data",
"description": "body for data content (Json format)",
"required": true,
"schema": {
"$ref": "#/definitions/json"
}
}
],
"responses": {
"200": {
"description": "{workspace} models.workspace"
}
}
}
},
"/{type}/search/{search}": {
"get": {
"tags": [
"oc-peer/controllersPeerController"
],
"description": "search workspace\n\u003cbr\u003e",
"operationId": "PeerController.Search",
"parameters": [
{
"in": "path",
"name": "type",
"description": "the type you want to get",
"required": true,
"type": "string"
},
{
"in": "path",
"name": "search",
"description": "the word search you want to get",
"required": true,
"type": "string"
},
{
"in": "query",
"name": "is_draft",
"description": "false",
"type": "string"
},
{
"in": "query",
"name": "offset",
"description": "false",
"type": "string"
},
{
"in": "query",
"name": "limit",
"description": "false",
"type": "string"
}
],
"responses": {
"200": {
"description": "{workspace} models.workspace"
}
}
}
}
},
"definitions": {
"json": {
"title": "json",
"type": "object"
},
"list": {
"title": "list",
"type": "object"
},
"models.peer": {
"title": "peer",
"type": "object"
}
},
"tags": [
+55 -235
View File
@@ -10,7 +10,7 @@ info:
license:
name: AGPL
url: https://www.gnu.org/licenses/agpl-3.0.html
basePath: /oc
basePath: /oc/
paths:
/:
get:
@@ -25,14 +25,6 @@ paths:
name: is_draft
description: "false"
type: string
- in: query
name: offset
description: "false"
type: string
- in: query
name: limit
description: "false"
type: string
responses:
"200":
description: '{peer} models.peer'
@@ -53,104 +45,31 @@ paths:
responses:
"200":
description: '{peer} models.peer'
delete:
put:
tags:
- oc-peer/controllersPeerController
description: |-
delete peer by peerid
create peers
<br>
operationId: PeerController.Delete
operationId: PeerController.Update
parameters:
- in: path
name: id
description: the peer id you want to delete state
description: the peer id you want to get
required: true
type: string
responses:
"200":
description: '{peer} models.peer'
/{type}/extended/search:
post:
tags:
- oc-peer/controllersPeerController
description: |-
search workspace
<br>
operationId: PeerController.Search
parameters:
- in: query
name: is_draft
description: "false"
type: string
- in: query
name: offset
description: "false"
type: string
- in: query
name: limit
description: "false"
type: string
- in: body
name: data
description: body for data content (Json format)
name: body
description: The peer content
required: true
schema:
$ref: '#/definitions/json'
$ref: '#/definitions/models.peer'
responses:
"200":
description: '{workspace} models.workspace'
/{type}/search/{search}:
get:
tags:
- oc-peer/controllersPeerController
description: |-
search workspace
<br>
operationId: PeerController.Search
parameters:
- in: path
name: type
description: the type you want to get
required: true
type: string
- in: path
name: search
description: the word search you want to get
required: true
type: string
- in: query
name: is_draft
description: "false"
type: string
- in: query
name: offset
description: "false"
type: string
- in: query
name: limit
description: "false"
type: string
responses:
"200":
description: '{workspace} models.workspace'
/add/{id}:
post:
tags:
- oc-peer/controllersPeerController
description: |-
add peer by peerid
<br>
operationId: PeerController.add
parameters:
- in: path
name: id
description: the peer id you want to blacklist
required: true
type: string
responses:
"200":
description: '{peer} models.peer'
/blacklist/{id}:
description: ""
schema:
$ref: '#/definitions/models.peer'
/{id}/blacklist:
post:
tags:
- oc-peer/controllersPeerController
@@ -167,127 +86,7 @@ paths:
responses:
"200":
description: '{peer} models.peer'
/known/{id}:
post:
tags:
- oc-peer/controllersPeerController
description: |-
add kwown peer by peerid
<br>
operationId: PeerController.known
parameters:
- in: path
name: id
description: the peer id you want to blacklist
required: true
type: string
responses:
"200":
description: '{peer} models.peer'
/master/{id}:
post:
tags:
- oc-peer/controllersPeerController
description: |-
add master peer by peerid
<br>
operationId: PeerController.Master
parameters:
- in: path
name: id
description: the peer id you want to blacklist
required: true
type: string
responses:
"200":
description: '{peer} models.peer'
/nano/{id}:
post:
tags:
- oc-peer/controllersPeerController
description: |-
add Nano peer by peerid
<br>
operationId: PeerController.Nano
parameters:
- in: path
name: id
description: the peer id you want to blacklist
required: true
type: string
responses:
"200":
description: '{peer} models.peer'
/organization:
put:
tags:
- oc-peer/controllersPeerController
description: |-
set organization data on self peer (only allowed when peer has no OrganizationMasterID)
<br>
operationId: PeerController.SetOrganization
parameters:
- in: body
name: data
description: organization data
required: true
schema:
$ref: '#/definitions/json'
responses:
"200":
description: '{peer} models.peer'
/organization_master/{id}:
post:
tags:
- oc-peer/controllersPeerController
description: |-
request to become the organization master of a peer (send them an ORGANIZATION_MEMBER relation)
<br>
operationId: PeerController.OrganizationMasterRequest
parameters:
- in: path
name: id
description: the peer id to become member of our org
required: true
type: string
responses:
"200":
description: '{peer} models.peer'
/organization_member/{id}:
post:
tags:
- oc-peer/controllersPeerController
description: |-
request to join a peer's organization as a member (send them an ORGANIZATION_MASTER relation)
<br>
operationId: PeerController.OrganizationMemberRequest
parameters:
- in: path
name: id
description: the peer id whose org we want to join
required: true
type: string
responses:
"200":
description: '{peer} models.peer'
/organization_partner/{id}:
post:
tags:
- oc-peer/controllersPeerController
description: |-
request organization partner relation with a peer
<br>
operationId: PeerController.OrganizationPartner
parameters:
- in: path
name: id
description: the peer id to set as organization partner
required: true
type: string
responses:
"200":
description: '{peer} models.peer'
/partner/{id}:
/{id}/partner:
post:
tags:
- oc-peer/controllersPeerController
@@ -298,12 +97,50 @@ paths:
parameters:
- in: path
name: id
description: the peer id you want to blacklist
description: the peer id you want to partner
required: true
type: string
responses:
"200":
description: '{peer} models.peer'
/{id}/undo_state:
post:
tags:
- oc-peer/controllersPeerController
description: |-
delete state peer by peerid
<br>
operationId: PeerController.DeleteState
parameters:
- in: path
name: id
description: the peer id you want to delete state
required: true
type: string
responses:
"200":
description: '{peer} models.peer'
/search/{search}:
get:
tags:
- oc-peer/controllersPeerController
description: |-
search workspace
<br>
operationId: PeerController.Search
parameters:
- in: path
name: search
description: the word search you want to get
required: true
type: string
- in: query
name: is_draft
description: "false"
type: string
responses:
"200":
description: '{workspace} models.workspace'
/status/:
post:
tags:
@@ -321,23 +158,6 @@ paths:
responses:
"200":
description: '{status} models.status'
/valid/{id}:
get:
tags:
- oc-peer/controllersPeerController
description: |-
find peer by peerid
<br>
operationId: PeerController.Valid
parameters:
- in: path
name: id
description: the peer id you want to get
required: true
type: string
responses:
"200":
description: '{peer} models.peer'
/version/:
get:
tags:
@@ -350,12 +170,12 @@ paths:
"200":
description: ""
definitions:
json:
title: json
type: object
list:
title: list
type: object
models.peer:
title: peer
type: object
tags:
- name: status
description: |
-102
View File
@@ -1,102 +0,0 @@
//go:build ignore
package main
import (
"encoding/json"
"flag"
"fmt"
"log"
"os"
"os/signal"
"time"
"golang.org/x/net/websocket"
)
func main() {
timeout := flag.Int("timeout", 10, "secondes sans message avant de quitter")
flag.Parse()
args := flag.Args()
url := "ws://localhost:8093/oc/decentralized/search/demo"
token := ""
if len(args) >= 1 {
url = args[0]
}
if len(args) >= 2 {
token = args[1]
}
// websocket.Dial attend une "origin" (peut être n'importe quelle URL)
origin := "http://localhost/"
config, err := websocket.NewConfig(url, origin)
if err != nil {
log.Fatalf("Config invalide : %v", err)
}
if token != "" {
config.Header.Set("Authorization", "Bearer "+token)
fmt.Printf("Token : %s...\n", token[:min(20, len(token))])
}
fmt.Printf("Connexion à : %s\n", url)
ws, err := websocket.DialConfig(config)
if err != nil {
log.Fatalf("Impossible de se connecter : %v", err)
}
defer ws.Close()
fmt.Println("Connecté — en attente de messages...\n")
// Gestion Ctrl+C
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt)
msgs := make(chan string)
errs := make(chan error, 1)
go func() {
for {
var raw string
if err := websocket.Message.Receive(ws, &raw); err != nil {
errs <- err
return
}
msgs <- raw
}
}()
idleTimer := time.NewTimer(time.Duration(*timeout) * time.Second)
defer idleTimer.Stop()
for {
select {
case <-stop:
fmt.Println("\nInterruption — fermeture.")
return
case err := <-errs:
fmt.Printf("Connexion fermée : %v\n", err)
return
case <-idleTimer.C:
fmt.Printf("Timeout (%ds) — aucun message reçu, fermeture.\n", *timeout)
return
case raw := <-msgs:
idleTimer.Reset(time.Duration(*timeout) * time.Second)
// Tente d'afficher en JSON formaté
var data any
if err := json.Unmarshal([]byte(raw), &data); err == nil {
b, _ := json.MarshalIndent(data, "", " ")
fmt.Println(string(b))
} else {
fmt.Printf("Message brut : %s\n", raw)
}
}
}
}
func min(a, b int) int {
if a < b {
return a
}
return b
}