Help us shape the future of Go! Take the 2026 Go Developer Survey

vaultresolve

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 7, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

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

type Binding struct {
	SecretName  string
	Placeholder string
}

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.

type Querier

type Querier interface {
	Query(ctx context.Context, sql string, args ...any) (pgx.Rows, error)
}

Querier is the read surface resolution needs — satisfied by a *pgxpool.Pool or a pgx.Tx. Resolution decrypts nothing, so it takes no cipher yet.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL