# VERIFY — Security Attestation Extension (Agent Instructions)

> Drop this file into your CLAUDE.md, .cursorrules, copilot-instructions.md, or agent system prompt to make your AI tool VERIFY-compliant. This document is self-contained — no external files or downloads are required.

**Standard:** VERIFY v1.0 | **Authors:** itsavibe.ai

> **Prerequisite:** This agent configuration implements the VERIFY security attestation extension. Your tool MUST already implement the VIBES data standard (see `vibes-agent.md`). VERIFY builds on top of VIBES audit data. For risk scoring, see `prism-agent.md`. For agent learning and governance, see `evolve-agent.md`. For incident response and forensics (which uses DSSE envelopes for sealed evidence bundles), see `trace-agent.md`.

## Table of Contents

| § | Section | Anchor |
|---|---|---|
| 1 | What is VERIFY? | [#1-what-is-verify](#1-what-is-verify) |
| 2 | The Attestation Pipeline | [#2-the-attestation-pipeline](#2-the-attestation-pipeline) |
| 3 | DSSE Envelope Format | [#3-dsse-envelope-format](#3-dsse-envelope-format) |
| 4 | in-toto v1 Attestation Statement | [#4-in-toto-v1-attestation-statement](#4-in-toto-v1-attestation-statement) |
| 5 | Ed25519 Key Management | [#5-ed25519-key-management](#5-ed25519-key-management) |
| 6 | PAE (Pre-Authentication Encoding) | [#6-pae-pre-authentication-encoding](#6-pae-pre-authentication-encoding) |
| 7 | Content-Addressed Attestation ID | [#7-content-addressed-attestation-id](#7-content-addressed-attestation-id) |
| 8 | Trust Tiers | [#8-trust-tiers](#8-trust-tiers) |
| 9 | Tool Provider Cosigning | [#9-tool-provider-cosigning](#9-tool-provider-cosigning) |
| 10 | Agent Behavior | [#10-agent-behavior](#10-agent-behavior) |
| 11 | Confidence Levels | [#11-confidence-levels](#11-confidence-levels) |
| 12 | CLI Commands | [#12-cli-commands](#12-cli-commands) |

**Deep-load examples:**
- Just the trust tiers: `https://itsavibe.ai/verify-agent.md#8-trust-tiers`
- Just the key management chapter: `https://itsavibe.ai/verify-agent.md#5-ed25519-key-management`

---

## 1. What is VERIFY?

VERIFY wraps VIBES audit data in cryptographic envelopes — Ed25519 signatures, DSSE containers, and temporal anchors — so that any modification after signing is detectable. It transforms self-reported audit data into independently verifiable evidence.

Without attestation, anyone could edit their `.ai-audit/` files after the fact — inflating or deflating AI usage numbers, changing prompts, or removing records entirely. VERIFY makes that detectable.

---

## 2. The Attestation Pipeline

The pipeline transforms raw audit data into a verifiable, tamper-evident record in seven steps:

| Step | Name | Description |
|------|------|-------------|
| 1 | **Audit** | Validate `.ai-audit/` directory — file structure, hash integrity, assurance level compliance |
| 2 | **Hash** | Compute SHA-256 hashes for `manifest.json`, `annotations.jsonl`, and `config.json` |
| 3 | **Tool Sign** | (Optional) If the AI tool supports cosigning, it signs the PAE hash at data-creation time via its provider's signing service. Only the 32-byte hash is sent — audit data stays local |
| 4 | **User Sign** | Ed25519 private key signs the hashes inside a DSSE envelope wrapping an in-toto v1 attestation statement |
| 5 | **Timestamp** | (Optional) OpenTimestamps proof anchors the attestation to the Bitcoin blockchain for temporal evidence |
| 6 | **Submit** | DSSE envelope is sent to `POST /api/attestation/submit`. Server computes a content-addressed ID (SHA-256 of canonicalized envelope JSON) |
| 7 | **Verify** | Server-side: `GET /api/attestation/verify/{id}` checks hash integrity. Client-side: `vibecheck verify-attestation` performs full Ed25519 signature verification |

The entire pipeline runs locally via the `vibecheck` CLI. The private key never leaves the machine. Only the signed envelope — containing hashes, not actual data — is submitted to the registry.

---

## 3. DSSE Envelope Format

Attestations are wrapped in [DSSE](https://github.com/secure-systems-lab/dsse) — a minimal signing envelope format designed for software supply chain security.

```json
{
  "payloadType": "application/vnd.in-toto+json",
  "payload": "<base64url-encoded in-toto statement>",
  "signatures": [
    {
      "keyid": "a1b2c3d4e5f6a7b8",
      "sig": "<base64url-encoded Ed25519 signature>",
      "keytype": "user"
    },
    {
      "keyid": "anthropic-vibes-2026-01",
      "sig": "<base64url-encoded Ed25519 signature>",
      "keytype": "tool_provider"
    }
  ]
}
```

| Field | Required | Description |
|-------|----------|-------------|
| `payloadType` | Yes | Always `"application/vnd.in-toto+json"` |
| `payload` | Yes | Base64url-encoded in-toto v1 attestation statement |
| `signatures` | Yes | Array of one or more Ed25519 signatures |
| `signatures[].keyid` | Yes | First 16 hex chars of SHA-256 of DER-encoded public key |
| `signatures[].sig` | Yes | Base64url-encoded Ed25519 signature over PAE bytes |
| `signatures[].keytype` | No | `"user"` or `"tool_provider"` — distinguishes signature origin |

---

## 4. in-toto v1 Attestation Statement

The payload inside the DSSE envelope is an [in-toto v1](https://github.com/in-toto/attestation) attestation statement. It binds subjects (audit files) to a predicate (validation metadata).

```json
{
  "_type": "https://in-toto.io/Statement/v1",
  "subject": [
    {
      "name": ".ai-audit/manifest.json",
      "digest": { "sha256": "a1b2c3..." }
    },
    {
      "name": ".ai-audit/annotations.jsonl",
      "digest": { "sha256": "d4e5f6..." }
    },
    {
      "name": ".ai-audit/config.json",
      "digest": { "sha256": "f7a8b9..." }
    }
  ],
  "predicateType": "https://itsavibe.ai/vibes/attestation/v1",
  "predicate": {
    "validation": { "result": "PASS", "version": "1.2.0" },
    "project": { "name": "my-project", "assurance_level": "medium" },
    "stats": { "total_annotations": 142, "unique_models": 2 }
  }
}
```

| Field | Required | Description |
|-------|----------|-------------|
| `_type` | Yes | Always `"https://in-toto.io/Statement/v1"` |
| `subject` | Yes | Array of three entries — `manifest.json`, `annotations.jsonl`, `config.json` — each with `name` and `digest.sha256` |
| `predicateType` | Yes | Always `"https://itsavibe.ai/vibes/attestation/v1"` |
| `predicate.validation` | Yes | Validation result (`"PASS"` or `"FAIL"`) and vibecheck version |
| `predicate.project` | Yes | Project name and assurance level from `config.json` |
| `predicate.stats` | Yes | Annotation count and unique model count from the audit data |

---

## 5. Ed25519 Key Management

### Key Storage

Keys are stored at `~/.vibescheck/keys/` with strict file permissions:

| File | Format | Permissions | Description |
|------|--------|-------------|-------------|
| `vibescheck.key` | PKCS8 PEM | `0600` (owner read/write only) | Ed25519 private key. Never transmitted. |
| `vibescheck.pub` | SPKI PEM | `0644` (world-readable) | Ed25519 public key. Shared with the registry. |

### Key ID Computation

The `keyid` in every DSSE envelope is computed deterministically:

```
keyid = SHA256(DER_encode(public_key)).hex()[0:16]
```

This produces a 16-character hex string that uniquely identifies the signing key.

### Security Rules

- You MUST NOT transmit the private key over any network.
- You MUST enforce `0600` permissions on the private key file.
- You SHOULD warn the user if the private key file has incorrect permissions.
- You MUST NOT include key material in VIBES audit data (manifest entries, annotations, etc.).

---

## 6. PAE (Pre-Authentication Encoding)

DSSE uses Pre-Authentication Encoding to prevent confused deputy attacks. Before signing, the payload type and payload are combined into an unambiguous byte string:

```
PAE(payloadType, payload) =
  "DSSEv1" + SP +
  len(payloadType) + SP + payloadType + SP +
  len(payload) + SP + payload
```

The Ed25519 signature is computed over the PAE-encoded bytes, not the raw payload. Both user and tool provider signatures (if present) MUST cover identical PAE bytes.

---

## 7. Content-Addressed Attestation ID

Every attestation receives a deterministic, content-addressed ID:

1. Take the DSSE envelope.
2. Sort all keys recursively.
3. Serialize with no whitespace: `JSON.stringify(sortKeys(envelope))`.
4. Compute SHA-256 of the resulting string.
5. Express as 64-character lowercase hex.

The same envelope always produces the same ID, regardless of where or when it's computed.

---

## 8. Trust Tiers

Attestations fall into one of three trust tiers based on which signatures are present:

| Tier | Signatures | Description |
|------|-----------|-------------|
| **Self-Attested** | User only | A human or CI/CD pipeline attests to the data. No independent confirmation that the claimed tool produced it. Valid and useful, but the signer vouches alone. |
| **Tool-Corroborated** | User + Tool provider | The tool provider independently confirms it generated the audit data at the claimed time. Strongest assurance against fabrication, post-hoc editing, and tool impersonation. |
| **Tool-Only** | Tool provider only | The tool signed but no user countersigned. Valid, but indicates no human reviewed the attestation. |

Trust tiers are orthogonal to VIBES assurance levels — a Low-assurance attestation can be Tool-Corroborated, and a High-assurance attestation can be Self-Attested.

---

## 9. Tool Provider Cosigning

Cosigning adds a second Ed25519 signature from the tool provider, proving the tool generated the audit data in real time.

### Cosigning Flow

1. Tool generates `.ai-audit/` files as normal.
2. Tool computes SHA-256 hashes of audit files.
3. Tool builds in-toto statement with those hashes.
4. Tool computes PAE bytes.
5. Tool sends only the 32-byte PAE hash to the provider's signing service.
6. Provider signs and returns the signature.
7. User signs the same PAE bytes locally.
8. Both signatures go into the DSSE envelope.

### Key Distribution

Tool providers publish their public keys at a standard HTTPS endpoint:

```
https://{provider-domain}/vibes/vibes-signing-keys.json
```

```json
{
  "provider": "Anthropic",
  "tool_name": "Claude Code",
  "keys": [
    {
      "keyid": "anthropic-vibes-2026-01",
      "algorithm": "Ed25519",
      "public_key_pem": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----",
      "valid_from": "2026-01-01T00:00:00Z",
      "valid_until": "2027-01-01T00:00:00Z",
      "status": "active"
    }
  ],
  "rotation_policy": "Annual key rotation. Previous keys remain valid until valid_until."
}
```

### Cosigning Rules

- The tool provider signature MUST be generated at data-creation time. It cannot be obtained after the fact.
- Only the 32-byte PAE hash is sent to the provider — full audit data stays local.
- Verifiers MAY cache provider keys for up to 24 hours.
- Cosigning is optional in VIBES 1.0. Existing single-signature attestations remain fully valid.

---

## 10. Agent Behavior

### At Attestation Time

When the user requests attestation (e.g., via `vibecheck attest`):

1. Validate the `.ai-audit/` directory structure and hash integrity.
2. Compute SHA-256 hashes for `manifest.json`, `annotations.jsonl`, and `config.json`.
3. Build the in-toto v1 statement with file subjects and predicate metadata.
4. Compute PAE bytes from the payload type and base64url-encoded statement.
5. (Optional) If cosigning is configured, send the PAE hash to the tool provider's signing endpoint.
6. Sign the PAE bytes with the user's Ed25519 private key.
7. Assemble the DSSE envelope with all signatures.
8. Compute the content-addressed attestation ID.
9. Submit to the registry at `POST /api/attestation/submit`.

### At Verification Time

When verifying an attestation (e.g., via `vibecheck verify-attestation`):

1. Retrieve the DSSE envelope (from registry or local file).
2. Decode the base64url payload to get the in-toto statement.
3. Recompute PAE bytes from the payload type and payload.
4. For each signature in the `signatures` array:
   - Look up the public key by `keyid`.
   - Verify the Ed25519 signature over the PAE bytes.
5. For each subject in the in-toto statement:
   - Recompute the SHA-256 hash of the local file.
   - Compare against the declared digest. Any mismatch indicates tampering.
6. Report trust tier based on which signature types are present.

### What Attestation Proves

- **Integrity** — the audit files have not been modified since signing.
- **Authenticity** — a specific entity (identified by their Ed25519 key) signed the data.
- **Temporal existence** — the signed data existed at the time of attestation (strengthened by OpenTimestamps).

### What Attestation Does NOT Prove

- **Audit data correctness** — the accuracy of manifest entries and annotations is the auditor's responsibility.
- **Code behavior** — attestation covers the audit metadata, not the audited source code itself.
- **Signer trustworthiness** — trust in the signing entity must be established out of band.

---

## 11. Confidence Levels

Attestations in the registry carry one of three confidence levels indicating review depth:

| Level | Description |
|-------|-------------|
| **Self-Attested** | The project maintainer signed their own audit data. No external review. |
| **Manually Validated** | A human reviewer has examined the attestation data for structural integrity, metadata plausibility, and alignment with git history. |
| **Machine Validated** | Automated verification has confirmed hash integrity, signature validity, structural compliance, and cross-referenced audit data against commit history. |

---

## 12. CLI Commands

```bash
# Generate Ed25519 key pair
vibecheck keygen

# Create and submit an attestation
vibecheck attest

# Create attestation with tool provider cosigning
vibecheck attest --cosign-url https://provider.example.com/vibes/sign

# Verify an attestation locally (full Ed25519 verification)
vibecheck verify-attestation

# Verify via API (hash integrity check only)
curl https://itsavibe.ai/api/attestation/verify/{id}
```
