Expose sequence identity registrations through the facade

This commit is contained in:
2026-10-23 20:59:23 +00:00
parent 33a51606da
commit 0023617a07
20 changed files with 530 additions and 212 deletions

View File

@@ -1,10 +1,5 @@
package engine
type sequenceRegistration struct {
path Path
identityField string
}
type sequenceSelectorSegmentKind uint8
const (
@@ -22,6 +17,24 @@ type sequenceIdentitySelector []sequenceSelectorSegment
type sequenceIdentityRegistration struct {
selector sequenceIdentitySelector
identityFields []string
invalidPath *Path
}
// SequenceIdentitySelectorSegment carries one root-owned selector segment into
// an engine definition. This transport type remains behind the internal package
// boundary.
type SequenceIdentitySelectorSegment struct {
Key string
AnyMappingKey bool
}
// SequenceIdentityRegistrationInput carries detached root-owned registration
// data into an engine definition without exposing its compiled policy. A
// non-nil ExactPath selects exact-path registration; otherwise Selector is used.
type SequenceIdentityRegistrationInput struct {
ExactPath *Path
Selector []SequenceIdentitySelectorSegment
IdentityFields []string
}
type sequenceSelectorTrie struct {
@@ -32,62 +45,59 @@ type sequenceSelectorTrie struct {
}
type sequencePolicy struct {
// identityFields preserves the old exact-path view for existing internal
// callers while selector matching is introduced behind the same policy.
identityFields map[string]string
selectorTrie *sequenceSelectorTrie
selectorTrie *sequenceSelectorTrie
}
// DefinitionWithSequenceRegistrations attaches facade-owned registrations to a
// detached engine definition without exposing the registration representation.
func DefinitionWithSequenceRegistrations[T any](definition Definition[T], paths []Path, identityFields []string) Definition[T] {
if paths == nil {
definition.sequenceRegistrations = nil
// DefinitionWithSequenceIdentityRegistrations attaches facade-owned
// registrations to a detached engine definition without exposing compiled
// engine policy.
func DefinitionWithSequenceIdentityRegistrations[T any](definition Definition[T], registrations []SequenceIdentityRegistrationInput) Definition[T] {
if registrations == nil {
definition.sequenceIdentityRegistrations = nil
return definition
}
definition.sequenceRegistrations = make([]sequenceRegistration, len(paths))
for index := range paths {
definition.sequenceRegistrations[index] = sequenceRegistration{
path: paths[index].clone(), identityField: identityFields[index],
definition.sequenceIdentityRegistrations = make([]sequenceIdentityRegistration, len(registrations))
for index, registration := range registrations {
compiled := sequenceIdentityRegistration{identityFields: append([]string(nil), registration.IdentityFields...)}
if registration.ExactPath != nil {
path, err := normalizeDestination(registration.ExactPath.clone())
if err != nil {
invalid := registration.ExactPath.clone()
compiled.invalidPath = &invalid
} else {
compiled.selector = make(sequenceIdentitySelector, len(path.segments))
for segmentIndex, segment := range path.segments {
compiled.selector[segmentIndex] = sequenceSelectorSegment{kind: sequenceSelectorLiteral, key: segment.key}
}
}
} else {
compiled.selector = make(sequenceIdentitySelector, len(registration.Selector))
for segmentIndex, segment := range registration.Selector {
kind := sequenceSelectorLiteral
if segment.AnyMappingKey {
kind = sequenceSelectorAnyMappingKey
}
compiled.selector[segmentIndex] = sequenceSelectorSegment{kind: kind, key: segment.Key}
}
}
definition.sequenceIdentityRegistrations[index] = compiled
}
return definition
}
func compileSequencePolicy(registrations []sequenceRegistration) (sequencePolicy, []Diagnostic) {
common := make([]sequenceIdentityRegistration, 0, len(registrations))
var diagnostics []Diagnostic
legacyPaths := make(map[string]string, len(registrations))
for _, registration := range registrations {
path, err := normalizeDestination(registration.path)
if err != nil {
diagnostics = append(diagnostics, Diagnostic{
Code: CodeOptionsInvalid, Severity: SeverityError,
Path: registration.path.clone(), Message: "sequence registration path must contain only non-reserved mapping keys",
})
continue
}
selector := make(sequenceIdentitySelector, len(path.segments))
for index, segment := range path.segments {
selector[index] = sequenceSelectorSegment{kind: sequenceSelectorLiteral, key: segment.key}
}
common = append(common, sequenceIdentityRegistration{
selector: selector, identityFields: []string{registration.identityField},
})
legacyPaths[path.String()] = registration.identityField
}
policy, compiledDiagnostics := compileSequenceIdentityPolicy(common)
policy.identityFields = legacyPaths
diagnostics = append(diagnostics, compiledDiagnostics...)
return policy, canonicalDiagnostics(diagnostics)
}
func compileSequenceIdentityPolicy(registrations []sequenceIdentityRegistration) (sequencePolicy, []Diagnostic) {
policy := sequencePolicy{}
compiled := make([]sequenceIdentityRegistration, 0, len(registrations))
var diagnostics []Diagnostic
for _, registration := range registrations {
selector := cloneSequenceIdentitySelector(registration.selector)
if registration.invalidPath != nil {
diagnostics = append(diagnostics, Diagnostic{
Code: CodeOptionsInvalid, Severity: SeverityError, Path: registration.invalidPath.clone(),
Message: "sequence registration path must contain only non-reserved mapping keys",
})
continue
}
fields, err := normalizeSequenceIdentityFields(registration.identityFields)
if err != nil {
diagnostics = append(diagnostics, Diagnostic{
@@ -172,11 +182,7 @@ func (p sequencePolicy) identityFieldsAt(path Path) ([]string, bool) {
return nil, false
}
if p.selectorTrie == nil {
field, ok := p.identityFields[path.String()]
if !ok {
return nil, false
}
return []string{field}, true
return nil, false
}
current := []*sequenceSelectorTrie{p.selectorTrie}
for _, segment := range path.segments {