From e42952469dadfb3535633c66c881050ac128703c Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Mon, 5 Oct 2026 17:05:14 -0400 Subject: fix: gather verbs, walk oom, admin path bypass, roulette refund --- internal/admin/api_rooms.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'internal/admin/api_rooms.go') diff --git a/internal/admin/api_rooms.go b/internal/admin/api_rooms.go index efc466c..586bfff 100644 --- a/internal/admin/api_rooms.go +++ b/internal/admin/api_rooms.go @@ -159,6 +159,16 @@ func (s *AdminServer) handleRooms(w http.ResponseWriter, r *http.Request) { // source room's new exit first, so a failed destination write left // a dangling exit pointing at a room that never existed, with no // undo entry to repair it. + // Validate before writing, exactly like the PUT and bulk-edit paths: + // otherwise a create can persist a room the loader/validator reject. + if content, marshalErr := marshalMapYAML(m); marshalErr != nil { + failJSON(w, fmt.Sprintf("marshal room: %v", marshalErr)) + return + } else if err := validateRoomSchema(content); err != nil { + writeJSONError(w, "room failed schema validation: "+err.Error(), http.StatusBadRequest) + return + } + path := filepath.Join(subdir, strconv.Itoa(id)+".yaml") newContent, writeErr := writeMapAsYAML(path, m) if writeErr != nil { @@ -1244,6 +1254,14 @@ func (s *AdminServer) handleRoomSwap(w http.ResponseWriter, r *http.Request) { return } + // The files now declare each other's content; refresh both rooms' live + // runtime state or each keeps its old objects/mobs alongside the new ones + // (seeding is add-only). + if s.reconcileRoom != nil { + s.reconcileRoom(aID) + s.reconcileRoom(bID) + } + s.undoStack.Push(ChangeDesc{ Description: fmt.Sprintf("swap room %d with %d (%s)", aID, bID, dir), FilePath: aPath, @@ -1433,6 +1451,14 @@ func (s *AdminServer) handleCreateEmptyRoom(w http.ResponseWriter, r *http.Reque "name": roomName, "description": []map[string]any{{"text": "An empty room."}}, } + // Validate before writing, exactly like the main create path. + if content, marshalErr := marshalMapYAML(m); marshalErr != nil { + failJSON(w, "marshal room: "+marshalErr.Error()) + return + } else if err := validateRoomSchema(content); err != nil { + writeJSONError(w, "room failed schema validation: "+err.Error(), http.StatusBadRequest) + return + } newContent, writeErr := writeMapAsYAML(path, m) if writeErr != nil { failJSON(w, "write room: "+writeErr.Error()) -- cgit v1.2.3