Documentation
¶
Overview ¶
Package mpc is cloud's client-side-CEK sealing client for the SEPARATE MPC node ring (ghcr.io/luxfi/mpc). It is the minimal inlined subset of the former github.com/hanzoai/kms/sdk/go client that clients/fleet and clients/provisioning use to seal per-org secrets (BYO kubeconfigs, provisioned-resource passwords) onto the MPC nodes so the nodes only ever store ciphertext.
WHY INLINED (HIP-0106 alignment). cloud embeds the canonical luxfi/kms SecretStore in-process (clients/kms — the deps.KMS / types.KMSClient), and MPC stays its own separate nodes on luxfi/mpc. Dropping that external dependency leaves cloud depending only on luxfi/kms (embedded) + hanzoai/iam (embedded). This package reproduces the SDK's wire protocol verbatim. The KEY SCHEDULE is no longer reproduced here: its second stage is hanzoai/cek, the estate's one derivation. The schedule this was inlined from survives only in hanzoai/kms/sdk/go, which is archived and read-only — this is the live client, so it derives where everything else in the estate derives rather than keeping a private copy of an HKDF and hoping the copy stays equal to something nobody maintains.
Zero-knowledge model: all encryption/decryption happens client-side with a Customer Encryption Key (CEK) derived from an admin passphrase; the CEK never leaves this process, and the MPC nodes only ever store encrypted blobs.
Passphrase -> Argon2id -> Master Key -> cek -> CEK (AES-256-GCM)
The two stages answer different questions and stay separate. Argon2id makes a GUESSABLE secret expensive to guess, which is a property a passphrase needs and a KMS master does not. cek turns a uniformly random 32-byte master into the key for one named thing. Neither substitutes for the other.
FOLLOW-UP (a separate, TESTED change — not this dependency move): fold fleet/provisioning sealing into cloud's embedded deps.KMS once types.KMSClient gains a Delete verb and the swap is verified against the live MPC ring, so there is exactly one KMS surface.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client connects to the MPC node ring and provides zero-knowledge secret management. All secret data is encrypted client-side with the CEK; the MPC nodes only store encrypted blobs. Goroutine-safe.
The zero value is not usable; construct with NewClient.
func NewClient ¶
NewClient creates a client. It is initially locked; call Unlock before any Set/Get/Delete.
func (*Client) Delete ¶
Delete removes a secret from the MPC nodes. Succeeds when at least threshold nodes acknowledge.
func (*Client) Get ¶
Get retrieves an encrypted blob from the MPC nodes and decrypts it client-side with the CEK.
type Config ¶
type Config struct {
// Nodes is the list of MPC node addresses
// (e.g. ["https://kms-mpc-0:9999", "https://kms-mpc-1:9999"]).
Nodes []string
// Namespace names the org whose secrets these are. It is a NAME rather than
// a slug because the caller builds it at cloud's one door (cloud.OrgNamespace)
// — this package derives a key from it and must not be the place a string
// becomes a tenant. Its id is the AES-GCM AAD and the path scope, so it binds
// every ciphertext to exactly one tenant.
Namespace namespace.Namespace
// Threshold is the minimum number of nodes required for an operation (t-of-n).
Threshold int
// HTTPClient is an optional custom client. nil ⇒ a default 30s-timeout client.
HTTPClient *http.Client
}
Config configures a client. Nodes/Namespace/Threshold are required; HTTPClient is optional (a 30-second-timeout client is used when nil).