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