Generate contract types, pin fixtures to spec, add build and ADRs
Some checks failed
ci / build (push) Failing after 1m6s
Some checks failed
ci / build (push) Failing after 1m6s
Completes FLUID-WP-0002. The record types in internal/contract are generated from schemas/ by a dependency-free generator; fixtures transcribed from the spec's worked examples validate against those schemas and round-trip through the generated types with DisallowUnknownFields, so a spec change that misses the schemas fails CI rather than drifting silently. Adds identifier prefix helpers, Makefile, GitHub Actions, and five ADRs recording the Go choice, out-of-process attachment, the wire contract as boundary, the evidence store, and revision identity. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014KmVxhJ35tCo7rE7UnLwWu Assistant: claude-code Assistant-Model: opus Assistant-Process: 1116572@bnt-lap001 Assistant-Session: 8ba9bb93-a72a-4883-b189-2499cce5c400
This commit is contained in:
parent
fbbf56df7a
commit
76912adef8
44 changed files with 4010 additions and 7 deletions
100
internal/contract/backend_requirement_gen.go
Normal file
100
internal/contract/backend_requirement_gen.go
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
// Code generated by tools/schemagen. DO NOT EDIT.
|
||||
// Source: schemas/. Regenerate with `make generate`.
|
||||
|
||||
package contract
|
||||
|
||||
type FluidBackendRequirementCapability struct {
|
||||
Description string `json:"description" yaml:"description"`
|
||||
Title string `json:"title" yaml:"title"`
|
||||
}
|
||||
|
||||
type FluidBackendRequirementDispositionState string
|
||||
|
||||
const (
|
||||
FluidBackendRequirementDispositionStateOPEN FluidBackendRequirementDispositionState = "OPEN"
|
||||
FluidBackendRequirementDispositionStateACCEPTED FluidBackendRequirementDispositionState = "ACCEPTED"
|
||||
FluidBackendRequirementDispositionStatePLANNED FluidBackendRequirementDispositionState = "PLANNED"
|
||||
FluidBackendRequirementDispositionStateAVAILABLE FluidBackendRequirementDispositionState = "AVAILABLE"
|
||||
FluidBackendRequirementDispositionStatePARTIALLYAVAILABLE FluidBackendRequirementDispositionState = "PARTIALLY_AVAILABLE"
|
||||
FluidBackendRequirementDispositionStateOUTOFSCOPE FluidBackendRequirementDispositionState = "OUT_OF_SCOPE"
|
||||
FluidBackendRequirementDispositionStateREJECTED FluidBackendRequirementDispositionState = "REJECTED"
|
||||
FluidBackendRequirementDispositionStateSUPERSEDED FluidBackendRequirementDispositionState = "SUPERSEDED"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidBackendRequirementDispositionState.
|
||||
func (v FluidBackendRequirementDispositionState) Valid() bool {
|
||||
switch v {
|
||||
case FluidBackendRequirementDispositionStateOPEN, FluidBackendRequirementDispositionStateACCEPTED, FluidBackendRequirementDispositionStatePLANNED, FluidBackendRequirementDispositionStateAVAILABLE, FluidBackendRequirementDispositionStatePARTIALLYAVAILABLE, FluidBackendRequirementDispositionStateOUTOFSCOPE, FluidBackendRequirementDispositionStateREJECTED, FluidBackendRequirementDispositionStateSUPERSEDED:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// The backend decides. Repeated OUT_OF_SCOPE feeds boundary learning
|
||||
// (ArchitectureBlueprint.md section 22).
|
||||
type FluidBackendRequirementDisposition struct {
|
||||
Reason *string `json:"reason,omitempty" yaml:"reason,omitempty"`
|
||||
State FluidBackendRequirementDispositionState `json:"state" yaml:"state"`
|
||||
TargetRef *string `json:"target_ref,omitempty" yaml:"target_ref,omitempty"`
|
||||
}
|
||||
|
||||
type FluidBackendRequirementExpectedUsage struct {
|
||||
RequestsPerDay *int64 `json:"requests_per_day,omitempty" yaml:"requests_per_day,omitempty"`
|
||||
}
|
||||
|
||||
type FluidBackendRequirementQuality struct {
|
||||
Availability *UnitInterval `json:"availability,omitempty" yaml:"availability,omitempty"`
|
||||
P95LatencyMS *float64 `json:"p95_latency_ms,omitempty" yaml:"p95_latency_ms,omitempty"`
|
||||
}
|
||||
|
||||
type FluidBackendRequirementSecurity struct {
|
||||
AuthorizationScope string `json:"authorization_scope,omitempty" yaml:"authorization_scope,omitempty"`
|
||||
TenantIsolation string `json:"tenant_isolation,omitempty" yaml:"tenant_isolation,omitempty"`
|
||||
}
|
||||
|
||||
type FluidBackendRequirementSemantics struct {
|
||||
Consistency string `json:"consistency,omitempty" yaml:"consistency,omitempty"`
|
||||
RequiredFields []string `json:"required_fields,omitempty" yaml:"required_fields,omitempty"`
|
||||
}
|
||||
|
||||
type FluidBackendRequirementUrgency string
|
||||
|
||||
const (
|
||||
FluidBackendRequirementUrgencyLOW FluidBackendRequirementUrgency = "LOW"
|
||||
FluidBackendRequirementUrgencyMEDIUM FluidBackendRequirementUrgency = "MEDIUM"
|
||||
FluidBackendRequirementUrgencyHIGH FluidBackendRequirementUrgency = "HIGH"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidBackendRequirementUrgency.
|
||||
func (v FluidBackendRequirementUrgency) Valid() bool {
|
||||
switch v {
|
||||
case FluidBackendRequirementUrgencyLOW, FluidBackendRequirementUrgencyMEDIUM, FluidBackendRequirementUrgencyHIGH:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type FluidBackendRequirement struct {
|
||||
BackendService string `json:"backend_service" yaml:"backend_service"`
|
||||
Capability FluidBackendRequirementCapability `json:"capability" yaml:"capability"`
|
||||
|
||||
// The backend decides. Repeated OUT_OF_SCOPE feeds boundary learning
|
||||
// (ArchitectureBlueprint.md section 22).
|
||||
Disposition FluidBackendRequirementDisposition `json:"disposition" yaml:"disposition"`
|
||||
ExpectedUsage *FluidBackendRequirementExpectedUsage `json:"expected_usage,omitempty" yaml:"expected_usage,omitempty"`
|
||||
ID BackendRequirementID `json:"id" yaml:"id"`
|
||||
OriginatingHypothesis *HypothesisID `json:"originating_hypothesis,omitempty" yaml:"originating_hypothesis,omitempty"`
|
||||
OriginatingInterface InterfaceID `json:"originating_interface" yaml:"originating_interface"`
|
||||
OriginatingRevision *RevisionID `json:"originating_revision,omitempty" yaml:"originating_revision,omitempty"`
|
||||
Quality *FluidBackendRequirementQuality `json:"quality,omitempty" yaml:"quality,omitempty"`
|
||||
SchemaVersion SchemaVersion `json:"schema_version" yaml:"schema_version"`
|
||||
Security *FluidBackendRequirementSecurity `json:"security,omitempty" yaml:"security,omitempty"`
|
||||
Semantics *FluidBackendRequirementSemantics `json:"semantics,omitempty" yaml:"semantics,omitempty"`
|
||||
Urgency *FluidBackendRequirementUrgency `json:"urgency,omitempty" yaml:"urgency,omitempty"`
|
||||
}
|
||||
|
||||
// Capability the interface needs but has no authority to build. FLUID escalates
|
||||
// rather than crossing the boundary (FluidAPIStandards.md section 30).
|
||||
type BackendRequirementDocument struct {
|
||||
FluidBackendRequirement FluidBackendRequirement `json:"fluid_backend_requirement" yaml:"fluid_backend_requirement"`
|
||||
}
|
||||
207
internal/contract/common_gen.go
Normal file
207
internal/contract/common_gen.go
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
// Code generated by tools/schemagen. DO NOT EDIT.
|
||||
// Source: schemas/. Regenerate with `make generate`.
|
||||
|
||||
package contract
|
||||
|
||||
import "time"
|
||||
|
||||
type ActorType string
|
||||
|
||||
const (
|
||||
ActorTypeHuman ActorType = "human"
|
||||
ActorTypeDaimon ActorType = "daimon"
|
||||
ActorTypePolicy ActorType = "policy"
|
||||
ActorTypeSystem ActorType = "system"
|
||||
ActorTypeConsumer ActorType = "consumer"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined ActorType.
|
||||
func (v ActorType) Valid() bool {
|
||||
switch v {
|
||||
case ActorTypeHuman, ActorTypeDaimon, ActorTypePolicy, ActorTypeSystem, ActorTypeConsumer:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Who or what performed an action. FLUID distinguishes these because trust levels
|
||||
// differ (ArchitectureBlueprint.md section 47).
|
||||
type Actor struct {
|
||||
ID string `json:"id" yaml:"id"`
|
||||
ModelOrAgent string `json:"model_or_agent,omitempty" yaml:"model_or_agent,omitempty"`
|
||||
Type ActorType `json:"type" yaml:"type"`
|
||||
}
|
||||
|
||||
// FluidAPIStandards.md section 16.
|
||||
type AdaptationClass string
|
||||
|
||||
const (
|
||||
AdaptationClassPresentation AdaptationClass = "presentation"
|
||||
AdaptationClassContract AdaptationClass = "contract"
|
||||
AdaptationClassComposition AdaptationClass = "composition"
|
||||
AdaptationClassImplementation AdaptationClass = "implementation"
|
||||
AdaptationClassRequirementEscalation AdaptationClass = "requirement_escalation"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined AdaptationClass.
|
||||
func (v AdaptationClass) Valid() bool {
|
||||
switch v {
|
||||
case AdaptationClassPresentation, AdaptationClassContract, AdaptationClassComposition, AdaptationClassImplementation, AdaptationClassRequirementEscalation:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Opaque reference into the artifact store.
|
||||
type ArtifactRef string
|
||||
|
||||
type BackendRequirementID string
|
||||
|
||||
type CohortID string
|
||||
|
||||
// Standard dimensions, implementation-defined scoring (FluidAPIStandards.md section
|
||||
// 22).
|
||||
type ComplexityDelta struct {
|
||||
ActiveRevisionCount *float64 `json:"active_revision_count,omitempty" yaml:"active_revision_count,omitempty"`
|
||||
AlternativePathCount *float64 `json:"alternative_path_count,omitempty" yaml:"alternative_path_count,omitempty"`
|
||||
BackendCompositionCount *float64 `json:"backend_composition_count,omitempty" yaml:"backend_composition_count,omitempty"`
|
||||
CognitiveLoad *float64 `json:"cognitive_load,omitempty" yaml:"cognitive_load,omitempty"`
|
||||
ConceptCount *float64 `json:"concept_count,omitempty" yaml:"concept_count,omitempty"`
|
||||
DependencyCount *float64 `json:"dependency_count,omitempty" yaml:"dependency_count,omitempty"`
|
||||
ExceptionCount *float64 `json:"exception_count,omitempty" yaml:"exception_count,omitempty"`
|
||||
OperationCount *float64 `json:"operation_count,omitempty" yaml:"operation_count,omitempty"`
|
||||
ParameterDimensionality *float64 `json:"parameter_dimensionality,omitempty" yaml:"parameter_dimensionality,omitempty"`
|
||||
SemanticOverlap *float64 `json:"semantic_overlap,omitempty" yaml:"semantic_overlap,omitempty"`
|
||||
SurfaceArea *float64 `json:"surface_area,omitempty" yaml:"surface_area,omitempty"`
|
||||
}
|
||||
|
||||
type DecisionID string
|
||||
|
||||
// Content address of an artifact.
|
||||
type Digest string
|
||||
|
||||
type EventID string
|
||||
|
||||
// Opaque reference into the evidence store, conventionally '<kind>:<locator>' such
|
||||
// as 'telemetry:invoice-pattern-2026w36'.
|
||||
type EvidenceRef string
|
||||
|
||||
type ExpectedOutcomeDirection string
|
||||
|
||||
const (
|
||||
ExpectedOutcomeDirectionLower ExpectedOutcomeDirection = "lower"
|
||||
ExpectedOutcomeDirectionHigher ExpectedOutcomeDirection = "higher"
|
||||
ExpectedOutcomeDirectionUnchanged ExpectedOutcomeDirection = "unchanged"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined ExpectedOutcomeDirection.
|
||||
func (v ExpectedOutcomeDirection) Valid() bool {
|
||||
switch v {
|
||||
case ExpectedOutcomeDirectionLower, ExpectedOutcomeDirectionHigher, ExpectedOutcomeDirectionUnchanged:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ExpectedOutcome struct {
|
||||
Baseline *float64 `json:"baseline,omitempty" yaml:"baseline,omitempty"`
|
||||
Cohort string `json:"cohort,omitempty" yaml:"cohort,omitempty"`
|
||||
Direction ExpectedOutcomeDirection `json:"direction" yaml:"direction"`
|
||||
Metric string `json:"metric" yaml:"metric"`
|
||||
Target float64 `json:"target" yaml:"target"`
|
||||
}
|
||||
|
||||
type ExperimentID string
|
||||
|
||||
type FeedbackID string
|
||||
|
||||
// FluidAPIStandards.md section 20. No universal scalar is defined on purpose.
|
||||
type FitnessDimensions struct {
|
||||
Availability *float64 `json:"availability,omitempty" yaml:"availability,omitempty"`
|
||||
ClientUtility *float64 `json:"client_utility,omitempty" yaml:"client_utility,omitempty"`
|
||||
Compatibility *float64 `json:"compatibility,omitempty" yaml:"compatibility,omitempty"`
|
||||
Correctness *float64 `json:"correctness,omitempty" yaml:"correctness,omitempty"`
|
||||
Discoverability *float64 `json:"discoverability,omitempty" yaml:"discoverability,omitempty"`
|
||||
ImplementationCost *float64 `json:"implementation_cost,omitempty" yaml:"implementation_cost,omitempty"`
|
||||
Maintainability *float64 `json:"maintainability,omitempty" yaml:"maintainability,omitempty"`
|
||||
OperationalCost *float64 `json:"operational_cost,omitempty" yaml:"operational_cost,omitempty"`
|
||||
Performance *float64 `json:"performance,omitempty" yaml:"performance,omitempty"`
|
||||
Reliability *float64 `json:"reliability,omitempty" yaml:"reliability,omitempty"`
|
||||
ResourceConsumption *float64 `json:"resource_consumption,omitempty" yaml:"resource_consumption,omitempty"`
|
||||
Security *float64 `json:"security,omitempty" yaml:"security,omitempty"`
|
||||
Simplicity *float64 `json:"simplicity,omitempty" yaml:"simplicity,omitempty"`
|
||||
}
|
||||
|
||||
type GuardrailOperator string
|
||||
|
||||
const (
|
||||
GuardrailOperatorLt GuardrailOperator = "<"
|
||||
GuardrailOperatorLte GuardrailOperator = "<="
|
||||
GuardrailOperatorEq GuardrailOperator = "=="
|
||||
GuardrailOperatorNeq GuardrailOperator = "!="
|
||||
GuardrailOperatorGte GuardrailOperator = ">="
|
||||
GuardrailOperatorGt GuardrailOperator = ">"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined GuardrailOperator.
|
||||
func (v GuardrailOperator) Valid() bool {
|
||||
switch v {
|
||||
case GuardrailOperatorLt, GuardrailOperatorLte, GuardrailOperatorEq, GuardrailOperatorNeq, GuardrailOperatorGte, GuardrailOperatorGt:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// A constraint that must not regress beyond threshold. Guardrails are evaluated
|
||||
// deterministically.
|
||||
type Guardrail struct {
|
||||
Metric string `json:"metric" yaml:"metric"`
|
||||
Operator GuardrailOperator `json:"operator" yaml:"operator"`
|
||||
Threshold any `json:"threshold" yaml:"threshold"`
|
||||
}
|
||||
|
||||
type HypothesisID string
|
||||
|
||||
// Stable identifier of the owning interface.
|
||||
type InterfaceID string
|
||||
|
||||
type ObservationWindow struct {
|
||||
// Null while the window is still open.
|
||||
End *Timestamp `json:"end,omitempty" yaml:"end,omitempty"`
|
||||
Start Timestamp `json:"start" yaml:"start"`
|
||||
}
|
||||
|
||||
// FluidAPIStandards.md section 13.
|
||||
type PressureClass string
|
||||
|
||||
const (
|
||||
PressureClassNaturalUsage PressureClass = "natural_usage"
|
||||
PressureClassSuccessfulButInefficientUsage PressureClass = "successful_but_inefficient_usage"
|
||||
PressureClassRecoverableMisunderstanding PressureClass = "recoverable_misunderstanding"
|
||||
PressureClassRepeatedExpectationMismatch PressureClass = "repeated_expectation_mismatch"
|
||||
PressureClassPoorDiscoverability PressureClass = "poor_discoverability"
|
||||
PressureClassMissingInterfaceCapability PressureClass = "missing_interface_capability"
|
||||
PressureClassMissingBackendCapability PressureClass = "missing_backend_capability"
|
||||
PressureClassOutOfScopeDemand PressureClass = "out_of_scope_demand"
|
||||
PressureClassProhibitedDemand PressureClass = "prohibited_demand"
|
||||
PressureClassImplementationFailure PressureClass = "implementation_failure"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined PressureClass.
|
||||
func (v PressureClass) Valid() bool {
|
||||
switch v {
|
||||
case PressureClassNaturalUsage, PressureClassSuccessfulButInefficientUsage, PressureClassRecoverableMisunderstanding, PressureClassRepeatedExpectationMismatch, PressureClassPoorDiscoverability, PressureClassMissingInterfaceCapability, PressureClassMissingBackendCapability, PressureClassOutOfScopeDemand, PressureClassProhibitedDemand, PressureClassImplementationFailure:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type PressureID string
|
||||
|
||||
type RevisionID string
|
||||
|
||||
type SchemaVersion string
|
||||
|
||||
type Timestamp = time.Time
|
||||
|
||||
type UnitInterval float64
|
||||
203
internal/contract/contract_test.go
Normal file
203
internal/contract/contract_test.go
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
package contract
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// fixtureDir holds JSON copies of the spec-derived YAML fixtures, written by
|
||||
// conformance/validate_schemas.py.
|
||||
const fixtureDir = "../../conformance/fixtures/json"
|
||||
|
||||
// roundTrip decodes a fixture into T, re-encodes it, and reports any field the
|
||||
// generated types dropped on the way through.
|
||||
//
|
||||
// This is the drift check that matters: a schema change that schemagen did not
|
||||
// pick up shows here as a field that vanishes.
|
||||
func roundTrip[T any](t *testing.T, name string) {
|
||||
t.Helper()
|
||||
|
||||
raw, err := os.ReadFile(filepath.Join(fixtureDir, name+".json"))
|
||||
if err != nil {
|
||||
t.Fatalf("read fixture: %v (run `make validate` first)", err)
|
||||
}
|
||||
|
||||
var typed T
|
||||
dec := json.NewDecoder(bytesReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&typed); err != nil {
|
||||
t.Fatalf("decode into %T: %v", typed, err)
|
||||
}
|
||||
|
||||
encoded, err := json.Marshal(typed)
|
||||
if err != nil {
|
||||
t.Fatalf("re-encode: %v", err)
|
||||
}
|
||||
|
||||
var before, after map[string]any
|
||||
if err := json.Unmarshal(raw, &before); err != nil {
|
||||
t.Fatalf("unmarshal fixture: %v", err)
|
||||
}
|
||||
if err := json.Unmarshal(encoded, &after); err != nil {
|
||||
t.Fatalf("unmarshal re-encoded: %v", err)
|
||||
}
|
||||
|
||||
if missing := missingKeys(before, after, ""); len(missing) > 0 {
|
||||
t.Errorf("round trip dropped fields: %v", missing)
|
||||
}
|
||||
}
|
||||
|
||||
// missingKeys walks want and reports paths absent from got.
|
||||
//
|
||||
// Explicit nulls and empty collections are skipped. The schemas treat
|
||||
// "end: null" and an absent "end" as the same statement (the window is still
|
||||
// open), so omitempty dropping them on re-encode is correct rather than drift.
|
||||
// Genuine drift -- a fixture field the generated types have no home for -- is
|
||||
// caught by DisallowUnknownFields on the way in.
|
||||
func missingKeys(want, got map[string]any, prefix string) []string {
|
||||
var missing []string
|
||||
for k, wv := range want {
|
||||
path := k
|
||||
if prefix != "" {
|
||||
path = prefix + "." + k
|
||||
}
|
||||
if isEmptyValue(wv) {
|
||||
continue
|
||||
}
|
||||
gv, ok := got[k]
|
||||
if !ok {
|
||||
missing = append(missing, path)
|
||||
continue
|
||||
}
|
||||
wm, wok := wv.(map[string]any)
|
||||
gm, gok := gv.(map[string]any)
|
||||
if wok && gok {
|
||||
missing = append(missing, missingKeys(wm, gm, path)...)
|
||||
}
|
||||
}
|
||||
return missing
|
||||
}
|
||||
|
||||
// isEmptyValue reports values the schema treats as equivalent to absent.
|
||||
func isEmptyValue(v any) bool {
|
||||
switch t := v.(type) {
|
||||
case nil:
|
||||
return true
|
||||
case []any:
|
||||
return len(t) == 0
|
||||
case map[string]any:
|
||||
return len(t) == 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func TestFixturesRoundTrip(t *testing.T) {
|
||||
t.Run("pressure", func(t *testing.T) { roundTrip[PressureDocument](t, "pressure") })
|
||||
t.Run("hypothesis", func(t *testing.T) { roundTrip[HypothesisDocument](t, "hypothesis") })
|
||||
t.Run("revision", func(t *testing.T) { roundTrip[RevisionDocument](t, "revision") })
|
||||
t.Run("experiment", func(t *testing.T) { roundTrip[ExperimentDocument](t, "experiment") })
|
||||
t.Run("event", func(t *testing.T) { roundTrip[EventDocument](t, "event") })
|
||||
t.Run("feedback", func(t *testing.T) { roundTrip[FeedbackDocument](t, "feedback") })
|
||||
t.Run("backend-requirement", func(t *testing.T) {
|
||||
roundTrip[BackendRequirementDocument](t, "backend-requirement")
|
||||
})
|
||||
t.Run("revision-descriptor", func(t *testing.T) {
|
||||
roundTrip[RevisionDescriptorDocument](t, "revision-descriptor")
|
||||
})
|
||||
t.Run("routing-policy", func(t *testing.T) { roundTrip[RoutingPolicyDocument](t, "routing-policy") })
|
||||
t.Run("telemetry-envelope", func(t *testing.T) {
|
||||
roundTrip[TelemetryEnvelopeDocument](t, "telemetry-envelope")
|
||||
})
|
||||
}
|
||||
|
||||
func TestKindOf(t *testing.T) {
|
||||
cases := map[string]EntityKind{
|
||||
"H-000184": KindHypothesis,
|
||||
"R-000221": KindRevision,
|
||||
"E-000093": KindExperiment,
|
||||
"P-1831": KindPressure,
|
||||
"BR-0041": KindBackendRequirement,
|
||||
"D-2811": KindDecision,
|
||||
"EV-990281": KindEvent,
|
||||
"F-9821": KindFeedback,
|
||||
"C-17": KindCohort,
|
||||
}
|
||||
for id, want := range cases {
|
||||
got, ok := KindOf(id)
|
||||
if !ok || got != want {
|
||||
t.Errorf("KindOf(%q) = %q, %v; want %q", id, got, ok, want)
|
||||
}
|
||||
}
|
||||
|
||||
// BR- and EV- must not be swallowed by the single-letter prefixes.
|
||||
if k, _ := KindOf("BR-1"); k != KindBackendRequirement {
|
||||
t.Errorf("BR- prefix mis-classified as %q", k)
|
||||
}
|
||||
if k, _ := KindOf("EV-1"); k != KindEvent {
|
||||
t.Errorf("EV- prefix mis-classified as %q", k)
|
||||
}
|
||||
|
||||
if _, ok := KindOf("something"); ok {
|
||||
t.Error("unprefixed identifier should not classify")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRequireKind(t *testing.T) {
|
||||
if err := RequireKind("R-1", KindRevision); err != nil {
|
||||
t.Errorf("valid revision id rejected: %v", err)
|
||||
}
|
||||
err := RequireKind("H-1", KindRevision)
|
||||
if err == nil {
|
||||
t.Fatal("hypothesis id accepted where a revision id was required")
|
||||
}
|
||||
var wrong *ErrWrongKind
|
||||
if !errorsAs(err, &wrong) {
|
||||
t.Fatalf("expected *ErrWrongKind, got %T", err)
|
||||
}
|
||||
if wrong.Got != KindHypothesis || wrong.Want != KindRevision {
|
||||
t.Errorf("unexpected error detail: %+v", wrong)
|
||||
}
|
||||
}
|
||||
|
||||
// Small helpers keep the test file free of imports the generated code does not
|
||||
// already require.
|
||||
func bytesReader(b []byte) *jsonReader { return &jsonReader{b: b} }
|
||||
|
||||
type jsonReader struct {
|
||||
b []byte
|
||||
i int
|
||||
}
|
||||
|
||||
func (r *jsonReader) Read(p []byte) (int, error) {
|
||||
if r.i >= len(r.b) {
|
||||
return 0, errEOF
|
||||
}
|
||||
n := copy(p, r.b[r.i:])
|
||||
r.i += n
|
||||
return n, nil
|
||||
}
|
||||
|
||||
var errEOF = errorString("EOF")
|
||||
|
||||
type errorString string
|
||||
|
||||
func (e errorString) Error() string { return string(e) }
|
||||
|
||||
func errorsAs(err error, target any) bool {
|
||||
tv := reflect.ValueOf(target).Elem()
|
||||
for err != nil {
|
||||
if reflect.TypeOf(err).AssignableTo(tv.Type()) {
|
||||
tv.Set(reflect.ValueOf(err))
|
||||
return true
|
||||
}
|
||||
u, ok := err.(interface{ Unwrap() error })
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
err = u.Unwrap()
|
||||
}
|
||||
return false
|
||||
}
|
||||
48
internal/contract/event_gen.go
Normal file
48
internal/contract/event_gen.go
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
// Code generated by tools/schemagen. DO NOT EDIT.
|
||||
// Source: schemas/. Regenerate with `make generate`.
|
||||
|
||||
package contract
|
||||
|
||||
type FluidEventEntityType string
|
||||
|
||||
const (
|
||||
FluidEventEntityTypePressure FluidEventEntityType = "pressure"
|
||||
FluidEventEntityTypeHypothesis FluidEventEntityType = "hypothesis"
|
||||
FluidEventEntityTypeRevision FluidEventEntityType = "revision"
|
||||
FluidEventEntityTypeExperiment FluidEventEntityType = "experiment"
|
||||
FluidEventEntityTypeBackendRequirement FluidEventEntityType = "backend_requirement"
|
||||
FluidEventEntityTypeIntent FluidEventEntityType = "intent"
|
||||
FluidEventEntityTypeDecision FluidEventEntityType = "decision"
|
||||
FluidEventEntityTypeRoutingPolicy FluidEventEntityType = "routing_policy"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidEventEntityType.
|
||||
func (v FluidEventEntityType) Valid() bool {
|
||||
switch v {
|
||||
case FluidEventEntityTypePressure, FluidEventEntityTypeHypothesis, FluidEventEntityTypeRevision, FluidEventEntityTypeExperiment, FluidEventEntityTypeBackendRequirement, FluidEventEntityTypeIntent, FluidEventEntityTypeDecision, FluidEventEntityTypeRoutingPolicy:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type FluidEvent struct {
|
||||
Actor Actor `json:"actor" yaml:"actor"`
|
||||
EntityID string `json:"entity_id" yaml:"entity_id"`
|
||||
EntityType FluidEventEntityType `json:"entity_type" yaml:"entity_type"`
|
||||
EventType string `json:"event_type" yaml:"event_type"`
|
||||
EvidenceRefs []EvidenceRef `json:"evidence_refs,omitempty" yaml:"evidence_refs,omitempty"`
|
||||
ID EventID `json:"id" yaml:"id"`
|
||||
|
||||
// Identifiers of the records this transition drew on.
|
||||
Inputs []string `json:"inputs,omitempty" yaml:"inputs,omitempty"`
|
||||
OccurredAt Timestamp `json:"occurred_at" yaml:"occurred_at"`
|
||||
Reason string `json:"reason,omitempty" yaml:"reason,omitempty"`
|
||||
SchemaVersion SchemaVersion `json:"schema_version" yaml:"schema_version"`
|
||||
}
|
||||
|
||||
// Append-only record of a material lifecycle transition. FLUID evolution is itself
|
||||
// a system behavior that must remain reconstructable
|
||||
// (FluidHypothesisRevisionSchema.md section 15).
|
||||
type EventDocument struct {
|
||||
FluidEvent FluidEvent `json:"fluid_event" yaml:"fluid_event"`
|
||||
}
|
||||
108
internal/contract/experiment_gen.go
Normal file
108
internal/contract/experiment_gen.go
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// Code generated by tools/schemagen. DO NOT EDIT.
|
||||
// Source: schemas/. Regenerate with `make generate`.
|
||||
|
||||
package contract
|
||||
|
||||
type FluidExperimentAmendmentsItem struct {
|
||||
Actor Actor `json:"actor" yaml:"actor"`
|
||||
At Timestamp `json:"at" yaml:"at"`
|
||||
Change string `json:"change" yaml:"change"`
|
||||
Reason string `json:"reason" yaml:"reason"`
|
||||
}
|
||||
|
||||
type FluidExperimentMechanism string
|
||||
|
||||
const (
|
||||
FluidExperimentMechanismSandbox FluidExperimentMechanism = "sandbox"
|
||||
FluidExperimentMechanismShadow FluidExperimentMechanism = "shadow"
|
||||
FluidExperimentMechanismSynthetic FluidExperimentMechanism = "synthetic"
|
||||
FluidExperimentMechanismReplay FluidExperimentMechanism = "replay"
|
||||
FluidExperimentMechanismCanary FluidExperimentMechanism = "canary"
|
||||
FluidExperimentMechanismOptIn FluidExperimentMechanism = "opt_in"
|
||||
FluidExperimentMechanismCohort FluidExperimentMechanism = "cohort"
|
||||
FluidExperimentMechanismTenant FluidExperimentMechanism = "tenant"
|
||||
FluidExperimentMechanismPercentage FluidExperimentMechanism = "percentage"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidExperimentMechanism.
|
||||
func (v FluidExperimentMechanism) Valid() bool {
|
||||
switch v {
|
||||
case FluidExperimentMechanismSandbox, FluidExperimentMechanismShadow, FluidExperimentMechanismSynthetic, FluidExperimentMechanismReplay, FluidExperimentMechanismCanary, FluidExperimentMechanismOptIn, FluidExperimentMechanismCohort, FluidExperimentMechanismTenant, FluidExperimentMechanismPercentage:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Primary metrics and guardrails are kept distinct so a scalar can never hide a
|
||||
// regression (ArchitectureBlueprint.md section 48.5).
|
||||
type FluidExperimentMetrics struct {
|
||||
Guardrails []string `json:"guardrails,omitempty" yaml:"guardrails,omitempty"`
|
||||
Learning []string `json:"learning,omitempty" yaml:"learning,omitempty"`
|
||||
Primary []string `json:"primary" yaml:"primary"`
|
||||
Secondary []string `json:"secondary,omitempty" yaml:"secondary,omitempty"`
|
||||
}
|
||||
|
||||
type FluidExperimentResultState string
|
||||
|
||||
const (
|
||||
FluidExperimentResultStatePLANNED FluidExperimentResultState = "PLANNED"
|
||||
FluidExperimentResultStateRUNNING FluidExperimentResultState = "RUNNING"
|
||||
FluidExperimentResultStateSTOPPED FluidExperimentResultState = "STOPPED"
|
||||
FluidExperimentResultStateCOMPLETED FluidExperimentResultState = "COMPLETED"
|
||||
FluidExperimentResultStateABANDONED FluidExperimentResultState = "ABANDONED"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidExperimentResultState.
|
||||
func (v FluidExperimentResultState) Valid() bool {
|
||||
switch v {
|
||||
case FluidExperimentResultStatePLANNED, FluidExperimentResultStateRUNNING, FluidExperimentResultStateSTOPPED, FluidExperimentResultStateCOMPLETED, FluidExperimentResultStateABANDONED:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type FluidExperimentResult struct {
|
||||
EvidenceRefs []EvidenceRef `json:"evidence_refs,omitempty" yaml:"evidence_refs,omitempty"`
|
||||
PreferredRevision *RevisionID `json:"preferred_revision,omitempty" yaml:"preferred_revision,omitempty"`
|
||||
State FluidExperimentResultState `json:"state" yaml:"state"`
|
||||
StoppedReason *string `json:"stopped_reason,omitempty" yaml:"stopped_reason,omitempty"`
|
||||
}
|
||||
|
||||
type FluidExperiment struct {
|
||||
// Shares by revision id or by the reserved key 'control'. Allocation is
|
||||
// deterministic and enacted by the router, never by this record.
|
||||
Allocation map[string]UnitInterval `json:"allocation" yaml:"allocation"`
|
||||
|
||||
// Success criteria may not be changed after results are visible without recording
|
||||
// the amendment (ArchitectureBlueprint.md section 18).
|
||||
Amendments []FluidExperimentAmendmentsItem `json:"amendments,omitempty" yaml:"amendments,omitempty"`
|
||||
CandidateRevisions []RevisionID `json:"candidate_revisions" yaml:"candidate_revisions"`
|
||||
Cohorts []CohortID `json:"cohorts,omitempty" yaml:"cohorts,omitempty"`
|
||||
ControlRevision RevisionID `json:"control_revision" yaml:"control_revision"`
|
||||
|
||||
// An experiment without a hypothesis measures nothing in particular.
|
||||
HypothesisRefs []HypothesisID `json:"hypothesis_refs" yaml:"hypothesis_refs"`
|
||||
ID ExperimentID `json:"id" yaml:"id"`
|
||||
InterfaceID InterfaceID `json:"interface_id" yaml:"interface_id"`
|
||||
MaxDurationHours *float64 `json:"max_duration_hours,omitempty" yaml:"max_duration_hours,omitempty"`
|
||||
Mechanism *FluidExperimentMechanism `json:"mechanism,omitempty" yaml:"mechanism,omitempty"`
|
||||
|
||||
// Primary metrics and guardrails are kept distinct so a scalar can never hide a
|
||||
// regression (ArchitectureBlueprint.md section 48.5).
|
||||
Metrics FluidExperimentMetrics `json:"metrics" yaml:"metrics"`
|
||||
PlannedEndAt *Timestamp `json:"planned_end_at,omitempty" yaml:"planned_end_at,omitempty"`
|
||||
Result FluidExperimentResult `json:"result" yaml:"result"`
|
||||
SchemaVersion SchemaVersion `json:"schema_version" yaml:"schema_version"`
|
||||
StartAt *Timestamp `json:"start_at,omitempty" yaml:"start_at,omitempty"`
|
||||
StartConditions []string `json:"start_conditions,omitempty" yaml:"start_conditions,omitempty"`
|
||||
|
||||
// Every experiment has a stop condition (ArchitectureBlueprint.md section 55,
|
||||
// invariant 7).
|
||||
StopConditions []string `json:"stop_conditions" yaml:"stop_conditions"`
|
||||
}
|
||||
|
||||
// Connects hypotheses to revisions under bounded conditions. Experiments must be
|
||||
// interruptible (ArchitectureBlueprint.md section 16).
|
||||
type ExperimentDocument struct {
|
||||
FluidExperiment FluidExperiment `json:"fluid_experiment" yaml:"fluid_experiment"`
|
||||
}
|
||||
33
internal/contract/feedback_gen.go
Normal file
33
internal/contract/feedback_gen.go
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Code generated by tools/schemagen. DO NOT EDIT.
|
||||
// Source: schemas/. Regenerate with `make generate`.
|
||||
|
||||
package contract
|
||||
|
||||
type FluidFeedbackImpact struct {
|
||||
Calls *int64 `json:"calls,omitempty" yaml:"calls,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
LatencyMS *float64 `json:"latency_ms,omitempty" yaml:"latency_ms,omitempty"`
|
||||
}
|
||||
|
||||
type FluidFeedback struct {
|
||||
Attempt string `json:"attempt,omitempty" yaml:"attempt,omitempty"`
|
||||
AttemptedOperations []string `json:"attempted_operations,omitempty" yaml:"attempted_operations,omitempty"`
|
||||
Cohort *CohortID `json:"cohort,omitempty" yaml:"cohort,omitempty"`
|
||||
Confidence *UnitInterval `json:"confidence,omitempty" yaml:"confidence,omitempty"`
|
||||
Goal string `json:"goal" yaml:"goal"`
|
||||
ID FeedbackID `json:"id" yaml:"id"`
|
||||
Impact *FluidFeedbackImpact `json:"impact,omitempty" yaml:"impact,omitempty"`
|
||||
InterfaceID InterfaceID `json:"interface_id" yaml:"interface_id"`
|
||||
MissingCapability string `json:"missing_capability,omitempty" yaml:"missing_capability,omitempty"`
|
||||
Outcome string `json:"outcome,omitempty" yaml:"outcome,omitempty"`
|
||||
ReceivedAt Timestamp `json:"received_at" yaml:"received_at"`
|
||||
Revision *RevisionID `json:"revision,omitempty" yaml:"revision,omitempty"`
|
||||
SchemaVersion SchemaVersion `json:"schema_version" yaml:"schema_version"`
|
||||
Workaround any `json:"workaround,omitempty" yaml:"workaround,omitempty"`
|
||||
}
|
||||
|
||||
// Structured feedback from a consumer. Treated as evidence and never as authority
|
||||
// to change anything (FluidAPIStandards.md section 15).
|
||||
type FeedbackDocument struct {
|
||||
FluidFeedback FluidFeedback `json:"fluid_feedback" yaml:"fluid_feedback"`
|
||||
}
|
||||
254
internal/contract/hypothesis_gen.go
Normal file
254
internal/contract/hypothesis_gen.go
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
// Code generated by tools/schemagen. DO NOT EDIT.
|
||||
// Source: schemas/. Regenerate with `make generate`.
|
||||
|
||||
package contract
|
||||
|
||||
type FluidHypothesisAudit struct {
|
||||
DecisionRefs []DecisionID `json:"decision_refs,omitempty" yaml:"decision_refs,omitempty"`
|
||||
ImmutableEventRefs []EventID `json:"immutable_event_refs,omitempty" yaml:"immutable_event_refs,omitempty"`
|
||||
}
|
||||
|
||||
type FluidHypothesisBackendRequirements struct {
|
||||
Required bool `json:"required" yaml:"required"`
|
||||
RequirementRefs []BackendRequirementID `json:"requirement_refs,omitempty" yaml:"requirement_refs,omitempty"`
|
||||
}
|
||||
|
||||
// Competing hypotheses are legitimate (FluidAPIStandards.md section 19).
|
||||
type FluidHypothesisCompetition struct {
|
||||
Alternatives []HypothesisID `json:"alternatives,omitempty" yaml:"alternatives,omitempty"`
|
||||
GroupID string `json:"group_id" yaml:"group_id"`
|
||||
}
|
||||
|
||||
type FluidHypothesisComplexity struct {
|
||||
ExpectedDelta ComplexityDelta `json:"expected_delta" yaml:"expected_delta"`
|
||||
Score *float64 `json:"score,omitempty" yaml:"score,omitempty"`
|
||||
}
|
||||
|
||||
type FluidHypothesisEconomicsExpectedValueClass string
|
||||
|
||||
const (
|
||||
FluidHypothesisEconomicsExpectedValueClassLOW FluidHypothesisEconomicsExpectedValueClass = "LOW"
|
||||
FluidHypothesisEconomicsExpectedValueClassMEDIUM FluidHypothesisEconomicsExpectedValueClass = "MEDIUM"
|
||||
FluidHypothesisEconomicsExpectedValueClassHIGH FluidHypothesisEconomicsExpectedValueClass = "HIGH"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidHypothesisEconomicsExpectedValueClass.
|
||||
func (v FluidHypothesisEconomicsExpectedValueClass) Valid() bool {
|
||||
switch v {
|
||||
case FluidHypothesisEconomicsExpectedValueClassLOW, FluidHypothesisEconomicsExpectedValueClassMEDIUM, FluidHypothesisEconomicsExpectedValueClassHIGH:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// A hypothesis may be valuable but not yet worth exploring
|
||||
// (ArchitectureBlueprint.md section 29).
|
||||
type FluidHypothesisEconomics struct {
|
||||
Currency string `json:"currency,omitempty" yaml:"currency,omitempty"`
|
||||
EstimatedExperimentCost *float64 `json:"estimated_experiment_cost,omitempty" yaml:"estimated_experiment_cost,omitempty"`
|
||||
EstimatedImplementationCost *float64 `json:"estimated_implementation_cost,omitempty" yaml:"estimated_implementation_cost,omitempty"`
|
||||
ExpectedValueClass *FluidHypothesisEconomicsExpectedValueClass `json:"expected_value_class,omitempty" yaml:"expected_value_class,omitempty"`
|
||||
}
|
||||
|
||||
// Explanatory reach is a prioritization signal, never a correctness claim
|
||||
// (FluidAPIStandards.md section 18).
|
||||
type FluidHypothesisExplanationReach struct {
|
||||
Explains []PressureID `json:"explains,omitempty" yaml:"explains,omitempty"`
|
||||
Notes string `json:"notes,omitempty" yaml:"notes,omitempty"`
|
||||
Score *float64 `json:"score,omitempty" yaml:"score,omitempty"`
|
||||
}
|
||||
|
||||
// What we think explains the observation.
|
||||
type FluidHypothesisExplanation struct {
|
||||
Claim string `json:"claim" yaml:"claim"`
|
||||
|
||||
// Explanatory reach is a prioritization signal, never a correctness claim
|
||||
// (FluidAPIStandards.md section 18).
|
||||
Reach *FluidHypothesisExplanationReach `json:"reach,omitempty" yaml:"reach,omitempty"`
|
||||
}
|
||||
|
||||
type FluidHypothesisFailureCriteria struct {
|
||||
Expression string `json:"expression" yaml:"expression"`
|
||||
}
|
||||
|
||||
type FluidHypothesisFitnessDimensions struct {
|
||||
Expected *FitnessDimensions `json:"expected,omitempty" yaml:"expected,omitempty"`
|
||||
}
|
||||
|
||||
type FluidHypothesisLearningValue struct {
|
||||
Notes string `json:"notes,omitempty" yaml:"notes,omitempty"`
|
||||
Score *float64 `json:"score,omitempty" yaml:"score,omitempty"`
|
||||
}
|
||||
|
||||
// What was seen. Not what it means.
|
||||
type FluidHypothesisObservation struct {
|
||||
AffectedCohorts []CohortID `json:"affected_cohorts,omitempty" yaml:"affected_cohorts,omitempty"`
|
||||
EvidenceRefs []EvidenceRef `json:"evidence_refs" yaml:"evidence_refs"`
|
||||
ObservationWindow *ObservationWindow `json:"observation_window,omitempty" yaml:"observation_window,omitempty"`
|
||||
Summary string `json:"summary" yaml:"summary"`
|
||||
}
|
||||
|
||||
type FluidHypothesisOutcomeStatus string
|
||||
|
||||
const (
|
||||
FluidHypothesisOutcomeStatusCONFIRMED FluidHypothesisOutcomeStatus = "CONFIRMED"
|
||||
FluidHypothesisOutcomeStatusREFUTED FluidHypothesisOutcomeStatus = "REFUTED"
|
||||
FluidHypothesisOutcomeStatusINCONCLUSIVE FluidHypothesisOutcomeStatus = "INCONCLUSIVE"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidHypothesisOutcomeStatus.
|
||||
func (v FluidHypothesisOutcomeStatus) Valid() bool {
|
||||
switch v {
|
||||
case FluidHypothesisOutcomeStatusCONFIRMED, FluidHypothesisOutcomeStatusREFUTED, FluidHypothesisOutcomeStatusINCONCLUSIVE:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// What happened afterwards. Null until evaluation completes.
|
||||
type FluidHypothesisOutcome struct {
|
||||
EvidenceRefs []EvidenceRef `json:"evidence_refs,omitempty" yaml:"evidence_refs,omitempty"`
|
||||
Status *FluidHypothesisOutcomeStatus `json:"status,omitempty" yaml:"status,omitempty"`
|
||||
Summary *string `json:"summary,omitempty" yaml:"summary,omitempty"`
|
||||
}
|
||||
|
||||
type FluidHypothesisPressure struct {
|
||||
Classes []PressureClass `json:"classes" yaml:"classes"`
|
||||
Confidence *UnitInterval `json:"confidence,omitempty" yaml:"confidence,omitempty"`
|
||||
PressureRefs []PressureID `json:"pressure_refs,omitempty" yaml:"pressure_refs,omitempty"`
|
||||
Severity *UnitInterval `json:"severity,omitempty" yaml:"severity,omitempty"`
|
||||
}
|
||||
|
||||
type FluidHypothesisPriority struct {
|
||||
DecidedBy string `json:"decided_by,omitempty" yaml:"decided_by,omitempty"`
|
||||
Score *float64 `json:"score,omitempty" yaml:"score,omitempty"`
|
||||
}
|
||||
|
||||
type FluidHypothesisProposedAdaptationImplementationScope string
|
||||
|
||||
const (
|
||||
FluidHypothesisProposedAdaptationImplementationScopeInterfaceOnly FluidHypothesisProposedAdaptationImplementationScope = "interface_only"
|
||||
FluidHypothesisProposedAdaptationImplementationScopeInterfaceAndBackend FluidHypothesisProposedAdaptationImplementationScope = "interface_and_backend"
|
||||
FluidHypothesisProposedAdaptationImplementationScopeDocumentationOnly FluidHypothesisProposedAdaptationImplementationScope = "documentation_only"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidHypothesisProposedAdaptationImplementationScope.
|
||||
func (v FluidHypothesisProposedAdaptationImplementationScope) Valid() bool {
|
||||
switch v {
|
||||
case FluidHypothesisProposedAdaptationImplementationScopeInterfaceOnly, FluidHypothesisProposedAdaptationImplementationScopeInterfaceAndBackend, FluidHypothesisProposedAdaptationImplementationScopeDocumentationOnly:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// What we propose to change.
|
||||
type FluidHypothesisProposedAdaptation struct {
|
||||
// Shape is protocol-specific and deliberately unconstrained.
|
||||
CandidateContract map[string]any `json:"candidate_contract,omitempty" yaml:"candidate_contract,omitempty"`
|
||||
Class AdaptationClass `json:"class" yaml:"class"`
|
||||
ImplementationScope *FluidHypothesisProposedAdaptationImplementationScope `json:"implementation_scope,omitempty" yaml:"implementation_scope,omitempty"`
|
||||
Summary string `json:"summary" yaml:"summary"`
|
||||
}
|
||||
|
||||
type FluidHypothesisRiskLevel string
|
||||
|
||||
const (
|
||||
FluidHypothesisRiskLevelLOW FluidHypothesisRiskLevel = "LOW"
|
||||
FluidHypothesisRiskLevelMEDIUM FluidHypothesisRiskLevel = "MEDIUM"
|
||||
FluidHypothesisRiskLevelHIGH FluidHypothesisRiskLevel = "HIGH"
|
||||
FluidHypothesisRiskLevelCRITICAL FluidHypothesisRiskLevel = "CRITICAL"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidHypothesisRiskLevel.
|
||||
func (v FluidHypothesisRiskLevel) Valid() bool {
|
||||
switch v {
|
||||
case FluidHypothesisRiskLevelLOW, FluidHypothesisRiskLevelMEDIUM, FluidHypothesisRiskLevelHIGH, FluidHypothesisRiskLevelCRITICAL:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type FluidHypothesisRisk struct {
|
||||
Level FluidHypothesisRiskLevel `json:"level" yaml:"level"`
|
||||
Reasons []string `json:"reasons,omitempty" yaml:"reasons,omitempty"`
|
||||
}
|
||||
|
||||
type FluidHypothesisState string
|
||||
|
||||
const (
|
||||
FluidHypothesisStateDRAFT FluidHypothesisState = "DRAFT"
|
||||
FluidHypothesisStateREADY FluidHypothesisState = "READY"
|
||||
FluidHypothesisStatePRIORITIZED FluidHypothesisState = "PRIORITIZED"
|
||||
FluidHypothesisStateDESIGNING FluidHypothesisState = "DESIGNING"
|
||||
FluidHypothesisStateEXPERIMENTING FluidHypothesisState = "EXPERIMENTING"
|
||||
FluidHypothesisStateEVALUATING FluidHypothesisState = "EVALUATING"
|
||||
FluidHypothesisStateACCEPTED FluidHypothesisState = "ACCEPTED"
|
||||
FluidHypothesisStateREJECTED FluidHypothesisState = "REJECTED"
|
||||
FluidHypothesisStateSUPERSEDED FluidHypothesisState = "SUPERSEDED"
|
||||
FluidHypothesisStateDEFERRED FluidHypothesisState = "DEFERRED"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidHypothesisState.
|
||||
func (v FluidHypothesisState) Valid() bool {
|
||||
switch v {
|
||||
case FluidHypothesisStateDRAFT, FluidHypothesisStateREADY, FluidHypothesisStatePRIORITIZED, FluidHypothesisStateDESIGNING, FluidHypothesisStateEXPERIMENTING, FluidHypothesisStateEVALUATING, FluidHypothesisStateACCEPTED, FluidHypothesisStateREJECTED, FluidHypothesisStateSUPERSEDED, FluidHypothesisStateDEFERRED:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type FluidHypothesisSuccessCriteria struct {
|
||||
Expression string `json:"expression" yaml:"expression"`
|
||||
}
|
||||
|
||||
type FluidHypothesis struct {
|
||||
Audit *FluidHypothesisAudit `json:"audit,omitempty" yaml:"audit,omitempty"`
|
||||
BackendRequirements *FluidHypothesisBackendRequirements `json:"backend_requirements,omitempty" yaml:"backend_requirements,omitempty"`
|
||||
CandidateRevisionRefs []RevisionID `json:"candidate_revision_refs,omitempty" yaml:"candidate_revision_refs,omitempty"`
|
||||
|
||||
// Competing hypotheses are legitimate (FluidAPIStandards.md section 19).
|
||||
Competition *FluidHypothesisCompetition `json:"competition,omitempty" yaml:"competition,omitempty"`
|
||||
Complexity FluidHypothesisComplexity `json:"complexity" yaml:"complexity"`
|
||||
CreatedAt *Timestamp `json:"created_at,omitempty" yaml:"created_at,omitempty"`
|
||||
CreatedBy *Actor `json:"created_by,omitempty" yaml:"created_by,omitempty"`
|
||||
|
||||
// A hypothesis may be valuable but not yet worth exploring
|
||||
// (ArchitectureBlueprint.md section 29).
|
||||
Economics *FluidHypothesisEconomics `json:"economics,omitempty" yaml:"economics,omitempty"`
|
||||
|
||||
// A hypothesis must be falsifiable (FluidAPIStandards.md section 17).
|
||||
ExpectedOutcomes []ExpectedOutcome `json:"expected_outcomes" yaml:"expected_outcomes"`
|
||||
ExperimentRefs []ExperimentID `json:"experiment_refs,omitempty" yaml:"experiment_refs,omitempty"`
|
||||
|
||||
// What we think explains the observation.
|
||||
Explanation FluidHypothesisExplanation `json:"explanation" yaml:"explanation"`
|
||||
FailureCriteria *FluidHypothesisFailureCriteria `json:"failure_criteria,omitempty" yaml:"failure_criteria,omitempty"`
|
||||
FitnessDimensions *FluidHypothesisFitnessDimensions `json:"fitness_dimensions,omitempty" yaml:"fitness_dimensions,omitempty"`
|
||||
Guardrails []Guardrail `json:"guardrails" yaml:"guardrails"`
|
||||
ID HypothesisID `json:"id" yaml:"id"`
|
||||
InterfaceID InterfaceID `json:"interface_id" yaml:"interface_id"`
|
||||
LearningValue *FluidHypothesisLearningValue `json:"learning_value,omitempty" yaml:"learning_value,omitempty"`
|
||||
|
||||
// What was seen. Not what it means.
|
||||
Observation FluidHypothesisObservation `json:"observation" yaml:"observation"`
|
||||
|
||||
// What happened afterwards. Null until evaluation completes.
|
||||
Outcome *FluidHypothesisOutcome `json:"outcome,omitempty" yaml:"outcome,omitempty"`
|
||||
Pressure FluidHypothesisPressure `json:"pressure" yaml:"pressure"`
|
||||
Priority *FluidHypothesisPriority `json:"priority,omitempty" yaml:"priority,omitempty"`
|
||||
|
||||
// What we propose to change.
|
||||
ProposedAdaptation FluidHypothesisProposedAdaptation `json:"proposed_adaptation" yaml:"proposed_adaptation"`
|
||||
Risk FluidHypothesisRisk `json:"risk" yaml:"risk"`
|
||||
SchemaVersion SchemaVersion `json:"schema_version" yaml:"schema_version"`
|
||||
State FluidHypothesisState `json:"state" yaml:"state"`
|
||||
SuccessCriteria FluidHypothesisSuccessCriteria `json:"success_criteria" yaml:"success_criteria"`
|
||||
Title string `json:"title" yaml:"title"`
|
||||
}
|
||||
|
||||
// Why an interface change should be explored. Observation, explanation, prediction,
|
||||
// intervention and result stay separate on purpose
|
||||
// (FluidHypothesisRevisionSchema.md section 18).
|
||||
type HypothesisDocument struct {
|
||||
FluidHypothesis FluidHypothesis `json:"fluid_hypothesis" yaml:"fluid_hypothesis"`
|
||||
}
|
||||
91
internal/contract/ids.go
Normal file
91
internal/contract/ids.go
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
package contract
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Identifier prefixes from FluidHypothesisRevisionSchema.md section 16.
|
||||
//
|
||||
// Implementations may use UUIDs internally; these human-readable prefixes exist
|
||||
// so that operational tooling and audit trails stay legible to people.
|
||||
const (
|
||||
PrefixHypothesis = "H-"
|
||||
PrefixRevision = "R-"
|
||||
PrefixExperiment = "E-"
|
||||
PrefixPressure = "P-"
|
||||
PrefixBackendRequirement = "BR-"
|
||||
PrefixDecision = "D-"
|
||||
PrefixEvent = "EV-"
|
||||
PrefixFeedback = "F-"
|
||||
PrefixCohort = "C-"
|
||||
)
|
||||
|
||||
// EntityKind names the FLUID artifact an identifier refers to.
|
||||
type EntityKind string
|
||||
|
||||
const (
|
||||
KindHypothesis EntityKind = "hypothesis"
|
||||
KindRevision EntityKind = "revision"
|
||||
KindExperiment EntityKind = "experiment"
|
||||
KindPressure EntityKind = "pressure"
|
||||
KindBackendRequirement EntityKind = "backend_requirement"
|
||||
KindDecision EntityKind = "decision"
|
||||
KindEvent EntityKind = "event"
|
||||
KindFeedback EntityKind = "feedback"
|
||||
KindCohort EntityKind = "cohort"
|
||||
)
|
||||
|
||||
// prefixOrder matters: "BR-" must be tested before "B"-less single letters
|
||||
// would otherwise mis-claim it, and "EV-" before "E-".
|
||||
var prefixOrder = []struct {
|
||||
prefix string
|
||||
kind EntityKind
|
||||
}{
|
||||
{PrefixBackendRequirement, KindBackendRequirement},
|
||||
{PrefixEvent, KindEvent},
|
||||
{PrefixHypothesis, KindHypothesis},
|
||||
{PrefixRevision, KindRevision},
|
||||
{PrefixExperiment, KindExperiment},
|
||||
{PrefixPressure, KindPressure},
|
||||
{PrefixDecision, KindDecision},
|
||||
{PrefixFeedback, KindFeedback},
|
||||
{PrefixCohort, KindCohort},
|
||||
}
|
||||
|
||||
// KindOf reports which FLUID artifact an identifier names.
|
||||
//
|
||||
// Audit trails carry bare identifiers across record boundaries, so being able to
|
||||
// classify one without knowing where it came from keeps trace reconstruction
|
||||
// from needing a lookup table at every hop.
|
||||
func KindOf(id string) (EntityKind, bool) {
|
||||
for _, p := range prefixOrder {
|
||||
if strings.HasPrefix(id, p.prefix) {
|
||||
return p.kind, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// ErrWrongKind reports an identifier used in the wrong position.
|
||||
type ErrWrongKind struct {
|
||||
ID string
|
||||
Want EntityKind
|
||||
Got EntityKind
|
||||
}
|
||||
|
||||
func (e *ErrWrongKind) Error() string {
|
||||
if e.Got == "" {
|
||||
return fmt.Sprintf("identifier %q has no recognized FLUID prefix, wanted a %s id", e.ID, e.Want)
|
||||
}
|
||||
return fmt.Sprintf("identifier %q is a %s id, wanted a %s id", e.ID, e.Got, e.Want)
|
||||
}
|
||||
|
||||
// RequireKind checks that id names the expected artifact.
|
||||
func RequireKind(id string, want EntityKind) error {
|
||||
got, ok := KindOf(id)
|
||||
if !ok || got != want {
|
||||
return &ErrWrongKind{ID: id, Want: want, Got: got}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
58
internal/contract/pressure_gen.go
Normal file
58
internal/contract/pressure_gen.go
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
// Code generated by tools/schemagen. DO NOT EDIT.
|
||||
// Source: schemas/. Regenerate with `make generate`.
|
||||
|
||||
package contract
|
||||
|
||||
type FluidPressureFrequency struct {
|
||||
IndependentConsumers *int64 `json:"independent_consumers,omitempty" yaml:"independent_consumers,omitempty"`
|
||||
Observations *int64 `json:"observations,omitempty" yaml:"observations,omitempty"`
|
||||
}
|
||||
|
||||
// ArchitectureBlueprint.md section 9. Pressure may remain unresolved on purpose.
|
||||
type FluidPressureStatus string
|
||||
|
||||
const (
|
||||
FluidPressureStatusOPEN FluidPressureStatus = "OPEN"
|
||||
FluidPressureStatusANALYZING FluidPressureStatus = "ANALYZING"
|
||||
FluidPressureStatusEXPLAINED FluidPressureStatus = "EXPLAINED"
|
||||
FluidPressureStatusADDRESSED FluidPressureStatus = "ADDRESSED"
|
||||
FluidPressureStatusDISMISSED FluidPressureStatus = "DISMISSED"
|
||||
FluidPressureStatusOUTOFSCOPE FluidPressureStatus = "OUT_OF_SCOPE"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidPressureStatus.
|
||||
func (v FluidPressureStatus) Valid() bool {
|
||||
switch v {
|
||||
case FluidPressureStatusOPEN, FluidPressureStatusANALYZING, FluidPressureStatusEXPLAINED, FluidPressureStatusADDRESSED, FluidPressureStatusDISMISSED, FluidPressureStatusOUTOFSCOPE:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type FluidPressure struct {
|
||||
AffectedCohorts []CohortID `json:"affected_cohorts,omitempty" yaml:"affected_cohorts,omitempty"`
|
||||
Class PressureClass `json:"class" yaml:"class"`
|
||||
Confidence *UnitInterval `json:"confidence,omitempty" yaml:"confidence,omitempty"`
|
||||
|
||||
// A pressure record without evidence references is not auditable and must be
|
||||
// rejected.
|
||||
EvidenceRefs []EvidenceRef `json:"evidence_refs" yaml:"evidence_refs"`
|
||||
FirstSeen Timestamp `json:"first_seen" yaml:"first_seen"`
|
||||
Frequency *FluidPressureFrequency `json:"frequency,omitempty" yaml:"frequency,omitempty"`
|
||||
ID PressureID `json:"id" yaml:"id"`
|
||||
InterfaceID InterfaceID `json:"interface_id" yaml:"interface_id"`
|
||||
LastSeen Timestamp `json:"last_seen" yaml:"last_seen"`
|
||||
LinkedHypotheses []HypothesisID `json:"linked_hypotheses,omitempty" yaml:"linked_hypotheses,omitempty"`
|
||||
SchemaVersion SchemaVersion `json:"schema_version" yaml:"schema_version"`
|
||||
Severity *UnitInterval `json:"severity,omitempty" yaml:"severity,omitempty"`
|
||||
|
||||
// ArchitectureBlueprint.md section 9. Pressure may remain unresolved on purpose.
|
||||
Status FluidPressureStatus `json:"status" yaml:"status"`
|
||||
Summary string `json:"summary" yaml:"summary"`
|
||||
}
|
||||
|
||||
// Evidence that the interface differs materially from consumer needs. Pressure is
|
||||
// evidence, not truth (FluidAPIStandards.md section 13).
|
||||
type PressureDocument struct {
|
||||
FluidPressure FluidPressure `json:"fluid_pressure" yaml:"fluid_pressure"`
|
||||
}
|
||||
215
internal/contract/revision_descriptor_gen.go
Normal file
215
internal/contract/revision_descriptor_gen.go
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
// Code generated by tools/schemagen. DO NOT EDIT.
|
||||
// Source: schemas/. Regenerate with `make generate`.
|
||||
|
||||
package contract
|
||||
|
||||
type RevisionContractType string
|
||||
|
||||
const (
|
||||
RevisionContractTypeOpenapi RevisionContractType = "openapi"
|
||||
RevisionContractTypeGraphql RevisionContractType = "graphql"
|
||||
RevisionContractTypeProtobuf RevisionContractType = "protobuf"
|
||||
RevisionContractTypeAsyncapi RevisionContractType = "asyncapi"
|
||||
RevisionContractTypeJsonschema RevisionContractType = "jsonschema"
|
||||
RevisionContractTypeCustom RevisionContractType = "custom"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined RevisionContractType.
|
||||
func (v RevisionContractType) Valid() bool {
|
||||
switch v {
|
||||
case RevisionContractTypeOpenapi, RevisionContractTypeGraphql, RevisionContractTypeProtobuf, RevisionContractTypeAsyncapi, RevisionContractTypeJsonschema, RevisionContractTypeCustom:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type RevisionContract struct {
|
||||
Digest Digest `json:"digest" yaml:"digest"`
|
||||
|
||||
// Where the contract artifact can be fetched.
|
||||
Source string `json:"source,omitempty" yaml:"source,omitempty"`
|
||||
Type RevisionContractType `json:"type" yaml:"type"`
|
||||
}
|
||||
|
||||
// Which interface evolution intent governs this revision. Required: a revision with
|
||||
// no governing intent cannot be audited.
|
||||
type RevisionIntent struct {
|
||||
Digest *Digest `json:"digest,omitempty" yaml:"digest,omitempty"`
|
||||
Version string `json:"version" yaml:"version"`
|
||||
}
|
||||
|
||||
type RevisionPolicyCompatibility string
|
||||
|
||||
const (
|
||||
RevisionPolicyCompatibilityBackwardCompatible RevisionPolicyCompatibility = "backward_compatible"
|
||||
RevisionPolicyCompatibilityForwardCompatible RevisionPolicyCompatibility = "forward_compatible"
|
||||
RevisionPolicyCompatibilityAdditive RevisionPolicyCompatibility = "additive"
|
||||
RevisionPolicyCompatibilityBehavioralChange RevisionPolicyCompatibility = "behavioral_change"
|
||||
RevisionPolicyCompatibilityBreaking RevisionPolicyCompatibility = "breaking"
|
||||
RevisionPolicyCompatibilityMigrationOnly RevisionPolicyCompatibility = "migration_only"
|
||||
RevisionPolicyCompatibilityInternalOnly RevisionPolicyCompatibility = "internal_only"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined RevisionPolicyCompatibility.
|
||||
func (v RevisionPolicyCompatibility) Valid() bool {
|
||||
switch v {
|
||||
case RevisionPolicyCompatibilityBackwardCompatible, RevisionPolicyCompatibilityForwardCompatible, RevisionPolicyCompatibilityAdditive, RevisionPolicyCompatibilityBehavioralChange, RevisionPolicyCompatibilityBreaking, RevisionPolicyCompatibilityMigrationOnly, RevisionPolicyCompatibilityInternalOnly:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type RevisionPolicyPolicyCheck string
|
||||
|
||||
const (
|
||||
RevisionPolicyPolicyCheckPending RevisionPolicyPolicyCheck = "pending"
|
||||
RevisionPolicyPolicyCheckPassed RevisionPolicyPolicyCheck = "passed"
|
||||
RevisionPolicyPolicyCheckFailed RevisionPolicyPolicyCheck = "failed"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined RevisionPolicyPolicyCheck.
|
||||
func (v RevisionPolicyPolicyCheck) Valid() bool {
|
||||
switch v {
|
||||
case RevisionPolicyPolicyCheckPending, RevisionPolicyPolicyCheckPassed, RevisionPolicyPolicyCheckFailed:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type RevisionPolicySecurityCheck string
|
||||
|
||||
const (
|
||||
RevisionPolicySecurityCheckPending RevisionPolicySecurityCheck = "pending"
|
||||
RevisionPolicySecurityCheckPassed RevisionPolicySecurityCheck = "passed"
|
||||
RevisionPolicySecurityCheckFailed RevisionPolicySecurityCheck = "failed"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined RevisionPolicySecurityCheck.
|
||||
func (v RevisionPolicySecurityCheck) Valid() bool {
|
||||
switch v {
|
||||
case RevisionPolicySecurityCheckPending, RevisionPolicySecurityCheckPassed, RevisionPolicySecurityCheckFailed:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type RevisionPolicy struct {
|
||||
Compatibility RevisionPolicyCompatibility `json:"compatibility" yaml:"compatibility"`
|
||||
PolicyCheck *RevisionPolicyPolicyCheck `json:"policy_check,omitempty" yaml:"policy_check,omitempty"`
|
||||
RollbackTo *RevisionID `json:"rollback_to,omitempty" yaml:"rollback_to,omitempty"`
|
||||
SecurityCheck RevisionPolicySecurityCheck `json:"security_check" yaml:"security_check"`
|
||||
}
|
||||
|
||||
type RevisionRouting struct {
|
||||
// Empty or absent means all cohorts are eligible.
|
||||
EligibleCohorts []CohortID `json:"eligible_cohorts,omitempty" yaml:"eligible_cohorts,omitempty"`
|
||||
|
||||
// Ceiling the router enforces regardless of what a routing policy asks for.
|
||||
MaxTrafficShare *UnitInterval `json:"max_traffic_share,omitempty" yaml:"max_traffic_share,omitempty"`
|
||||
}
|
||||
|
||||
type RevisionRuntimeCircuitBreaker struct {
|
||||
FailureThreshold *int64 `json:"failure_threshold,omitempty" yaml:"failure_threshold,omitempty"`
|
||||
ResetAfterMS *int64 `json:"reset_after_ms,omitempty" yaml:"reset_after_ms,omitempty"`
|
||||
}
|
||||
|
||||
type RevisionRuntimeRetry struct {
|
||||
BackoffMS *int64 `json:"backoff_ms,omitempty" yaml:"backoff_ms,omitempty"`
|
||||
MaxAttempts *int64 `json:"max_attempts,omitempty" yaml:"max_attempts,omitempty"`
|
||||
RetryOn []string `json:"retry_on,omitempty" yaml:"retry_on,omitempty"`
|
||||
}
|
||||
|
||||
// Out-of-process attachment: the adapter is an upstream reached over the network,
|
||||
// so it may be implemented in any language.
|
||||
type RevisionRuntime struct {
|
||||
CircuitBreaker *RevisionRuntimeCircuitBreaker `json:"circuit_breaker,omitempty" yaml:"circuit_breaker,omitempty"`
|
||||
Digest *Digest `json:"digest,omitempty" yaml:"digest,omitempty"`
|
||||
Image string `json:"image,omitempty" yaml:"image,omitempty"`
|
||||
Retry *RevisionRuntimeRetry `json:"retry,omitempty" yaml:"retry,omitempty"`
|
||||
TimeoutMS *int64 `json:"timeout_ms,omitempty" yaml:"timeout_ms,omitempty"`
|
||||
|
||||
// Base URL of the adapter process serving this revision.
|
||||
Upstream string `json:"upstream" yaml:"upstream"`
|
||||
}
|
||||
|
||||
type RevisionSignatureAlgorithm string
|
||||
|
||||
const (
|
||||
RevisionSignatureAlgorithmEd25519 RevisionSignatureAlgorithm = "ed25519"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined RevisionSignatureAlgorithm.
|
||||
func (v RevisionSignatureAlgorithm) Valid() bool {
|
||||
switch v {
|
||||
case RevisionSignatureAlgorithmEd25519:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// The router accepts only signed published descriptors (ArchitectureBlueprint.md
|
||||
// section 35). The signature covers the canonical form of this document with the
|
||||
// signature member removed.
|
||||
type RevisionSignature struct {
|
||||
Algorithm RevisionSignatureAlgorithm `json:"algorithm" yaml:"algorithm"`
|
||||
KeyID string `json:"key_id" yaml:"key_id"`
|
||||
SignedAt *Timestamp `json:"signed_at,omitempty" yaml:"signed_at,omitempty"`
|
||||
Value string `json:"value" yaml:"value"`
|
||||
}
|
||||
|
||||
// The router refuses to route to created, failed or retired revisions
|
||||
// (ArchitectureBlueprint.md section 5.3).
|
||||
type RevisionState string
|
||||
|
||||
const (
|
||||
RevisionStateCreated RevisionState = "created"
|
||||
RevisionStateVerified RevisionState = "verified"
|
||||
RevisionStateExperiment RevisionState = "experiment"
|
||||
RevisionStateCandidate RevisionState = "candidate"
|
||||
RevisionStateStable RevisionState = "stable"
|
||||
RevisionStateDeprecated RevisionState = "deprecated"
|
||||
RevisionStateRetired RevisionState = "retired"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined RevisionState.
|
||||
func (v RevisionState) Valid() bool {
|
||||
switch v {
|
||||
case RevisionStateCreated, RevisionStateVerified, RevisionStateExperiment, RevisionStateCandidate, RevisionStateStable, RevisionStateDeprecated, RevisionStateRetired:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type Revision struct {
|
||||
Contract RevisionContract `json:"contract" yaml:"contract"`
|
||||
ID RevisionID `json:"id" yaml:"id"`
|
||||
|
||||
// Which interface evolution intent governs this revision. Required: a revision
|
||||
// with no governing intent cannot be audited.
|
||||
Intent RevisionIntent `json:"intent" yaml:"intent"`
|
||||
Interface InterfaceID `json:"interface" yaml:"interface"`
|
||||
Policy RevisionPolicy `json:"policy" yaml:"policy"`
|
||||
Routing *RevisionRouting `json:"routing,omitempty" yaml:"routing,omitempty"`
|
||||
|
||||
// Out-of-process attachment: the adapter is an upstream reached over the network,
|
||||
// so it may be implemented in any language.
|
||||
Runtime RevisionRuntime `json:"runtime" yaml:"runtime"`
|
||||
SchemaVersion SchemaVersion `json:"schema_version" yaml:"schema_version"`
|
||||
|
||||
// The router accepts only signed published descriptors (ArchitectureBlueprint.md
|
||||
// section 35). The signature covers the canonical form of this document with the
|
||||
// signature member removed.
|
||||
Signature *RevisionSignature `json:"signature,omitempty" yaml:"signature,omitempty"`
|
||||
|
||||
// The router refuses to route to created, failed or retired revisions
|
||||
// (ArchitectureBlueprint.md section 5.3).
|
||||
State RevisionState `json:"state" yaml:"state"`
|
||||
}
|
||||
|
||||
// The runtime-facing projection of a revision, deliberately small enough to be
|
||||
// consumed deterministically by infrastructure (ArchitectureBlueprint.md section
|
||||
// 36). This is a wire artifact: the gateway must be able to read it without any
|
||||
// fluid-core library.
|
||||
type RevisionDescriptorDocument struct {
|
||||
Revision Revision `json:"revision" yaml:"revision"`
|
||||
}
|
||||
314
internal/contract/revision_gen.go
Normal file
314
internal/contract/revision_gen.go
Normal file
|
|
@ -0,0 +1,314 @@
|
|||
// Code generated by tools/schemagen. DO NOT EDIT.
|
||||
// Source: schemas/. Regenerate with `make generate`.
|
||||
|
||||
package contract
|
||||
|
||||
// Adoption is evidence, not proof of quality (FluidAPIStandards.md section 32).
|
||||
type FluidRevisionAdoption struct {
|
||||
ActiveConsumers *int64 `json:"active_consumers,omitempty" yaml:"active_consumers,omitempty"`
|
||||
AdoptionRate *UnitInterval `json:"adoption_rate,omitempty" yaml:"adoption_rate,omitempty"`
|
||||
EligibleConsumers *int64 `json:"eligible_consumers,omitempty" yaml:"eligible_consumers,omitempty"`
|
||||
RetainedAdoptionRate *UnitInterval `json:"retained_adoption_rate,omitempty" yaml:"retained_adoption_rate,omitempty"`
|
||||
}
|
||||
|
||||
type FluidRevisionAudit struct {
|
||||
ImmutableEventRefs []EventID `json:"immutable_event_refs,omitempty" yaml:"immutable_event_refs,omitempty"`
|
||||
}
|
||||
|
||||
type FluidRevisionCompatibilityClass string
|
||||
|
||||
const (
|
||||
FluidRevisionCompatibilityClassBACKWARDCOMPATIBLE FluidRevisionCompatibilityClass = "BACKWARD_COMPATIBLE"
|
||||
FluidRevisionCompatibilityClassFORWARDCOMPATIBLE FluidRevisionCompatibilityClass = "FORWARD_COMPATIBLE"
|
||||
FluidRevisionCompatibilityClassADDITIVE FluidRevisionCompatibilityClass = "ADDITIVE"
|
||||
FluidRevisionCompatibilityClassBEHAVIORALCHANGE FluidRevisionCompatibilityClass = "BEHAVIORAL_CHANGE"
|
||||
FluidRevisionCompatibilityClassBREAKING FluidRevisionCompatibilityClass = "BREAKING"
|
||||
FluidRevisionCompatibilityClassMIGRATIONONLY FluidRevisionCompatibilityClass = "MIGRATION_ONLY"
|
||||
FluidRevisionCompatibilityClassINTERNALONLY FluidRevisionCompatibilityClass = "INTERNAL_ONLY"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidRevisionCompatibilityClass.
|
||||
func (v FluidRevisionCompatibilityClass) Valid() bool {
|
||||
switch v {
|
||||
case FluidRevisionCompatibilityClassBACKWARDCOMPATIBLE, FluidRevisionCompatibilityClassFORWARDCOMPATIBLE, FluidRevisionCompatibilityClassADDITIVE, FluidRevisionCompatibilityClassBEHAVIORALCHANGE, FluidRevisionCompatibilityClassBREAKING, FluidRevisionCompatibilityClassMIGRATIONONLY, FluidRevisionCompatibilityClassINTERNALONLY:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type FluidRevisionCompatibility struct {
|
||||
BreakingChanges []string `json:"breaking_changes,omitempty" yaml:"breaking_changes,omitempty"`
|
||||
Class FluidRevisionCompatibilityClass `json:"class" yaml:"class"`
|
||||
CompatibilityEvidenceRefs []EvidenceRef `json:"compatibility_evidence_refs,omitempty" yaml:"compatibility_evidence_refs,omitempty"`
|
||||
Deprecations []string `json:"deprecations,omitempty" yaml:"deprecations,omitempty"`
|
||||
Supersedes []RevisionID `json:"supersedes,omitempty" yaml:"supersedes,omitempty"`
|
||||
}
|
||||
|
||||
type FluidRevisionComplexityBudgetStatus string
|
||||
|
||||
const (
|
||||
FluidRevisionComplexityBudgetStatusWITHINBUDGET FluidRevisionComplexityBudgetStatus = "WITHIN_BUDGET"
|
||||
FluidRevisionComplexityBudgetStatusATBUDGET FluidRevisionComplexityBudgetStatus = "AT_BUDGET"
|
||||
FluidRevisionComplexityBudgetStatusOVERBUDGET FluidRevisionComplexityBudgetStatus = "OVER_BUDGET"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidRevisionComplexityBudgetStatus.
|
||||
func (v FluidRevisionComplexityBudgetStatus) Valid() bool {
|
||||
switch v {
|
||||
case FluidRevisionComplexityBudgetStatusWITHINBUDGET, FluidRevisionComplexityBudgetStatusATBUDGET, FluidRevisionComplexityBudgetStatusOVERBUDGET:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type FluidRevisionComplexity struct {
|
||||
After *ComplexityDelta `json:"after,omitempty" yaml:"after,omitempty"`
|
||||
Before *ComplexityDelta `json:"before,omitempty" yaml:"before,omitempty"`
|
||||
BudgetStatus *FluidRevisionComplexityBudgetStatus `json:"budget_status,omitempty" yaml:"budget_status,omitempty"`
|
||||
DeltaScore *float64 `json:"delta_score,omitempty" yaml:"delta_score,omitempty"`
|
||||
}
|
||||
|
||||
type FluidRevisionContractType string
|
||||
|
||||
const (
|
||||
FluidRevisionContractTypeOpenapi FluidRevisionContractType = "openapi"
|
||||
FluidRevisionContractTypeGraphql FluidRevisionContractType = "graphql"
|
||||
FluidRevisionContractTypeProtobuf FluidRevisionContractType = "protobuf"
|
||||
FluidRevisionContractTypeAsyncapi FluidRevisionContractType = "asyncapi"
|
||||
FluidRevisionContractTypeJsonschema FluidRevisionContractType = "jsonschema"
|
||||
FluidRevisionContractTypeCustom FluidRevisionContractType = "custom"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidRevisionContractType.
|
||||
func (v FluidRevisionContractType) Valid() bool {
|
||||
switch v {
|
||||
case FluidRevisionContractTypeOpenapi, FluidRevisionContractTypeGraphql, FluidRevisionContractTypeProtobuf, FluidRevisionContractTypeAsyncapi, FluidRevisionContractTypeJsonschema, FluidRevisionContractTypeCustom:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type FluidRevisionContract struct {
|
||||
ArtifactRef ArtifactRef `json:"artifact_ref" yaml:"artifact_ref"`
|
||||
Digest Digest `json:"digest" yaml:"digest"`
|
||||
Type FluidRevisionContractType `json:"type" yaml:"type"`
|
||||
Version string `json:"version,omitempty" yaml:"version,omitempty"`
|
||||
}
|
||||
|
||||
type FluidRevisionDeploymentCurrentExposure struct {
|
||||
Cohorts []CohortID `json:"cohorts,omitempty" yaml:"cohorts,omitempty"`
|
||||
TrafficShare *UnitInterval `json:"traffic_share,omitempty" yaml:"traffic_share,omitempty"`
|
||||
}
|
||||
|
||||
type FluidRevisionDeploymentEnvironmentsItem struct {
|
||||
Name string `json:"name" yaml:"name"`
|
||||
RoutingPolicyRef string `json:"routing_policy_ref,omitempty" yaml:"routing_policy_ref,omitempty"`
|
||||
StartedAt *Timestamp `json:"started_at,omitempty" yaml:"started_at,omitempty"`
|
||||
}
|
||||
|
||||
type FluidRevisionDeployment struct {
|
||||
CurrentExposure *FluidRevisionDeploymentCurrentExposure `json:"current_exposure,omitempty" yaml:"current_exposure,omitempty"`
|
||||
Environments []FluidRevisionDeploymentEnvironmentsItem `json:"environments,omitempty" yaml:"environments,omitempty"`
|
||||
}
|
||||
|
||||
type FluidRevisionEconomics struct {
|
||||
BuildCost *float64 `json:"build_cost,omitempty" yaml:"build_cost,omitempty"`
|
||||
Currency string `json:"currency,omitempty" yaml:"currency,omitempty"`
|
||||
ExperimentCostToDate *float64 `json:"experiment_cost_to_date,omitempty" yaml:"experiment_cost_to_date,omitempty"`
|
||||
}
|
||||
|
||||
type FluidRevisionFitnessMetricsValue struct {
|
||||
Baseline *float64 `json:"baseline,omitempty" yaml:"baseline,omitempty"`
|
||||
Current *float64 `json:"current,omitempty" yaml:"current,omitempty"`
|
||||
Guardrail *float64 `json:"guardrail,omitempty" yaml:"guardrail,omitempty"`
|
||||
Target *float64 `json:"target,omitempty" yaml:"target,omitempty"`
|
||||
}
|
||||
|
||||
type FluidRevisionFitness struct {
|
||||
BaselineRevision *RevisionID `json:"baseline_revision,omitempty" yaml:"baseline_revision,omitempty"`
|
||||
MeasurementWindow *ObservationWindow `json:"measurement_window,omitempty" yaml:"measurement_window,omitempty"`
|
||||
Metrics map[string]FluidRevisionFitnessMetricsValue `json:"metrics,omitempty" yaml:"metrics,omitempty"`
|
||||
}
|
||||
|
||||
type FluidRevisionImplementation struct {
|
||||
ArtifactRef ArtifactRef `json:"artifact_ref" yaml:"artifact_ref"`
|
||||
BuildRef string `json:"build_ref,omitempty" yaml:"build_ref,omitempty"`
|
||||
Digest Digest `json:"digest" yaml:"digest"`
|
||||
SourceRef string `json:"source_ref,omitempty" yaml:"source_ref,omitempty"`
|
||||
}
|
||||
|
||||
// Every revision is governed by a specific intent version, so audit can ask whether
|
||||
// the change was valid under the intent that existed at the time
|
||||
// (ArchitectureBlueprint.md section 27).
|
||||
type FluidRevisionInterfaceEvolutionIntent struct {
|
||||
ArtifactRef *ArtifactRef `json:"artifact_ref,omitempty" yaml:"artifact_ref,omitempty"`
|
||||
Version string `json:"version" yaml:"version"`
|
||||
}
|
||||
|
||||
type FluidRevisionPromotionRecommendedState string
|
||||
|
||||
const (
|
||||
FluidRevisionPromotionRecommendedStateCREATED FluidRevisionPromotionRecommendedState = "CREATED"
|
||||
FluidRevisionPromotionRecommendedStateVERIFIED FluidRevisionPromotionRecommendedState = "VERIFIED"
|
||||
FluidRevisionPromotionRecommendedStateEXPERIMENT FluidRevisionPromotionRecommendedState = "EXPERIMENT"
|
||||
FluidRevisionPromotionRecommendedStateCANDIDATE FluidRevisionPromotionRecommendedState = "CANDIDATE"
|
||||
FluidRevisionPromotionRecommendedStateSTABLE FluidRevisionPromotionRecommendedState = "STABLE"
|
||||
FluidRevisionPromotionRecommendedStateDEPRECATED FluidRevisionPromotionRecommendedState = "DEPRECATED"
|
||||
FluidRevisionPromotionRecommendedStateRETIRED FluidRevisionPromotionRecommendedState = "RETIRED"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidRevisionPromotionRecommendedState.
|
||||
func (v FluidRevisionPromotionRecommendedState) Valid() bool {
|
||||
switch v {
|
||||
case FluidRevisionPromotionRecommendedStateCREATED, FluidRevisionPromotionRecommendedStateVERIFIED, FluidRevisionPromotionRecommendedStateEXPERIMENT, FluidRevisionPromotionRecommendedStateCANDIDATE, FluidRevisionPromotionRecommendedStateSTABLE, FluidRevisionPromotionRecommendedStateDEPRECATED, FluidRevisionPromotionRecommendedStateRETIRED:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type FluidRevisionPromotion struct {
|
||||
AuthorizedAt *Timestamp `json:"authorized_at,omitempty" yaml:"authorized_at,omitempty"`
|
||||
AuthorizedBy *Actor `json:"authorized_by,omitempty" yaml:"authorized_by,omitempty"`
|
||||
Eligible *bool `json:"eligible,omitempty" yaml:"eligible,omitempty"`
|
||||
RecommendationReason *string `json:"recommendation_reason,omitempty" yaml:"recommendation_reason,omitempty"`
|
||||
RecommendedState *FluidRevisionPromotionRecommendedState `json:"recommended_state,omitempty" yaml:"recommended_state,omitempty"`
|
||||
}
|
||||
|
||||
type FluidRevisionProvenance struct {
|
||||
DecisionRefs []DecisionID `json:"decision_refs,omitempty" yaml:"decision_refs,omitempty"`
|
||||
ExperimentRefs []ExperimentID `json:"experiment_refs,omitempty" yaml:"experiment_refs,omitempty"`
|
||||
TelemetryRefs []EvidenceRef `json:"telemetry_refs,omitempty" yaml:"telemetry_refs,omitempty"`
|
||||
}
|
||||
|
||||
type FluidRevisionRollback struct {
|
||||
ProcedureRef string `json:"procedure_ref,omitempty" yaml:"procedure_ref,omitempty"`
|
||||
Supported bool `json:"supported" yaml:"supported"`
|
||||
TargetRevision *RevisionID `json:"target_revision,omitempty" yaml:"target_revision,omitempty"`
|
||||
}
|
||||
|
||||
type FluidRevisionState string
|
||||
|
||||
const (
|
||||
FluidRevisionStateCREATED FluidRevisionState = "CREATED"
|
||||
FluidRevisionStateVERIFIED FluidRevisionState = "VERIFIED"
|
||||
FluidRevisionStateEXPERIMENT FluidRevisionState = "EXPERIMENT"
|
||||
FluidRevisionStateCANDIDATE FluidRevisionState = "CANDIDATE"
|
||||
FluidRevisionStateSTABLE FluidRevisionState = "STABLE"
|
||||
FluidRevisionStateDEPRECATED FluidRevisionState = "DEPRECATED"
|
||||
FluidRevisionStateRETIRED FluidRevisionState = "RETIRED"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidRevisionState.
|
||||
func (v FluidRevisionState) Valid() bool {
|
||||
switch v {
|
||||
case FluidRevisionStateCREATED, FluidRevisionStateVERIFIED, FluidRevisionStateEXPERIMENT, FluidRevisionStateCANDIDATE, FluidRevisionStateSTABLE, FluidRevisionStateDEPRECATED, FluidRevisionStateRETIRED:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type FluidRevisionVerificationPolicyCheck string
|
||||
|
||||
const (
|
||||
FluidRevisionVerificationPolicyCheckPENDING FluidRevisionVerificationPolicyCheck = "PENDING"
|
||||
FluidRevisionVerificationPolicyCheckPASSED FluidRevisionVerificationPolicyCheck = "PASSED"
|
||||
FluidRevisionVerificationPolicyCheckFAILED FluidRevisionVerificationPolicyCheck = "FAILED"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidRevisionVerificationPolicyCheck.
|
||||
func (v FluidRevisionVerificationPolicyCheck) Valid() bool {
|
||||
switch v {
|
||||
case FluidRevisionVerificationPolicyCheckPENDING, FluidRevisionVerificationPolicyCheckPASSED, FluidRevisionVerificationPolicyCheckFAILED:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type FluidRevisionVerificationSecurityCheck string
|
||||
|
||||
const (
|
||||
FluidRevisionVerificationSecurityCheckPENDING FluidRevisionVerificationSecurityCheck = "PENDING"
|
||||
FluidRevisionVerificationSecurityCheckPASSED FluidRevisionVerificationSecurityCheck = "PASSED"
|
||||
FluidRevisionVerificationSecurityCheckFAILED FluidRevisionVerificationSecurityCheck = "FAILED"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidRevisionVerificationSecurityCheck.
|
||||
func (v FluidRevisionVerificationSecurityCheck) Valid() bool {
|
||||
switch v {
|
||||
case FluidRevisionVerificationSecurityCheckPENDING, FluidRevisionVerificationSecurityCheckPASSED, FluidRevisionVerificationSecurityCheckFAILED:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type FluidRevisionVerificationStatus string
|
||||
|
||||
const (
|
||||
FluidRevisionVerificationStatusPENDING FluidRevisionVerificationStatus = "PENDING"
|
||||
FluidRevisionVerificationStatusPASSED FluidRevisionVerificationStatus = "PASSED"
|
||||
FluidRevisionVerificationStatusFAILED FluidRevisionVerificationStatus = "FAILED"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidRevisionVerificationStatus.
|
||||
func (v FluidRevisionVerificationStatus) Valid() bool {
|
||||
switch v {
|
||||
case FluidRevisionVerificationStatusPENDING, FluidRevisionVerificationStatusPASSED, FluidRevisionVerificationStatusFAILED:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// The primary safety barrier between adaptive generation and deterministic runtime
|
||||
// (ArchitectureBlueprint.md section 15).
|
||||
type FluidRevisionVerification struct {
|
||||
PolicyCheck *FluidRevisionVerificationPolicyCheck `json:"policy_check,omitempty" yaml:"policy_check,omitempty"`
|
||||
SecurityCheck *FluidRevisionVerificationSecurityCheck `json:"security_check,omitempty" yaml:"security_check,omitempty"`
|
||||
Status FluidRevisionVerificationStatus `json:"status" yaml:"status"`
|
||||
TestRefs []string `json:"test_refs,omitempty" yaml:"test_refs,omitempty"`
|
||||
}
|
||||
|
||||
type FluidRevision struct {
|
||||
AdaptationClasses []AdaptationClass `json:"adaptation_classes,omitempty" yaml:"adaptation_classes,omitempty"`
|
||||
|
||||
// Adoption is evidence, not proof of quality (FluidAPIStandards.md section 32).
|
||||
Adoption *FluidRevisionAdoption `json:"adoption,omitempty" yaml:"adoption,omitempty"`
|
||||
Audit *FluidRevisionAudit `json:"audit,omitempty" yaml:"audit,omitempty"`
|
||||
BackendRequirements []BackendRequirementID `json:"backend_requirements,omitempty" yaml:"backend_requirements,omitempty"`
|
||||
Compatibility FluidRevisionCompatibility `json:"compatibility" yaml:"compatibility"`
|
||||
Complexity *FluidRevisionComplexity `json:"complexity,omitempty" yaml:"complexity,omitempty"`
|
||||
Contract FluidRevisionContract `json:"contract" yaml:"contract"`
|
||||
CreatedAt *Timestamp `json:"created_at,omitempty" yaml:"created_at,omitempty"`
|
||||
CreatedBy *Actor `json:"created_by,omitempty" yaml:"created_by,omitempty"`
|
||||
Deployment *FluidRevisionDeployment `json:"deployment,omitempty" yaml:"deployment,omitempty"`
|
||||
Economics *FluidRevisionEconomics `json:"economics,omitempty" yaml:"economics,omitempty"`
|
||||
Fitness *FluidRevisionFitness `json:"fitness,omitempty" yaml:"fitness,omitempty"`
|
||||
ID RevisionID `json:"id" yaml:"id"`
|
||||
Implementation FluidRevisionImplementation `json:"implementation" yaml:"implementation"`
|
||||
|
||||
// Every revision is governed by a specific intent version, so audit can ask
|
||||
// whether the change was valid under the intent that existed at the time
|
||||
// (ArchitectureBlueprint.md section 27).
|
||||
InterfaceEvolutionIntent FluidRevisionInterfaceEvolutionIntent `json:"interface_evolution_intent" yaml:"interface_evolution_intent"`
|
||||
InterfaceID InterfaceID `json:"interface_id" yaml:"interface_id"`
|
||||
OriginatingHypotheses []HypothesisID `json:"originating_hypotheses,omitempty" yaml:"originating_hypotheses,omitempty"`
|
||||
|
||||
// Null marks genesis.
|
||||
ParentRevision *RevisionID `json:"parent_revision" yaml:"parent_revision"`
|
||||
Promotion *FluidRevisionPromotion `json:"promotion,omitempty" yaml:"promotion,omitempty"`
|
||||
Provenance FluidRevisionProvenance `json:"provenance" yaml:"provenance"`
|
||||
RevisionNumber int64 `json:"revision_number" yaml:"revision_number"`
|
||||
Rollback FluidRevisionRollback `json:"rollback" yaml:"rollback"`
|
||||
SchemaVersion SchemaVersion `json:"schema_version" yaml:"schema_version"`
|
||||
State FluidRevisionState `json:"state" yaml:"state"`
|
||||
|
||||
// The primary safety barrier between adaptive generation and deterministic runtime
|
||||
// (ArchitectureBlueprint.md section 15).
|
||||
Verification FluidRevisionVerification `json:"verification" yaml:"verification"`
|
||||
}
|
||||
|
||||
// What deterministic interface state was built, verified, exposed and measured.
|
||||
// Published revisions should be immutable; corrections create successors
|
||||
// (FluidAPIStandards.md section 8).
|
||||
type RevisionDocument struct {
|
||||
FluidRevision FluidRevision `json:"fluid_revision" yaml:"fluid_revision"`
|
||||
}
|
||||
82
internal/contract/routing_policy_gen.go
Normal file
82
internal/contract/routing_policy_gen.go
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
// Code generated by tools/schemagen. DO NOT EDIT.
|
||||
// Source: schemas/. Regenerate with `make generate`.
|
||||
|
||||
package contract
|
||||
|
||||
// What keeps a long-lived consumer on one side of an experiment.
|
||||
type RoutingPolicyRulesItemStickyBy string
|
||||
|
||||
const (
|
||||
RoutingPolicyRulesItemStickyByConsumerID RoutingPolicyRulesItemStickyBy = "consumer_id"
|
||||
RoutingPolicyRulesItemStickyByTenant RoutingPolicyRulesItemStickyBy = "tenant"
|
||||
RoutingPolicyRulesItemStickyByCorrelationID RoutingPolicyRulesItemStickyBy = "correlation_id"
|
||||
RoutingPolicyRulesItemStickyByNone RoutingPolicyRulesItemStickyBy = "none"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined RoutingPolicyRulesItemStickyBy.
|
||||
func (v RoutingPolicyRulesItemStickyBy) Valid() bool {
|
||||
switch v {
|
||||
case RoutingPolicyRulesItemStickyByConsumerID, RoutingPolicyRulesItemStickyByTenant, RoutingPolicyRulesItemStickyByCorrelationID, RoutingPolicyRulesItemStickyByNone:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type RoutingPolicyRulesItem struct {
|
||||
// Revision id to traffic share. Shares must sum to 1. Assignment of a given
|
||||
// consumer must be stable across requests.
|
||||
Allocation map[string]UnitInterval `json:"allocation" yaml:"allocation"`
|
||||
Cohort *CohortID `json:"cohort,omitempty" yaml:"cohort,omitempty"`
|
||||
Experiment *ExperimentID `json:"experiment,omitempty" yaml:"experiment,omitempty"`
|
||||
|
||||
// What keeps a long-lived consumer on one side of an experiment.
|
||||
StickyBy *RoutingPolicyRulesItemStickyBy `json:"sticky_by,omitempty" yaml:"sticky_by,omitempty"`
|
||||
Tenant string `json:"tenant,omitempty" yaml:"tenant,omitempty"`
|
||||
}
|
||||
|
||||
type RoutingPolicySignatureAlgorithm string
|
||||
|
||||
const (
|
||||
RoutingPolicySignatureAlgorithmEd25519 RoutingPolicySignatureAlgorithm = "ed25519"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined RoutingPolicySignatureAlgorithm.
|
||||
func (v RoutingPolicySignatureAlgorithm) Valid() bool {
|
||||
switch v {
|
||||
case RoutingPolicySignatureAlgorithmEd25519:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type RoutingPolicySignature struct {
|
||||
Algorithm RoutingPolicySignatureAlgorithm `json:"algorithm" yaml:"algorithm"`
|
||||
KeyID string `json:"key_id" yaml:"key_id"`
|
||||
Value string `json:"value" yaml:"value"`
|
||||
}
|
||||
|
||||
type RoutingPolicy struct {
|
||||
// Where a request lands when no earlier resolution step matched.
|
||||
DefaultRevision RevisionID `json:"default_revision" yaml:"default_revision"`
|
||||
|
||||
// Monotonic. The router ignores a policy older than the one it holds.
|
||||
Generation int64 `json:"generation" yaml:"generation"`
|
||||
ID string `json:"id,omitempty" yaml:"id,omitempty"`
|
||||
Interface InterfaceID `json:"interface" yaml:"interface"`
|
||||
IssuedAt *Timestamp `json:"issued_at,omitempty" yaml:"issued_at,omitempty"`
|
||||
IssuedBy *Actor `json:"issued_by,omitempty" yaml:"issued_by,omitempty"`
|
||||
|
||||
// Evaluated in order; the first matching rule wins. Matching must be a pure
|
||||
// function of the request and its cohort assignment.
|
||||
Rules []RoutingPolicyRulesItem `json:"rules" yaml:"rules"`
|
||||
SchemaVersion SchemaVersion `json:"schema_version" yaml:"schema_version"`
|
||||
Signature *RoutingPolicySignature `json:"signature,omitempty" yaml:"signature,omitempty"`
|
||||
}
|
||||
|
||||
// Deterministic routing written by the experiment controller and consumed by the
|
||||
// revision router. The controller never touches traffic itself; this separation
|
||||
// keeps experimental intent out of the runtime decision mechanism
|
||||
// (ArchitectureBlueprint.md section 17).
|
||||
type RoutingPolicyDocument struct {
|
||||
RoutingPolicy RoutingPolicy `json:"routing_policy" yaml:"routing_policy"`
|
||||
}
|
||||
172
internal/contract/telemetry_envelope_gen.go
Normal file
172
internal/contract/telemetry_envelope_gen.go
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
// Code generated by tools/schemagen. DO NOT EDIT.
|
||||
// Source: schemas/. Regenerate with `make generate`.
|
||||
|
||||
package contract
|
||||
|
||||
type FluidTelemetryAdoptionEvent string
|
||||
|
||||
const (
|
||||
FluidTelemetryAdoptionEventFirstUse FluidTelemetryAdoptionEvent = "first_use"
|
||||
FluidTelemetryAdoptionEventContinuedUse FluidTelemetryAdoptionEvent = "continued_use"
|
||||
FluidTelemetryAdoptionEventMigration FluidTelemetryAdoptionEvent = "migration"
|
||||
FluidTelemetryAdoptionEventReversion FluidTelemetryAdoptionEvent = "reversion"
|
||||
FluidTelemetryAdoptionEventDeprecationResponse FluidTelemetryAdoptionEvent = "deprecation_response"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidTelemetryAdoptionEvent.
|
||||
func (v FluidTelemetryAdoptionEvent) Valid() bool {
|
||||
switch v {
|
||||
case FluidTelemetryAdoptionEventFirstUse, FluidTelemetryAdoptionEventContinuedUse, FluidTelemetryAdoptionEventMigration, FluidTelemetryAdoptionEventReversion, FluidTelemetryAdoptionEventDeprecationResponse:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type FluidTelemetryAdoption struct {
|
||||
Event FluidTelemetryAdoptionEvent `json:"event" yaml:"event"`
|
||||
FromRevision *RevisionID `json:"from_revision,omitempty" yaml:"from_revision,omitempty"`
|
||||
}
|
||||
|
||||
type FluidTelemetryErrorClass string
|
||||
|
||||
const (
|
||||
FluidTelemetryErrorClassValidation FluidTelemetryErrorClass = "validation"
|
||||
FluidTelemetryErrorClassUnknownPath FluidTelemetryErrorClass = "unknown_path"
|
||||
FluidTelemetryErrorClassUnknownField FluidTelemetryErrorClass = "unknown_field"
|
||||
FluidTelemetryErrorClassUnsupportedParameter FluidTelemetryErrorClass = "unsupported_parameter"
|
||||
FluidTelemetryErrorClassAuthorization FluidTelemetryErrorClass = "authorization"
|
||||
FluidTelemetryErrorClassBackendFailure FluidTelemetryErrorClass = "backend_failure"
|
||||
FluidTelemetryErrorClassTimeout FluidTelemetryErrorClass = "timeout"
|
||||
FluidTelemetryErrorClassPolicyRejection FluidTelemetryErrorClass = "policy_rejection"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidTelemetryErrorClass.
|
||||
func (v FluidTelemetryErrorClass) Valid() bool {
|
||||
switch v {
|
||||
case FluidTelemetryErrorClassValidation, FluidTelemetryErrorClassUnknownPath, FluidTelemetryErrorClassUnknownField, FluidTelemetryErrorClassUnsupportedParameter, FluidTelemetryErrorClassAuthorization, FluidTelemetryErrorClassBackendFailure, FluidTelemetryErrorClassTimeout, FluidTelemetryErrorClassPolicyRejection:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type FluidTelemetryError struct {
|
||||
Class FluidTelemetryErrorClass `json:"class" yaml:"class"`
|
||||
|
||||
// Redacted. Must not carry backend internals or consumer data.
|
||||
Detail string `json:"detail,omitempty" yaml:"detail,omitempty"`
|
||||
Field string `json:"field,omitempty" yaml:"field,omitempty"`
|
||||
}
|
||||
|
||||
// ArchitectureBlueprint.md section 6.1.
|
||||
type FluidTelemetryKind string
|
||||
|
||||
const (
|
||||
FluidTelemetryKindRequest FluidTelemetryKind = "request"
|
||||
FluidTelemetryKindError FluidTelemetryKind = "error"
|
||||
FluidTelemetryKindSequence FluidTelemetryKind = "sequence"
|
||||
FluidTelemetryKindAdoption FluidTelemetryKind = "adoption"
|
||||
FluidTelemetryKindFeedback FluidTelemetryKind = "feedback"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidTelemetryKind.
|
||||
func (v FluidTelemetryKind) Valid() bool {
|
||||
switch v {
|
||||
case FluidTelemetryKindRequest, FluidTelemetryKindError, FluidTelemetryKindSequence, FluidTelemetryKindAdoption, FluidTelemetryKindFeedback:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// What the privacy filter removed. Recorded so analysis knows what it cannot see.
|
||||
type FluidTelemetryRedaction struct {
|
||||
Applied bool `json:"applied" yaml:"applied"`
|
||||
Rules []string `json:"rules,omitempty" yaml:"rules,omitempty"`
|
||||
}
|
||||
|
||||
type FluidTelemetryRequest struct {
|
||||
LatencyMS *float64 `json:"latency_ms,omitempty" yaml:"latency_ms,omitempty"`
|
||||
Method string `json:"method,omitempty" yaml:"method,omitempty"`
|
||||
Operation string `json:"operation,omitempty" yaml:"operation,omitempty"`
|
||||
RequestBytes *int64 `json:"request_bytes,omitempty" yaml:"request_bytes,omitempty"`
|
||||
ResponseBytes *int64 `json:"response_bytes,omitempty" yaml:"response_bytes,omitempty"`
|
||||
Route string `json:"route,omitempty" yaml:"route,omitempty"`
|
||||
Status *int64 `json:"status,omitempty" yaml:"status,omitempty"`
|
||||
}
|
||||
|
||||
type FluidTelemetryResolutionReason string
|
||||
|
||||
const (
|
||||
FluidTelemetryResolutionReasonExplicitRevision FluidTelemetryResolutionReason = "explicit_revision"
|
||||
FluidTelemetryResolutionReasonBoundContract FluidTelemetryResolutionReason = "bound_contract"
|
||||
FluidTelemetryResolutionReasonExperimentAssignment FluidTelemetryResolutionReason = "experiment_assignment"
|
||||
FluidTelemetryResolutionReasonCohortRule FluidTelemetryResolutionReason = "cohort_rule"
|
||||
FluidTelemetryResolutionReasonStableDefault FluidTelemetryResolutionReason = "stable_default"
|
||||
)
|
||||
|
||||
// Valid reports whether v is a defined FluidTelemetryResolutionReason.
|
||||
func (v FluidTelemetryResolutionReason) Valid() bool {
|
||||
switch v {
|
||||
case FluidTelemetryResolutionReasonExplicitRevision, FluidTelemetryResolutionReasonBoundContract, FluidTelemetryResolutionReasonExperimentAssignment, FluidTelemetryResolutionReasonCohortRule, FluidTelemetryResolutionReasonStableDefault:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Why this revision was chosen. Revision resolution must be deterministic and
|
||||
// auditable (ArchitectureBlueprint.md section 5.2).
|
||||
type FluidTelemetryResolution struct {
|
||||
PolicyGeneration *int64 `json:"policy_generation,omitempty" yaml:"policy_generation,omitempty"`
|
||||
Reason FluidTelemetryResolutionReason `json:"reason" yaml:"reason"`
|
||||
}
|
||||
|
||||
// Interaction topology is often more informative than error counts
|
||||
// (ArchitectureBlueprint.md section 6.4).
|
||||
type FluidTelemetrySequence struct {
|
||||
ChainID string `json:"chain_id,omitempty" yaml:"chain_id,omitempty"`
|
||||
Pattern string `json:"pattern,omitempty" yaml:"pattern,omitempty"`
|
||||
Position *int64 `json:"position,omitempty" yaml:"position,omitempty"`
|
||||
RepeatCount *int64 `json:"repeat_count,omitempty" yaml:"repeat_count,omitempty"`
|
||||
}
|
||||
|
||||
type FluidTelemetry struct {
|
||||
Adoption *FluidTelemetryAdoption `json:"adoption,omitempty" yaml:"adoption,omitempty"`
|
||||
Cohort *CohortID `json:"cohort,omitempty" yaml:"cohort,omitempty"`
|
||||
|
||||
// Pseudonymous and stable. Never a raw end-user identifier.
|
||||
ConsumerRef string `json:"consumer_ref,omitempty" yaml:"consumer_ref,omitempty"`
|
||||
|
||||
// Ties an event to the response the consumer saw, and to the other events in its
|
||||
// call chain.
|
||||
CorrelationID string `json:"correlation_id,omitempty" yaml:"correlation_id,omitempty"`
|
||||
Error *FluidTelemetryError `json:"error,omitempty" yaml:"error,omitempty"`
|
||||
Experiment *ExperimentID `json:"experiment,omitempty" yaml:"experiment,omitempty"`
|
||||
FeedbackRef *FeedbackID `json:"feedback_ref,omitempty" yaml:"feedback_ref,omitempty"`
|
||||
ID string `json:"id" yaml:"id"`
|
||||
InterfaceID InterfaceID `json:"interface_id" yaml:"interface_id"`
|
||||
|
||||
// ArchitectureBlueprint.md section 6.1.
|
||||
Kind FluidTelemetryKind `json:"kind" yaml:"kind"`
|
||||
OccurredAt Timestamp `json:"occurred_at" yaml:"occurred_at"`
|
||||
|
||||
// What the privacy filter removed. Recorded so analysis knows what it cannot see.
|
||||
Redaction *FluidTelemetryRedaction `json:"redaction,omitempty" yaml:"redaction,omitempty"`
|
||||
Request *FluidTelemetryRequest `json:"request,omitempty" yaml:"request,omitempty"`
|
||||
|
||||
// Why this revision was chosen. Revision resolution must be deterministic and
|
||||
// auditable (ArchitectureBlueprint.md section 5.2).
|
||||
Resolution *FluidTelemetryResolution `json:"resolution,omitempty" yaml:"resolution,omitempty"`
|
||||
Revision *RevisionID `json:"revision,omitempty" yaml:"revision,omitempty"`
|
||||
SchemaVersion SchemaVersion `json:"schema_version" yaml:"schema_version"`
|
||||
|
||||
// Interaction topology is often more informative than error counts
|
||||
// (ArchitectureBlueprint.md section 6.4).
|
||||
Sequence *FluidTelemetrySequence `json:"sequence,omitempty" yaml:"sequence,omitempty"`
|
||||
}
|
||||
|
||||
// The normalized interaction event. Designed for interface learning, not
|
||||
// unrestricted behavioral capture: raw payload capture is never the default and
|
||||
// redaction happens before an event reaches the store (ArchitectureBlueprint.md
|
||||
// section 6.2).
|
||||
type TelemetryEnvelopeDocument struct {
|
||||
FluidTelemetry FluidTelemetry `json:"fluid_telemetry" yaml:"fluid_telemetry"`
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue