Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a8e571905 |
@@ -12,6 +12,48 @@ import (
|
|||||||
// a reference only; it does not expose another owner's storage.
|
// a reference only; it does not expose another owner's storage.
|
||||||
type SemanticReference = ids.SemanticRef
|
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
|
type PrincipalRealm string
|
||||||
|
|
||||||
const (
|
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 "git.cin.su/m/Assistant/contracts/world"
|
||||||
|
|
||||||
|
import "sort"
|
||||||
|
|
||||||
func ValidateObject(value world.WorldObject) error { return value.Validate() }
|
func ValidateObject(value world.WorldObject) error { return value.Validate() }
|
||||||
|
|
||||||
func ValidateKindDefinition(value world.WorldObjectKindDefinition) 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 ValidateResolution(value world.IdentityResolutionDecisionRecord) error { return value.Validate() }
|
||||||
|
|
||||||
func ValidateLineage(value world.WorldLineage) 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