@@ -1049,6 +1049,54 @@ function isMessagingCredentialPlaceholderAssignment(
10491049 return CREDENTIAL_ENV_NAME_PATTERN . test ( envKey ) && envKey === placeholderEnvKey ;
10501050}
10511051
1052+ function isMessagingRuntimeEnvAliasPath ( path : readonly string [ ] ) : boolean {
1053+ return (
1054+ path . length === 5 &&
1055+ path [ 0 ] === "messaging" &&
1056+ path [ 1 ] === "plan" &&
1057+ path [ 2 ] === "runtimeSetup" &&
1058+ path [ 3 ] === "envAliases" &&
1059+ JSON_ARRAY_INDEX_SEGMENT_RE . test ( path [ 4 ] ?? "" )
1060+ ) ;
1061+ }
1062+
1063+ function ownDataPropertyValue ( value : Record < string , unknown > , key : string ) : unknown {
1064+ const descriptor = Object . getOwnPropertyDescriptor ( value , key ) ;
1065+ return descriptor && "value" in descriptor ? descriptor . value : undefined ;
1066+ }
1067+
1068+ function isCanonicalMessagingRuntimeEnvAlias (
1069+ path : readonly string [ ] ,
1070+ value : Record < string , unknown > ,
1071+ ) : boolean {
1072+ if ( ! isMessagingRuntimeEnvAliasPath ( path ) ) return false ;
1073+ const envKey = ownDataPropertyValue ( value , "envKey" ) ;
1074+ const match = ownDataPropertyValue ( value , "match" ) ;
1075+ const placeholder = ownDataPropertyValue ( value , "value" ) ;
1076+ return (
1077+ typeof envKey === "string" &&
1078+ CREDENTIAL_ENV_NAME_PATTERN . test ( envKey ) &&
1079+ match === `^openshell:resolve:env:(v[0-9]+_)?${ envKey } $` &&
1080+ typeof placeholder === "string" &&
1081+ messagingCredentialPlaceholderEnvKey ( placeholder ) === envKey
1082+ ) ;
1083+ }
1084+
1085+ function isAllowedMessagingRuntimeAliasStringPath (
1086+ path : readonly string [ ] ,
1087+ allowedAliasIndexes : ReadonlySet < string > ,
1088+ ) : boolean {
1089+ return (
1090+ path . length === 6 &&
1091+ path [ 0 ] === "messaging" &&
1092+ path [ 1 ] === "plan" &&
1093+ path [ 2 ] === "runtimeSetup" &&
1094+ path [ 3 ] === "envAliases" &&
1095+ allowedAliasIndexes . has ( path [ 4 ] ?? "" ) &&
1096+ ( path [ 5 ] === "match" || path [ 5 ] === "value" )
1097+ ) ;
1098+ }
1099+
10521100function isMessagingPackagePin ( path : readonly string [ ] , value : unknown ) : boolean {
10531101 return (
10541102 path . length === 6 &&
@@ -1399,6 +1447,7 @@ function assertPayloadStructureAndCredentialShapes(root: unknown): void {
13991447 depth : number ;
14001448 path : readonly string [ ] ;
14011449 } > = [ { value : root , depth : 0 , path : [ ] } ] ;
1450+ const allowedRuntimeAliasIndexes = new Set < string > ( ) ;
14021451 let discoveredNodes = 1 ;
14031452 let observedBytes = 0 ;
14041453
@@ -1426,6 +1475,7 @@ function assertPayloadStructureAndCredentialShapes(root: unknown): void {
14261475 if ( typeof current . value === "string" ) {
14271476 observeText ( current . value ) ;
14281477 if (
1478+ ! isAllowedMessagingRuntimeAliasStringPath ( current . path , allowedRuntimeAliasIndexes ) &&
14291479 ! isMessagingCredentialPlaceholder ( current . path , current . value ) &&
14301480 ! isMessagingCredentialPlaceholderAssignment ( current . path , current . value ) &&
14311481 ( valueLooksLikeSecret ( current . value ) ||
@@ -1485,6 +1535,9 @@ function assertPayloadStructureAndCredentialShapes(root: unknown): void {
14851535 if ( "toJSON" in current . value ) {
14861536 invalid ( "payload must not define a custom JSON serializer" ) ;
14871537 }
1538+ if ( isCanonicalMessagingRuntimeEnvAlias ( current . path , current . value ) ) {
1539+ allowedRuntimeAliasIndexes . add ( current . path [ 4 ] as string ) ;
1540+ }
14881541 const keys = Object . getOwnPropertyNames ( current . value ) ;
14891542 if (
14901543 Object . getOwnPropertySymbols ( current . value ) . length > 0 ||
0 commit comments