package sign import ( "bytes" "crypto/ed25519" "encoding/json" "github.com/netkingdom/access-engine/pkg/api" "testing" ) func TestProducerNumericEnvelopeDecodeCompatibility(t *testing.T) { key := ed25519.NewKeyFromSeed(bytes.Repeat([]byte{11}, 32)) keys := map[string]ed25519.PublicKey{"synthetic-numeric": key.Public().(ed25519.PublicKey)} for _, raw := range []string{`1`, `1.0`, `-0.0`, `1e-07`, `1e+20`, `9007199254740993`, `1.7976931348623157e308`, `5e-324`, `true`, `"<>&\u2028\u2029 café"`, `[1,1.0,-0.0]`, `{"nested":1.0}`} { t.Run(raw, func(t *testing.T) { var value any decoder := json.NewDecoder(bytes.NewBufferString(raw)) decoder.UseNumber() if err := decoder.Decode(&value); err != nil { t.Fatal(err) } original := api.DecisionEnvelope{Binding: &api.DecisionBinding{Context: map[string]any{"numeric": value}}} if err := Sign(&original, key, "synthetic-numeric"); err != nil { t.Fatal(err) } wire, _ := json.Marshal(original) decoded, err := DecodeEnvelope(wire) if err != nil { t.Fatal(err) } if err := Verify(decoded, keys); err != nil { t.Fatal(err) } before, _ := CanonicalBytes(original) after, _ := CanonicalBytes(decoded) if !bytes.Equal(before, after) { t.Fatal("producer canonical bytes changed") } }) } // Existing float64 producer profile still verifies through the new decoder. legacy := api.DecisionEnvelope{Binding: &api.DecisionBinding{Context: map[string]any{"number": float64(1), "exponent": float64(1e-7)}}} Sign(&legacy, key, "synthetic-numeric") wire, _ := json.Marshal(legacy) decoded, err := DecodeEnvelope(wire) if err != nil || Verify(decoded, keys) != nil { t.Fatal("legacy producer compatibility failed") } for _, raw := range []string{`{} {}`, `{"new_unknown_authority":true}`} { if _, err := DecodeEnvelope([]byte(raw)); err == nil { t.Fatal("invalid envelope accepted") } } }