policy_test.go raw

   1  package policy
   2  
   3  import (
   4  	"context"
   5  	"encoding/json"
   6  	"os"
   7  	"path/filepath"
   8  	"strings"
   9  	"testing"
  10  	"time"
  11  
  12  	"next.orly.dev/pkg/lol/chk"
  13  	"next.orly.dev/pkg/nostr/interfaces/signer/p8k"
  14  	"next.orly.dev/pkg/nostr/encoders/event"
  15  	"next.orly.dev/pkg/nostr/encoders/hex"
  16  	"next.orly.dev/pkg/nostr/encoders/tag"
  17  )
  18  
  19  // Helper function to create int64 pointer
  20  func int64Ptr(i int64) *int64 {
  21  	return &i
  22  }
  23  
  24  // Helper function to generate a keypair for testing
  25  func generateTestKeypair(t *testing.T) (signer *p8k.Signer, pubkey []byte) {
  26  	signer = p8k.MustNew()
  27  	if err := signer.Generate(); chk.E(err) {
  28  		t.Fatalf("Failed to generate test keypair: %v", err)
  29  	}
  30  	pubkey = signer.Pub()
  31  	return
  32  }
  33  
  34  // Helper function to generate a keypair for benchmarks
  35  func generateTestKeypairB(b *testing.B) (signer *p8k.Signer, pubkey []byte) {
  36  	signer = p8k.MustNew()
  37  	if err := signer.Generate(); chk.E(err) {
  38  		b.Fatalf("Failed to generate test keypair: %v", err)
  39  	}
  40  	pubkey = signer.Pub()
  41  	return
  42  }
  43  
  44  // Helper function to create a real test event with proper signing
  45  func createTestEvent(t *testing.T, signer *p8k.Signer, content string, kind uint16) *event.E {
  46  	ev := event.New()
  47  	ev.CreatedAt = time.Now().Unix()
  48  	ev.Kind = kind
  49  	ev.Content = []byte(content)
  50  	ev.Tags = tag.NewS()
  51  
  52  	// Sign the event properly
  53  	if err := ev.Sign(signer); chk.E(err) {
  54  		t.Fatalf("Failed to sign test event: %v", err)
  55  	}
  56  
  57  	return ev
  58  }
  59  
  60  // Helper function to create a test event with a specific pubkey (for unauthorized tests)
  61  func createTestEventWithPubkey(t *testing.T, signer *p8k.Signer, content string, kind uint16) *event.E {
  62  	ev := event.New()
  63  	ev.CreatedAt = time.Now().Unix()
  64  	ev.Kind = kind
  65  	ev.Content = []byte(content)
  66  	ev.Tags = tag.NewS()
  67  
  68  	// Sign the event properly
  69  	if err := ev.Sign(signer); chk.E(err) {
  70  		t.Fatalf("Failed to sign test event: %v", err)
  71  	}
  72  
  73  	return ev
  74  }
  75  
  76  // Helper function to add p tag with hex-encoded pubkey to event
  77  func addPTag(ev *event.E, pubkey []byte) {
  78  	pTag := tag.NewFromAny("p", hex.Enc(pubkey))
  79  	ev.Tags.Append(pTag)
  80  }
  81  
  82  // Helper function to add other tags to event
  83  func addTag(ev *event.E, key, value string) {
  84  	tagItem := tag.NewFromAny(key, value)
  85  	ev.Tags.Append(tagItem)
  86  }
  87  
  88  func TestNew(t *testing.T) {
  89  	tests := []struct {
  90  		name        string
  91  		policyJSON  []byte
  92  		expectError bool
  93  		expectRules int
  94  	}{
  95  		{
  96  			name:        "empty JSON",
  97  			policyJSON:  []byte("{}"),
  98  			expectError: false,
  99  			expectRules: 0,
 100  		},
 101  		{
 102  			name:        "valid policy JSON",
 103  			policyJSON:  []byte(`{"kind":{"whitelist":[1,3,5]},"rules":{"1":{"description":"test"}}}`),
 104  			expectError: false,
 105  			expectRules: 1,
 106  		},
 107  		{
 108  			name:        "invalid JSON",
 109  			policyJSON:  []byte(`{"invalid": json}`),
 110  			expectError: true,
 111  			expectRules: 0,
 112  		},
 113  		{
 114  			name:        "nil JSON",
 115  			policyJSON:  nil,
 116  			expectError: false,
 117  			expectRules: 0,
 118  		},
 119  	}
 120  
 121  	for _, tt := range tests {
 122  		t.Run(tt.name, func(t *testing.T) {
 123  			policy, err := New(tt.policyJSON)
 124  			if tt.expectError {
 125  				if err == nil {
 126  					t.Errorf("Expected error but got none")
 127  				}
 128  				return
 129  			}
 130  			if err != nil {
 131  				t.Errorf("Unexpected error: %v", err)
 132  				return
 133  			}
 134  			if policy == nil {
 135  				t.Errorf("Expected policy but got nil")
 136  				return
 137  			}
 138  			if len(policy.rules) != tt.expectRules {
 139  				t.Errorf("Expected %d rules, got %d", tt.expectRules, len(policy.rules))
 140  			}
 141  		})
 142  	}
 143  }
 144  
 145  func TestCheckKindsPolicy(t *testing.T) {
 146  	tests := []struct {
 147  		name     string
 148  		policy   *P
 149  		access   string // "read" or "write"
 150  		kind     uint16
 151  		expected bool
 152  	}{
 153  		{
 154  			name: "no whitelist or blacklist - allow (no rules at all)",
 155  			policy: &P{
 156  				Kind:  Kinds{},
 157  				rules: map[int]Rule{}, // No rules defined
 158  			},
 159  			access:   "write",
 160  			kind:     1,
 161  			expected: true, // Should be allowed (no rules = allow all kinds)
 162  		},
 163  		{
 164  			name: "no whitelist or blacklist - deny (has other rules)",
 165  			policy: &P{
 166  				Kind: Kinds{},
 167  				rules: map[int]Rule{
 168  					2: {Description: "Rule for kind 2"},
 169  				},
 170  			},
 171  			access:   "write",
 172  			kind:     1,
 173  			expected: false, // Should be denied (implicit whitelist, no rule for kind 1)
 174  		},
 175  		{
 176  			name: "no whitelist or blacklist - allow (has rule)",
 177  			policy: &P{
 178  				Kind: Kinds{},
 179  				rules: map[int]Rule{
 180  					1: {Description: "Rule for kind 1"},
 181  				},
 182  			},
 183  			access:   "write",
 184  			kind:     1,
 185  			expected: true, // Should be allowed (has rule)
 186  		},
 187  		{
 188  			name: "no whitelist or blacklist - allow (has global rule)",
 189  			policy: &P{
 190  				Kind: Kinds{},
 191  				Global: Rule{
 192  					AccessControl: AccessControl{
 193  						WriteAllow: []string{"test"}, // Global rule exists
 194  					},
 195  				},
 196  				rules: map[int]Rule{}, // No specific rules
 197  			},
 198  			access:   "write",
 199  			kind:     1,
 200  			expected: true, // Should be allowed (global rule exists)
 201  		},
 202  		{
 203  			name: "whitelist - kind allowed",
 204  			policy: &P{
 205  				Kind: Kinds{
 206  					Whitelist: []int{1, 3, 5},
 207  				},
 208  			},
 209  			access:   "write",
 210  			kind:     1,
 211  			expected: true,
 212  		},
 213  		{
 214  			name: "whitelist - kind not allowed",
 215  			policy: &P{
 216  				Kind: Kinds{
 217  					Whitelist: []int{1, 3, 5},
 218  				},
 219  			},
 220  			access:   "write",
 221  			kind:     2,
 222  			expected: false,
 223  		},
 224  		{
 225  			name: "blacklist - kind not blacklisted (no rule)",
 226  			policy: &P{
 227  				Kind: Kinds{
 228  					Blacklist: []int{2, 4, 6},
 229  				},
 230  				rules: map[int]Rule{
 231  					3: {Description: "Rule for kind 3"}, // Has at least one rule
 232  				},
 233  			},
 234  			access:   "write",
 235  			kind:     1,
 236  			expected: false, // Should be denied (not blacklisted but no rule for kind 1)
 237  		},
 238  		{
 239  			name: "blacklist - kind not blacklisted (has rule)",
 240  			policy: &P{
 241  				Kind: Kinds{
 242  					Blacklist: []int{2, 4, 6},
 243  				},
 244  				rules: map[int]Rule{
 245  					1: {Description: "Rule for kind 1"},
 246  				},
 247  			},
 248  			access:   "write",
 249  			kind:     1,
 250  			expected: true, // Should be allowed (not blacklisted and has rule)
 251  		},
 252  		{
 253  			name: "blacklist - kind blacklisted",
 254  			policy: &P{
 255  				Kind: Kinds{
 256  					Blacklist: []int{2, 4, 6},
 257  				},
 258  			},
 259  			access:   "write",
 260  			kind:     2,
 261  			expected: false,
 262  		},
 263  		{
 264  			name: "whitelist overrides blacklist",
 265  			policy: &P{
 266  				Kind: Kinds{
 267  					Whitelist: []int{1, 3, 5},
 268  					Blacklist: []int{1, 2, 3},
 269  				},
 270  			},
 271  			access:   "write",
 272  			kind:     1,
 273  			expected: true,
 274  		},
 275  		// Tests for new permissive flags
 276  		{
 277  			name: "read_allow_permissive - allows read for non-whitelisted kind",
 278  			policy: &P{
 279  				Kind: Kinds{
 280  					Whitelist: []int{1, 3, 5},
 281  				},
 282  				Global: Rule{
 283  					AccessControl: AccessControl{
 284  						ReadAllowPermissive: true,
 285  					},
 286  				},
 287  			},
 288  			access:   "read",
 289  			kind:     2,
 290  			expected: true, // Should be allowed (read permissive overrides whitelist)
 291  		},
 292  		{
 293  			name: "read_allow_permissive - write still blocked for non-whitelisted kind",
 294  			policy: &P{
 295  				Kind: Kinds{
 296  					Whitelist: []int{1, 3, 5},
 297  				},
 298  				Global: Rule{
 299  					AccessControl: AccessControl{
 300  						ReadAllowPermissive: true,
 301  					},
 302  				},
 303  			},
 304  			access:   "write",
 305  			kind:     2,
 306  			expected: false, // Should be denied (only read is permissive)
 307  		},
 308  		{
 309  			name: "write_allow_permissive - allows write for non-whitelisted kind",
 310  			policy: &P{
 311  				Kind: Kinds{
 312  					Whitelist: []int{1, 3, 5},
 313  				},
 314  				Global: Rule{
 315  					AccessControl: AccessControl{
 316  						WriteAllowPermissive: true,
 317  					},
 318  				},
 319  			},
 320  			access:   "write",
 321  			kind:     2,
 322  			expected: true, // Should be allowed (write permissive overrides whitelist)
 323  		},
 324  		{
 325  			name: "write_allow_permissive - read still blocked for non-whitelisted kind",
 326  			policy: &P{
 327  				Kind: Kinds{
 328  					Whitelist: []int{1, 3, 5},
 329  				},
 330  				Global: Rule{
 331  					AccessControl: AccessControl{
 332  						WriteAllowPermissive: true,
 333  					},
 334  				},
 335  			},
 336  			access:   "read",
 337  			kind:     2,
 338  			expected: false, // Should be denied (only write is permissive)
 339  		},
 340  		{
 341  			name: "blacklist - permissive flags do NOT override blacklist",
 342  			policy: &P{
 343  				Kind: Kinds{
 344  					Blacklist: []int{2, 4, 6},
 345  				},
 346  				Global: Rule{
 347  					AccessControl: AccessControl{
 348  						ReadAllowPermissive:  true,
 349  						WriteAllowPermissive: true,
 350  					},
 351  				},
 352  			},
 353  			access:   "write",
 354  			kind:     2,
 355  			expected: false, // Should be denied (blacklist always applies)
 356  		},
 357  	}
 358  
 359  	for _, tt := range tests {
 360  		t.Run(tt.name, func(t *testing.T) {
 361  			result := tt.policy.checkKindsPolicy(tt.access, tt.kind)
 362  			if result != tt.expected {
 363  				t.Errorf("Expected %v, got %v", tt.expected, result)
 364  			}
 365  		})
 366  	}
 367  }
 368  
 369  func TestCheckRulePolicy(t *testing.T) {
 370  	// Generate real keypairs for testing
 371  	eventSigner, eventPubkey := generateTestKeypair(t)
 372  	_, pTagPubkey := generateTestKeypair(t)
 373  	_, unauthorizedPubkey := generateTestKeypair(t)
 374  
 375  	// Create real test event with proper signing
 376  	testEvent := createTestEvent(t, eventSigner, "test content", 1)
 377  	// Add p tag with hex-encoded pubkey
 378  	addPTag(testEvent, pTagPubkey)
 379  	addTag(testEvent, "expiration", "1234567890")
 380  
 381  	tests := []struct {
 382  		name           string
 383  		access         string
 384  		event          *event.E
 385  		rule           Rule
 386  		loggedInPubkey []byte
 387  		expected       bool
 388  	}{
 389  		{
 390  			name:   "write access - no restrictions",
 391  			access: "write",
 392  			event:  testEvent,
 393  			rule: Rule{
 394  				Description: "no restrictions",
 395  			},
 396  			loggedInPubkey: eventPubkey,
 397  			expected:       true,
 398  		},
 399  		{
 400  			name:   "write access - pubkey allowed",
 401  			access: "write",
 402  			event:  testEvent,
 403  			rule: Rule{
 404  				Description: "pubkey allowed",
 405  				AccessControl: AccessControl{
 406  					WriteAllow: []string{hex.Enc(testEvent.Pubkey)},
 407  				},
 408  			},
 409  			loggedInPubkey: eventPubkey,
 410  			expected:       true,
 411  		},
 412  		{
 413  			name:   "write access - pubkey not allowed",
 414  			access: "write",
 415  			event:  testEvent,
 416  			rule: Rule{
 417  				Description: "pubkey not allowed",
 418  				AccessControl: AccessControl{
 419  					WriteAllow: []string{hex.Enc(pTagPubkey)}, // Different pubkey
 420  				},
 421  			},
 422  			loggedInPubkey: eventPubkey,
 423  			expected:       false,
 424  		},
 425  		{
 426  			name:   "size limit - within limit",
 427  			access: "write",
 428  			event:  testEvent,
 429  			rule: Rule{
 430  				Description: "size limit",
 431  				Constraints: Constraints{
 432  					SizeLimit: int64Ptr(10000),
 433  				},
 434  			},
 435  			loggedInPubkey: eventPubkey,
 436  			expected:       true,
 437  		},
 438  		{
 439  			name:   "size limit - exceeds limit",
 440  			access: "write",
 441  			event:  testEvent,
 442  			rule: Rule{
 443  				Description: "size limit exceeded",
 444  				Constraints: Constraints{
 445  					SizeLimit: int64Ptr(10),
 446  				},
 447  			},
 448  			loggedInPubkey: eventPubkey,
 449  			expected:       false,
 450  		},
 451  		{
 452  			name:   "content limit - within limit",
 453  			access: "write",
 454  			event:  testEvent,
 455  			rule: Rule{
 456  				Description: "content limit",
 457  				Constraints: Constraints{
 458  					ContentLimit: int64Ptr(1000),
 459  				},
 460  			},
 461  			loggedInPubkey: eventPubkey,
 462  			expected:       true,
 463  		},
 464  		{
 465  			name:   "content limit - exceeds limit",
 466  			access: "write",
 467  			event:  testEvent,
 468  			rule: Rule{
 469  				Description: "content limit exceeded",
 470  				Constraints: Constraints{
 471  					ContentLimit: int64Ptr(5),
 472  				},
 473  			},
 474  			loggedInPubkey: eventPubkey,
 475  			expected:       false,
 476  		},
 477  		{
 478  			name:   "required tags - has required tag",
 479  			access: "write",
 480  			event:  testEvent,
 481  			rule: Rule{
 482  				Description: "required tags",
 483  				TagValidationConfig: TagValidationConfig{
 484  					MustHaveTags: []string{"p"},
 485  				},
 486  			},
 487  			loggedInPubkey: eventPubkey,
 488  			expected:       true,
 489  		},
 490  		{
 491  			name:   "required tags - missing required tag",
 492  			access: "write",
 493  			event:  testEvent,
 494  			rule: Rule{
 495  				Description: "required tags missing",
 496  				TagValidationConfig: TagValidationConfig{
 497  					MustHaveTags: []string{"e"},
 498  				},
 499  			},
 500  			loggedInPubkey: eventPubkey,
 501  			expected:       false,
 502  		},
 503  		{
 504  			name:   "privileged write - event authored by logged in user (privileged doesn't affect write)",
 505  			access: "write",
 506  			event:  testEvent,
 507  			rule: Rule{
 508  				Description: "privileged event",
 509  				Constraints: Constraints{
 510  					Privileged: true,
 511  				},
 512  			},
 513  			loggedInPubkey: testEvent.Pubkey,
 514  			expected:       true, // Privileged doesn't restrict write, uses default (allow)
 515  		},
 516  		{
 517  			name:   "privileged write - event contains logged in user in p tag (privileged doesn't affect write)",
 518  			access: "write",
 519  			event:  testEvent,
 520  			rule: Rule{
 521  				Description: "privileged event with p tag",
 522  				Constraints: Constraints{
 523  					Privileged: true,
 524  				},
 525  			},
 526  			loggedInPubkey: pTagPubkey,
 527  			expected:       true, // Privileged doesn't restrict write, uses default (allow)
 528  		},
 529  		{
 530  			name:   "privileged write - not authenticated (privileged doesn't affect write)",
 531  			access: "write",
 532  			event:  testEvent,
 533  			rule: Rule{
 534  				Description: "privileged event not authenticated",
 535  				Constraints: Constraints{
 536  					Privileged: true,
 537  				},
 538  			},
 539  			loggedInPubkey: nil,
 540  			expected:       true, // Privileged doesn't restrict write, uses default (allow)
 541  		},
 542  		{
 543  			name:   "privileged write - authenticated but not authorized (privileged doesn't affect write)",
 544  			access: "write",
 545  			event:  testEvent,
 546  			rule: Rule{
 547  				Description: "privileged event unauthorized user",
 548  				Constraints: Constraints{
 549  					Privileged: true,
 550  				},
 551  			},
 552  			loggedInPubkey: unauthorizedPubkey,
 553  			expected:       true, // Privileged doesn't restrict write, uses default (allow)
 554  		},
 555  		{
 556  			name:   "privileged read - event authored by logged in user",
 557  			access: "read",
 558  			event:  testEvent,
 559  			rule: Rule{
 560  				Description: "privileged event read access",
 561  				Constraints: Constraints{
 562  					Privileged: true,
 563  				},
 564  			},
 565  			loggedInPubkey: testEvent.Pubkey,
 566  			expected:       true,
 567  		},
 568  		{
 569  			name:   "privileged read - event contains logged in user in p tag",
 570  			access: "read",
 571  			event:  testEvent,
 572  			rule: Rule{
 573  				Description: "privileged event read access with p tag",
 574  				Constraints: Constraints{
 575  					Privileged: true,
 576  				},
 577  			},
 578  			loggedInPubkey: pTagPubkey,
 579  			expected:       true,
 580  		},
 581  		{
 582  			name:   "privileged read - not authenticated",
 583  			access: "read",
 584  			event:  testEvent,
 585  			rule: Rule{
 586  				Description: "privileged event read access not authenticated",
 587  				Constraints: Constraints{
 588  					Privileged: true,
 589  				},
 590  			},
 591  			loggedInPubkey: nil,
 592  			expected:       false,
 593  		},
 594  		{
 595  			name:   "privileged read - authenticated but not authorized (different pubkey, not in p tags)",
 596  			access: "read",
 597  			event:  testEvent,
 598  			rule: Rule{
 599  				Description: "privileged event read access unauthorized user",
 600  				Constraints: Constraints{
 601  					Privileged: true,
 602  				},
 603  			},
 604  			loggedInPubkey: unauthorizedPubkey,
 605  			expected:       false,
 606  		},
 607  	}
 608  
 609  	for _, tt := range tests {
 610  		t.Run(tt.name, func(t *testing.T) {
 611  			policy := &P{}
 612  			result, err := policy.checkRulePolicy(tt.access, tt.event, tt.rule, tt.loggedInPubkey)
 613  			if err != nil {
 614  				t.Errorf("Unexpected error: %v", err)
 615  				return
 616  			}
 617  			if result != tt.expected {
 618  				t.Errorf("Expected %v, got %v", tt.expected, result)
 619  			}
 620  		})
 621  	}
 622  }
 623  
 624  func TestCheckPolicy(t *testing.T) {
 625  	// Generate real keypair for testing
 626  	eventSigner, eventPubkey := generateTestKeypair(t)
 627  
 628  	// Create real test event with proper signing
 629  	testEvent := createTestEvent(t, eventSigner, "test content", 1)
 630  
 631  	tests := []struct {
 632  		name           string
 633  		access         string
 634  		event          *event.E
 635  		policy         *P
 636  		loggedInPubkey []byte
 637  		ipAddress      string
 638  		expected       bool
 639  		expectError    bool
 640  	}{
 641  		{
 642  			name:   "no policy rules - allow",
 643  			access: "write",
 644  			event:  testEvent,
 645  			policy: &P{
 646  				Kind:  Kinds{},
 647  				rules: map[int]Rule{},
 648  			},
 649  			loggedInPubkey: eventPubkey,
 650  			ipAddress:      "127.0.0.1",
 651  			expected:       true,
 652  			expectError:    false,
 653  		},
 654  		{
 655  			name:   "kinds policy blocks - deny",
 656  			access: "write",
 657  			event:  testEvent,
 658  			policy: &P{
 659  				Kind: Kinds{
 660  					Whitelist: []int{3, 5},
 661  				},
 662  				rules: map[int]Rule{},
 663  			},
 664  			loggedInPubkey: eventPubkey,
 665  			ipAddress:      "127.0.0.1",
 666  			expected:       false,
 667  			expectError:    false,
 668  		},
 669  		{
 670  			name:   "rule blocks - deny",
 671  			access: "write",
 672  			event:  testEvent,
 673  			policy: &P{
 674  				Kind: Kinds{},
 675  				rules: map[int]Rule{
 676  					1: {
 677  						Description: "block test",
 678  						AccessControl: AccessControl{
 679  							WriteDeny: []string{hex.Enc(testEvent.Pubkey)},
 680  						},
 681  					},
 682  				},
 683  			},
 684  			loggedInPubkey: eventPubkey,
 685  			ipAddress:      "127.0.0.1",
 686  			expected:       false,
 687  			expectError:    false,
 688  		},
 689  	}
 690  
 691  	for _, tt := range tests {
 692  		t.Run(tt.name, func(t *testing.T) {
 693  			result, err := tt.policy.CheckPolicy(tt.access, tt.event, tt.loggedInPubkey, tt.ipAddress)
 694  			if tt.expectError {
 695  				if err == nil {
 696  					t.Errorf("Expected error but got none")
 697  				}
 698  				return
 699  			}
 700  			if err != nil {
 701  				t.Errorf("Unexpected error: %v", err)
 702  				return
 703  			}
 704  			if result != tt.expected {
 705  				t.Errorf("Expected %v, got %v", tt.expected, result)
 706  			}
 707  		})
 708  	}
 709  }
 710  
 711  func TestLoadFromFile(t *testing.T) {
 712  	// Create temporary directory
 713  	tempDir := t.TempDir()
 714  	configPath := filepath.Join(tempDir, "policy.json")
 715  
 716  	tests := []struct {
 717  		name        string
 718  		configData  string
 719  		expectError bool
 720  		expectRules int
 721  	}{
 722  		{
 723  			name:        "valid policy file",
 724  			configData:  `{"kind":{"whitelist":[1,3,5]},"rules":{"1":{"description":"test"}}}`,
 725  			expectError: false,
 726  			expectRules: 1,
 727  		},
 728  		{
 729  			name:        "empty policy file",
 730  			configData:  `{}`,
 731  			expectError: false,
 732  			expectRules: 0,
 733  		},
 734  		{
 735  			name:        "invalid JSON",
 736  			configData:  `{"invalid": json}`,
 737  			expectError: true,
 738  			expectRules: 0,
 739  		},
 740  	}
 741  
 742  	for _, tt := range tests {
 743  		t.Run(tt.name, func(t *testing.T) {
 744  			// Write test config file
 745  			if tt.configData != "" {
 746  				err := os.WriteFile(configPath, []byte(tt.configData), 0644)
 747  				if err != nil {
 748  					t.Fatalf("Failed to write test config file: %v", err)
 749  				}
 750  			}
 751  
 752  			policy := &P{}
 753  			err := policy.LoadFromFile(configPath)
 754  			if tt.expectError {
 755  				if err == nil {
 756  					t.Errorf("Expected error but got none")
 757  				}
 758  				return
 759  			}
 760  			if err != nil {
 761  				t.Errorf("Unexpected error: %v", err)
 762  				return
 763  			}
 764  			if len(policy.rules) != tt.expectRules {
 765  				t.Errorf("Expected %d rules, got %d", tt.expectRules, len(policy.rules))
 766  			}
 767  		})
 768  	}
 769  
 770  	// Test file not found
 771  	t.Run("file not found", func(t *testing.T) {
 772  		policy := &P{}
 773  		err := policy.LoadFromFile("/nonexistent/policy.json")
 774  		if err == nil {
 775  			t.Errorf("Expected error for nonexistent file but got none")
 776  		}
 777  	})
 778  }
 779  
 780  func TestPolicyEventSerialization(t *testing.T) {
 781  	// Generate real keypair for testing
 782  	eventSigner, eventPubkey := generateTestKeypair(t)
 783  
 784  	// Create real test event with proper signing
 785  	testEvent := createTestEvent(t, eventSigner, "test content", 1)
 786  
 787  	// Create policy event
 788  	policyEvent := &PolicyEvent{
 789  		E:              testEvent,
 790  		LoggedInPubkey: hex.Enc(eventPubkey),
 791  		IPAddress:      "127.0.0.1",
 792  	}
 793  
 794  	// Test JSON serialization
 795  	jsonData, err := json.Marshal(policyEvent)
 796  	if err != nil {
 797  		t.Fatalf("Failed to marshal policy event: %v", err)
 798  	}
 799  
 800  	// Verify the JSON contains expected fields
 801  	jsonStr := string(jsonData)
 802  	t.Logf("Generated JSON: %s", jsonStr)
 803  
 804  	if !strings.Contains(jsonStr, hex.Enc(eventPubkey)) {
 805  		t.Error("JSON should contain logged_in_pubkey field")
 806  	}
 807  	if !strings.Contains(jsonStr, "127.0.0.1") {
 808  		t.Error("JSON should contain ip_address field")
 809  	}
 810  	if !strings.Contains(jsonStr, hex.Enc(testEvent.ID)) {
 811  		t.Error("JSON should contain event id field (hex encoded)")
 812  	}
 813  
 814  	// Test with nil event
 815  	nilPolicyEvent := &PolicyEvent{
 816  		E:              nil,
 817  		LoggedInPubkey: "test-logged-in-pubkey",
 818  		IPAddress:      "127.0.0.1",
 819  	}
 820  
 821  	jsonData2, err := json.Marshal(nilPolicyEvent)
 822  	if err != nil {
 823  		t.Fatalf("Failed to marshal nil policy event: %v", err)
 824  	}
 825  
 826  	jsonStr2 := string(jsonData2)
 827  	if !strings.Contains(jsonStr2, "test-logged-in-pubkey") {
 828  		t.Error("JSON should contain logged_in_pubkey field even with nil event")
 829  	}
 830  	if !strings.Contains(jsonStr2, "127.0.0.1") {
 831  		t.Error("JSON should contain ip_address field even with nil event")
 832  	}
 833  }
 834  
 835  func TestPolicyResponseSerialization(t *testing.T) {
 836  	// Test JSON serialization
 837  	response := &PolicyResponse{
 838  		ID:     "test-id",
 839  		Action: "accept",
 840  		Msg:    "test message",
 841  	}
 842  
 843  	jsonData, err := json.Marshal(response)
 844  	if err != nil {
 845  		t.Fatalf("Failed to marshal policy response: %v", err)
 846  	}
 847  
 848  	// Test JSON deserialization
 849  	var deserializedResponse PolicyResponse
 850  	err = json.Unmarshal(jsonData, &deserializedResponse)
 851  	if err != nil {
 852  		t.Fatalf("Failed to unmarshal policy response: %v", err)
 853  	}
 854  
 855  	// Verify fields
 856  	if deserializedResponse.ID != response.ID {
 857  		t.Errorf("Expected ID %s, got %s", response.ID, deserializedResponse.ID)
 858  	}
 859  	if deserializedResponse.Action != response.Action {
 860  		t.Errorf("Expected Action %s, got %s", response.Action, deserializedResponse.Action)
 861  	}
 862  	if deserializedResponse.Msg != response.Msg {
 863  		t.Errorf("Expected Msg %s, got %s", response.Msg, deserializedResponse.Msg)
 864  	}
 865  }
 866  
 867  func TestNewWithManager(t *testing.T) {
 868  	ctx := context.Background()
 869  	appName := "test-app"
 870  
 871  	// Test with disabled policy (doesn't require policy.json file)
 872  	t.Run("disabled policy", func(t *testing.T) {
 873  		enabled := false
 874  		policy := NewWithManager(ctx, appName, enabled, "")
 875  
 876  		if policy == nil {
 877  			t.Fatal("Expected policy but got nil")
 878  		}
 879  
 880  		if policy.manager == nil {
 881  			t.Fatal("Expected policy manager but got nil")
 882  		}
 883  
 884  		if policy.manager.IsEnabled() {
 885  			t.Error("Expected policy manager to be disabled")
 886  		}
 887  
 888  		if policy.manager.IsRunning() {
 889  			t.Error("Expected policy manager to not be running")
 890  		}
 891  
 892  		// Verify default policy was set
 893  		if policy.DefaultPolicy != "allow" {
 894  			t.Errorf("Expected default_policy='allow', got '%s'", policy.DefaultPolicy)
 895  		}
 896  
 897  		// Clean up
 898  		policy.manager.Shutdown()
 899  	})
 900  
 901  	// Test with enabled policy and valid config file
 902  	t.Run("enabled policy with valid config", func(t *testing.T) {
 903  		// Create a temporary config directory with a valid policy.json
 904  		tmpDir := t.TempDir()
 905  		configDir := filepath.Join(tmpDir, "test-policy-enabled")
 906  		if err := os.MkdirAll(configDir, 0755); err != nil {
 907  			t.Fatalf("Failed to create config dir: %v", err)
 908  		}
 909  
 910  		// Write a minimal valid policy.json
 911  		policyJSON := `{
 912  			"default_policy": "allow",
 913  			"kind": {
 914  				"whitelist": [1, 3, 4]
 915  			},
 916  			"rules": {
 917  				"1": {
 918  					"description": "Text notes"
 919  				}
 920  			}
 921  		}`
 922  		policyPath := filepath.Join(configDir, "policy.json")
 923  		if err := os.WriteFile(policyPath, []byte(policyJSON), 0644); err != nil {
 924  			t.Fatalf("Failed to write policy.json: %v", err)
 925  		}
 926  
 927  		// Create policy manager manually to use custom config path
 928  		ctx, cancel := context.WithCancel(context.Background())
 929  		defer cancel()
 930  
 931  		manager := &PolicyManager{
 932  			ctx:        ctx,
 933  			cancel:     cancel,
 934  			configDir:  configDir,
 935  			scriptPath: filepath.Join(configDir, "policy.sh"),
 936  			enabled:    true,
 937  			runners:    make(map[string]*ScriptRunner),
 938  		}
 939  
 940  		policy := &P{
 941  			DefaultPolicy: "allow",
 942  			manager:       manager,
 943  		}
 944  
 945  		// Load policy from our test file
 946  		if err := policy.LoadFromFile(policyPath); err != nil {
 947  			t.Fatalf("Failed to load policy: %v", err)
 948  		}
 949  
 950  		if policy.manager == nil {
 951  			t.Fatal("Expected policy manager but got nil")
 952  		}
 953  
 954  		if !policy.manager.IsEnabled() {
 955  			t.Error("Expected policy manager to be enabled")
 956  		}
 957  
 958  		// Verify policy was loaded correctly
 959  		if len(policy.Kind.Whitelist) != 3 {
 960  			t.Errorf("Expected 3 whitelisted kinds, got %d", len(policy.Kind.Whitelist))
 961  		}
 962  
 963  		if policy.DefaultPolicy != "allow" {
 964  			t.Errorf("Expected default_policy='allow', got '%s'", policy.DefaultPolicy)
 965  		}
 966  
 967  		// Clean up
 968  		policy.manager.Shutdown()
 969  	})
 970  }
 971  
 972  func TestPolicyManagerLifecycle(t *testing.T) {
 973  	// Test basic manager initialization without script execution
 974  	ctx, cancel := context.WithCancel(context.Background())
 975  	defer cancel()
 976  
 977  	manager := &PolicyManager{
 978  		ctx:        ctx,
 979  		cancel:     cancel,
 980  		configDir:  "/tmp",
 981  		scriptPath: "/tmp/policy.sh",
 982  		enabled:    true,
 983  		runners:    make(map[string]*ScriptRunner),
 984  	}
 985  
 986  	// Test manager state
 987  	if !manager.IsEnabled() {
 988  		t.Error("Expected policy manager to be enabled")
 989  	}
 990  
 991  	if manager.IsRunning() {
 992  		t.Error("Expected policy manager to not be running initially")
 993  	}
 994  
 995  	// Test getting or creating a runner for a non-existent script
 996  	runner := manager.getOrCreateRunner("/tmp/policy.sh")
 997  	if runner == nil {
 998  		t.Fatal("Expected runner to be created")
 999  	}
1000  
1001  	// Test starting with non-existent script (should fail gracefully)
1002  	err := runner.Start()
1003  	if err == nil {
1004  		t.Error("Expected error when starting script with non-existent file")
1005  	}
1006  
1007  	// Test stopping when not running (should fail gracefully)
1008  	err = runner.Stop()
1009  	if err == nil {
1010  		t.Error("Expected error when stopping script that's not running")
1011  	}
1012  }
1013  
1014  func TestPolicyManagerProcessEvent(t *testing.T) {
1015  	// Test processing event when runner is not running (should fail gracefully)
1016  	ctx, cancel := context.WithCancel(context.Background())
1017  	defer cancel()
1018  
1019  	manager := &PolicyManager{
1020  		ctx:        ctx,
1021  		cancel:     cancel,
1022  		configDir:  "/tmp",
1023  		scriptPath: "/tmp/policy.sh",
1024  		enabled:    true,
1025  		runners:    make(map[string]*ScriptRunner),
1026  	}
1027  
1028  	// Generate real keypair for testing
1029  	eventSigner, eventPubkey := generateTestKeypair(t)
1030  
1031  	// Create real test event with proper signing
1032  	testEvent := createTestEvent(t, eventSigner, "test content", 1)
1033  
1034  	// Create policy event
1035  	policyEvent := &PolicyEvent{
1036  		E:              testEvent,
1037  		LoggedInPubkey: hex.Enc(eventPubkey),
1038  		IPAddress:      "127.0.0.1",
1039  	}
1040  
1041  	// Get or create a runner
1042  	runner := manager.getOrCreateRunner("/tmp/policy.sh")
1043  
1044  	// Process event when not running (should fail gracefully)
1045  	_, err := runner.ProcessEvent(policyEvent)
1046  	if err == nil {
1047  		t.Error("Expected error when processing event with non-running script")
1048  	}
1049  }
1050  
1051  func TestEdgeCasesEmptyPolicy(t *testing.T) {
1052  	policy := &P{}
1053  
1054  	// Generate real keypair for testing
1055  	eventSigner, eventPubkey := generateTestKeypair(t)
1056  
1057  	// Create real test event with proper signing
1058  	testEvent := createTestEvent(t, eventSigner, "test content", 1)
1059  
1060  	// Should allow all events when policy is empty
1061  	allowed, err := policy.CheckPolicy("write", testEvent, eventPubkey, "127.0.0.1")
1062  	if err != nil {
1063  		t.Errorf("Unexpected error: %v", err)
1064  	}
1065  	if !allowed {
1066  		t.Error("Expected event to be allowed with empty policy")
1067  	}
1068  }
1069  
1070  func TestEdgeCasesNilEvent(t *testing.T) {
1071  	policy := &P{}
1072  
1073  	// Should handle nil event gracefully
1074  	allowed, err := policy.CheckPolicy("write", nil, []byte("test-pubkey"), "127.0.0.1")
1075  	if err == nil {
1076  		t.Error("Expected error when event is nil")
1077  	}
1078  	if allowed {
1079  		t.Error("Expected event to be blocked when nil")
1080  	}
1081  
1082  	// Verify the error message
1083  	if err != nil && !strings.Contains(err.Error(), "event cannot be nil") {
1084  		t.Errorf("Expected error message to contain 'event cannot be nil', got: %v", err)
1085  	}
1086  }
1087  
1088  func TestEdgeCasesLargeEvent(t *testing.T) {
1089  	// Create large content
1090  	largeContent := strings.Repeat("a", 100000) // 100KB content
1091  
1092  	policy := &P{
1093  		Kind: Kinds{},
1094  		rules: map[int]Rule{
1095  			1: {
1096  				Description: "size limit test",
1097  				Constraints: Constraints{
1098  					SizeLimit:    int64Ptr(50000), // 50KB limit
1099  					ContentLimit: int64Ptr(10000), // 10KB content limit
1100  				},
1101  			},
1102  		},
1103  	}
1104  
1105  	// Generate real keypair for testing
1106  	eventSigner, eventPubkey := generateTestKeypair(t)
1107  
1108  	// Create real test event with large content
1109  	testEvent := createTestEvent(t, eventSigner, largeContent, 1)
1110  
1111  	// Should block large event
1112  	allowed, err := policy.CheckPolicy("write", testEvent, eventPubkey, "127.0.0.1")
1113  	if err != nil {
1114  		t.Errorf("Unexpected error: %v", err)
1115  	}
1116  	if allowed {
1117  		t.Error("Expected large event to be blocked")
1118  	}
1119  }
1120  
1121  func TestEdgeCasesWhitelistBlacklistConflict(t *testing.T) {
1122  	policy := &P{
1123  		Kind: Kinds{
1124  			Whitelist: []int{1, 3, 5},
1125  			Blacklist: []int{1, 2, 3}, // Overlap with whitelist
1126  		},
1127  	}
1128  
1129  	// Test kind in both whitelist and blacklist - whitelist should win
1130  	allowed := policy.checkKindsPolicy("write", 1)
1131  	if !allowed {
1132  		t.Error("Expected whitelist to override blacklist")
1133  	}
1134  
1135  	// Test kind in blacklist but not whitelist
1136  	allowed = policy.checkKindsPolicy("write", 2)
1137  	if allowed {
1138  		t.Error("Expected kind in blacklist but not whitelist to be blocked")
1139  	}
1140  
1141  	// Test kind in whitelist but not blacklist
1142  	allowed = policy.checkKindsPolicy("write", 5)
1143  	if !allowed {
1144  		t.Error("Expected kind in whitelist to be allowed")
1145  	}
1146  }
1147  
1148  func TestEdgeCasesManagerWithInvalidScript(t *testing.T) {
1149  	// Create temporary directory
1150  	tempDir := t.TempDir()
1151  	scriptPath := filepath.Join(tempDir, "policy.sh")
1152  
1153  	// Create invalid script (not executable, wrong shebang, etc.)
1154  	scriptContent := `invalid script content`
1155  	err := os.WriteFile(scriptPath, []byte(scriptContent), 0644) // Not executable
1156  	if err != nil {
1157  		t.Fatalf("Failed to create invalid script: %v", err)
1158  	}
1159  
1160  	ctx, cancel := context.WithCancel(context.Background())
1161  	defer cancel()
1162  
1163  	manager := &PolicyManager{
1164  		ctx:        ctx,
1165  		cancel:     cancel,
1166  		configDir:  tempDir,
1167  		scriptPath: scriptPath,
1168  		enabled:    true,
1169  		runners:    make(map[string]*ScriptRunner),
1170  	}
1171  
1172  	// Get runner and try to start with invalid script
1173  	runner := manager.getOrCreateRunner(scriptPath)
1174  	err = runner.Start()
1175  	if err == nil {
1176  		t.Error("Expected error when starting invalid script")
1177  	}
1178  }
1179  
1180  func TestEdgeCasesManagerDoubleStart(t *testing.T) {
1181  	// Test double start without actually starting (simpler test)
1182  	ctx, cancel := context.WithCancel(context.Background())
1183  	defer cancel()
1184  
1185  	manager := &PolicyManager{
1186  		ctx:        ctx,
1187  		cancel:     cancel,
1188  		configDir:  "/tmp",
1189  		scriptPath: "/tmp/policy.sh",
1190  		enabled:    true,
1191  		runners:    make(map[string]*ScriptRunner),
1192  	}
1193  
1194  	// Get runner
1195  	runner := manager.getOrCreateRunner("/tmp/policy.sh")
1196  
1197  	// Try to start with non-existent script - should fail
1198  	err := runner.Start()
1199  	if err == nil {
1200  		t.Error("Expected error when starting script with non-existent file")
1201  	}
1202  
1203  	// Try to start again - should still fail
1204  	err = runner.Start()
1205  	if err == nil {
1206  		t.Error("Expected error when starting script twice")
1207  	}
1208  }
1209  
1210  func TestCheckGlobalRulePolicy(t *testing.T) {
1211  	// Generate real keypairs for testing
1212  	eventSigner, _ := generateTestKeypair(t)
1213  	_, loggedInPubkey := generateTestKeypair(t)
1214  
1215  	tests := []struct {
1216  		name           string
1217  		globalRule     Rule
1218  		event          *event.E
1219  		loggedInPubkey []byte
1220  		expected       bool
1221  	}{
1222  		{
1223  			name: "global rule with write allow - submitter allowed",
1224  			globalRule: Rule{
1225  				AccessControl: AccessControl{
1226  					WriteAllow: []string{hex.Enc(loggedInPubkey)}, // Allow the submitter
1227  				},
1228  			},
1229  			event:          createTestEvent(t, eventSigner, "test content", 1),
1230  			loggedInPubkey: loggedInPubkey,
1231  			expected:       true,
1232  		},
1233  		{
1234  			name: "global rule with write deny - submitter denied",
1235  			globalRule: Rule{
1236  				AccessControl: AccessControl{
1237  					WriteDeny: []string{hex.Enc(loggedInPubkey)}, // Deny the submitter
1238  				},
1239  			},
1240  			event:          createTestEvent(t, eventSigner, "test content", 1),
1241  			loggedInPubkey: loggedInPubkey,
1242  			expected:       false,
1243  		},
1244  		{
1245  			name: "global rule with size limit - event too large",
1246  			globalRule: Rule{
1247  				Constraints: Constraints{
1248  					SizeLimit: func() *int64 { v := int64(10); return &v }(),
1249  				},
1250  			},
1251  			event:          createTestEvent(t, eventSigner, "this is a very long content that exceeds the size limit", 1),
1252  			loggedInPubkey: loggedInPubkey,
1253  			expected:       false,
1254  		},
1255  		{
1256  			name: "global rule with max age of event - event too old",
1257  			globalRule: Rule{
1258  				Constraints: Constraints{
1259  					MaxAgeOfEvent: func() *int64 { v := int64(3600); return &v }(), // 1 hour
1260  				},
1261  			},
1262  			event: func() *event.E {
1263  				ev := createTestEvent(t, eventSigner, "test content", 1)
1264  				ev.CreatedAt = time.Now().Unix() - 7200 // 2 hours ago
1265  				return ev
1266  			}(),
1267  			loggedInPubkey: loggedInPubkey,
1268  			expected:       false,
1269  		},
1270  		{
1271  			name: "global rule with max age event in future - event too far in future",
1272  			globalRule: Rule{
1273  				Constraints: Constraints{
1274  					MaxAgeEventInFuture: func() *int64 { v := int64(3600); return &v }(), // 1 hour
1275  				},
1276  			},
1277  			event: func() *event.E {
1278  				ev := createTestEvent(t, eventSigner, "test content", 1)
1279  				ev.CreatedAt = time.Now().Unix() + 7200 // 2 hours in future
1280  				return ev
1281  			}(),
1282  			loggedInPubkey: loggedInPubkey,
1283  			expected:       false,
1284  		},
1285  	}
1286  
1287  	for _, tt := range tests {
1288  		t.Run(tt.name, func(t *testing.T) {
1289  			policy := &P{
1290  				Global: tt.globalRule,
1291  			}
1292  
1293  			result := policy.checkGlobalRulePolicy("write", tt.event, tt.loggedInPubkey)
1294  			if result != tt.expected {
1295  				t.Errorf("Expected %v, got %v", tt.expected, result)
1296  			}
1297  		})
1298  	}
1299  }
1300  
1301  func TestCheckPolicyWithGlobalRule(t *testing.T) {
1302  	// Generate real keypairs for testing
1303  	eventSigner, eventPubkey := generateTestKeypair(t)
1304  	_, loggedInPubkey := generateTestKeypair(t)
1305  
1306  	// Test that global rule is applied first
1307  	policy := &P{
1308  		Global: Rule{
1309  			AccessControl: AccessControl{
1310  				WriteDeny: []string{hex.Enc(eventPubkey)}, // Deny event pubkey globally
1311  			},
1312  		},
1313  		Kind: Kinds{
1314  			Whitelist: []int{1}, // Allow kind 1
1315  		},
1316  		rules: map[int]Rule{
1317  			1: {
1318  				AccessControl: AccessControl{
1319  					WriteAllow: []string{hex.Enc(eventPubkey)}, // Allow event pubkey for kind 1
1320  				},
1321  			},
1322  		},
1323  	}
1324  
1325  	event := createTestEvent(t, eventSigner, "test content", 1)
1326  
1327  	// Global rule should deny this event even though kind-specific rule would allow it
1328  	allowed, err := policy.CheckPolicy("write", event, loggedInPubkey, "127.0.0.1")
1329  	if err != nil {
1330  		t.Fatalf("CheckPolicy failed: %v", err)
1331  	}
1332  
1333  	if allowed {
1334  		t.Error("Expected event to be denied by global rule, but it was allowed")
1335  	}
1336  }
1337  
1338  func TestMaxAgeChecks(t *testing.T) {
1339  	// Generate real keypairs for testing
1340  	eventSigner, _ := generateTestKeypair(t)
1341  	_, loggedInPubkey := generateTestKeypair(t)
1342  
1343  	tests := []struct {
1344  		name           string
1345  		rule           Rule
1346  		event          *event.E
1347  		loggedInPubkey []byte
1348  		expected       bool
1349  	}{
1350  		{
1351  			name: "max age of event - event within allowed age",
1352  			rule: Rule{
1353  				Constraints: Constraints{
1354  					MaxAgeOfEvent: func() *int64 { v := int64(3600); return &v }(), // 1 hour
1355  				},
1356  			},
1357  			event: func() *event.E {
1358  				ev := createTestEvent(t, eventSigner, "test content", 1)
1359  				ev.CreatedAt = time.Now().Unix() - 1800 // 30 minutes ago
1360  				return ev
1361  			}(),
1362  			loggedInPubkey: loggedInPubkey,
1363  			expected:       true,
1364  		},
1365  		{
1366  			name: "max age of event - event too old",
1367  			rule: Rule{
1368  				Constraints: Constraints{
1369  					MaxAgeOfEvent: func() *int64 { v := int64(3600); return &v }(), // 1 hour
1370  				},
1371  			},
1372  			event: func() *event.E {
1373  				ev := createTestEvent(t, eventSigner, "test content", 1)
1374  				ev.CreatedAt = time.Now().Unix() - 7200 // 2 hours ago
1375  				return ev
1376  			}(),
1377  			loggedInPubkey: loggedInPubkey,
1378  			expected:       false,
1379  		},
1380  		{
1381  			name: "max age event in future - event within allowed future time",
1382  			rule: Rule{
1383  				Constraints: Constraints{
1384  					MaxAgeEventInFuture: func() *int64 { v := int64(3600); return &v }(), // 1 hour
1385  				},
1386  			},
1387  			event: func() *event.E {
1388  				ev := createTestEvent(t, eventSigner, "test content", 1)
1389  				ev.CreatedAt = time.Now().Unix() + 1800 // 30 minutes in future
1390  				return ev
1391  			}(),
1392  			loggedInPubkey: loggedInPubkey,
1393  			expected:       true,
1394  		},
1395  		{
1396  			name: "max age event in future - event too far in future",
1397  			rule: Rule{
1398  				Constraints: Constraints{
1399  					MaxAgeEventInFuture: func() *int64 { v := int64(3600); return &v }(), // 1 hour
1400  				},
1401  			},
1402  			event: func() *event.E {
1403  				ev := createTestEvent(t, eventSigner, "test content", 1)
1404  				ev.CreatedAt = time.Now().Unix() + 7200 // 2 hours in future
1405  				return ev
1406  			}(),
1407  			loggedInPubkey: loggedInPubkey,
1408  			expected:       false,
1409  		},
1410  		{
1411  			name: "both age checks - event within both limits",
1412  			rule: Rule{
1413  				Constraints: Constraints{
1414  					MaxAgeOfEvent:       func() *int64 { v := int64(3600); return &v }(), // 1 hour
1415  					MaxAgeEventInFuture: func() *int64 { v := int64(1800); return &v }(), // 30 minutes
1416  				},
1417  			},
1418  			event: func() *event.E {
1419  				ev := createTestEvent(t, eventSigner, "test content", 1)
1420  				ev.CreatedAt = time.Now().Unix() + 900 // 15 minutes in future
1421  				return ev
1422  			}(),
1423  			loggedInPubkey: loggedInPubkey,
1424  			expected:       true,
1425  		},
1426  	}
1427  
1428  	for _, tt := range tests {
1429  		t.Run(tt.name, func(t *testing.T) {
1430  			policy := &P{}
1431  
1432  			allowed, err := policy.checkRulePolicy("write", tt.event, tt.rule, tt.loggedInPubkey)
1433  			if err != nil {
1434  				t.Fatalf("checkRulePolicy failed: %v", err)
1435  			}
1436  
1437  			if allowed != tt.expected {
1438  				t.Errorf("Expected %v, got %v", tt.expected, allowed)
1439  			}
1440  		})
1441  	}
1442  }
1443  
1444  func TestScriptPolicyDisabledFallsBackToDefault(t *testing.T) {
1445  	// Generate real keypair for testing
1446  	eventSigner, eventPubkey := generateTestKeypair(t)
1447  
1448  	// Create a policy with a script rule but policy is disabled, default policy is "allow"
1449  	policy := &P{
1450  		DefaultPolicy: "allow",
1451  		rules: map[int]Rule{
1452  			1: {
1453  				Description: "script rule",
1454  				Script:      "policy.sh",
1455  			},
1456  		},
1457  		manager: &PolicyManager{
1458  			enabled: false, // Policy is disabled
1459  			runners: make(map[string]*ScriptRunner),
1460  		},
1461  	}
1462  
1463  	// Create real test event with proper signing
1464  	testEvent := createTestEvent(t, eventSigner, "test content", 1)
1465  
1466  	// Should allow the event when policy is disabled (falls back to default "allow")
1467  	allowed, err := policy.CheckPolicy("write", testEvent, eventPubkey, "127.0.0.1")
1468  	if err != nil {
1469  		t.Errorf("Unexpected error: %v", err)
1470  	}
1471  	if !allowed {
1472  		t.Error("Expected event to be allowed when policy is disabled (should fall back to default policy 'allow')")
1473  	}
1474  
1475  	// Test with default policy "deny"
1476  	policy.DefaultPolicy = "deny"
1477  	allowed2, err2 := policy.CheckPolicy("write", testEvent, eventPubkey, "127.0.0.1")
1478  	if err2 != nil {
1479  		t.Errorf("Unexpected error: %v", err2)
1480  	}
1481  	if allowed2 {
1482  		t.Error("Expected event to be denied when policy is disabled and default policy is 'deny'")
1483  	}
1484  }
1485  
1486  func TestDefaultPolicyAllow(t *testing.T) {
1487  	// Generate real keypair for testing
1488  	eventSigner, eventPubkey := generateTestKeypair(t)
1489  
1490  	// Test default policy "allow" behavior
1491  	policy := &P{
1492  		DefaultPolicy: "allow",
1493  		Kind:          Kinds{},
1494  		rules:         map[int]Rule{}, // No specific rules
1495  	}
1496  
1497  	// Create real test event with proper signing
1498  	testEvent := createTestEvent(t, eventSigner, "test content", 1)
1499  
1500  	// Should allow the event with default policy "allow"
1501  	allowed, err := policy.CheckPolicy("write", testEvent, eventPubkey, "127.0.0.1")
1502  	if err != nil {
1503  		t.Errorf("Unexpected error: %v", err)
1504  	}
1505  	if !allowed {
1506  		t.Error("Expected event to be allowed with default_policy 'allow'")
1507  	}
1508  }
1509  
1510  func TestDefaultPolicyDeny(t *testing.T) {
1511  	// Generate real keypair for testing
1512  	eventSigner, eventPubkey := generateTestKeypair(t)
1513  
1514  	// Test default policy "deny" behavior
1515  	policy := &P{
1516  		DefaultPolicy: "deny",
1517  		Kind:          Kinds{},
1518  		rules:         map[int]Rule{}, // No specific rules
1519  	}
1520  
1521  	// Create real test event with proper signing
1522  	testEvent := createTestEvent(t, eventSigner, "test content", 1)
1523  
1524  	// Should deny the event with default policy "deny"
1525  	allowed, err := policy.CheckPolicy("write", testEvent, eventPubkey, "127.0.0.1")
1526  	if err != nil {
1527  		t.Errorf("Unexpected error: %v", err)
1528  	}
1529  	if allowed {
1530  		t.Error("Expected event to be denied with default_policy 'deny'")
1531  	}
1532  }
1533  
1534  func TestDefaultPolicyEmpty(t *testing.T) {
1535  	// Generate real keypair for testing
1536  	eventSigner, eventPubkey := generateTestKeypair(t)
1537  
1538  	// Test empty default policy (should default to "allow")
1539  	policy := &P{
1540  		DefaultPolicy: "",
1541  		Kind:          Kinds{},
1542  		rules:         map[int]Rule{}, // No specific rules
1543  	}
1544  
1545  	// Create real test event with proper signing
1546  	testEvent := createTestEvent(t, eventSigner, "test content", 1)
1547  
1548  	// Should allow the event with empty default policy (defaults to "allow")
1549  	allowed, err := policy.CheckPolicy("write", testEvent, eventPubkey, "127.0.0.1")
1550  	if err != nil {
1551  		t.Errorf("Unexpected error: %v", err)
1552  	}
1553  	if !allowed {
1554  		t.Error("Expected event to be allowed with empty default_policy (should default to 'allow')")
1555  	}
1556  }
1557  
1558  func TestDefaultPolicyInvalid(t *testing.T) {
1559  	// Generate real keypair for testing
1560  	eventSigner, eventPubkey := generateTestKeypair(t)
1561  
1562  	// Test invalid default policy (should default to "allow")
1563  	policy := &P{
1564  		DefaultPolicy: "invalid",
1565  		Kind:          Kinds{},
1566  		rules:         map[int]Rule{}, // No specific rules
1567  	}
1568  
1569  	// Create real test event with proper signing
1570  	testEvent := createTestEvent(t, eventSigner, "test content", 1)
1571  
1572  	// Should allow the event with invalid default policy (defaults to "allow")
1573  	allowed, err := policy.CheckPolicy("write", testEvent, eventPubkey, "127.0.0.1")
1574  	if err != nil {
1575  		t.Errorf("Unexpected error: %v", err)
1576  	}
1577  	if !allowed {
1578  		t.Error("Expected event to be allowed with invalid default_policy (should default to 'allow')")
1579  	}
1580  }
1581  
1582  func TestDefaultPolicyWithSpecificRule(t *testing.T) {
1583  	// Generate real keypair for testing
1584  	eventSigner, eventPubkey := generateTestKeypair(t)
1585  
1586  	// Test that specific rules override default policy
1587  	policy := &P{
1588  		DefaultPolicy: "deny", // Default is deny
1589  		Kind:          Kinds{},
1590  		rules: map[int]Rule{
1591  			1: {
1592  				Description: "allow kind 1",
1593  				AccessControl: AccessControl{
1594  					WriteAllow: []string{}, // Allow all for kind 1
1595  				},
1596  			},
1597  		},
1598  	}
1599  
1600  	// Create real test event with proper signing for kind 1 (has specific rule)
1601  	testEvent := createTestEvent(t, eventSigner, "test content", 1)
1602  
1603  	// Should allow the event because specific rule allows it, despite default policy being "deny"
1604  	allowed, err := policy.CheckPolicy("write", testEvent, eventPubkey, "127.0.0.1")
1605  	if err != nil {
1606  		t.Errorf("Unexpected error: %v", err)
1607  	}
1608  	if !allowed {
1609  		t.Error("Expected event to be allowed by specific rule, despite default_policy 'deny'")
1610  	}
1611  
1612  	// Create real test event with proper signing for kind 2 (no specific rule exists)
1613  	testEvent2 := createTestEvent(t, eventSigner, "test content", 2)
1614  
1615  	// Should deny the event because no specific rule and default policy is "deny"
1616  	allowed2, err2 := policy.CheckPolicy("write", testEvent2, eventPubkey, "127.0.0.1")
1617  	if err2 != nil {
1618  		t.Errorf("Unexpected error: %v", err2)
1619  	}
1620  	if allowed2 {
1621  		t.Error("Expected event to be denied with default_policy 'deny' for kind without specific rule")
1622  	}
1623  }
1624  
1625  func TestNewPolicyDefaultsToAllow(t *testing.T) {
1626  	// Test that New() function sets default policy to "allow"
1627  	policy, err := New([]byte(`{}`))
1628  	if err != nil {
1629  		t.Fatalf("Failed to create policy: %v", err)
1630  	}
1631  
1632  	if policy.DefaultPolicy != "allow" {
1633  		t.Errorf("Expected default policy to be 'allow', got '%s'", policy.DefaultPolicy)
1634  	}
1635  }
1636  
1637  func TestNewPolicyWithDefaultPolicyJSON(t *testing.T) {
1638  	// Test loading default policy from JSON
1639  	jsonConfig := `{"default_policy": "deny"}`
1640  	policy, err := New([]byte(jsonConfig))
1641  	if err != nil {
1642  		t.Fatalf("Failed to create policy: %v", err)
1643  	}
1644  
1645  	if policy.DefaultPolicy != "deny" {
1646  		t.Errorf("Expected default policy to be 'deny', got '%s'", policy.DefaultPolicy)
1647  	}
1648  }
1649  
1650  func TestScriptProcessingDisabledFallsBackToDefault(t *testing.T) {
1651  	// Generate real keypair for testing
1652  	eventSigner, eventPubkey := generateTestKeypair(t)
1653  
1654  	// Test that when policy is disabled, it falls back to default policy
1655  	policy := &P{
1656  		DefaultPolicy: "allow",
1657  		rules: map[int]Rule{
1658  			1: {
1659  				Description: "script rule",
1660  				Script:      "policy.sh",
1661  			},
1662  		},
1663  		manager: &PolicyManager{
1664  			enabled: false, // Policy is disabled
1665  			runners: make(map[string]*ScriptRunner),
1666  		},
1667  	}
1668  
1669  	// Create real test event with proper signing
1670  	testEvent := createTestEvent(t, eventSigner, "test content", 1)
1671  
1672  	// Should allow the event when policy is disabled (falls back to default "allow")
1673  	allowed, err := policy.checkScriptPolicy("write", testEvent, "policy.sh", eventPubkey, "127.0.0.1")
1674  	if err != nil {
1675  		t.Errorf("Unexpected error: %v", err)
1676  	}
1677  	if !allowed {
1678  		t.Error("Expected event to be allowed when policy is disabled (should fall back to default policy 'allow')")
1679  	}
1680  
1681  	// Test with default policy "deny"
1682  	policy.DefaultPolicy = "deny"
1683  	allowed2, err2 := policy.checkScriptPolicy("write", testEvent, "policy.sh", eventPubkey, "127.0.0.1")
1684  	if err2 != nil {
1685  		t.Errorf("Unexpected error: %v", err2)
1686  	}
1687  	if allowed2 {
1688  		t.Error("Expected event to be denied when policy is disabled and default policy is 'deny'")
1689  	}
1690  }
1691  
1692  func TestDefaultPolicyLogicWithRules(t *testing.T) {
1693  	// Generate real keypairs for testing
1694  	testSigner, _ := generateTestKeypair(t)
1695  	_, deniedPubkey := generateTestKeypair(t)  // Only need pubkey for denied user
1696  	_, loggedInPubkey := generateTestKeypair(t)
1697  
1698  	// Test that default policy logic works correctly with rules
1699  
1700  	// Test 1: default_policy "deny" - should only allow if rule explicitly allows
1701  	policy1 := &P{
1702  		DefaultPolicy: "deny",
1703  		Kind: Kinds{
1704  			Whitelist: []int{1, 2, 3}, // Allow kinds 1, 2, 3
1705  		},
1706  		rules: map[int]Rule{
1707  			1: {
1708  				Description: "allow all for kind 1",
1709  				AccessControl: AccessControl{
1710  					WriteAllow: []string{}, // Empty means allow all
1711  				},
1712  			},
1713  			2: {
1714  				Description: "deny specific pubkey for kind 2",
1715  				AccessControl: AccessControl{
1716  					WriteDeny: []string{hex.Enc(deniedPubkey)},
1717  				},
1718  			},
1719  			// No rule for kind 3
1720  		},
1721  	}
1722  
1723  	// Kind 1: has rule that allows all - should be allowed
1724  	event1 := createTestEvent(t, testSigner, "content", 1)
1725  	allowed1, err1 := policy1.CheckPolicy("write", event1, loggedInPubkey, "127.0.0.1")
1726  	if err1 != nil {
1727  		t.Errorf("Unexpected error for kind 1: %v", err1)
1728  	}
1729  	if !allowed1 {
1730  		t.Error("Expected kind 1 to be allowed (rule allows all)")
1731  	}
1732  
1733  	// Kind 2: has rule that denies specific pubkey - should be allowed for other pubkeys
1734  	event2 := createTestEvent(t, testSigner, "content", 2)
1735  	allowed2, err2 := policy1.CheckPolicy("write", event2, loggedInPubkey, "127.0.0.1")
1736  	if err2 != nil {
1737  		t.Errorf("Unexpected error for kind 2: %v", err2)
1738  	}
1739  	if !allowed2 {
1740  		t.Error("Expected kind 2 to be allowed for non-denied pubkey")
1741  	}
1742  
1743  	// Kind 2: submitter in deny list should be denied
1744  	event2Denied := createTestEvent(t, testSigner, "content", 2)  // Event can be from anyone
1745  	allowed2Denied, err2Denied := policy1.CheckPolicy("write", event2Denied, deniedPubkey, "127.0.0.1")  // But submitted by denied user
1746  	if err2Denied != nil {
1747  		t.Errorf("Unexpected error for kind 2 denied: %v", err2Denied)
1748  	}
1749  	if allowed2Denied {
1750  		t.Error("Expected kind 2 to be denied when submitter is in deny list")
1751  	}
1752  
1753  	// Kind 3: whitelisted but no rule - should follow default policy (deny)
1754  	event3 := createTestEvent(t, testSigner, "content", 3)
1755  	allowed3, err3 := policy1.CheckPolicy("write", event3, loggedInPubkey, "127.0.0.1")
1756  	if err3 != nil {
1757  		t.Errorf("Unexpected error for kind 3: %v", err3)
1758  	}
1759  	if allowed3 {
1760  		t.Error("Expected kind 3 to be denied (no rule, default policy is deny)")
1761  	}
1762  
1763  	// Test 2: default_policy "allow" - should allow unless rule explicitly denies
1764  	policy2 := &P{
1765  		DefaultPolicy: "allow",
1766  		Kind: Kinds{
1767  			Whitelist: []int{1, 2, 3}, // Allow kinds 1, 2, 3
1768  		},
1769  		rules: map[int]Rule{
1770  			1: {
1771  				Description: "deny specific pubkey for kind 1",
1772  				AccessControl: AccessControl{
1773  					WriteDeny: []string{hex.Enc(deniedPubkey)},
1774  				},
1775  			},
1776  			// No rules for kind 2, 3
1777  		},
1778  	}
1779  
1780  	// Kind 1: has rule that denies specific pubkey - should be allowed for other pubkeys
1781  	event1Allow := createTestEvent(t, testSigner, "content", 1)
1782  	allowed1Allow, err1Allow := policy2.CheckPolicy("write", event1Allow, loggedInPubkey, "127.0.0.1")
1783  	if err1Allow != nil {
1784  		t.Errorf("Unexpected error for kind 1 allow: %v", err1Allow)
1785  	}
1786  	if !allowed1Allow {
1787  		t.Error("Expected kind 1 to be allowed for non-denied pubkey")
1788  	}
1789  
1790  	// Kind 1: denied pubkey should be denied when they try to submit
1791  	event1Deny := createTestEvent(t, testSigner, "content", 1)  // Event can be authored by anyone
1792  	allowed1Deny, err1Deny := policy2.CheckPolicy("write", event1Deny, deniedPubkey, "127.0.0.1")  // But denied user cannot submit
1793  	if err1Deny != nil {
1794  		t.Errorf("Unexpected error for kind 1 deny: %v", err1Deny)
1795  	}
1796  	if allowed1Deny {
1797  		t.Error("Expected kind 1 to be denied for denied pubkey")
1798  	}
1799  
1800  	// Kind 2: whitelisted but no rule - should follow default policy (allow)
1801  	event2Allow := createTestEvent(t, testSigner, "content", 2)
1802  	allowed2Allow, err2Allow := policy2.CheckPolicy("write", event2Allow, loggedInPubkey, "127.0.0.1")
1803  	if err2Allow != nil {
1804  		t.Errorf("Unexpected error for kind 2 allow: %v", err2Allow)
1805  	}
1806  	if !allowed2Allow {
1807  		t.Error("Expected kind 2 to be allowed (no rule, default policy is allow)")
1808  	}
1809  }
1810  
1811  func TestRuleScriptLoading(t *testing.T) {
1812  	// This test validates that a policy script loads for a specific Rule
1813  	// and properly processes events
1814  
1815  	// Create temporary directory for test files
1816  	tempDir := t.TempDir()
1817  	scriptPath := filepath.Join(tempDir, "test-rule-script.sh")
1818  
1819  	// Create a test script that accepts events with "allowed" in content
1820  	scriptContent := `#!/bin/bash
1821  while IFS= read -r line; do
1822      if echo "$line" | grep -q 'allowed'; then
1823          echo '{"action":"accept","msg":"Content approved"}'
1824      else
1825          echo '{"action":"reject","msg":"Content not allowed"}'
1826      fi
1827  done
1828  `
1829  	err := os.WriteFile(scriptPath, []byte(scriptContent), 0755)
1830  	if err != nil {
1831  		t.Fatalf("Failed to create test script: %v", err)
1832  	}
1833  
1834  	// Create policy manager with script support
1835  	ctx, cancel := context.WithCancel(context.Background())
1836  	defer cancel()
1837  
1838  	manager := &PolicyManager{
1839  		ctx:        ctx,
1840  		cancel:     cancel,
1841  		configDir:  tempDir,
1842  		scriptPath: filepath.Join(tempDir, "default-policy.sh"), // Different from rule script
1843  		enabled:    true,
1844  		runners:    make(map[string]*ScriptRunner),
1845  	}
1846  
1847  	// Create policy with a rule that uses the script
1848  	policy := &P{
1849  		DefaultPolicy: "deny",
1850  		manager:       manager,
1851  		rules: map[int]Rule{
1852  			4678: {
1853  				Description: "Test rule with custom script",
1854  				Script:      scriptPath, // Rule-specific script path
1855  			},
1856  		},
1857  	}
1858  
1859  	// Generate test keypairs
1860  	eventSigner, eventPubkey := generateTestKeypair(t)
1861  
1862  	// Pre-start the script before running tests
1863  	runner := manager.getOrCreateRunner(scriptPath)
1864  	err = runner.Start()
1865  	if err != nil {
1866  		t.Fatalf("Failed to start script: %v", err)
1867  	}
1868  
1869  	// Wait for script to be ready
1870  	time.Sleep(200 * time.Millisecond)
1871  
1872  	if !runner.IsRunning() {
1873  		t.Fatal("Script should be running after Start()")
1874  	}
1875  
1876  	// Test sending a warmup event to ensure script is responsive
1877  	signer := p8k.MustNew()
1878  	signer.Generate()
1879  	warmupEv := event.New()
1880  	warmupEv.CreatedAt = time.Now().Unix()
1881  	warmupEv.Kind = 4678
1882  	warmupEv.Content = []byte("warmup")
1883  	warmupEv.Tags = tag.NewS()
1884  	warmupEv.Sign(signer)
1885  
1886  	warmupEvent := &PolicyEvent{
1887  		E:         warmupEv,
1888  		IPAddress: "127.0.0.1",
1889  	}
1890  
1891  	// Send warmup event to verify script is responding
1892  	_, err = runner.ProcessEvent(warmupEvent)
1893  	if err != nil {
1894  		t.Fatalf("Script not responding to warmup event: %v", err)
1895  	}
1896  
1897  	t.Log("Script is ready and responding")
1898  
1899  	// Test 1: Event with "allowed" content should be accepted
1900  	t.Run("script_accepts_allowed_content", func(t *testing.T) {
1901  		testEvent := createTestEvent(t, eventSigner, "this is allowed content", 4678)
1902  
1903  		allowed, err := policy.CheckPolicy("write", testEvent, eventPubkey, "127.0.0.1")
1904  		if err != nil {
1905  			t.Logf("Policy check failed: %v", err)
1906  			// Check if script exists
1907  			if _, statErr := os.Stat(scriptPath); statErr != nil {
1908  				t.Errorf("Script file error: %v", statErr)
1909  			}
1910  			t.Fatalf("Unexpected error during policy check: %v", err)
1911  		}
1912  		if !allowed {
1913  			t.Error("Expected event with 'allowed' content to be accepted by script")
1914  			t.Logf("Event content: %s", string(testEvent.Content))
1915  		}
1916  
1917  		// Verify the script runner was created and is running
1918  		manager.mutex.RLock()
1919  		runner, exists := manager.runners[scriptPath]
1920  		manager.mutex.RUnlock()
1921  
1922  		if !exists {
1923  			t.Fatal("Expected script runner to be created for rule script path")
1924  		}
1925  		if !runner.IsRunning() {
1926  			t.Error("Expected script runner to be running after processing event")
1927  		}
1928  	})
1929  
1930  	// Test 2: Event without "allowed" content should be rejected
1931  	t.Run("script_rejects_disallowed_content", func(t *testing.T) {
1932  		testEvent := createTestEvent(t, eventSigner, "this is not permitted", 4678)
1933  
1934  		allowed, err := policy.CheckPolicy("write", testEvent, eventPubkey, "127.0.0.1")
1935  		if err != nil {
1936  			t.Errorf("Unexpected error: %v", err)
1937  		}
1938  		if allowed {
1939  			t.Error("Expected event without 'allowed' content to be rejected by script")
1940  		}
1941  	})
1942  
1943  	// Test 3: Verify script path is correct (rule-specific, not default)
1944  	t.Run("script_path_is_rule_specific", func(t *testing.T) {
1945  		manager.mutex.RLock()
1946  		runner, exists := manager.runners[scriptPath]
1947  		_, defaultExists := manager.runners[manager.scriptPath]
1948  		manager.mutex.RUnlock()
1949  
1950  		if !exists {
1951  			t.Fatal("Expected rule-specific script runner to exist")
1952  		}
1953  		if defaultExists {
1954  			t.Error("Default script runner should not be created when only rule-specific scripts are used")
1955  		}
1956  
1957  		// Verify the runner is using the correct script path
1958  		if runner.scriptPath != scriptPath {
1959  			t.Errorf("Expected runner to use script path %s, got %s", scriptPath, runner.scriptPath)
1960  		}
1961  	})
1962  
1963  	// Test 4: Multiple events should use the same script instance
1964  	t.Run("script_reused_for_multiple_events", func(t *testing.T) {
1965  		// Get initial runner
1966  		manager.mutex.RLock()
1967  		initialRunner, _ := manager.runners[scriptPath]
1968  		initialRunnerCount := len(manager.runners)
1969  		manager.mutex.RUnlock()
1970  
1971  		// Process multiple events
1972  		for i := 0; i < 5; i++ {
1973  			content := "this is allowed message " + string(rune('0'+i))
1974  			testEvent := createTestEvent(t, eventSigner, content, 4678)
1975  			_, err := policy.CheckPolicy("write", testEvent, eventPubkey, "127.0.0.1")
1976  			if err != nil {
1977  				t.Errorf("Unexpected error on event %d: %v", i, err)
1978  			}
1979  		}
1980  
1981  		// Verify same runner is used
1982  		manager.mutex.RLock()
1983  		currentRunner, _ := manager.runners[scriptPath]
1984  		currentRunnerCount := len(manager.runners)
1985  		manager.mutex.RUnlock()
1986  
1987  		if currentRunner != initialRunner {
1988  			t.Error("Expected same runner instance to be reused for multiple events")
1989  		}
1990  		if currentRunnerCount != initialRunnerCount {
1991  			t.Errorf("Expected runner count to stay at %d, got %d", initialRunnerCount, currentRunnerCount)
1992  		}
1993  	})
1994  
1995  	// Test 5: Different kind without script should use default policy
1996  	t.Run("different_kind_uses_default_policy", func(t *testing.T) {
1997  		testEvent := createTestEvent(t, eventSigner, "any content", 1) // Kind 1 has no rule
1998  
1999  		allowed, err := policy.CheckPolicy("write", testEvent, eventPubkey, "127.0.0.1")
2000  		if err != nil {
2001  			t.Errorf("Unexpected error: %v", err)
2002  		}
2003  		// Should be denied by default policy (deny)
2004  		if allowed {
2005  			t.Error("Expected event of kind without rule to be denied by default policy")
2006  		}
2007  	})
2008  
2009  	// Cleanup: Stop the script
2010  	manager.mutex.RLock()
2011  	runner, exists := manager.runners[scriptPath]
2012  	manager.mutex.RUnlock()
2013  	if exists && runner.IsRunning() {
2014  		runner.Stop()
2015  	}
2016  }
2017  
2018  func TestPolicyFilterProcessing(t *testing.T) {
2019  	// Test policy filter processing using the provided filter JSON specification
2020  	filterJSON := []byte(`{
2021  		"kind": {
2022  			"whitelist": [4678, 10306, 30520, 30919]
2023  		},
2024  		"rules": {
2025  			"4678": {
2026  				"description": "Zenotp message events",
2027  				"script": "/home/orly/.config/ORLY/validate4678.js",
2028  				"privileged": true
2029  			},
2030  			"10306": {
2031  				"description": "End user whitelist changes",
2032  				"read_allow": [
2033  					"04eeb1ed409c0b9205e722f8bf1780f553b61876ef323aff16c9f80a9d8ee9f5"
2034  				],
2035  				"privileged": true
2036  			},
2037  			"30520": {
2038  				"description": "Zenotp events",
2039  				"write_allow": [
2040  					"04eeb1ed409c0b9205e722f8bf1780f553b61876ef323aff16c9f80a9d8ee9f5"
2041  				],
2042  				"privileged": true
2043  			},
2044  			"30919": {
2045  				"description": "Zenotp events",
2046  				"write_allow": [
2047  					"04eeb1ed409c0b9205e722f8bf1780f553b61876ef323aff16c9f80a9d8ee9f5"
2048  				],
2049  				"privileged": true
2050  			}
2051  		}
2052  	}`)
2053  
2054  	// Create policy from JSON
2055  	policy, err := New(filterJSON)
2056  	if err != nil {
2057  		t.Fatalf("Failed to create policy from JSON: %v", err)
2058  	}
2059  
2060  	// Verify whitelist is set correctly
2061  	if len(policy.Kind.Whitelist) != 4 {
2062  		t.Errorf("Expected whitelist to have 4 kinds, got %d", len(policy.Kind.Whitelist))
2063  	}
2064  	expectedKinds := map[int]bool{4678: true, 10306: true, 30520: true, 30919: true}
2065  	for _, kind := range policy.Kind.Whitelist {
2066  		if !expectedKinds[kind] {
2067  			t.Errorf("Unexpected kind in whitelist: %d", kind)
2068  		}
2069  	}
2070  
2071  	// Verify rules are loaded correctly
2072  	if len(policy.rules) != 4 {
2073  		t.Errorf("Expected 4 rules, got %d", len(policy.rules))
2074  	}
2075  
2076  	// Verify rule 4678 (script-based)
2077  	rule4678, ok := policy.rules[4678]
2078  	if !ok {
2079  		t.Fatal("Rule 4678 not found")
2080  	}
2081  	if rule4678.Description != "Zenotp message events" {
2082  		t.Errorf("Expected description 'Zenotp message events', got '%s'", rule4678.Description)
2083  	}
2084  	if rule4678.Script != "/home/orly/.config/ORLY/validate4678.js" {
2085  		t.Errorf("Expected script path '/home/orly/.config/ORLY/validate4678.js', got '%s'", rule4678.Script)
2086  	}
2087  	if !rule4678.Privileged {
2088  		t.Error("Expected rule 4678 to be privileged")
2089  	}
2090  
2091  	// Verify rule 10306 (read_allow)
2092  	rule10306, ok := policy.rules[10306]
2093  	if !ok {
2094  		t.Fatal("Rule 10306 not found")
2095  	}
2096  	if rule10306.Description != "End user whitelist changes" {
2097  		t.Errorf("Expected description 'End user whitelist changes', got '%s'", rule10306.Description)
2098  	}
2099  	if len(rule10306.ReadAllow) != 1 {
2100  		t.Errorf("Expected 1 read_allow pubkey, got %d", len(rule10306.ReadAllow))
2101  	}
2102  	if rule10306.ReadAllow[0] != "04eeb1ed409c0b9205e722f8bf1780f553b61876ef323aff16c9f80a9d8ee9f5" {
2103  		t.Errorf("Expected read_allow pubkey '04eeb1ed409c0b9205e722f8bf1780f553b61876ef323aff16c9f80a9d8ee9f5', got '%s'", rule10306.ReadAllow[0])
2104  	}
2105  	if !rule10306.Privileged {
2106  		t.Error("Expected rule 10306 to be privileged")
2107  	}
2108  
2109  	// Verify rule 30520 (write_allow)
2110  	rule30520, ok := policy.rules[30520]
2111  	if !ok {
2112  		t.Fatal("Rule 30520 not found")
2113  	}
2114  	if rule30520.Description != "Zenotp events" {
2115  		t.Errorf("Expected description 'Zenotp events', got '%s'", rule30520.Description)
2116  	}
2117  	if len(rule30520.WriteAllow) != 1 {
2118  		t.Errorf("Expected 1 write_allow pubkey, got %d", len(rule30520.WriteAllow))
2119  	}
2120  	if rule30520.WriteAllow[0] != "04eeb1ed409c0b9205e722f8bf1780f553b61876ef323aff16c9f80a9d8ee9f5" {
2121  		t.Errorf("Expected write_allow pubkey '04eeb1ed409c0b9205e722f8bf1780f553b61876ef323aff16c9f80a9d8ee9f5', got '%s'", rule30520.WriteAllow[0])
2122  	}
2123  	if !rule30520.Privileged {
2124  		t.Error("Expected rule 30520 to be privileged")
2125  	}
2126  
2127  	// Verify rule 30919 (write_allow)
2128  	rule30919, ok := policy.rules[30919]
2129  	if !ok {
2130  		t.Fatal("Rule 30919 not found")
2131  	}
2132  	if rule30919.Description != "Zenotp events" {
2133  		t.Errorf("Expected description 'Zenotp events', got '%s'", rule30919.Description)
2134  	}
2135  	if len(rule30919.WriteAllow) != 1 {
2136  		t.Errorf("Expected 1 write_allow pubkey, got %d", len(rule30919.WriteAllow))
2137  	}
2138  	if rule30919.WriteAllow[0] != "04eeb1ed409c0b9205e722f8bf1780f553b61876ef323aff16c9f80a9d8ee9f5" {
2139  		t.Errorf("Expected write_allow pubkey '04eeb1ed409c0b9205e722f8bf1780f553b61876ef323aff16c9f80a9d8ee9f5', got '%s'", rule30919.WriteAllow[0])
2140  	}
2141  	if !rule30919.Privileged {
2142  		t.Error("Expected rule 30919 to be privileged")
2143  	}
2144  
2145  	// Test kind whitelist filtering
2146  	t.Run("kind whitelist filtering", func(t *testing.T) {
2147  		eventSigner, eventPubkey := generateTestKeypair(t)
2148  		_, loggedInPubkey := generateTestKeypair(t)
2149  
2150  		// Test whitelisted kind (should pass kind check, but may fail other checks)
2151  		whitelistedEvent := createTestEvent(t, eventSigner, "test content", 4678)
2152  		addPTag(whitelistedEvent, loggedInPubkey)
2153  		allowed, err := policy.CheckPolicy("write", whitelistedEvent, loggedInPubkey, "127.0.0.1")
2154  		if err != nil {
2155  			t.Errorf("Unexpected error: %v", err)
2156  		}
2157  		// Should be allowed because script isn't running (falls back to default "allow")
2158  		// and privileged check passes (loggedInPubkey is in p tag)
2159  		if !allowed {
2160  			t.Error("Expected whitelisted kind to be allowed when script not running and privileged check passes")
2161  		}
2162  
2163  		// Test non-whitelisted kind (should be denied)
2164  		nonWhitelistedEvent := createTestEvent(t, eventSigner, "test content", 1)
2165  		allowed, err = policy.CheckPolicy("write", nonWhitelistedEvent, eventPubkey, "127.0.0.1")
2166  		if err != nil {
2167  			t.Errorf("Unexpected error: %v", err)
2168  		}
2169  		if allowed {
2170  			t.Error("Expected non-whitelisted kind to be denied")
2171  		}
2172  	})
2173  
2174  	// Test read access for kind 10306
2175  	t.Run("read access for kind 10306", func(t *testing.T) {
2176  		allowedPubkeyHex := "04eeb1ed409c0b9205e722f8bf1780f553b61876ef323aff16c9f80a9d8ee9f5"
2177  		allowedPubkeyBytes, err := hex.Dec(allowedPubkeyHex)
2178  		if err != nil {
2179  			t.Fatalf("Failed to decode allowed pubkey: %v", err)
2180  		}
2181  
2182  		// Create event with allowed pubkey using a temporary signer
2183  		// Note: We can't actually sign with just the pubkey, so we'll create the event
2184  		// with a random signer and then manually set the pubkey for testing
2185  		tempSigner, _ := generateTestKeypair(t)
2186  		event10306 := createTestEvent(t, tempSigner, "test content", 10306)
2187  		event10306.Pubkey = allowedPubkeyBytes
2188  		// Re-sign won't work without private key, but policy checks use the pubkey field
2189  		// So we'll test with the pubkey set correctly
2190  
2191  		// Test read access with allowed pubkey (logged in user matches event pubkey)
2192  		allowed, err := policy.CheckPolicy("read", event10306, allowedPubkeyBytes, "127.0.0.1")
2193  		if err != nil {
2194  			t.Errorf("Unexpected error: %v", err)
2195  		}
2196  		if !allowed {
2197  			t.Error("Expected event to be allowed for read access with allowed pubkey")
2198  		}
2199  
2200  		// Test read access with non-allowed pubkey
2201  		_, unauthorizedPubkey := generateTestKeypair(t)
2202  		allowed, err = policy.CheckPolicy("read", event10306, unauthorizedPubkey, "127.0.0.1")
2203  		if err != nil {
2204  			t.Errorf("Unexpected error: %v", err)
2205  		}
2206  		if allowed {
2207  			t.Error("Expected event to be denied for read access with non-allowed pubkey")
2208  		}
2209  
2210  		// Test read access without authentication (privileged check)
2211  		allowed, err = policy.CheckPolicy("read", event10306, nil, "127.0.0.1")
2212  		if err != nil {
2213  			t.Errorf("Unexpected error: %v", err)
2214  		}
2215  		if allowed {
2216  			t.Error("Expected event to be denied for read access without authentication (privileged)")
2217  		}
2218  	})
2219  
2220  	// Test write access for kind 30520
2221  	t.Run("write access for kind 30520", func(t *testing.T) {
2222  		allowedPubkeyHex := "04eeb1ed409c0b9205e722f8bf1780f553b61876ef323aff16c9f80a9d8ee9f5"
2223  		allowedPubkeyBytes, err := hex.Dec(allowedPubkeyHex)
2224  		if err != nil {
2225  			t.Fatalf("Failed to decode allowed pubkey: %v", err)
2226  		}
2227  
2228  		// Create event with allowed pubkey using a temporary signer
2229  		// We'll set the pubkey manually for testing since we don't have the private key
2230  		tempSigner, _ := generateTestKeypair(t)
2231  		event30520 := createTestEvent(t, tempSigner, "test content", 30520)
2232  		event30520.Pubkey = allowedPubkeyBytes
2233  
2234  		// Test write access with allowed pubkey (event pubkey matches write_allow)
2235  		allowed, err := policy.CheckPolicy("write", event30520, allowedPubkeyBytes, "127.0.0.1")
2236  		if err != nil {
2237  			t.Errorf("Unexpected error: %v", err)
2238  		}
2239  		if !allowed {
2240  			t.Error("Expected event to be allowed for write access with allowed pubkey")
2241  		}
2242  
2243  		// Test write access with non-allowed pubkey
2244  		unauthorizedSigner, unauthorizedPubkey := generateTestKeypair(t)
2245  		unauthorizedEvent := createTestEvent(t, unauthorizedSigner, "test content", 30520)
2246  		allowed, err = policy.CheckPolicy("write", unauthorizedEvent, unauthorizedPubkey, "127.0.0.1")
2247  		if err != nil {
2248  			t.Errorf("Unexpected error: %v", err)
2249  		}
2250  		if allowed {
2251  			t.Error("Expected event to be denied for write access with non-allowed pubkey")
2252  		}
2253  
2254  		// Test write access without authentication (privileged check)
2255  		allowed, err = policy.CheckPolicy("write", event30520, nil, "127.0.0.1")
2256  		if err != nil {
2257  			t.Errorf("Unexpected error: %v", err)
2258  		}
2259  		if allowed {
2260  			t.Error("Expected event to be denied for write access without authentication (privileged)")
2261  		}
2262  	})
2263  
2264  	// Test write access for kind 30919
2265  	t.Run("write access for kind 30919", func(t *testing.T) {
2266  		allowedPubkeyHex := "04eeb1ed409c0b9205e722f8bf1780f553b61876ef323aff16c9f80a9d8ee9f5"
2267  		allowedPubkeyBytes, err := hex.Dec(allowedPubkeyHex)
2268  		if err != nil {
2269  			t.Fatalf("Failed to decode allowed pubkey: %v", err)
2270  		}
2271  
2272  		// Create event with allowed pubkey using a temporary signer
2273  		// We'll set the pubkey manually for testing since we don't have the private key
2274  		tempSigner, _ := generateTestKeypair(t)
2275  		event30919 := createTestEvent(t, tempSigner, "test content", 30919)
2276  		event30919.Pubkey = allowedPubkeyBytes
2277  
2278  		// Test write access with allowed pubkey (event pubkey matches write_allow)
2279  		allowed, err := policy.CheckPolicy("write", event30919, allowedPubkeyBytes, "127.0.0.1")
2280  		if err != nil {
2281  			t.Errorf("Unexpected error: %v", err)
2282  		}
2283  		if !allowed {
2284  			t.Error("Expected event to be allowed for write access with allowed pubkey")
2285  		}
2286  
2287  		// Test write access with non-allowed pubkey
2288  		unauthorizedSigner, unauthorizedPubkey := generateTestKeypair(t)
2289  		unauthorizedEvent := createTestEvent(t, unauthorizedSigner, "test content", 30919)
2290  		allowed, err = policy.CheckPolicy("write", unauthorizedEvent, unauthorizedPubkey, "127.0.0.1")
2291  		if err != nil {
2292  			t.Errorf("Unexpected error: %v", err)
2293  		}
2294  		if allowed {
2295  			t.Error("Expected event to be denied for write access with non-allowed pubkey")
2296  		}
2297  
2298  		// Test write access without authentication (privileged check)
2299  		allowed, err = policy.CheckPolicy("write", event30919, nil, "127.0.0.1")
2300  		if err != nil {
2301  			t.Errorf("Unexpected error: %v", err)
2302  		}
2303  		if allowed {
2304  			t.Error("Expected event to be denied for write access without authentication (privileged)")
2305  		}
2306  	})
2307  
2308  	// Test privileged flag behavior with p tags
2309  	t.Run("privileged flag with p tags", func(t *testing.T) {
2310  		eventSigner, _ := generateTestKeypair(t)
2311  		_, loggedInPubkey := generateTestKeypair(t)
2312  		allowedPubkeyHex := "04eeb1ed409c0b9205e722f8bf1780f553b61876ef323aff16c9f80a9d8ee9f5"
2313  		allowedPubkeyBytes, err := hex.Dec(allowedPubkeyHex)
2314  		if err != nil {
2315  			t.Fatalf("Failed to decode allowed pubkey: %v", err)
2316  		}
2317  
2318  		// Create event with allowed pubkey and logged-in pubkey in p tag
2319  		event30520 := createTestEvent(t, eventSigner, "test content", 30520)
2320  		event30520.Pubkey = allowedPubkeyBytes
2321  		addPTag(event30520, loggedInPubkey)
2322  
2323  		// Test that event is DENIED when submitter (logged-in pubkey) is not in write_allow
2324  		// Even though the submitter is in p-tag, write_allow is about who can submit
2325  		allowed, err := policy.CheckPolicy("write", event30520, loggedInPubkey, "127.0.0.1")
2326  		if err != nil {
2327  			t.Errorf("Unexpected error: %v", err)
2328  		}
2329  		if allowed {
2330  			t.Error("Expected event to be denied when submitter (logged-in pubkey) is not in write_allow")
2331  		}
2332  
2333  		// Test that event is denied when submitter is not in write_allow (even without p-tag)
2334  		event30520NoPTag := createTestEvent(t, eventSigner, "test content", 30520)
2335  		event30520NoPTag.Pubkey = allowedPubkeyBytes
2336  		allowed, err = policy.CheckPolicy("write", event30520NoPTag, loggedInPubkey, "127.0.0.1")
2337  		if err != nil {
2338  			t.Errorf("Unexpected error: %v", err)
2339  		}
2340  		if allowed {
2341  			t.Error("Expected event to be denied when submitter is not in write_allow")
2342  		}
2343  	})
2344  
2345  	// Test script-based rule (kind 4678)
2346  	t.Run("script-based rule for kind 4678", func(t *testing.T) {
2347  		eventSigner, _ := generateTestKeypair(t)
2348  		_, loggedInPubkey := generateTestKeypair(t)
2349  
2350  		event4678 := createTestEvent(t, eventSigner, "test content", 4678)
2351  		addPTag(event4678, loggedInPubkey)
2352  
2353  		// Test with script not running (should fall back to default policy)
2354  		allowed, err := policy.CheckPolicy("write", event4678, loggedInPubkey, "127.0.0.1")
2355  		if err != nil {
2356  			t.Errorf("Unexpected error: %v", err)
2357  		}
2358  		// Should allow because default policy is "allow" and script is not running
2359  		// and privileged check passes (loggedInPubkey is in p tag)
2360  		if !allowed {
2361  			t.Error("Expected event to be allowed when script is not running (falls back to default 'allow') and privileged check passes")
2362  		}
2363  
2364  		// Test without authentication (privileged doesn't affect write operations)
2365  		allowed, err = policy.CheckPolicy("write", event4678, nil, "127.0.0.1")
2366  		if err != nil {
2367  			t.Errorf("Unexpected error: %v", err)
2368  		}
2369  		// Should be allowed because privileged doesn't affect write operations
2370  		// Falls back to default policy which is "allow"
2371  		if !allowed {
2372  			t.Error("Expected event to be allowed without authentication (privileged doesn't affect write)")
2373  		}
2374  	})
2375  }
2376