Creates a vault entry, either an encryption key (material generated by DeltaForge) or a credential (caller-supplied secret or pointer to an external secret). VAULT and CREDENTIAL are keyword aliases for the same object.
CREATE { VAULT | CREDENTIAL } [IF NOT EXISTS] <name>
TYPE = { ENCRYPTION_KEY | CREDENTIAL }
[ALGORITHM '<algo>']
[KEY_SIZE <bits>]
[ SECRET '<value>' | GENERATE | LINKED EXTERNAL SECRET '<external_name>' ]
[IN CREDENTIAL STORAGE <backend_name>]
[DESCRIPTION '<text>']
[EXPIRES '<timestamp>']
## Overview CREATE VAULT (aliased as CREATE CREDENTIAL) registers a named secret in the DeltaForge vault. It mirrors the "New Entry" form in the GUI's Vault page. The same row is produced regardless of whether the entry is created via SQL or via the GUI, the Control Plane API is the single execution path. ## Entry kinds - **ENCRYPTION_KEY**, symmetric key material used by MASK() pseudonymisation functions (keyed_hash, encrypt, tokenize). Typically combined with `GENERATE` so DeltaForge creates random bytes directly in the backend. The algorithm and key size are stored as metadata but not enforced. - **CREDENTIAL**, caller-supplied secret (API token, password, certificate content, connection string). The value is passed through `SECRET '<value>'` as a string literal or referenced via `LINKED EXTERNAL SECRET` when the secret already exists in an external vault. ## Secret source (mutually exclusive) Exactly one of the following may appear: - `SECRET '<value>'`, the caller supplies the secret directly. The value is parsed, immediately wrapped in the redacting `SecretLiteral` type (whose `Debug` impl prints `SecretLiteral(***)`), and forwarded to the backend. It never hits the catalog, logs, or formatted SQL output. - `GENERATE`: DeltaForge generates random material using the OS CSPRNG. Valid only for `TYPE = ENCRYPTION_KEY`. The bytes are hex-encoded and stored in the credential backend under profile `vault::<entry_id>` (keys `key` and `salt`). - `LINKED EXTERNAL SECRET '<name>'`, register a pointer to an existing secret in the backend namespace. Material is never copied into DeltaForge. The runtime resolves the value on demand from the backend on every read. Requires `IN CREDENTIAL STORAGE <backend_name>` (cannot default to OS Keychain, you can only link into a named cloud backend). - *None of the above*, metadata-only entry. Useful for bootstrapping an entry whose secret will be set later via `ALTER VAULT ... SET SECRET '...'`. ## Storage backend selection When `IN CREDENTIAL STORAGE <backend_name>` is omitted, the default OS Keychain backend is used. This is the right choice for local development. For production, create a cloud backend via `CREATE CREDENTIAL STORAGE` (Azure Key Vault, AWS Secrets Manager, GCP Secret Manager) and reference it explicitly. ## VAULT vs CREDENTIAL The two keywords produce the identical catalog row. The parser records which spelling was used purely for diagnostic purposes (`used_credential_alias` in the AST, surfaced in error messages and SHOW output); execution treats them identically. Use whichever reads better at the call site: - `CREATE CREDENTIAL api_token ...` reads naturally when the entry is a token or password. - `CREATE VAULT pii_key ...` reads naturally when the entry is encryption material. ## Idempotency `IF NOT EXISTS` makes the statement safe to re-run, the second execution is a no-op. There is intentionally **no** `OR REPLACE` form: on a re-run it would destroy existing secret material (which is non-recoverable), breaking every downstream consumer of that secret. To replace a secret's value use `ALTER VAULT … SET SECRET '…'`; to rotate an encryption key use `ALTER VAULT … ROTATE`.
| Name | Type | Description |
|---|---|---|
name | Unique vault entry name. Must be unique across the catalog (enforced by a UNIQUE constraint on vault_entries.display_name). | |
entry_kind | ENCRYPTION_KEY for symmetric key material generated by DeltaForge (used by MASK() pseudonymisation functions), or CREDENTIAL for caller-supplied secrets (API tokens, passwords, connection strings, OAuth refresh tokens). | |
algorithm | Crypto algorithm label stored alongside the material. Typical values: 'aes-256', 'hmac-sha256', 'chacha20-poly1305'. DeltaForge does not enforce the label, downstream consumers (MASK() functions) read it to route encryption. | |
key_size_bits | Key size in bits for GENERATE. Typical values: 128, 256 (default for aes-256), 512 (hmac-sha512). Stored in vault_entries.key_size_bits for audit. | |
secret | Caller-supplied secret value. Parsed as a string literal, wrapped in SecretLiteral (redacting Debug impl), forwarded directly to the credential backend store, and never serialized into the catalog, logs, or formatted SQL. Mutually exclusive with GENERATE and LINKED EXTERNAL SECRET. | |
generate | Generate random material using the OS CSPRNG. Valid only for TYPE = ENCRYPTION_KEY. The generated bytes are hex-encoded and stored in the credential backend under profile `vault::<entry_id>` with keys `key` and `salt`. | |
linked_external_secret | Register a pointer to an existing secret in the backend (typically Azure Key Vault, AWS Secrets Manager, or GCP Secret Manager). DeltaForge stores only the reference, the material never leaves the backend. Must be combined with IN CREDENTIAL STORAGE. | |
storage_backend | Name of a CREDENTIAL STORAGE backend (see CREATE CREDENTIAL STORAGE). Defaults to the built-in OS Keychain backend (id `00000000-0000-0000-0000-000000000001`) when omitted. | |
description | Human-readable description. Appears in the GUI Vault page and SHOW/DESCRIBE output. | |
expires_at | Advisory expiry timestamp (ISO 8601). Stored in vault_entries.expires_at; not currently enforced by the runtime, consumers query it to implement rotation policies. |
-- Generate an AES-256 encryption key in the OS keychain
CREATE VAULT pii_key
TYPE = ENCRYPTION_KEY
ALGORITHM 'aes-256'
KEY_SIZE 256
GENERATE
DESCRIPTION 'Key for pseudonymising customer PII';
-- Store a caller-supplied API token (CREDENTIAL is an alias for VAULT)
CREATE CREDENTIAL IF NOT EXISTS stripe_api_token
TYPE = CREDENTIAL
SECRET 'sk_live_REDACTED'
IN CREDENTIAL STORAGE local_keychain
DESCRIPTION 'Stripe production API token'
EXPIRES '2027-01-01T00:00:00Z';
-- Register a pointer to an existing Azure Key Vault secret (material never copied)
CREATE VAULT prod_db_password
TYPE = CREDENTIAL
LINKED EXTERNAL SECRET 'prod-db-password'
IN CREDENTIAL STORAGE azure_kv;
-- Store an OAuth refresh token for a connection
CREATE CREDENTIAL github_pat
TYPE = CREDENTIAL
SECRET 'ghp_REDACTED'
DESCRIPTION 'GitHub personal access token for repo sync';