docs: update architecture and API documentation to clarify job processing, in-memory registry usage, and future broker integration plans. Enhance OpenAPI specifications for enrollment responses and refine quickstart instructions for Docker setups.
CI / changes (push) Successful in 4s
CI / openapi (push) Successful in 24s
CI / go (push) Successful in 22s
CI / bird2 (push) Successful in 13s
CI / docker-images (deploy/docker/bird2/Dockerfile, evobgp-bird2) (push) Successful in 38s
CI / docker-images (deploy/docker/evobgp-agent/Dockerfile, evobgp-agent) (push) Successful in 1m8s
CI / docker-images (deploy/docker/evobgp-web/Dockerfile, evobgp-web) (push) Successful in 49s
CI / docker-images (evobgp-all, 1, deploy/docker/gobinary/Dockerfile, evobgp-all) (push) Successful in 1m30s
CI / docker-images (evobgp-api, 1, deploy/docker/gobinary/Dockerfile, evobgp-api) (push) Successful in 1m31s
CI / docker-images (evobgp-ingest, 0, deploy/docker/gobinary/Dockerfile, evobgp-ingest) (push) Has been cancelled
CI / docker-images (evobgp-deploy, 0, deploy/docker/gobinary/Dockerfile, evobgp-deploy) (push) Has been cancelled
CI / docker-images (evobgp-node, 0, deploy/docker/gobinary/Dockerfile, evobgp-node) (push) Has been cancelled
CI / docker-images (evobgp-render, 0, deploy/docker/gobinary/Dockerfile, evobgp-render) (push) Has been cancelled
CI / docker-images (evobgp-scheduler, 0, deploy/docker/gobinary/Dockerfile, evobgp-scheduler) (push) Has been cancelled
CI / changes (push) Successful in 4s
CI / openapi (push) Successful in 24s
CI / go (push) Successful in 22s
CI / bird2 (push) Successful in 13s
CI / docker-images (deploy/docker/bird2/Dockerfile, evobgp-bird2) (push) Successful in 38s
CI / docker-images (deploy/docker/evobgp-agent/Dockerfile, evobgp-agent) (push) Successful in 1m8s
CI / docker-images (deploy/docker/evobgp-web/Dockerfile, evobgp-web) (push) Successful in 49s
CI / docker-images (evobgp-all, 1, deploy/docker/gobinary/Dockerfile, evobgp-all) (push) Successful in 1m30s
CI / docker-images (evobgp-api, 1, deploy/docker/gobinary/Dockerfile, evobgp-api) (push) Successful in 1m31s
CI / docker-images (evobgp-ingest, 0, deploy/docker/gobinary/Dockerfile, evobgp-ingest) (push) Has been cancelled
CI / docker-images (evobgp-deploy, 0, deploy/docker/gobinary/Dockerfile, evobgp-deploy) (push) Has been cancelled
CI / docker-images (evobgp-node, 0, deploy/docker/gobinary/Dockerfile, evobgp-node) (push) Has been cancelled
CI / docker-images (evobgp-render, 0, deploy/docker/gobinary/Dockerfile, evobgp-render) (push) Has been cancelled
CI / docker-images (evobgp-scheduler, 0, deploy/docker/gobinary/Dockerfile, evobgp-scheduler) (push) Has been cancelled
This commit is contained in:
@@ -5,6 +5,8 @@ import (
|
||||
"crypto/ed25519"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
@@ -672,14 +674,72 @@ func (s *Server) handleNodeEnroll(w http.ResponseWriter, r *http.Request) {
|
||||
if !s.requireNode(w, a) {
|
||||
return
|
||||
}
|
||||
var req map[string]any
|
||||
_ = json.NewDecoder(r.Body).Decode(&req)
|
||||
var body struct {
|
||||
SpeakerID string `json:"speaker_id"`
|
||||
PublicKey string `json:"public_key"`
|
||||
}
|
||||
dec := json.NewDecoder(r.Body)
|
||||
if err := dec.Decode(&body); err != nil && !errors.Is(err, io.EOF) {
|
||||
writeProblem(w, http.StatusBadRequest, "Bad Request", "invalid JSON body")
|
||||
return
|
||||
}
|
||||
sid := strings.TrimSpace(body.SpeakerID)
|
||||
if sid == "" {
|
||||
writeProblem(w, http.StatusUnprocessableEntity, "Unprocessable Entity", "speaker_id is required")
|
||||
return
|
||||
}
|
||||
sp, err := s.store.GetSpeaker(a.TenantID, sid)
|
||||
if err != nil {
|
||||
writeProblem(w, http.StatusNotFound, "Not Found", "speaker not found")
|
||||
return
|
||||
}
|
||||
updates := map[string]any{
|
||||
"node_enrolled_at": time.Now().UTC().Format(time.RFC3339Nano),
|
||||
}
|
||||
if pk := strings.TrimSpace(body.PublicKey); pk != "" {
|
||||
updates["node_public_key"] = pk
|
||||
}
|
||||
meta, err := mergeSpeakerMetaJSON(sp.MetaJSON, updates)
|
||||
if err != nil {
|
||||
writeProblem(w, http.StatusUnprocessableEntity, "Unprocessable Entity", "speaker meta_json must be a JSON object (or empty)")
|
||||
return
|
||||
}
|
||||
patch := &store.SpeakerPatch{MetaJSON: &meta}
|
||||
if _, err := s.store.UpdateSpeaker(a.TenantID, sid, patch); err != nil {
|
||||
writeProblem(w, http.StatusInternalServerError, "Internal Error", err.Error())
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]any{
|
||||
"status": "accepted",
|
||||
"message": "enrollment stub; operator approval required in production",
|
||||
"status": "enrolled",
|
||||
"speaker_id": sp.ID,
|
||||
"tenant_id": a.TenantID,
|
||||
})
|
||||
}
|
||||
|
||||
func mergeSpeakerMetaJSON(existing string, updates map[string]any) (string, error) {
|
||||
existing = strings.TrimSpace(existing)
|
||||
var m map[string]any
|
||||
if existing != "" {
|
||||
if err := json.Unmarshal([]byte(existing), &m); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if m == nil {
|
||||
return "", errors.New("meta must be a JSON object")
|
||||
}
|
||||
}
|
||||
if m == nil {
|
||||
m = make(map[string]any)
|
||||
}
|
||||
for k, v := range updates {
|
||||
m[k] = v
|
||||
}
|
||||
b, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
func sortedFragmentKeys(m map[string]string) []string {
|
||||
keys := make([]string, 0, len(m))
|
||||
for k := range m {
|
||||
|
||||
Reference in New Issue
Block a user