ephemeral modifier on an input field tells ubx that the value is sensitive. ubx wraps it in pulumi.secret() semantics, which means Pulumi encrypts it in the state file and redacts it from plan and output displays. Any expression that references an ephemeral input becomes Pending<T> — ubx emits .apply() wrapping wherever needed.
Syntax
ephemeral modifier appears between the field name and the colon. It is compatible with all XCL types.
What it generates
A required ephemeral field (no default) generatesconfig.require_secret():
config.get_secret(), falling back to the default when the config key is not set:
Ephemeral inputs are always Pending<T>
config.require_secret() and config.get_secret() both return pulumi.Output[str] — Pulumi’s async wrapper. This means any expression that includes an ephemeral input is Pending<T> and must be resolved at apply time, not compile time.
ubx tracks this automatically. You do not annotate use sites — the compiler propagates Pending<T> through the expression tree and emits .apply() wrapping wherever the generated Python needs it.
Direct property assignment
Passing an ephemeral input directly to a resource property is valid. Pulumi’s Python SDK acceptsInput[T] (which includes Output[T]) for all resource properties:
Object expressions
Ephemeral inputs inside object literals are treated identically. Pulumi acceptsOutput[T] as map values:
F-string interpolation in sync values
When an ephemeral input appears inside avalues {} block inside a sync argocd or sync flux block, ubx wraps the entire values list with pulumi.Output.all().apply(). All pending expressions — including f-string fragments containing ephemeral refs — are collected into the dependency list and resolved before the values are passed to the deployment target:
Output.all() and indexed as _deps[0], _deps[1], etc. inside the lambda.
Default values
Whenephemeral and a default are combined, the generated accessor is config.get_secret() (optional) rather than config.require_secret() (required). The default is appended with or:
"" as the default if you want the field to be optional in development but always provided a real secret in production.
When to use ephemeral
Useephemeral for any value that must not appear in plain text in Pulumi’s state file:
- Database passwords (
db_password ephemeral: string) - API keys and tokens (
api_key ephemeral: string) - TLS private keys or certificate passphrases
- Webhook secrets
- OAuth client secrets
ephemeral for configuration that is sensitive in transit but safe to record in state (for example, a region name that is derived from a secret path but is not itself a secret).
What ephemeral protects — and what it does not
ephemeral protects state persistence. Pulumi encrypts the value in .ubx/state/ and redacts it from pulumi stack output and plan previews. It does not protect the value in transit — it is still passed to the resource constructor in plain text inside the running Pulumi program, and may appear in provider logs or cloud audit trails.
For secret storage and retrieval at runtime, combine ephemeral with from = "secretsmanager:..." or from = "ssm:/..." (see from attribute):
from attribute is a UBX-207 feature — refer to the input reference for current availability.
Relationship to import and module imports
ephemeral is an attribute on an input field, not a top-level block. It is unrelated to:

