Consolidate the architecture plan into fewer packages

This commit is contained in:
2026-07-03 10:01:28 -05:00
parent 5a6e82f599
commit b4ee4c64f0
14 changed files with 364 additions and 242 deletions

View File

@@ -1,4 +1,4 @@
package extractorregistry
package pipeline
import (
"fmt"
@@ -8,19 +8,19 @@ import (
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
)
type Constructor func() (contracts.Extractor, error)
type ExtractorConstructor func() (contracts.Extractor, error)
type Registry struct {
constructors map[string]Constructor
type ExtractorRegistry struct {
constructors map[string]ExtractorConstructor
}
func New() *Registry {
return &Registry{
constructors: make(map[string]Constructor),
func NewExtractorRegistry() *ExtractorRegistry {
return &ExtractorRegistry{
constructors: make(map[string]ExtractorConstructor),
}
}
func (r *Registry) Register(key string, constructor Constructor) error {
func (r *ExtractorRegistry) Register(key string, constructor ExtractorConstructor) error {
if r == nil {
return fmt.Errorf("extractor registry must not be nil")
}
@@ -40,7 +40,7 @@ func (r *Registry) Register(key string, constructor Constructor) error {
return nil
}
func (r *Registry) Build(key string) (contracts.Extractor, error) {
func (r *ExtractorRegistry) Build(key string) (contracts.Extractor, error) {
if r == nil {
return nil, fmt.Errorf("extractor registry must not be nil")
}
@@ -69,7 +69,7 @@ func (r *Registry) Build(key string) (contracts.Extractor, error) {
return extractor, nil
}
func (r *Registry) RegisteredKeys() []string {
func (r *ExtractorRegistry) RegisteredKeys() []string {
if r == nil {
return nil
}

View File

@@ -1,4 +1,4 @@
package extractorregistry
package pipeline
import (
"context"
@@ -10,10 +10,10 @@ import (
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
)
func TestRegisterAndBuild(t *testing.T) {
registry := New()
func TestExtractorRegistryRegisterAndBuild(t *testing.T) {
registry := NewExtractorRegistry()
if err := registry.Register("generic-extractor", fakeConstructor("generic-extractor")); err != nil {
if err := registry.Register("generic-extractor", fakeExtractorConstructor("generic-extractor")); err != nil {
t.Fatalf("Register() error = %v, want nil", err)
}
@@ -26,10 +26,10 @@ func TestRegisterAndBuild(t *testing.T) {
}
}
func TestRegisterAndBuildTrimKeys(t *testing.T) {
registry := New()
func TestExtractorRegistryRegisterAndBuildTrimKeys(t *testing.T) {
registry := NewExtractorRegistry()
if err := registry.Register(" generic-extractor ", fakeConstructor("generic-extractor")); err != nil {
if err := registry.Register(" generic-extractor ", fakeExtractorConstructor("generic-extractor")); err != nil {
t.Fatalf("Register() error = %v, want nil", err)
}
@@ -42,10 +42,10 @@ func TestRegisterAndBuildTrimKeys(t *testing.T) {
}
}
func TestRegisterRejectsEmptyKey(t *testing.T) {
registry := New()
func TestExtractorRegistryRegisterRejectsEmptyKey(t *testing.T) {
registry := NewExtractorRegistry()
err := registry.Register(" \t", fakeConstructor("generic-extractor"))
err := registry.Register(" \t", fakeExtractorConstructor("generic-extractor"))
if err == nil {
t.Fatal("Register() error = nil, want error")
@@ -55,13 +55,13 @@ func TestRegisterRejectsEmptyKey(t *testing.T) {
}
}
func TestRegisterRejectsDuplicateKey(t *testing.T) {
registry := New()
if err := registry.Register("generic-extractor", fakeConstructor("generic-extractor")); err != nil {
func TestExtractorRegistryRegisterRejectsDuplicateKey(t *testing.T) {
registry := NewExtractorRegistry()
if err := registry.Register("generic-extractor", fakeExtractorConstructor("generic-extractor")); err != nil {
t.Fatalf("Register() error = %v, want nil", err)
}
err := registry.Register(" generic-extractor ", fakeConstructor("generic-extractor"))
err := registry.Register(" generic-extractor ", fakeExtractorConstructor("generic-extractor"))
if err == nil {
t.Fatal("Register() error = nil, want error")
@@ -71,8 +71,8 @@ func TestRegisterRejectsDuplicateKey(t *testing.T) {
}
}
func TestRegisterRejectsNilConstructor(t *testing.T) {
registry := New()
func TestExtractorRegistryRegisterRejectsNilConstructor(t *testing.T) {
registry := NewExtractorRegistry()
err := registry.Register("generic-extractor", nil)
@@ -84,8 +84,8 @@ func TestRegisterRejectsNilConstructor(t *testing.T) {
}
}
func TestBuildRejectsUnknownKey(t *testing.T) {
registry := New()
func TestExtractorRegistryBuildRejectsUnknownKey(t *testing.T) {
registry := NewExtractorRegistry()
_, err := registry.Build("missing-extractor")
@@ -97,8 +97,8 @@ func TestBuildRejectsUnknownKey(t *testing.T) {
}
}
func TestBuildWrapsConstructorError(t *testing.T) {
registry := New()
func TestExtractorRegistryBuildWrapsConstructorError(t *testing.T) {
registry := NewExtractorRegistry()
constructorErr := errors.New("constructor failed")
if err := registry.Register("generic-extractor", func() (contracts.Extractor, error) {
return nil, constructorErr
@@ -119,8 +119,8 @@ func TestBuildWrapsConstructorError(t *testing.T) {
}
}
func TestBuildRejectsNilExtractor(t *testing.T) {
registry := New()
func TestExtractorRegistryBuildRejectsNilExtractor(t *testing.T) {
registry := NewExtractorRegistry()
if err := registry.Register("generic-extractor", func() (contracts.Extractor, error) {
return nil, nil
}); err != nil {
@@ -137,9 +137,9 @@ func TestBuildRejectsNilExtractor(t *testing.T) {
}
}
func TestBuildRejectsExtractorKeyMismatch(t *testing.T) {
registry := New()
if err := registry.Register("generic-extractor", fakeConstructor("other-extractor")); err != nil {
func TestExtractorRegistryBuildRejectsExtractorKeyMismatch(t *testing.T) {
registry := NewExtractorRegistry()
if err := registry.Register("generic-extractor", fakeExtractorConstructor("other-extractor")); err != nil {
t.Fatalf("Register() error = %v, want nil", err)
}
@@ -153,10 +153,10 @@ func TestBuildRejectsExtractorKeyMismatch(t *testing.T) {
}
}
func TestRegisteredKeysReturnsSortedCopy(t *testing.T) {
registry := New()
func TestExtractorRegistryRegisteredKeysReturnsSortedCopy(t *testing.T) {
registry := NewExtractorRegistry()
for _, key := range []string{"zeta", "alpha", "middle"} {
if err := registry.Register(key, fakeConstructor(key)); err != nil {
if err := registry.Register(key, fakeExtractorConstructor(key)); err != nil {
t.Fatalf("Register(%q) error = %v, want nil", key, err)
}
}
@@ -174,10 +174,10 @@ func TestRegisteredKeysReturnsSortedCopy(t *testing.T) {
}
}
func TestNilRegistryBehavior(t *testing.T) {
var registry *Registry
func TestExtractorRegistryNilRegistryBehavior(t *testing.T) {
var registry *ExtractorRegistry
if err := registry.Register("generic-extractor", fakeConstructor("generic-extractor")); err == nil {
if err := registry.Register("generic-extractor", fakeExtractorConstructor("generic-extractor")); err == nil {
t.Fatal("Register() error = nil, want error")
}
if _, err := registry.Build("generic-extractor"); err == nil {
@@ -188,8 +188,8 @@ func TestNilRegistryBehavior(t *testing.T) {
}
}
func TestBuildRejectsEmptyKey(t *testing.T) {
registry := New()
func TestExtractorRegistryBuildRejectsEmptyKey(t *testing.T) {
registry := NewExtractorRegistry()
_, err := registry.Build(" \n")
@@ -201,32 +201,32 @@ func TestBuildRejectsEmptyKey(t *testing.T) {
}
}
type fakeExtractor struct {
type registryFakeExtractor struct {
key string
}
func fakeConstructor(key string) Constructor {
func fakeExtractorConstructor(key string) ExtractorConstructor {
return func() (contracts.Extractor, error) {
return fakeExtractor{key: key}, nil
return registryFakeExtractor{key: key}, nil
}
}
func (extractor fakeExtractor) Key() string {
func (extractor registryFakeExtractor) Key() string {
return extractor.key
}
func (extractor fakeExtractor) ArtifactType() string {
func (extractor registryFakeExtractor) ArtifactType() string {
return "generic-artifact"
}
func (extractor fakeExtractor) SchemaVersion() string {
func (extractor registryFakeExtractor) SchemaVersion() string {
return "v1"
}
func (extractor fakeExtractor) Validators() []contracts.Validator {
func (extractor registryFakeExtractor) Validators() []contracts.Validator {
return nil
}
func (extractor fakeExtractor) Extract(ctx context.Context, req contracts.ExtractionRequest) (contracts.ExtractionResult, error) {
func (extractor registryFakeExtractor) Extract(ctx context.Context, req contracts.ExtractionRequest) (contracts.ExtractionResult, error) {
return contracts.ExtractionResult{}, nil
}

View File

@@ -1,4 +1,4 @@
package inputregistry
package pipeline
import (
"fmt"
@@ -8,19 +8,19 @@ import (
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
)
type Constructor func() (contracts.InputAdapter, error)
type InputAdapterConstructor func() (contracts.InputAdapter, error)
type Registry struct {
constructors map[string]Constructor
type InputAdapterRegistry struct {
constructors map[string]InputAdapterConstructor
}
func New() *Registry {
return &Registry{
constructors: make(map[string]Constructor),
func NewInputAdapterRegistry() *InputAdapterRegistry {
return &InputAdapterRegistry{
constructors: make(map[string]InputAdapterConstructor),
}
}
func (r *Registry) Register(key string, constructor Constructor) error {
func (r *InputAdapterRegistry) Register(key string, constructor InputAdapterConstructor) error {
if r == nil {
return fmt.Errorf("input adapter registry must not be nil")
}
@@ -40,7 +40,7 @@ func (r *Registry) Register(key string, constructor Constructor) error {
return nil
}
func (r *Registry) Build(key string) (contracts.InputAdapter, error) {
func (r *InputAdapterRegistry) Build(key string) (contracts.InputAdapter, error) {
if r == nil {
return nil, fmt.Errorf("input adapter registry must not be nil")
}
@@ -69,7 +69,7 @@ func (r *Registry) Build(key string) (contracts.InputAdapter, error) {
return adapter, nil
}
func (r *Registry) RegisteredKeys() []string {
func (r *InputAdapterRegistry) RegisteredKeys() []string {
if r == nil {
return nil
}

View File

@@ -1,4 +1,4 @@
package inputregistry
package pipeline
import (
"context"
@@ -11,10 +11,10 @@ import (
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
)
func TestRegisterAndBuild(t *testing.T) {
registry := New()
func TestInputAdapterRegistryRegisterAndBuild(t *testing.T) {
registry := NewInputAdapterRegistry()
if err := registry.Register("generic-input", fakeConstructor("generic-input")); err != nil {
if err := registry.Register("generic-input", fakeInputAdapterConstructor("generic-input")); err != nil {
t.Fatalf("Register() error = %v, want nil", err)
}
@@ -27,10 +27,10 @@ func TestRegisterAndBuild(t *testing.T) {
}
}
func TestRegisterAndBuildTrimKeys(t *testing.T) {
registry := New()
func TestInputAdapterRegistryRegisterAndBuildTrimKeys(t *testing.T) {
registry := NewInputAdapterRegistry()
if err := registry.Register(" generic-input ", fakeConstructor("generic-input")); err != nil {
if err := registry.Register(" generic-input ", fakeInputAdapterConstructor("generic-input")); err != nil {
t.Fatalf("Register() error = %v, want nil", err)
}
@@ -43,10 +43,10 @@ func TestRegisterAndBuildTrimKeys(t *testing.T) {
}
}
func TestRegisterRejectsEmptyKey(t *testing.T) {
registry := New()
func TestInputAdapterRegistryRegisterRejectsEmptyKey(t *testing.T) {
registry := NewInputAdapterRegistry()
err := registry.Register(" \t", fakeConstructor("generic-input"))
err := registry.Register(" \t", fakeInputAdapterConstructor("generic-input"))
if err == nil {
t.Fatal("Register() error = nil, want error")
@@ -56,13 +56,13 @@ func TestRegisterRejectsEmptyKey(t *testing.T) {
}
}
func TestRegisterRejectsDuplicateKey(t *testing.T) {
registry := New()
if err := registry.Register("generic-input", fakeConstructor("generic-input")); err != nil {
func TestInputAdapterRegistryRegisterRejectsDuplicateKey(t *testing.T) {
registry := NewInputAdapterRegistry()
if err := registry.Register("generic-input", fakeInputAdapterConstructor("generic-input")); err != nil {
t.Fatalf("Register() error = %v, want nil", err)
}
err := registry.Register(" generic-input ", fakeConstructor("generic-input"))
err := registry.Register(" generic-input ", fakeInputAdapterConstructor("generic-input"))
if err == nil {
t.Fatal("Register() error = nil, want error")
@@ -72,8 +72,8 @@ func TestRegisterRejectsDuplicateKey(t *testing.T) {
}
}
func TestRegisterRejectsNilConstructor(t *testing.T) {
registry := New()
func TestInputAdapterRegistryRegisterRejectsNilConstructor(t *testing.T) {
registry := NewInputAdapterRegistry()
err := registry.Register("generic-input", nil)
@@ -85,8 +85,8 @@ func TestRegisterRejectsNilConstructor(t *testing.T) {
}
}
func TestBuildRejectsUnknownKey(t *testing.T) {
registry := New()
func TestInputAdapterRegistryBuildRejectsUnknownKey(t *testing.T) {
registry := NewInputAdapterRegistry()
_, err := registry.Build("missing-input")
@@ -98,8 +98,8 @@ func TestBuildRejectsUnknownKey(t *testing.T) {
}
}
func TestBuildWrapsConstructorError(t *testing.T) {
registry := New()
func TestInputAdapterRegistryBuildWrapsConstructorError(t *testing.T) {
registry := NewInputAdapterRegistry()
constructorErr := errors.New("constructor failed")
if err := registry.Register("generic-input", func() (contracts.InputAdapter, error) {
return nil, constructorErr
@@ -120,8 +120,8 @@ func TestBuildWrapsConstructorError(t *testing.T) {
}
}
func TestBuildRejectsNilAdapter(t *testing.T) {
registry := New()
func TestInputAdapterRegistryBuildRejectsNilAdapter(t *testing.T) {
registry := NewInputAdapterRegistry()
if err := registry.Register("generic-input", func() (contracts.InputAdapter, error) {
return nil, nil
}); err != nil {
@@ -138,9 +138,9 @@ func TestBuildRejectsNilAdapter(t *testing.T) {
}
}
func TestBuildRejectsAdapterKeyMismatch(t *testing.T) {
registry := New()
if err := registry.Register("generic-input", fakeConstructor("other-input")); err != nil {
func TestInputAdapterRegistryBuildRejectsAdapterKeyMismatch(t *testing.T) {
registry := NewInputAdapterRegistry()
if err := registry.Register("generic-input", fakeInputAdapterConstructor("other-input")); err != nil {
t.Fatalf("Register() error = %v, want nil", err)
}
@@ -154,10 +154,10 @@ func TestBuildRejectsAdapterKeyMismatch(t *testing.T) {
}
}
func TestRegisteredKeysReturnsSortedCopy(t *testing.T) {
registry := New()
func TestInputAdapterRegistryRegisteredKeysReturnsSortedCopy(t *testing.T) {
registry := NewInputAdapterRegistry()
for _, key := range []string{"zeta", "alpha", "middle"} {
if err := registry.Register(key, fakeConstructor(key)); err != nil {
if err := registry.Register(key, fakeInputAdapterConstructor(key)); err != nil {
t.Fatalf("Register(%q) error = %v, want nil", key, err)
}
}
@@ -175,10 +175,10 @@ func TestRegisteredKeysReturnsSortedCopy(t *testing.T) {
}
}
func TestNilRegistryBehavior(t *testing.T) {
var registry *Registry
func TestInputAdapterRegistryNilRegistryBehavior(t *testing.T) {
var registry *InputAdapterRegistry
if err := registry.Register("generic-input", fakeConstructor("generic-input")); err == nil {
if err := registry.Register("generic-input", fakeInputAdapterConstructor("generic-input")); err == nil {
t.Fatal("Register() error = nil, want error")
}
if _, err := registry.Build("generic-input"); err == nil {
@@ -189,8 +189,8 @@ func TestNilRegistryBehavior(t *testing.T) {
}
}
func TestBuildRejectsEmptyKey(t *testing.T) {
registry := New()
func TestInputAdapterRegistryBuildRejectsEmptyKey(t *testing.T) {
registry := NewInputAdapterRegistry()
_, err := registry.Build(" \n")
@@ -206,7 +206,7 @@ type fakeAdapter struct {
key string
}
func fakeConstructor(key string) Constructor {
func fakeInputAdapterConstructor(key string) InputAdapterConstructor {
return func() (contracts.InputAdapter, error) {
return fakeAdapter{key: key}, nil
}

View File

@@ -1,4 +1,4 @@
package runner
package pipeline
import (
"context"
@@ -8,14 +8,14 @@ import (
"gitea.maximumdirect.net/eric/notarius/internal/core/artifacts"
"gitea.maximumdirect.net/eric/notarius/internal/core/source"
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
"gitea.maximumdirect.net/eric/notarius/internal/framework/extractorregistry"
validationhelpers "gitea.maximumdirect.net/eric/notarius/internal/framework/validators"
validate "gitea.maximumdirect.net/eric/notarius/internal/framework/validate"
)
func TestRunnerUsesExtractorRegistry(t *testing.T) {
var builtKeys []string
var executedKeys []string
registry := extractorregistry.New()
registry := NewExtractorRegistry()
registerIntegrationExtractor(t, registry, "second", &builtKeys, &executedKeys, []contracts.Validator{
integrationValidator{name: "reject-second", approve: false},
@@ -46,7 +46,7 @@ func TestRunnerUsesExtractorRegistry(t *testing.T) {
}
}
func registerIntegrationExtractor(t *testing.T, registry *extractorregistry.Registry, key string, builtKeys *[]string, executedKeys *[]string, validators []contracts.Validator) {
func registerIntegrationExtractor(t *testing.T, registry *ExtractorRegistry, key string, builtKeys *[]string, executedKeys *[]string, validators []contracts.Validator) {
t.Helper()
if err := registry.Register(key, func() (contracts.Extractor, error) {
@@ -101,9 +101,9 @@ func (validator integrationValidator) Validate(ctx context.Context, req contract
decisions := make([]contracts.ValidationDecision, 0, len(req.Candidates))
for _, candidate := range req.Candidates {
if validator.approve {
decisions = append(decisions, validationhelpers.Approved(candidate.Index))
decisions = append(decisions, validate.Approved(candidate.Index))
} else {
decisions = append(decisions, validationhelpers.Rejected(candidate.Index, "invalid", "not accepted"))
decisions = append(decisions, validate.Rejected(candidate.Index, "invalid", "not accepted"))
}
}
return contracts.ValidationResult{

View File

@@ -1,4 +1,4 @@
package runner
package pipeline
import (
"context"
@@ -7,7 +7,7 @@ import (
"gitea.maximumdirect.net/eric/notarius/internal/core/artifacts"
"gitea.maximumdirect.net/eric/notarius/internal/core/source"
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
"gitea.maximumdirect.net/eric/notarius/internal/framework/validators"
"gitea.maximumdirect.net/eric/notarius/internal/framework/validate"
)
type ExtractorFactory interface {
@@ -140,7 +140,7 @@ func runValidators(ctx context.Context, extractor contracts.Extractor, doc *sour
if result.ValidatorName != validator.Name() {
return nil, rejected, warnings, fmt.Errorf("validator %q returned result for %q", validator.Name(), result.ValidatorName)
}
if err := validators.EnforceDecisionCardinality(eligible, result.Decisions); err != nil {
if err := validate.EnforceDecisionCardinality(eligible, result.Decisions); err != nil {
return nil, rejected, warnings, fmt.Errorf("validate extractor %q with validator %q: %w", extractor.Key(), validator.Name(), err)
}

View File

@@ -1,4 +1,4 @@
package runner
package pipeline
import (
"context"
@@ -10,7 +10,7 @@ import (
"gitea.maximumdirect.net/eric/notarius/internal/core/artifacts"
"gitea.maximumdirect.net/eric/notarius/internal/core/source"
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
validationhelpers "gitea.maximumdirect.net/eric/notarius/internal/framework/validators"
validate "gitea.maximumdirect.net/eric/notarius/internal/framework/validate"
)
func TestNewAndDataTypes(t *testing.T) {
@@ -103,7 +103,7 @@ func TestRunUsesConfiguredExtractorOrderAndAssignsGlobalIndices(t *testing.T) {
decisions := make([]contracts.ValidationDecision, 0, len(candidates))
for _, candidate := range candidates {
seenIndices = append(seenIndices, candidate.Index)
decisions = append(decisions, validationhelpers.Approved(candidate.Index))
decisions = append(decisions, validate.Approved(candidate.Index))
}
return decisions
}
@@ -195,7 +195,7 @@ func TestRunApprovesCandidatesWithoutValidators(t *testing.T) {
func TestRunValidatorApprovalProducesApprovedArtifacts(t *testing.T) {
validator := fakeValidator{name: "generic-validator", decisions: func(candidates []artifacts.ArtifactCandidate) []contracts.ValidationDecision {
return []contracts.ValidationDecision{validationhelpers.Approved(candidates[0].Index)}
return []contracts.ValidationDecision{validate.Approved(candidates[0].Index)}
}}
factory := fakeFactory{extractors: map[string]contracts.Extractor{
"generic-extractor": fakeExtractor{key: "generic-extractor", artifactType: "generic-artifact", schemaVersion: "v1", candidateCount: 1, validators: []contracts.Validator{validator}},
@@ -214,13 +214,13 @@ func TestRunValidatorRejectionRemovesCandidateFromLaterValidators(t *testing.T)
var laterSeen int
rejectFirst := fakeValidator{name: "reject-first", decisions: func(candidates []artifacts.ArtifactCandidate) []contracts.ValidationDecision {
return []contracts.ValidationDecision{
validationhelpers.Rejected(candidates[0].Index, "invalid", "not accepted"),
validationhelpers.Approved(candidates[1].Index),
validate.Rejected(candidates[0].Index, "invalid", "not accepted"),
validate.Approved(candidates[1].Index),
}
}}
approveRemaining := fakeValidator{name: "approve-remaining", decisions: func(candidates []artifacts.ArtifactCandidate) []contracts.ValidationDecision {
laterSeen = len(candidates)
return []contracts.ValidationDecision{validationhelpers.Approved(candidates[0].Index)}
return []contracts.ValidationDecision{validate.Approved(candidates[0].Index)}
}}
factory := fakeFactory{extractors: map[string]contracts.Extractor{
"generic-extractor": fakeExtractor{key: "generic-extractor", artifactType: "generic-artifact", schemaVersion: "v1", candidateCount: 2, validators: []contracts.Validator{rejectFirst, approveRemaining}},
@@ -439,7 +439,7 @@ func factoryWithValidator(validator contracts.Validator) fakeFactory {
func approveAll(candidates []artifacts.ArtifactCandidate) []contracts.ValidationDecision {
decisions := make([]contracts.ValidationDecision, 0, len(candidates))
for _, candidate := range candidates {
decisions = append(decisions, validationhelpers.Approved(candidate.Index))
decisions = append(decisions, validate.Approved(candidate.Index))
}
return decisions
}

View File

@@ -1,4 +1,4 @@
package validators
package validate
import (
"fmt"

View File

@@ -1,4 +1,4 @@
package validators
package validate
import (
"strings"