Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a8e571905 |
@@ -12,6 +12,48 @@ import (
|
||||
// a reference only; it does not expose another owner's storage.
|
||||
type SemanticReference = ids.SemanticRef
|
||||
|
||||
// VersionBinding is a typed applicability constraint. Absence of VersionRef
|
||||
// means unknown, never an implicit "latest".
|
||||
type VersionMatchMode string
|
||||
|
||||
const (
|
||||
VersionExact VersionMatchMode = "EXACT"
|
||||
VersionCompatibleFamily VersionMatchMode = "COMPATIBLE_FAMILY"
|
||||
VersionAtOrBefore VersionMatchMode = "AT_OR_BEFORE"
|
||||
VersionUnknown VersionMatchMode = "UNKNOWN"
|
||||
)
|
||||
|
||||
type VersionBinding struct {
|
||||
SubjectRef SemanticReference
|
||||
VersionRef SemanticReference
|
||||
MatchMode VersionMatchMode
|
||||
}
|
||||
|
||||
type EnvironmentReference struct {
|
||||
EnvironmentRef SemanticReference
|
||||
VersionRef *SemanticReference
|
||||
}
|
||||
|
||||
func (b VersionBinding) Validate() error {
|
||||
if !b.SubjectRef.Valid() || !b.VersionRef.Valid() {
|
||||
return fmt.Errorf("version binding references are invalid")
|
||||
}
|
||||
if b.MatchMode != VersionExact && b.MatchMode != VersionCompatibleFamily && b.MatchMode != VersionAtOrBefore && b.MatchMode != VersionUnknown {
|
||||
return fmt.Errorf("version binding match mode is invalid")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r EnvironmentReference) Validate() error {
|
||||
if !r.EnvironmentRef.Valid() {
|
||||
return fmt.Errorf("environment reference is invalid")
|
||||
}
|
||||
if r.VersionRef != nil && !r.VersionRef.Valid() {
|
||||
return fmt.Errorf("environment version reference is invalid")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PrincipalRealm string
|
||||
|
||||
const (
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"task_file":"dev/tasks/GEN2-004-replace-project-centric-focus-with-contextscope-focusframe-focusstack.json","task_id":"GEN2-004","task_revision":1}
|
||||
{"task_file":"dev/tasks/GEN2-005-world-identity-resolution-and-version-environment-bindings.json","task_id":"GEN2-005","task_revision":1}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package domain_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.cin.su/m/Assistant/contracts/world"
|
||||
"git.cin.su/m/Assistant/modules/world/domain"
|
||||
)
|
||||
|
||||
func TestResolveCandidatesDoesNotAutoMergeAmbiguousPeopleOrSystems(t *testing.T) {
|
||||
decision, candidates := domain.ResolveCandidates([]world.IdentityResolutionCandidate{
|
||||
{ObjectRef: world.SemanticReference{OwnerNamespace: "world", SemanticKind: "person", StableID: "ivan-telegram"}, Confidence: 800},
|
||||
{ObjectRef: world.SemanticReference{OwnerNamespace: "world", SemanticKind: "person", StableID: "ivan-crm"}, Confidence: 800},
|
||||
}, 700)
|
||||
if decision != world.ResolutionUnresolved || len(candidates) != 2 {
|
||||
t.Fatalf("ambiguous result = %s, %#v", decision, candidates)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVersionAndEnvironmentReferencesAreTyped(t *testing.T) {
|
||||
version := world.SemanticReference{OwnerNamespace: "world", SemanticKind: "version", StableID: "unf-3"}
|
||||
binding := world.VersionBinding{SubjectRef: world.SemanticReference{OwnerNamespace: "world", SemanticKind: "database", StableID: "company-a-unf"}, VersionRef: version, MatchMode: world.VersionExact}
|
||||
if err := binding.Validate(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
environment := world.EnvironmentReference{EnvironmentRef: world.SemanticReference{OwnerNamespace: "world", SemanticKind: "environment", StableID: "company-a-prod"}, VersionRef: &version}
|
||||
if err := environment.Validate(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package domain
|
||||
|
||||
import "git.cin.su/m/Assistant/contracts/world"
|
||||
|
||||
import "sort"
|
||||
|
||||
func ValidateObject(value world.WorldObject) error { return value.Validate() }
|
||||
|
||||
func ValidateKindDefinition(value world.WorldObjectKindDefinition) error { return value.Validate() }
|
||||
@@ -15,3 +17,18 @@ func ValidateRelationDefinition(value world.RelationDefinition) error { return v
|
||||
func ValidateResolution(value world.IdentityResolutionDecisionRecord) error { return value.Validate() }
|
||||
|
||||
func ValidateLineage(value world.WorldLineage) error { return value.Validate() }
|
||||
|
||||
// ResolveCandidates deliberately refuses to merge an ambiguous result. A
|
||||
// caller may persist the returned UNRESOLVED decision and later re-evaluate it
|
||||
// with additional evidence.
|
||||
func ResolveCandidates(candidates []world.IdentityResolutionCandidate, minimumConfidence int64) (world.ResolutionDecision, []world.IdentityResolutionCandidate) {
|
||||
ordered := append([]world.IdentityResolutionCandidate(nil), candidates...)
|
||||
sort.SliceStable(ordered, func(i, j int) bool { return ordered[i].Confidence > ordered[j].Confidence })
|
||||
if len(ordered) == 0 || ordered[0].Confidence < minimumConfidence {
|
||||
return world.ResolutionUnresolved, ordered
|
||||
}
|
||||
if len(ordered) > 1 && ordered[0].Confidence == ordered[1].Confidence {
|
||||
return world.ResolutionUnresolved, ordered
|
||||
}
|
||||
return world.ResolutionSame, ordered[:1]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user