@@ -45,9 +45,11 @@ pub fn canonicalize_advisor_add_rule(
4545 } )
4646 . cloned ( )
4747 . map ( |mut endpoint| {
48- // This marker is derived from provider/credential context by the
49- // gateway and must never be persisted from an advisor proposal.
48+ // Provenance does not change the endpoint contract. The gateway
49+ // derives the credential marker, and the advisor marker records
50+ // where a persisted endpoint came from.
5051 endpoint. provider_credentialed = false ;
52+ endpoint. advisor_proposed = false ;
5153 // A denial observes one binary-to-port authorization. Preserve the
5254 // existing inspection contract, but never copy sibling ports from
5355 // a multi-port endpoint into the proposal.
@@ -84,6 +86,7 @@ pub fn canonicalize_advisor_add_rule(
8486 . any ( |endpoint| {
8587 let mut normalized = endpoint. clone ( ) ;
8688 normalized. provider_credentialed = false ;
89+ normalized. advisor_proposed = false ;
8790 normalize_endpoint ( & mut normalized) ;
8891 normalized == contract
8992 } )
@@ -92,6 +95,12 @@ pub fn canonicalize_advisor_add_rule(
9295 . collect :: < Vec < _ > > ( ) ;
9396 sandbox_owners. sort ( ) ;
9497
98+ let mut contract = contract;
99+ if sandbox_owners. is_empty ( ) {
100+ // A provider-owned contract is mirrored into a new sandbox-owned
101+ // advisor overlay, so retain the incoming proposal provenance.
102+ contract. advisor_proposed = incoming_endpoint. advisor_proposed ;
103+ }
95104 let target_name = sandbox_owners
96105 . first ( )
97106 . cloned ( )
@@ -2220,6 +2229,7 @@ mod tests {
22202229 assert_eq ! ( canonical. endpoints[ 0 ] . protocol, "rest" ) ;
22212230 assert_eq ! ( canonical. endpoints[ 0 ] . access, "read-only" ) ;
22222231 assert ! ( !canonical. endpoints[ 0 ] . provider_credentialed) ;
2232+ assert ! ( canonical. endpoints[ 0 ] . advisor_proposed) ;
22232233 assert_eq ! (
22242234 effective. network_policies[ "_provider_example" ] . endpoints[ 0 ] ,
22252235 provider_endpoint
0 commit comments