package attesto import ( "encoding/json" "os" "path/filepath" "testing" ) type webhookParityVectors struct { Cases []struct { ID string `json:"id"` Secret string `json:"secret"` Body string `json:"body"` Headers map[string]string `json:"headers"` Now int64 `json:"now"` MaxSkewS int `json:"max_skew_s"` ExpectOK bool `json:"expect_ok"` } `json:"cases"` } func TestParityWebhookVerification(t *testing.T) { path := filepath.Join("..", "..", "golden-vectors", "sdk-parity", "webhook.json") raw, err := os.ReadFile(path) if err != nil { t.Fatalf("read webhook vectors: %v", err) } var v webhookParityVectors if err := json.Unmarshal(raw, &v); err != nil { t.Fatalf("decode webhook vectors: %v", err) } for _, c := range v.Cases { ok := verifyWebhookAt([]byte(c.Body), c.Headers, c.Secret, c.MaxSkewS, c.Now) if ok != c.ExpectOK { t.Errorf("webhook %s: ok=%v want %v", c.ID, ok, c.ExpectOK) } } } func TestWebhookHeaderLookupIsCaseInsensitive(t *testing.T) { path := filepath.Join("..", "..", "golden-vectors", "sdk-parity", "webhook.json") raw, err := os.ReadFile(path) if err != nil { t.Fatalf("read webhook vectors: %v", err) } var v webhookParityVectors if err := json.Unmarshal(raw, &v); err != nil { t.Fatalf("decode webhook vectors: %v", err) } for _, c := range v.Cases { if c.ID != "valid" { continue } lowered := map[string]string{} for key, value := range c.Headers { lowered[key] = value } // Re-key with different casing. lowered["X-ATTESTO-TIMESTAMP"] = lowered["X-Attesto-Timestamp"] delete(lowered, "X-Attesto-Timestamp") if !verifyWebhookAt([]byte(c.Body), lowered, c.Secret, c.MaxSkewS, c.Now) { t.Error("case-insensitive header lookup failed") } } }