Documentation
¶
Overview ¶
Package vaultresolve is read-time vault-credential resolution: it turns a session's attached vault_ids into the environment-variable bindings a sandbox is provisioned with. Resolution reads current rows every time it runs (no cache), so rotation and archive propagate without a session restart (docs/plan/12_vaults-credentials.md, D5).
Two resolutions share one selection rule (winnersFor, first-vault-wins), so they can never disagree on which credential a secret_name resolves to. Bindings yields the sandbox-visible half: each active environment_variable credential's secret_name paired with an opaque placeholder derived per (session, secret_name) (internal/egress) — stable across re-provision. Credentials yields the gate half: the same winners with their secrets decrypted, which the per-session egress gate substitutes back for the placeholder at egress time. The sandbox only ever sees the placeholder; the secret is never injected into it.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Binding ¶
Binding is one resolved environment-variable credential: the sandbox-visible env var, injected at provision as SecretName=Placeholder. The placeholder is opaque and inert on its own — a request that carries it egresses the literal token until the gate substitutes the real secret.
func Bindings ¶
func Bindings(ctx context.Context, q Querier, sessionID string, vaultIDs []string) ([]Binding, error)
Bindings resolves the active environment_variable credentials of sessionID's attached vaults into placeholder bindings. When several attached vaults carry the same secret_name, the first vault in vaultIDs order wins (D5). An archived vault contributes nothing: archiving a vault archives and purges its credentials, so the archived_at filter already excludes them. Placeholders are derived per (session, secret_name), so resolution is fully deterministic — a re-provision or the egress gate recovers the exact tokens already injected.
type Credential ¶
type Credential struct {
CredentialID string // vcrd_… — non-secret; the substitution span's credential_id (plan 12)
VaultID string // vlt_… — the containing vault; a credential_host_unreachable_error names both ids
SecretName string // the sandbox env-var name; the winner key
Placeholder string // egress.Placeholder(sessionID, SecretName) — identical to the Binding's token
Secret string // plaintext secret_value; memory-only
AllowedHosts []string // the limited allow-list (nil when Unrestricted)
Unrestricted bool // the credential's networking arm
Header bool // injection_location.header
Body bool // injection_location.body
}
Credential is one resolved environment_variable credential ready for the egress gate: the sandbox-visible Placeholder, the Secret it stands for, the credential's own networking half (Unrestricted, or AllowedHosts for limited), and the injection locations it is enabled for. It is the gate-side twin of a Binding — both resolve from the same winner (see winnersFor), so a placeholder injected into the sandbox and the secret substituted at egress always agree.
Secret is plaintext: it lives only in the resolving process's memory and the config response body — never logged, never stored (docs/plan/12, D1).
func Credentials ¶
func Credentials(ctx context.Context, q Querier, cipher secrets.Cipher, sessionID string, vaultIDs []string) ([]Credential, error)
Credentials resolves the active environment_variable credentials of sessionID's attached vaults into their decrypted secrets — the gate's substitution set. It shares winnersFor with Bindings, so both halves select the same credential per secret_name (first vault in vaultIDs order wins).
A cipher is required once the session has any active environment_variable credential (a winner) — even one whose ciphertext was purged: a vault-attached session on a cipher-less deployment is a misconfiguration, not a silent no-op. A decrypt failure or a sealed document missing its secret_value fails the whole call — a cipher outage or tampering deserves a loud, fail-closed error rather than a partial set that would let a placeholder egress as a literal with no signal. An active credential whose ciphertext is absent (a purge anomaly, not reachable through the write path) is skipped: its sandbox placeholder simply egresses literally, which is fail-closed. Error messages carry credential ids, never secret or ciphertext bytes.