@@ -66,6 +66,8 @@ func TestProgramManifestCanonicalFingerprintContract(t *testing.T) {
6666 },
6767 "target-phase" : func (value * delivery.ProgramManifest ) {
6868 value .Transitions [0 ].TargetPhases = []delivery.ProtocolPhase {delivery .PhaseFrontier }
69+ phase := string (delivery .PhaseFrontier )
70+ value .Transitions [0 ].StateEffect .Assignments [0 ].Value = & phase
6971 },
7072 "authority" : func (value * delivery.ProgramManifest ) {
7173 value .Transitions [0 ].Authority = []delivery.AuthorityClass {delivery .AuthorityHuman }
@@ -83,12 +85,23 @@ func TestProgramManifestCanonicalFingerprintContract(t *testing.T) {
8385 value .Transitions [0 ].Verifier = "alternate.verifier"
8486 },
8587 "postcondition" : func (value * delivery.ProgramManifest ) {
86- value .Transitions [0 ].TargetConditions [0 ].Values = []string {"alternate" }
88+ value .Transitions [0 ].TargetConditions [0 ].Values = []string {"published" }
89+ published := "published"
90+ value .Transitions [0 ].StateEffect .Assignments [1 ].Value = & published
8791 },
8892 "recovery" : func (value * delivery.ProgramManifest ) {
8993 value .Transitions [0 ].Interruption .Recovery = "alternate.recover"
9094 },
9195 "priority" : func (value * delivery.ProgramManifest ) { value .Transitions [0 ].Priority ++ },
96+ "owned-facets" : func (value * delivery.ProgramManifest ) {
97+ value .Transitions [0 ].OwnedFacets = []delivery.StateFacet {delivery .StateFacetControl }
98+ value .Transitions [0 ].StateEffect .Assignments = value .Transitions [0 ].StateEffect .Assignments [:1 ]
99+ value .Transitions [0 ].TargetConditions = []delivery.FacetCondition {delivery .KnownCondition (delivery .FacetProgram , "current" )}
100+ },
101+ "state-effect" : func (value * delivery.ProgramManifest ) {
102+ nonterminal := "nonterminal"
103+ value .Transitions [0 ].StateEffect .Assignments = append (value .Transitions [0 ].StateEffect .Assignments , delivery.StateAssignment {Facet : "terminal" , Value : & nonterminal })
104+ },
92105 }
93106 for name , mutate := range mutations {
94107 t .Run (name , func (t * testing.T ) {
@@ -108,6 +121,37 @@ func TestProgramManifestCanonicalFingerprintContract(t *testing.T) {
108121 }
109122}
110123
124+ func TestProgramManifestCanonicalizesStateEffectSets (t * testing.T ) {
125+ fixture := func () delivery.ProgramManifest {
126+ manifest := programFixture ()
127+ transition := & manifest .Transitions [0 ]
128+ transition .SourcePhases = []delivery.ProtocolPhase {delivery .PhaseActive , delivery .PhaseObserved }
129+ transition .SourceConditions = append (transition .SourceConditions , delivery .KnownCondition (delivery .FacetTerminal , "nonterminal" ))
130+ transition .TargetConditions = append (transition .TargetConditions , delivery .KnownCondition (delivery .FacetTerminal , "established" ))
131+ phase , terminal , deliveryState := string (delivery .PhaseTerminal ), "established" , "terminal"
132+ transition .StateEffect = delivery.StateEffect {
133+ Kind : delivery .StateEffectAssignments ,
134+ Preconditions : []delivery.StatePrecondition {
135+ {Facet : "phase" , Values : []string {string (delivery .PhaseActive ), string (delivery .PhaseObserved )}},
136+ {Facet : "terminal" , Values : []string {"nonterminal" }},
137+ },
138+ Assignments : []delivery.StateAssignment {{Facet : "phase" , Value : & phase }, {Facet : "terminal" , Value : & terminal }, {Facet : "delivery" , Value : & deliveryState }},
139+ }
140+ return manifest
141+ }
142+
143+ oneManifest := fixture ()
144+ one := loadManifest (t , oneManifest )
145+ twoManifest := fixture ()
146+ reverse (twoManifest .Transitions [0 ].StateEffect .Preconditions )
147+ reverse (twoManifest .Transitions [0 ].StateEffect .Preconditions [1 ].Values )
148+ reverse (twoManifest .Transitions [0 ].StateEffect .Assignments )
149+ two := loadManifest (t , twoManifest )
150+ if one .Fingerprint () != two .Fingerprint () {
151+ t .Fatalf ("state-effect set ordering changed executable identity: %s != %s" , one .Fingerprint (), two .Fingerprint ())
152+ }
153+ }
154+
111155func TestProgramManifestNamespaceAndCompatibilityBoundary (t * testing.T ) {
112156 // control-law: only-compatible-validated-programs-reach-the-runtime-registry
113157 first := programFixture ()
@@ -152,6 +196,22 @@ func TestProgramManifestNamespaceAndCompatibilityBoundary(t *testing.T) {
152196 {"under-declared-kernel-effect" , func (value * delivery.ProgramManifest ) {
153197 value .Capabilities .CapabilitySurface = []delivery.Capability {delivery .CapabilityRepositoryWrite }
154198 }, runtimeFixture (), delivery .ProgramInvalid },
199+ {"host-native-state-handler" , func (value * delivery.ProgramManifest ) {
200+ value .Transitions [0 ].StateEffect = delivery.StateEffect {Kind : delivery .StateEffectNative , NativeHandler : "abandon-delivery" }
201+ }, runtimeFixture (), delivery .ProgramInvalid },
202+ {"product-only-owned-facets" , func (value * delivery.ProgramManifest ) {
203+ value .Transitions [0 ].OwnedFacets = []delivery.StateFacet {delivery .StateFacetProduct }
204+ }, runtimeFixture (), delivery .ProgramInvalid },
205+ {"unclosed-verified-configuration" , func (value * delivery.ProgramManifest ) {
206+ verified := "verified"
207+ value .Transitions [0 ].SourceConditions = append (value .Transitions [0 ].SourceConditions , delivery .KnownCondition (delivery .FacetConfiguration , "unsupported" ))
208+ value .Transitions [0 ].TargetConditions = append (value .Transitions [0 ].TargetConditions , delivery .KnownCondition (delivery .FacetConfiguration , verified ))
209+ value .Transitions [0 ].StateEffect .Assignments = []delivery.StateAssignment {{Facet : "configuration" , Value : & verified }}
210+ }, runtimeFixture (), delivery .ProgramInvalid },
211+ {"optional-assignment-parameter" , func (value * delivery.ProgramManifest ) {
212+ value .Transitions [0 ].Parameters = append (value .Transitions [0 ].Parameters , delivery.ParameterSpec {Name : "optional_state" })
213+ value .Transitions [0 ].StateEffect .Assignments = []delivery.StateAssignment {{Facet : "phase" , ValueFrom : delivery.StateValueReference {Parameter : "optional_state" }}}
214+ }, runtimeFixture (), delivery .ProgramInvalid },
155215 {"duplicate-condition" , func (value * delivery.ProgramManifest ) {
156216 value .Transitions [0 ].SourceConditions = append (value .Transitions [0 ].SourceConditions , value .Transitions [0 ].SourceConditions [0 ])
157217 }, runtimeFixture (), delivery .ProgramInvalid },
@@ -234,18 +294,21 @@ func TestValidatedProgramIsTheKernelRegistry(t *testing.T) {
234294}
235295
236296func programFixture () delivery.ProgramManifest {
297+ activePhase := string (delivery .PhaseActive )
237298 recovery := delivery.ProgramTransition {
238299 ID : "recover" , Version : 1 , SelectionClass : delivery .SelectionProgramRecovery , Class : delivery .EventRecovery ,
239300 SourcePhases : []delivery.ProtocolPhase {delivery .PhaseRecovery }, TargetPhases : []delivery.ProtocolPhase {delivery .PhaseActive },
240301 RequiredIdentity : []string {"repository-id" }, Authority : []delivery.AuthorityClass {delivery .AuthorityRepository }, RequiredCapabilities : []delivery.Capability {delivery .CapabilityRepositoryWrite }, RequiredEvidence : []string {"snapshot" },
241- OwnedResources : []string {"program.state" }, Effect : "program.recover" , LocalEffects : []delivery.EffectID {"program.recover" }, Idempotent : true ,
302+ OwnedResources : []string {"program.state" }, OwnedFacets : []delivery.StateFacet {delivery .StateFacetControl }, StateEffect : delivery.StateEffect {Kind : delivery .StateEffectAssignments , Assignments : []delivery.StateAssignment {{Facet : "phase" , Value : & activePhase }}},
303+ Effect : "program.recover" , LocalEffects : []delivery.EffectID {"program.recover" }, Idempotent : true ,
242304 Prescription : delivery.Prescription {Operation : "recover" , ExpectedPostcondition : "active" }, SourcePredicate : "recovery-required" ,
243- SourceConditions : []delivery.FacetCondition {delivery .KnownCondition (delivery .FacetRecovery , "required" )}, AdmissionPredicate : "exact-admission" ,
305+ SourceConditions : []delivery.FacetCondition {delivery .KnownCondition (delivery .FacetRecovery , "required" ), delivery . KnownCondition ( delivery . FacetProgram , "current" ) }, AdmissionPredicate : "exact-admission" ,
244306 TargetPredicate : "active" , TargetConditions : []delivery.FacetCondition {delivery .KnownCondition (delivery .FacetProgram , "current" )}, Verifier : "program.current" ,
245307 Interruption : interruption ("recover" ), Reversibility : delivery .Reversible , TerminalEffect : "none" ,
246308 PrivacyClassification : "metadata-only" , TelemetryClassification : "transition-receipt" , CostClass : "local" , Policy : delivery.PolicyContract {ObjectiveScope : delivery .ObjectiveScopeOptionalPreserve }, Priority : 1 ,
247309 }
248310 advance := recovery
311+ terminalPhase , terminalDelivery := string (delivery .PhaseTerminal ), "terminal"
249312 advance .ID = "advance"
250313 advance .SelectionClass = delivery .SelectionProgramProgress
251314 advance .Class = delivery .EventOwnedLocal
@@ -260,6 +323,8 @@ func programFixture() delivery.ProgramManifest {
260323 advance .SourceConditions = []delivery.FacetCondition {delivery .KnownCondition (delivery .FacetProgram , "current" ), delivery .KnownCondition (delivery .FacetDelivery , "active" )}
261324 advance .TargetPredicate = "terminal"
262325 advance .TargetConditions = []delivery.FacetCondition {delivery .KnownCondition (delivery .FacetDelivery , "terminal" )}
326+ advance .OwnedFacets = []delivery.StateFacet {delivery .StateFacetControl , delivery .StateFacetProduct }
327+ advance .StateEffect .Assignments = []delivery.StateAssignment {{Facet : "phase" , Value : & terminalPhase }, {Facet : "delivery" , Value : & terminalDelivery }}
263328 advance .Verifier = "program.terminal"
264329 advance .Policy .ObjectiveScope = delivery .ObjectiveScopeBoundExact
265330 return delivery.ProgramManifest {
0 commit comments