# MVG Receipt Countersign Specification (v1.0.0)

This document describes the **optional, reviewer‑generated countersignature** format used by MVG’s offline verifiers (e.g., `/verify-assurance/`, `/verify-trust/`) to produce a **signed internal approval record**.

- **Public‑safe spec**: no customer data required.
- **Offline by design**: no uploads, no network calls (CSP `connect-src 'none'` + runtime air‑gap guard).
- **Reviewer‑generated**: countersignatures attest that *a specific reviewer* verified an artifact locally. MVG does **not** attest to reviewer identity.

---

## 1) Objects

### 1.1 Base verification receipt (existing)

`schema_id: "mvg.verification_receipt@1"`

Generated by the offline verifier after verifying:
- integrity (SHA‑256 digest),
- signatures (DSSE Ed25519),
- contents manifest,
- optional key transparency log.

Key fields used by countersign:
- `artifact_fingerprint` (deterministic from verifier+policy+artifacts+verdicts)
- `verification_run_id` (hash of the full base receipt)
- `generated_utc`, `verifier`, `policy`, `artifacts`, `verdicts`

### 1.2 Countersigned verification receipt (wrapper)

`schema_id: "mvg.countersigned_verification_receipt@1"`

A wrapper that keeps the **base receipt immutable** and attaches one or more reviewer countersignatures:

```json
{
  "schema_id": "mvg.countersigned_verification_receipt@1",
  "countersigned_receipt_version": "1.0.0",
  "generated_utc": "2026-02-11T00:00:00Z",
  "base_receipt": { /* mvg.verification_receipt@1 */ },
  "base_receipt_sha256": "sha256:<hex>",
  "countersigned_receipt_id": "sha256:<hex>",
  "countersignatures": [ /* mvg.receipt.countersignature@1 */ ],
  "notes": [ "..." ]
}
```

Notes:
- `base_receipt_sha256` is computed over **canonical JSON** of `base_receipt` (see §2).
- `countersigned_receipt_id` is computed over a deterministic subset:  
  `{schema_id, base_receipt_sha256, countersignatures[{payload_sha256, signature_b64u}]}`.

### 1.3 Countersignature object

`schema_id: "mvg.receipt.countersignature@1"`

```json
{
  "schema_id": "mvg.receipt.countersignature@1",
  "payload": { /* mvg.receipt.countersign_payload@1 */ },
  "payload_sha256": "sha256:<hex>",
  "signature_b64u": "<base64url>"
}
```

### 1.4 Signed payload

`schema_id: "mvg.receipt.countersign_payload@1"`

The verifier signs the canonical JSON of this `payload` object:

```json
{
  "schema_id": "mvg.receipt.countersign_payload@1",
  "signed_utc": "2026-02-11T00:00:00Z",
  "algorithm": "ECDSA_P256_SHA256",
  "base_receipt_sha256": "sha256:<hex>",
  "base_artifact_fingerprint": "sha256:<hex>",
  "base_verification_run_id": "sha256:<hex>",
  "public_key_fingerprint_sha256": "sha256:<hex>",
  "public_key_jwk": { "kty":"EC", "crv":"P-256", "x":"...", "y":"..." },   // optional but recommended
  "signer": { "organization":"...", "name":"...", "email":"..." },        // optional
  "statement": "Verified offline; approved for internal procurement review." // optional
}
```

Binding requirements (verification MUST enforce):
- `payload.base_receipt_sha256 == countersigned_receipt.base_receipt_sha256`
- `payload_sha256 == sha256(canonical_json(payload))`
- `signature` verifies over the canonical JSON bytes of `payload`

---

## 2) Canonical JSON

All hashes and signatures are computed over a deterministic canonicalization:

- **Recursive key sorting** (lexicographic by key)
- **No whitespace** in JSON serialization
- **UTF‑8** encoding of the resulting string

(Implementation: a minimal recursive canonicalizer + `JSON.stringify()` with no indentation.)

---

## 3) Hash format

- Digest algorithm: **SHA‑256**
- Output: lowercase hex
- Stored as: `"sha256:<hex>"`

---

## 4) Signature format

- Algorithm: **ECDSA P‑256 with SHA‑256** (`ECDSA_P256_SHA256`)
  - Chosen for broad WebCrypto compatibility.
- `signature_b64u` stores the raw WebCrypto signature bytes as **base64url**.
  - Many engines emit DER‑encoded ECDSA signatures; verification uses the same WebCrypto semantics.

---

## 5) Verification procedure

To verify a countersigned receipt:

1. Parse JSON.
2. Check wrapper `schema_id == "mvg.countersigned_verification_receipt@1"`.
3. Recompute `base_receipt_sha256` from `base_receipt` canonical JSON; compare.
4. For each countersignature:
   - Check `schema_id`.
   - Recompute `payload_sha256`; compare.
   - Check payload is bound to the wrapper base sha.
   - Import `payload.public_key_jwk` (if present) as EC P‑256 public key.
   - Verify `signature_b64u` over canonical JSON of `payload`.
5. Output:
   - **PASS** if all countersignatures verify
   - **FAIL** if any countersignature fails
   - **HOLD** if verification cannot be performed (e.g., missing public key / unsupported crypto)

---

## 6) Security notes

- Do **not** upload private keys to any website. The verifier is designed to run offline.
- Your org should establish signer identity and key provenance (e.g., MDM‑provisioned keys, internal PKI, or key escrow policy).
- Countersignatures provide **integrity** and **non‑repudiation within your org’s trust model**; they do not make claims about universal AI safety.

