Fallout-build / Fallout-build/Fallout

First-class variables + secret-substitution layer in build invocations

Open
#213 0 comments 0 reactions 0 assignees View on GitHub
enhancement target/backlog
Dominant language
C#
Stars
154
Forks
19
Avg merge
1d 22h
Merged PRs (30d)
15

Description

## Context
We have basic secrets today (`fallout :secrets`, `v1:`-encrypted values in `parameters.json` — see #212 for the audit). It's a *storage* mechanism: put secrets in the file, the build reads them via `[Parameter] [Secret] readonly string ApiKey;`.

We don't have a first-class **variable** layer — non-secret named values that can be:
- Defined once per repo (or per profile / environment) in a structured way.
- **Substituted into other parameter values, tool arguments, and CI config generators** — e.g. `apiUrl = "https://${env}.example.com/api"` where `${env}` resolves from a variable.
- Sourced from layered config (build defaults → repo profile → environment override → CLI arg), with clear precedence.

Variables and secrets go together:
- Both are named values configured per repo/profile/environment.
- Both want the same substitution syntax (`${name}` in tool args, CI config, artifact paths).
- Same resolution order: command-line > env var > profile > default.
- Only difference: is the value sensitive. Secrets get encrypted at rest, redacted in logs, never echoed into CI config.

Treating them as one feature with a `Sensitive=true` flag (not two parallel mechanisms) keeps the mental model small.

## What "first-class" buys consumers
Today in C#:
```csharp
[Parameter] readonly string Environment = "dev";
[Parameter] readonly string ApiUrl => $"https://{Environment}.example.com/api";
```
Works, but every consumer reinvents interpolation, and `[GitHubActions]`-generated workflows can't express "use this variable in the step args" — it's hardcoded at gen-time.

First-class variables let you write:
```json5
// .fallout/parameters.json
{
"Variables": {
"Environment": "dev",
"ApiUrl": "https://${Environment}.example.com/api"
},
"Secrets": {
"ApiKey": "v2:..." // existing encrypted-secret shape
}
}
```
and reference `${ApiUrl}` from a tool argument, a CI step's `env:` block, an artifact path. The resolver handles substitution, layering, redaction.

## Open design questions
- **Substitution syntax.** `${name}`, `{{ name }}`, `<>`? Pick one and document it.
- **Where substitution happens.** Parameter-injection time (so `[Parameter] readonly string ApiUrl` sees the resolved string)? Tool-invocation time? Both, with attribute opt-in?
- **Profile/environment layering.** Partly exists via `parameters..json` profiles. Variables + secrets should follow it. Document the precedence chain.
- **CI-config generators.** Do `[GitHubActions]` / `[AzurePipelines]` emit `${{ env.X }}` placeholders the CI engine resolves, or resolve at gen-time? Probably placeholders for secrets (no leaking into committed YAML), gen-time for non-sensitive variables.
- **External secret managers (#168 — 1Password, Bitwarden, Vault).** The variable layer is the natural plug-in surface: `secrets.VaultRef("my-org/api-key")` resolved at injection time. Sketch the seam now even if backends land later.
- **Plugin SDK touch points.** v12 ships `Fallout.Plugin.Sdk`; variable resolvers and secret backends are natural extension points. Decide whether the variable subsystem ships *before* the SDK (internal seams) or as part of it (public seams).

## Milestone
Maintainer pick:
- **v10.x** — probably too late; this is a public-API addition.
- **v11** — plausible if scoped to internal substitution + a layered-config refactor that keeps the public API stable. Pairs with the foundation work (god-class split, internal `IBuildMiddleware`).
- **v12** — more natural if we want public extension seams (`IVariableResolver`, `ISecretBackend`) shipping with `Fallout.Plugin.Sdk`. Pairs with #168 and #180.

Chris's call. Both defensible; v12 feels right for the public-API shape, but an internal v11 cut works if internal value is high enough.

## Refs
- Existing secret storage: `src/Fallout.Utilities/Security/EncryptionUtility.cs` + `fallout :secrets` (`Program.Secrets.cs`).
- Security audit: #212.
- External secret backends: #168.
- OS keychain integration: #180.
- ADR-0002 (cross-provider auth/secret conventions): `docs/adr/0002-cross-provider-auth-and-secret-conventions.md`.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.