diff --git a/cmd/orchestra/main.go b/cmd/orchestra/main.go index 77d2fc1..ad9bd00 100644 --- a/cmd/orchestra/main.go +++ b/cmd/orchestra/main.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "io" "log" "net/http" "orchestra/internal/authz" @@ -121,6 +122,31 @@ func main() { } json.NewEncoder(w).Encode(s.Events(n)) }) + mux.HandleFunc("/v1/artifacts", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + return + } + // Reports and handoffs are content-addressed evidence. Keep uploads + // bounded because event payloads only carry their resulting hash. + r.Body = http.MaxBytesReader(w, r.Body, 4<<20) + b, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, "artifact too large or unreadable", http.StatusRequestEntityTooLarge) + return + } + if len(b) == 0 { + http.Error(w, "artifact is empty", http.StatusBadRequest) + return + } + ref, err := s.PutArtifact(b) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusCreated) + json.NewEncoder(w).Encode(map[string]string{"ref": ref}) + }) mux.HandleFunc("/v1/brief", func(w http.ResponseWriter, r *http.Request) { to := time.Now().UTC() from := to.Add(-12 * time.Hour) diff --git a/progress.md b/progress.md index 63b80bb..7bb1008 100644 --- a/progress.md +++ b/progress.md @@ -57,6 +57,8 @@ Item 1 substrate hardening pass: newly appended events use schema envelope versi Harness registration now uses configured `harness` and `protocol` fields, pings each configured herdr before exposing it to orchestration, selects Claude/Codex/opencode adapters accordingly, and skips unavailable or unsupported deployments at startup. This is an initial discovery/health slice; active-session discovery and ongoing heartbeats remain open. +Added bounded `POST /v1/artifacts` CAS upload support for report/handoff evidence. It returns the verified content hash used by lifecycle events and rejects empty or oversized uploads. + Recommended order: 1. Add the orchestration coordinator: lease → worktree → harness session → bootstrap → lifecycle events.