How the SWT3 protocol securely transfers compliance factors to your custody before clearing.
Reading guide: If you are evaluating this from a governance or procurement perspective, start with Sections 1 and 2, then skip to Sections 4 and 6. The integration details in Sections 3 and 5 are written for development teams.
The Factor Handoff is a custody transfer, not a backup.
When the SWT3 SDK creates an anchor on your system, it holds the raw data (the "factors") needed to prove that anchor is real. At Clearing Level 2 or 3, the SDK needs to get that data safely into your hands before it wipes its own copy and sends the stripped payload to TeNova.
Once the handoff is complete, your copy is the only copy that exists. TeNova's copy has been destroyed. If you lose your copy, no one can help you re-verify that anchor. That is the trade-off of higher clearing levels, and it is by design.
The data included in a handoff depends on your clearing level.
At Level 2, your factors and hashes still go to TeNova. What gets stripped is contextual metadata. The handoff captures what was removed:
| What you receive | What it is | Example |
|---|---|---|
| Provider name | Which AI service was used | "openai" |
| Guardrail names | Which safety filters were active | ["content_filter", "pii_redactor"] |
| System fingerprint | Provider's internal system ID | "fp-abc123" |
| Clearing level | The level that was applied | 2 |
| Anchor fingerprint | The sealed SWT3 fingerprint | "96b7d56c0245" |
| Timestamp | When the anchor was created | 1712188800000 |
At Level 3, nearly everything is stripped. The handoff captures all the data you need to independently prove any anchor is real:
| What you receive | What it is | Example |
|---|---|---|
| Procedure ID | Which compliance check was witnessed | "AI-INF.1" |
| Factor A, B, C | The three numeric values that form the proof | 1, 1, 0 |
| Model ID | The original (unhashed) model name | "gpt-4o-2024-05-13" |
| Prompt hash | SHA-256 hash of the input | "a1b2c3..." |
| Response hash | SHA-256 hash of the output | "d4e5f6..." |
| Latency | How long the inference took | 1240 ms |
| Token counts | Input and output token usage | 512 in / 1024 out |
| Full context | Provider, guardrails, system fingerprint | {"provider": "openai", ...} |
| Anchor fingerprint | The sealed SWT3 fingerprint | "96b7d56c0245" |
| Timestamp | When the anchor was created | 1712188800000 |
The SWT3 SDK supports four methods for receiving your factors. You choose one (or more) when you set up the SDK. The handoff always fires after the anchor is sealed but before the clearing engine wipes the local copy.
The simplest option. The SDK writes your factor data to a JSON file on your local system. Works everywhere, including air-gapped environments.
from swt3_ai import Witness
witness = Witness(
tenant_id="ACME_DEFENSE",
clearing_level=3,
factor_handoff="file",
factor_handoff_path="/secure/vault/factors/"
)
import { Witness } from "@tenova/swt3-ai";
const witness = new Witness({
tenantId: "ACME_DEFENSE",
clearingLevel: 3,
factorHandoff: "file",
factorHandoffPath: "/secure/vault/factors/"
});
Each anchor gets its own file, named by its fingerprint. Store on an encrypted filesystem with restricted permissions (owner read/write only).
The SDK sends factor data to an HTTPS endpoint you control. Ideal if you run a centralized secrets manager or compliance vault.
witness = Witness(
tenant_id="ACME_DEFENSE",
clearing_level=3,
factor_handoff="webhook",
factor_handoff_url="https://vault.acme-defense.com/api/v1/factors",
factor_handoff_headers={"Authorization": "Bearer <your-vault-token>"}
)
const witness = new Witness({
tenantId: "ACME_DEFENSE",
clearingLevel: 3,
factorHandoff: "webhook",
factorHandoffUrl: "https://vault.acme-defense.com/api/v1/factors",
factorHandoffHeaders: { Authorization: "Bearer <your-vault-token>" }
});
Safety rules:
For organizations already using HashiCorp Vault, the SDK writes factors directly to a KV v2 secrets engine.
witness = Witness(
tenant_id="ACME_DEFENSE",
clearing_level=3,
factor_handoff="vault",
factor_handoff_vault_addr="https://vault.acme-defense.com",
factor_handoff_vault_token="hvs.your-token",
factor_handoff_vault_path="secret/data/swt3/factors"
)
const witness = new Witness({
tenantId: "ACME_DEFENSE",
clearingLevel: 3,
factorHandoff: "vault",
factorHandoffVaultAddr: "https://vault.acme-defense.com",
factorHandoffVaultToken: "hvs.your-token",
factorHandoffVaultPath: "secret/data/swt3/factors"
});
We recommend a dedicated Vault policy scoped to the SWT3 factor path so the SDK token can only write to that location.
For organizations using cloud key management, the SDK encrypts factor data with a key you control before writing it locally. The encrypted file can be stored anywhere because the data is unreadable without your KMS key.
witness = Witness(
tenant_id="ACME_DEFENSE",
clearing_level=3,
factor_handoff="kms",
factor_handoff_kms_key_id="arn:aws:kms:us-east-1:123456789:key/abc-def",
factor_handoff_path="/secure/factors/"
)
const witness = new Witness({
tenantId: "ACME_DEFENSE",
clearingLevel: 3,
factorHandoff: "kms",
factorHandoffKmsKeyId: "arn:aws:kms:us-east-1:123456789:key/abc-def",
factorHandoffPath: "/secure/factors/"
});
One encrypted file per anchor. Decryption requires access to the KMS key. Key rotation is managed by your cloud provider.
The handoff follows a strict sequence designed to prevent data loss:
Steps 4 and 5 are the key. If the handoff fails for any reason (your vault is down, the disk is full, the network is unreachable), the SDK stops. It does not clear. It does not transmit. Your factors stay on your system until the handoff succeeds.
Your data is never destroyed until it is safely in your hands.
That is a hard guarantee, not a best-effort policy.
Once you hold the factors, you can verify any anchor at any time without contacting TeNova and without any network connection. The formula is:
fingerprint = SHA256("WITNESS:" + tenant_id + ":" + procedure_id + ":" + factor_a + ":" + factor_b + ":" + factor_c + ":" + timestamp_ms)
take the first 12 characters of the hex result
If the fingerprint you compute matches the one in the SWT3 Anchor string, the anchor is valid and has not been tampered with.
import hashlib
def verify(tenant_id, procedure_id, fa, fb, fc, ts_ms, expected):
msg = f"WITNESS:{tenant_id}:{procedure_id}:{fa}:{fb}:{fc}:{ts_ms}"
return hashlib.sha256(msg.encode()).hexdigest()[:12] == expected
import { createHash } from "crypto";
function verify(
tenantId: string, procId: string,
fa: number, fb: number, fc: number,
tsMs: number, expected: string
): boolean {
const msg = `WITNESS:${tenantId}:${procId}:${fa}:${fb}:${fc}:${tsMs}`;
return createHash("sha256").update(msg).digest("hex").slice(0, 12) === expected;
}
This is the same algorithm used by the TeNova platform, the public verifier at sovereign.tenova.io/verify, and the libswt3 reference implementation. There is no proprietary step, no secret key, and no TeNova dependency.
TeNova does not tell you how to store your factors. That is your decision based on your security requirements and regulatory environment. But we strongly recommend:
| Method | Python SDK | TypeScript SDK | Status |
|---|---|---|---|
| Local File Export | v0.2.1 | v0.2.1 | Implemented |
| Webhook | v0.3.0 | v0.3.0 | Specification complete |
| HashiCorp Vault | v0.4.0 | v0.4.0 | Specification complete |
| Cloud KMS Envelope | v0.4.0 | v0.4.0 | Specification complete |
Local File Export is available now in both SDKs. Configure factorHandoff: "file" and factorHandoffPath on the Witness constructor. The webhook, Vault, and KMS methods are specified and planned for future releases.