Enforce durable D&D evidence ranges

This commit is contained in:
2026-08-09 01:54:43 +00:00
parent d653bf1b90
commit b3644abc0e
19 changed files with 330 additions and 31 deletions

View File

@@ -168,5 +168,5 @@ func canonicalReferences(refs []source.SourceRef) []source.SourceRef {
}
func validIdentityReference(ref source.SourceRef) bool {
return strings.TrimSpace(ref.SourceID) == ref.SourceID && ref.SourceID != "" && ref.StartUnitID > 0 && ref.EndUnitID > 0
return strings.TrimSpace(ref.SourceID) == ref.SourceID && ref.SourceID != "" && ref.StartUnitID > 0 && ref.EndUnitID > 0 && ref.StartUnitID <= ref.EndUnitID
}

View File

@@ -75,6 +75,16 @@ func TestDeriveIDRejectsMissingIdentityComponents(t *testing.T) {
}
}
func TestDeriveIDRejectsReversedOnlyEvidence(t *testing.T) {
if got := DeriveID("The Tavern", []source.SourceRef{{SourceID: "session", StartUnitID: 2, EndUnitID: 1}}); got != "" {
t.Fatalf("DeriveID() = %q, want empty ID", got)
}
valid := source.SourceRef{SourceID: "session", StartUnitID: 3, EndUnitID: 3}
if got, want := DeriveID("The Tavern", []source.SourceRef{{SourceID: "session", StartUnitID: 2, EndUnitID: 1}, valid}), DeriveID("The Tavern", []source.SourceRef{valid}); got != want {
t.Fatalf("DeriveID() = %q, want %q after filtering reversed evidence", got, want)
}
}
func TestIsValidID(t *testing.T) {
valid := DeriveID("The Tavern", []source.SourceRef{{SourceID: "session", StartUnitID: 1, EndUnitID: 1}})
if !IsValidID(valid) || !ValidID(valid) {

View File

@@ -88,6 +88,18 @@ func TestResolveRejectsInvalidReferenceInputs(t *testing.T) {
}
}
func TestResolveRejectsReversedEvidenceInDirectRegistryReference(t *testing.T) {
value := registryFixture()
value.Locations[0].SourceRefs[0] = source.SourceRef{SourceID: "session-alpha", StartUnitID: 2, EndUnitID: 1}
content, err := locationcodec.New().EncodeCandidate(value)
if err != nil {
t.Fatalf("EncodeCandidate() error = %v", err)
}
if _, err := Resolve(referenceSet(item(content))); err == nil || !strings.Contains(err.Error(), "invalid approved") {
t.Fatalf("Resolve() error = %v, want direct-reference rejection", err)
}
}
func TestResolverHandlesConstructionAndOperationReferences(t *testing.T) {
placeholder, err := NewResolver(referenceSet())
if err != nil || placeholder.Seeded().Bound() {