Validate artifact candidates before final encoding

This commit is contained in:
2026-07-17 15:13:19 +00:00
parent 3772b308e9
commit 35bffdf336
5 changed files with 338 additions and 10 deletions

View File

@@ -2,6 +2,7 @@ package spells
import (
"bytes"
"context"
"encoding/json"
"os"
"reflect"
@@ -12,6 +13,7 @@ import (
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd"
spellshape "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/validate/spells/shape"
)
func TestCodecMatchesMaintainedDurableFixture(t *testing.T) {
@@ -101,6 +103,25 @@ func TestCodecRejectsInvalidCanonicalValues(t *testing.T) {
}
}
func TestCodecEncodesIncompleteCandidateWithoutWeakeningFinalEncoding(t *testing.T) {
codec := New()
candidate := dnd.SpellList{}
content, err := codec.EncodeCandidate(candidate)
if err != nil {
t.Fatalf("EncodeCandidate() error = %v, want nil", err)
}
if !json.Valid(content) {
t.Fatalf("EncodeCandidate() = %q, want JSON", content)
}
result, err := spellshape.New(spellshape.Options{}).Validate(context.Background(), contracts.TypedValidationRequest[dnd.SpellList]{Value: candidate})
if err != nil || result.Approved || result.ReasonCode != spellshape.ReasonCode {
t.Fatalf("shape validation = %#v, %v; want candidate rejection", result, err)
}
if _, err := codec.Encode(candidate); err == nil || !strings.Contains(err.Error(), "spell_casts must be present") {
t.Fatalf("Encode() error = %v, want strict final shape error", err)
}
}
func TestCodecSchemaIsMutationSafe(t *testing.T) {
first := New().Schema()
first.JSONSchema[0] = '['