Build a Vault Connector

Implement the vault connector interface to become a HUMΛN-compatible vault provider

The Vault Connector Contract

Implement six actions, return ciphertext, never decrypt. That's it. Your connector receives opaque bytes and returns opaque bytes. The client holds the keys; you hold the ciphertext.

The Invariant

Your connector is a ciphertext carrier. You will receive opaque bytes and you will return opaque bytes. You will never see plaintext. This is the security guarantee, not a limitation. If your connector ever decrypts data, it violates the contract and cannot be a HUMΛN vault provider.

Critical: The server must never have a plaintext decoder. The VaultConnectorTestHarness includes a ciphertext opacity assertion — it verifies that your connector returns only ciphertext and IV, never decrypted content.

Implementing the Manifest

Required actions: vault:store, vault:retrieve, vault:delete, vault:list, vault:migrate-in, vault:export. Optional: vault:share.

json
{
"id": "my-vault-connector",
"name": "My Vault",
"description": "Self-hosted vault with ciphertext-only storage",
"provider": "acme",
"version": "1.0.0",
"capabilities": ["vault/read", "vault/write", "vault/admin", "vault/migrate"],
"actions": [
{ "name": "vault:store", "paramsSchema": { ... } },
{ "name": "vault:retrieve", "paramsSchema": { ... } },
{ "name": "vault:delete", "paramsSchema": { ... } },
{ "name": "vault:list", "paramsSchema": { ... } },
{ "name": "vault:export", "paramsSchema": { ... } },
{ "name": "vault:migrate-in", "paramsSchema": { ... } }
]
}

Wiring Up the API

The API routes delegate to the connector via invoke(). Extend BaseConnector from @human/connector-sdk and implement the dispatch pattern. The vault API at /v1/vault/:entityDid/:namespace/:collection calls your connector when the org's vault_endpoint points to your deployment.

The Migration Protocol

vault:export produces documents with their original doc_id preserved. vault:migrate-in accepts documents with explicit IDs. Why: vault:// URI stability. If a migration changes doc IDs, it breaks every pointer in every Passport. The URI vault://did:human:alice/health/mri/scan-2026.dcm must resolve to the same document after migration.

typescript
// vault:export — return documents with doc_id preserved
{ documents: [{ doc_id: "scan-2026.dcm", ciphertext: "...", iv: "...", metadata: {} }] }
// vault:migrate-in — accept documents with explicit doc_id
POST body: { documents: [{ doc_id: "scan-2026.dcm", ciphertext: "...", iv: "..." }] }

Testing Your Connector

Use the VaultConnectorTestHarness from @human/connector-vault/test-harness. Smoke tests: store → retrieve round-trip, doc ID stability across migrate (when implemented), ciphertext opacity (assert server never has a plaintext decoder).

typescript
import { VaultConnectorTestHarness } from '@human/connector-vault/test-harness';
const harness = new VaultConnectorTestHarness({
entityDid: 'did:human:test',
invoke: async (action, params) => myConnector.invoke(action, params),
});
const result = await harness.runAll();
if (!result.passed) {
throw new Error(result.error ?? 'Harness failed');
}

Registering in the Marketplace

Submit your connector with ConnectorRegistration, distribution: 'marketplace', and capabilities: ['vault/read', 'vault/write', 'vault/admin', 'vault/migrate']. Orgs can then select your vault as their vault_endpoint during setup.

Next Steps

Understand what your connector protects before you build it. Read Your Data, Your Key to see the full sovereignty model.

Your Data, Your Key