tinyrelaycommit

Commit 688625fe875d

browse files at this commit | history

1diff --git a/internal/community/agent_grant_requests.go b/internal/community/agent_grant_requests.go
2index 8139e84..c3e4521 100644
3--- a/internal/community/agent_grant_requests.go
4+++ b/internal/community/agent_grant_requests.go
5@@ -23,23 +23,30 @@ const agentGrantReasonMax = 500
6
7 type grantRequestReader interface {
8 QueryRowContext(context.Context, string, ...any) *sql.Row
9+ QueryContext(context.Context, string, ...any) (*sql.Rows, error)
10 }
11
12 func grantRequestOpen(ctx context.Context, db grantRequestReader, request event.Event, now int64) error {
13 if expires := event.Expiration(request); expires != 0 && expires <= now {
14 return errors.New("conflict: grant request has expired")
15 }
16- var denied bool
17- err := db.QueryRowContext(ctx, `SELECT EXISTS(SELECT 1 FROM events AS reaction
18- WHERE kind=7 AND pubkey=? AND trim(json_extract(raw,'$.content'))='-' AND EXISTS(
19- SELECT 1 FROM tags WHERE event_id=reaction.id AND name='e' AND value=?))`, event.Tag(request, "p"), request.ID).Scan(&denied)
20+ rows, err := db.QueryContext(ctx, `SELECT json_extract(raw,'$.content') FROM events AS reaction
21+ WHERE kind=7 AND pubkey=? AND (expires=0 OR expires>?) AND EXISTS(
22+ SELECT 1 FROM tags WHERE event_id=reaction.id AND name='e' AND value=?)`, event.Tag(request, "p"), now, request.ID)
23 if err != nil {
24 return err
25 }
26- if denied {
27- return errors.New("conflict: grant request was denied")
28+ defer rows.Close()
29+ for rows.Next() {
30+ var content string
31+ if err := rows.Scan(&content); err != nil {
32+ return err
33+ }
34+ if strings.TrimSpace(content) == "-" {
35+ return errors.New("conflict: grant request was denied")
36+ }
37 }
38- return nil
39+ return rows.Err()
40 }
41
42 type AgentGrantChanges struct {
43@@ -193,6 +200,9 @@ func (s *Service) reviewAgainstGrant(e event.Event, req AgentGrantRequest, befor
44 afterEvent.Tags = grantRequestTags(beforeEvent.Tags, req.Changes)
45 afterEvent.Tags = append(afterEvent.Tags, []string{"grant-request", e.ID}, []string{"grant-base", req.Base}, []string{"e", e.ID, "", "grant-request"})
46 afterEvent.ID, afterEvent.Sig, afterEvent.CreatedAt = "", "", now
47+ if afterEvent.CreatedAt <= beforeEvent.CreatedAt {
48+ afterEvent.CreatedAt = beforeEvent.CreatedAt + 1
49+ }
50 after, err := ParseAgentGrant(afterEvent, now)
51 if err != nil {
52 return AgentGrantReview{}, err
53diff --git a/internal/daemon/grant_approvals_test.go b/internal/daemon/grant_approvals_test.go
54index 113d2ae..ea082c8 100644
55--- a/internal/daemon/grant_approvals_test.go
56+++ b/internal/daemon/grant_approvals_test.go
57@@ -114,7 +114,7 @@ func TestGrantApprovalDenialAndStaleReview(t *testing.T) {
58 t.Fatal(err)
59 }
60 if scenario == "deny" {
61- if err := publishAs(t, tenant, signedEvent(t, testOwnerSecret, 7, now-10, [][]string{{"e", request.ID}, {"p", agent}}, "-")); err != nil {
62+ if err := publishAs(t, tenant, signedEvent(t, testOwnerSecret, 7, now-10, [][]string{{"e", request.ID}, {"p", agent}}, "\n-\t")); err != nil {
63 t.Fatal(err)
64 }
65 } else if err := publishAs(t, tenant, agentGrantEvent(t, agent, now-5, now+3600, []string{"k", "1"})); err != nil {
66@@ -155,3 +155,21 @@ func TestGrantRequestNotificationRequiresReview(t *testing.T) {
67 t.Fatalf("grant request notification: %+v", notices)
68 }
69 }
70+
71+func TestGrantReviewReplacementAdvancesTimestamp(t *testing.T) {
72+ _, tenant := testTenant(t)
73+ now := time.Now().Unix()
74+ agent, _ := event.PublicKey(testAgentSecret)
75+ grant := agentGrantEvent(t, agent, now, now+3600, []string{"k", "9"})
76+ if err := publishAs(t, tenant, grant); err != nil {
77+ t.Fatal(err)
78+ }
79+ request := approvalGrantRequest(t, grant, now)
80+ review, err := tenant.community.ReviewAgentGrantRequest(context.Background(), request, now)
81+ if err != nil {
82+ t.Fatal(err)
83+ }
84+ if review.Unsigned.CreatedAt <= grant.CreatedAt {
85+ t.Fatal("replacement can lose the same-second event ordering tie")
86+ }
87+}

About

ownerc01503e8035f
visibilitypublic
head688625fe875d

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

  • https://012.run/npub1cq2s86qrtadf36eqq3epm38wmhdynrrcwxf84eldk3f94dkv7ttsrulrz5/tinyrelay.git

Refs