feat: typed loader gets interactive prompting for missing secrets, matching the untyped API - #375
feat: typed loader gets interactive prompting for missing secrets, matching the untyped API#375Ch4s3r wants to merge 1 commit into
Conversation
`declare_secrets!`'s generated builder gets a `prompt_missing(bool)` method mirroring `Secrets::ensure_secrets` on the untyped API: when a required secret is missing and stdin is a real terminal, it prompts and stores the value instead of failing with `RequiredSecretMissing`. Off by default, no behavior change for existing callers.
|
@domenkozar: is the opt-in I would recommend to default to prompting. It matches the untyped API's own default and the typed loader already only prompts when stdin is a real terminal, so CI/non-interactive callers are unaffected either way. I only made it opt-in here to avoid a behavior change for existing |
|
Hmmmm, I need to think about this. |
|
My goal it to just have the same experience with the declare macro, that it asks the user for missing variables if on a terminal. |
What
declare_secrets!'s generated builder getsprompt_missing(bool), mirroringSecrets::ensure_secretson the untyped API: when a required secret ismissing and stdin is a real terminal, it prompts and stores the value
instead of failing with
RequiredSecretMissing. It delegates to the exactsame
ensure_secretscall the untyped API already uses — no new prompt orstorage logic. Off by default (
false), so existing callers are unaffected.First run with nothing stored yet:
Second run: resolves from the keychain, no prompt. Non-interactive (CI,
piped stdin): same
RequiredSecretMissingasprompt_missing(false), neverhangs.
Same behavior on the untyped API, for comparison
This is not new — it's what the untyped
SecretsAPI already does today.prompt_missing(true)above is a thin pass-through to the same call(verified running, not just compiling):
Same prompt, same keychain write, same
RequiredSecretMissingon anon-terminal stdin — only the surface differs: a builder method that returns
typed struct fields vs. a function parameter that returns a name-keyed map.
Why
The typed and untyped APIs otherwise behave identically; this was the one
capability only the untyped
SecretsAPI had.Changes
secretspec-derive:SecretSpecBuilder::prompt_missing, threaded throughload()andload_profile().fallback, constraint-violation-vs-missing-secret guard, and
load_profile()wiring (separate from
load()'s).secretspec-derive/examples/prompt_missing.rs, referenced from theRust SDK docs.