feat: Build Manager, Crucible ops deck, branding, and portable Cloudflare tunnel
Add Build Manager with pin-to-dropper, Crucible multi-node terminal with SSH probe/wake, Command Deck chart balance and pretty stats, AetherForge logo and sacred geometry UI, Field Guide refresh, and LAUNCH.bat Cloudflare MSI + token service install flow.
This commit is contained in:
@@ -113,6 +113,37 @@ func (h *Handler) ListBuilds(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, builds)
|
||||
}
|
||||
|
||||
// PUT /api/v1/builds/{id}/pin
|
||||
// Pins the specified build as the active dropper target.
|
||||
// Send an empty id or DELETE to a fake pin endpoint to unpin all.
|
||||
func (h *Handler) PinBuild(w http.ResponseWriter, r *http.Request) {
|
||||
id := chi.URLParam(r, "id")
|
||||
if err := h.db.SetPinnedBuild(id); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
writeJSON(w, map[string]interface{}{"ok": true, "pinned_id": id})
|
||||
}
|
||||
|
||||
// DELETE /api/v1/builds/pin (unpin all without deleting anything)
|
||||
func (h *Handler) UnpinAll(w http.ResponseWriter, r *http.Request) {
|
||||
if err := h.db.SetPinnedBuild(""); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
writeJSON(w, map[string]interface{}{"ok": true})
|
||||
}
|
||||
|
||||
// DELETE /api/v1/builds/{id}
|
||||
func (h *Handler) DeleteBuild(w http.ResponseWriter, r *http.Request) {
|
||||
id := chi.URLParam(r, "id")
|
||||
if err := h.db.DeleteBuild(id); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
writeJSON(w, map[string]interface{}{"ok": true, "deleted_id": id})
|
||||
}
|
||||
|
||||
func writeJSON(w http.ResponseWriter, v interface{}) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(v)
|
||||
|
||||
Reference in New Issue
Block a user