URI-Scheme Value References

script_vars.interpolate hardcodes a single indirection (${secrets.NAME} → vault) and AssetStore credential references are vault-name-only. There was no general, pluggable read-time indirection — the modern config pattern of storing a pointer (env://TOKEN, file://./token, secret://api-key) rather than the value. This adds that resolver.

Pure standard library (os / re); imports no PySide6. The env reader, secret resolver, and base directory are injectable, so resolution is safe and deterministic in CI.

Headless API

from je_auto_control import resolve_ref, resolve_refs_in, RefResolver

token = resolve_ref("env://API_TOKEN")
key = resolve_ref("file://./secrets/key.pem")

config = resolve_refs_in({
    "token": "env://API_TOKEN",
    "db": {"password": "secret://db-password"},
})

resolve_ref resolves one reference: env:// reads an environment variable (from an injectable mapping, falling back to os.environ), file:// reads a file (with an optional base_dir realpath guard against traversal), and secret:// delegates to an injectable resolver or the governance credential broker. resolve_refs_in walks a nested dict/list and resolves every reference in place, leaving non-reference values untouched. is_ref tests a value, and RefResolver bundles the injectable backends for repeated use. Unresolvable or unknown-scheme references raise SecretRefError.

Executor commands

AC_resolve_ref resolves a single ref into {value}; AC_resolve_refs resolves every reference inside obj and returns {resolved}. Both are exposed as MCP tools (ac_resolve_ref / ac_resolve_refs) and as Script Builder commands under Security.