Skip to content

VVS-1 Header Reference

All VVS-1 compliant outgoing messages MUST include:

HeaderFormatDescription
X-Venmail-Agent{name}@{domain}Agent identity (e.g., [email protected])
X-Venmail-Signaturebase64urlEd25519 signature of the canonical payload
X-Venmail-Algorithmed25519Signing algorithm
X-Venmail-TimestampUnix secondsTime of signing
X-Venmail-Nonce32 hex charsCryptographically random 16-byte value
X-Venmail-Content-Hashsha256={base64url}SHA-256 hash of canonicalized body
X-Venmail-Verify-Methodcomma-separatedOrdered resolution methods
HeaderFormatDescription
X-Venmail-Public-Keybase64urlEd25519 public key (bootstrapping only)
X-Venmail-Key-VersionintegerKey version for rotation support
X-Venmail-ContextstringThread or workflow identifier

Before hashing:

  1. Encode body as UTF-8
  2. Normalize all line endings to \n (LF)
  3. Strip trailing whitespace from each line
  4. Do not strip leading whitespace
content_hash = "sha256=" + base64url(sha256(normalized_body))

Take these email header fields: from, to, subject, date

  1. Lowercase all field names
  2. Strip leading and trailing whitespace from values
  3. Fold multi-line values: replace \r\n <whitespace> with a single space
  4. Sort fields alphabetically by name
  5. Join as {name}:{value} separated by \n

Example output:

date:Mon, 30 Mar 2026 12:00:00 +0000
subject:Invoice #8821
canonical_payload =
agent_id + "\n" +
timestamp + "\n" +
nonce + "\n" +
content_hash + "\n" +
canonicalized_headers + "\n"
signature = base64url(Ed25519_sign(canonical_payload, private_key))
GET https://{domain}/.well-known/venmail-agent/{agent-name}

Response (application/json):

{
"agent_id": "[email protected]",
"public_key": "<base64url Ed25519 public key>",
"key_version": 1,
"status": "active",
"valid_from": "2026-01-01T00:00:00Z",
"valid_until": null
}

Status must be active. revoked or suspended results in FAILED immediately.

TXT record on _venmail.{domain}:

v=VVS1; agent={agent-name}; pubkey={base64url key}; kv={key-version}; status=active

Uses X-Venmail-Public-Key header value. Lowest trust — results in PARTIAL.

  • Timestamp: abs(current_time - X-Venmail-Timestamp) <= 3600 seconds (default)
  • Nonce: Receivers SHOULD store observed nonces for the replay window duration and reject duplicates

All binary values (signatures, keys, hashes) use base64url encoding without padding (RFC 4648 section 5, no = padding characters).