2026-03-06 19:35:26 -05:00
export type SecretRefSource = "env" | "file" | "exec" ; // pragma: allowlist secret
2026-02-21 10:55:17 -08:00
/ * *
* Stable identifier for a secret in a configured source .
* Examples :
2026-02-25 17:39:31 -06:00
* - env source : provider "default" , id "OPENAI_API_KEY"
* - file source : provider "mounted-json" , id "/providers/openai/apiKey"
* - exec source : provider "vault" , id "openai/api-key"
2026-02-21 10:55:17 -08:00
* /
export type SecretRef = {
source : SecretRefSource ;
2026-02-25 17:39:31 -06:00
provider : string ;
2026-02-21 10:55:17 -08:00
id : string ;
} ;
export type SecretInput = string | SecretRef ;
2026-03-06 19:35:26 -05:00
export const DEFAULT_SECRET_PROVIDER_ALIAS = "default" ; // pragma: allowlist secret
2026-03-05 12:53:56 -06:00
export const ENV_SECRET_REF_ID_RE = /^[A-Z][A-Z0-9_]{0,127}$/ ;
2026-02-25 17:39:31 -06:00
const ENV_SECRET_TEMPLATE_RE = /^\$\{([A-Z][A-Z0-9_]{0,127})\}$/ ;
2026-03-02 20:58:20 -06:00
type SecretDefaults = {
env? : string ;
file? : string ;
exec? : string ;
} ;
2026-02-21 10:55:17 -08:00
2026-03-05 12:53:56 -06:00
export function isValidEnvSecretRefId ( value : string ) : boolean {
return ENV_SECRET_REF_ID_RE . test ( value ) ;
}
2026-02-21 17:08:14 -08:00
function isRecord ( value : unknown ) : value is Record < string , unknown > {
return typeof value === "object" && value !== null && ! Array . isArray ( value ) ;
}
export function isSecretRef ( value : unknown ) : value is SecretRef {
if ( ! isRecord ( value ) ) {
return false ;
}
2026-02-25 17:39:31 -06:00
if ( Object . keys ( value ) . length !== 3 ) {
2026-02-21 17:08:14 -08:00
return false ;
}
return (
2026-02-25 17:39:31 -06:00
( value . source === "env" || value . source === "file" || value . source === "exec" ) &&
typeof value . provider === "string" &&
value . provider . trim ( ) . length > 0 &&
2026-02-21 17:08:14 -08:00
typeof value . id === "string" &&
value . id . trim ( ) . length > 0
) ;
}
2026-02-25 17:39:31 -06:00
function isLegacySecretRefWithoutProvider (
value : unknown ,
) : value is { source : SecretRefSource ; id : string } {
if ( ! isRecord ( value ) ) {
return false ;
}
return (
( value . source === "env" || value . source === "file" || value . source === "exec" ) &&
typeof value . id === "string" &&
value . id . trim ( ) . length > 0 &&
value . provider === undefined
) ;
}
export function parseEnvTemplateSecretRef (
value : unknown ,
provider = DEFAULT_SECRET_PROVIDER_ALIAS ,
) : SecretRef | null {
if ( typeof value !== "string" ) {
return null ;
}
const match = ENV_SECRET_TEMPLATE_RE . exec ( value . trim ( ) ) ;
if ( ! match ) {
return null ;
}
return {
source : "env" ,
provider : provider.trim ( ) || DEFAULT_SECRET_PROVIDER_ALIAS ,
id : match [ 1 ] ,
} ;
}
2026-03-02 20:58:20 -06:00
export function coerceSecretRef ( value : unknown , defaults? : SecretDefaults ) : SecretRef | null {
2026-02-25 17:39:31 -06:00
if ( isSecretRef ( value ) ) {
return value ;
}
if ( isLegacySecretRefWithoutProvider ( value ) ) {
const provider =
value . source === "env"
? ( defaults ? . env ? ? DEFAULT_SECRET_PROVIDER_ALIAS )
: value . source === "file"
? ( defaults ? . file ? ? DEFAULT_SECRET_PROVIDER_ALIAS )
: ( defaults ? . exec ? ? DEFAULT_SECRET_PROVIDER_ALIAS ) ;
return {
source : value.source ,
provider ,
id : value.id ,
} ;
}
const envTemplate = parseEnvTemplateSecretRef ( value , defaults ? . env ) ;
if ( envTemplate ) {
return envTemplate ;
}
return null ;
}
2026-03-02 20:58:20 -06:00
export function hasConfiguredSecretInput ( value : unknown , defaults? : SecretDefaults ) : boolean {
if ( normalizeSecretInputString ( value ) ) {
return true ;
}
return coerceSecretRef ( value , defaults ) !== null ;
}
export function normalizeSecretInputString ( value : unknown ) : string | undefined {
if ( typeof value !== "string" ) {
return undefined ;
}
const trimmed = value . trim ( ) ;
return trimmed . length > 0 ? trimmed : undefined ;
}
function formatSecretRefLabel ( ref : SecretRef ) : string {
return ` ${ ref . source } : ${ ref . provider } : ${ ref . id } ` ;
}
export function assertSecretInputResolved ( params : {
value : unknown ;
refValue? : unknown ;
defaults? : SecretDefaults ;
path : string ;
} ) : void {
const { ref } = resolveSecretInputRef ( {
value : params.value ,
refValue : params.refValue ,
defaults : params.defaults ,
} ) ;
if ( ! ref ) {
return ;
}
throw new Error (
` ${ params . path } : unresolved SecretRef " ${ formatSecretRefLabel ( ref ) } ". Resolve this command against an active gateway runtime snapshot before reading it. ` ,
) ;
}
export function normalizeResolvedSecretInputString ( params : {
value : unknown ;
refValue? : unknown ;
defaults? : SecretDefaults ;
path : string ;
} ) : string | undefined {
const normalized = normalizeSecretInputString ( params . value ) ;
if ( normalized ) {
return normalized ;
}
assertSecretInputResolved ( params ) ;
return undefined ;
}
export function resolveSecretInputRef ( params : {
value : unknown ;
refValue? : unknown ;
defaults? : SecretDefaults ;
} ) : {
explicitRef : SecretRef | null ;
inlineRef : SecretRef | null ;
ref : SecretRef | null ;
} {
const explicitRef = coerceSecretRef ( params . refValue , params . defaults ) ;
const inlineRef = explicitRef ? null : coerceSecretRef ( params . value , params . defaults ) ;
return {
explicitRef ,
inlineRef ,
ref : explicitRef ? ? inlineRef ,
} ;
}
2026-02-25 17:39:31 -06:00
export type EnvSecretProviderConfig = {
source : "env" ;
/** Optional env var allowlist (exact names). */
allowlist? : string [ ] ;
2026-02-21 10:55:17 -08:00
} ;
2026-03-06 19:35:26 -05:00
export type FileSecretProviderMode = "singleValue" | "json" ; // pragma: allowlist secret
2026-02-25 17:39:31 -06:00
export type FileSecretProviderConfig = {
source : "file" ;
2026-02-21 10:55:17 -08:00
path : string ;
2026-02-25 17:39:31 -06:00
mode? : FileSecretProviderMode ;
timeoutMs? : number ;
maxBytes? : number ;
} ;
export type ExecSecretProviderConfig = {
source : "exec" ;
command : string ;
args? : string [ ] ;
2026-02-21 10:55:17 -08:00
timeoutMs? : number ;
2026-02-25 17:39:31 -06:00
noOutputTimeoutMs? : number ;
maxOutputBytes? : number ;
jsonOnly? : boolean ;
env? : Record < string , string > ;
passEnv? : string [ ] ;
trustedDirs? : string [ ] ;
allowInsecurePath? : boolean ;
2026-02-25 23:25:23 -06:00
allowSymlinkCommand? : boolean ;
2026-02-21 10:55:17 -08:00
} ;
2026-02-25 17:39:31 -06:00
export type SecretProviderConfig =
| EnvSecretProviderConfig
| FileSecretProviderConfig
| ExecSecretProviderConfig ;
2026-02-21 10:55:17 -08:00
export type SecretsConfig = {
2026-02-25 17:39:31 -06:00
providers? : Record < string , SecretProviderConfig > ;
defaults ? : {
env? : string ;
file? : string ;
exec? : string ;
} ;
resolution ? : {
maxProviderConcurrency? : number ;
maxRefsPerProvider? : number ;
maxBatchBytes? : number ;
2026-02-21 10:55:17 -08:00
} ;
} ;