From 5ff45f355ad1fa8b52b73c0438ec0eb54550a1cc Mon Sep 17 00:00:00 2001 From: Smokey <150986568+jacisjake@users.noreply.github.com> Date: Wed, 28 Oct 2026 05:29:57 -0600 Subject: [PATCH] =?UTF-8?q?feat(claim):=20arbitration=20per=20mode=20(#5)?= =?UTF-8?q?=20=E2=80=94=20first=20claim=20wins=20except=20conspiracy=20(#2?= =?UTF-8?q?3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nestapi.go | 11 +++++++++++ nestlog.go | 13 +++++++++++++ 2 files changed, 24 insertions(+) diff --git a/nestapi.go b/nestapi.go index ed47452..5af1c3c 100644 --- a/nestapi.go +++ b/nestapi.go @@ -132,6 +132,17 @@ func (s *Server) postNestMessage(w http.ResponseWriter, r *http.Request) { // Mode (Epic C, same rule shape as kind): Jev first, header escape, "" when unsure. mode, modeBy := s.tagMode(kind, body.Mode, body.Text) + // Claim arbitration (#5, Epic C): first claim wins unless the referent is a + // conspiracy, which expects multiple claims. + if kind == "claim" && body.RefersTo != "" { + if origin, found := s.msgs.ByMsgID(body.RefersTo); found && origin.Mode != "conspiracy" { + if owner, claimed := s.msgs.FirstClaim(origin.NestID, origin.MsgID()); claimed { + httpError(w, http.StatusConflict, origin.MsgID()+" is claimed by "+owner+"; review it instead of redoing it.") + return + } + } + } + msg := Message{ NestID: nestID, Kind: kind, diff --git a/nestlog.go b/nestlog.go index 587c800..82ea705 100644 --- a/nestlog.go +++ b/nestlog.go @@ -119,6 +119,19 @@ func (s *MessageStore) ByMsgID(msgID string) (Message, bool) { return Message{}, false } +// FirstClaim returns the author of the first claim against a message, and +// whether any claim exists. +func (s *MessageStore) FirstClaim(nestID, referentID string) (string, bool) { + s.mu.Lock() + defer s.mu.Unlock() + for _, m := range s.log[nestID] { + if m.Kind == "claim" && m.RefersTo == referentID { + return m.Author, true + } + } + return "", false +} + func (s *MessageStore) save(nestID string) error { if err := os.MkdirAll(s.dir, 0o755); err != nil { return err