Skip to content

Test Vectors — HARP

Test Vectors

Byte-level conformance tests for validating HARP implementations.

This document provides deterministic canonicalization, hashing, and signing test vectors for HARP-CORE implementations.

Canonical JSON bytes are produced by:

  • UTF-8 encoding
  • Object keys sorted lexicographically
  • No insignificant whitespace (separators , and :)
  • No trailing newline

Implementations MUST reproduce the exact byte sequences shown below.

Artifact (signable form: WITHOUT artifactHash)

Section titled “Artifact (signable form: WITHOUT artifactHash)”
{
"requestId": "01J2V8V3K6B2Z9X6G1V7Y2QK8H",
"sessionId": "01J2V8V3M2YF0KX9Q0Z7E6H9R1",
"artifactType": "plan.review",
"repoRef": "repo:acme/widgets",
"baseRevision": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"createdAt": "2026-02-21T12:00:00Z",
"expiresAt": "2026-02-21T12:10:00Z",
"payload": {
"kind": "plan",
"title": "Refactor Parser",
"steps": [
"Extract tokenizer",
"Add unit tests",
"Replace recursive descent with Pratt parser"
],
"risk": "medium"
},
"artifactHashAlg": "SHA-256"
}
{"artifactHashAlg":"SHA-256","artifactType":"plan.review","baseRevision":"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08","createdAt":"2026-02-21T12:00:00Z","expiresAt":"2026-02-21T12:10:00Z","payload":{"kind":"plan","risk":"medium","steps":["Extract tokenizer","Add unit tests","Replace recursive descent with Pratt parser"],"title":"Refactor Parser"},"repoRef":"repo:acme/widgets","requestId":"01J2V8V3K6B2Z9X6G1V7Y2QK8H","sessionId":"01J2V8V3M2YF0KX9Q0Z7E6H9R1"}
8e326e1f69e5859a3b5b12965f06b5829f09b12d1748aa2fddb609fb44f831c1

Test Vector 2: Decision Signature (Ed25519)

Section titled “Test Vector 2: Decision Signature (Ed25519)”
68GYuLi_rncjJ4w7MWKfKd5ygpeXzMjCzM5tlDakz_I
{"artifactHash":"8e326e1f69e5859a3b5b12965f06b5829f09b12d1748aa2fddb609fb44f831c1","artifactHashAlg":"SHA-256","decision":"approve","expiresAt":"2026-02-21T12:05:00Z","nonce":"bm9uY2UtMDAx","repoRef":"repo:acme/widgets","requestId":"01J2V8V3K6B2Z9X6G1V7Y2QK8H","scope":"once","sigAlg":"Ed25519","signerKeyId":"ma-key-01"}
tszU90YldEomMTTrJpUYz-h8xXcAvJ6U97aaEy-1-Oo_vkCx3o63aZps6dN0VaJVKmXY2UnVW6ldoCuXv5sZDA
  • Signature input is the canonical JSON bytes of DecisionSignable (Decision without signature).
  • Signature is the raw 64-byte Ed25519 signature encoded base64url (no padding).

This document provides deterministic canonicalization and hashing test vectors for the HARP-PROMPT extension.

Canonical JSON bytes are produced by:

  • UTF-8 encoding
  • Object keys sorted lexicographically
  • No insignificant whitespace (separators , and :)
  • No trailing newline

Implementations MUST reproduce the exact byte sequence below.

{
"requestId": "01J2V9K3M2W1J5R6S7T8U9V0W1",
"sessionId": "01J2V8V3M2YF0KX9Q0Z7E6H9R1",
"repoRef": "repo:acme/widgets",
"artifactType": "prompt.send",
"createdAt": "2026-02-21T12:01:00Z",
"target": "agentChat",
"text": "Please summarize the plan and list risks. Keep it concise.",
"promptHashAlg": "SHA-256"
}
{"artifactType":"prompt.send","createdAt":"2026-02-21T12:01:00Z","promptHashAlg":"SHA-256","repoRef":"repo:acme/widgets","requestId":"01J2V9K3M2W1J5R6S7T8U9V0W1","sessionId":"01J2V8V3M2YF0KX9Q0Z7E6H9R1","target":"agentChat","text":"Please summarize the plan and list risks. Keep it concise."}
0b18f65f2e4d81b0bbfa89267138163a439ee2381393f95b41f01fbdfdbabd50
  • promptHash is computed over the canonical JSON of the prompt object excluding promptHash.
  • If optional fields (e.g., metadata, extensions) are present, they MUST be included in the hash input.

Canonical JSON bytes are produced by:

  • UTF-8 encoding
  • Object keys sorted lexicographically
  • No insignificant whitespace
  • No trailing newline
{
"sessionId": "01J2V8V3M2YF0KX9Q0Z7E6H9R1",
"eventType": "session.snapshot",
"snapshotId": "snap-001",
"snapshotType": "summary",
"createdAt": "2026-02-21T12:02:00Z",
"payload": {
"summary": "Parser refactor planned. Medium risk due to grammar changes.",
"filesAffected": [
"parser.py",
"lexer.py"
]
},
"snapshotHashAlg": "SHA-256"
}
{"createdAt":"2026-02-21T12:02:00Z","eventType":"session.snapshot","payload":{"filesAffected":["parser.py","lexer.py"],"summary":"Parser refactor planned. Medium risk due to grammar changes."},"sessionId":"01J2V8V3M2YF0KX9Q0Z7E6H9R1","snapshotHashAlg":"SHA-256","snapshotId":"snap-001","snapshotType":"summary"}
5145a558f7390a66768c6da0195f12484bb1f01c44b8bc33518733970ac06e5d
  • snapshotHash is computed over canonical JSON of snapshot object excluding snapshotHash.
  • If metadata is present, it MUST be included in hash input.

The following test vectors validate HARP Gateway HTTP Binding message flows. Each vector demonstrates a specific exchange message or control frame.

Test Vector 1: Artifact Submit (with well-known metadata)

Section titled “Test Vector 1: Artifact Submit (with well-known metadata)”
{
"msgType": "artifact.submit",
"requestId": "req-u6s2nku4oo",
"createdAt": "2026-02-24T10:00:00Z",
"sender": {
"enforcerId": "enf-01"
},
"body": {
"artifactType": "core.artifact",
"artifactHash": "sha256:fe94a9a087129947cc76a6749363bff39e0dcfd64398906bb3123df38913b2a9",
"ciphertext": {
"alg": "XChaCha20-Poly1305",
"data": "BASE64_CIPHERTEXT_PLACEHOLDER"
},
"metadata": {
"routingToken": "rt-opaque-abc123",
"workspaceName": "airlock",
"repoName": "harp-spec"
},
"expiresAt": "2026-02-24T10:10:00Z"
}
}

Validation: metadata.routingToken is routing-sensitive and MUST be stripped before forwarding. workspaceName and repoName are display-safe and SHOULD be forwarded.

Test Vector 2: Approval Request (with forwarded metadata)

Section titled “Test Vector 2: Approval Request (with forwarded metadata)”
{
"msgId": "msg-87fxyntx85",
"msgType": "approval.request",
"requestId": "req-u6s2nku4oo",
"createdAt": "2026-02-24T10:00:01Z",
"expiresAt": "2026-02-24T10:10:00Z",
"sender": {
"gatewayId": "gw-01"
},
"recipient": {
"approverId": "app-01"
},
"body": {
"artifactType": "core.artifact",
"artifactHash": "sha256:fe94a9a087129947cc76a6749363bff39e0dcfd64398906bb3123df38913b2a9",
"ciphertextRef": {
"kind": "inline",
"data": "BASE64_CIPHERTEXT_PLACEHOLDER"
},
"metadata": {
"workspaceName": "airlock",
"repoName": "harp-spec"
},
"policyHint": {
"ui": "Approve or Reject"
}
}
}

Validation: routingToken has been stripped (routing-sensitive). workspaceName and repoName are preserved (display-safe).

{
"msgType": "exchange.withdrawn",
"requestId": "req-u6s2nku4oo",
"createdAt": "2026-02-24T10:03:00Z",
"sender": {
"gatewayId": "gw-01"
},
"body": {
"state": "Withdrawn",
"withdrawnAt": "2026-02-24T10:03:00Z",
"reason": "Enforcer-initiated withdrawal"
}
}

Test Vector 7: Hello Message (WebSocket control)

Section titled “Test Vector 7: Hello Message (WebSocket control)”
{
"msgType": "hello",
"capabilities": {
"push": true,
"poll": false,
"sse": false
},
"workspaceName": "airlock",
"enforcerLabel": "Antigravity"
}

Note: This is a bare JSON control message, NOT a HARP Envelope. See HTTP Binding §5.1.

{
"msgType": "refresh.request",
"requestId": "req-u6s2nku4oo",
"createdAt": "2026-02-24T10:12:00Z",
"sender": {
"gatewayId": "gw-01"
},
"body": {
"reason": "Approver requested refresh for expired artifact"
}
}
[
{
"enforcerDeviceId": "enf-01",
"status": "online",
"lastSeenAt": "2026-02-24T10:00:00Z",
"transport": "websocket",
"workspaceName": "airlock",
"enforcerLabel": "Antigravity",
"capabilities": {
"push": true
}
},
{
"enforcerDeviceId": "enf-02",
"status": "offline",
"lastSeenAt": "2026-02-24T09:45:00Z",
"transport": "poll"
}
]
{
"_comment": "Pairing flow: initiate → resolve → complete",
"initiate_request": {
"enforcerId": "enf-01",
"enforcerLabel": "Antigravity",
"workspaceName": "airlock",
"publicKey": "BASE64URL_PUBLIC_KEY_PLACEHOLDER"
},
"initiate_response": {
"code": "A1B2C3",
"nonce": "nonce-xyz789",
"expiresAt": "2026-02-24T10:10:00Z"
},
"resolve_response": {
"nonce": "nonce-xyz789",
"enforcerLabel": "Antigravity",
"workspaceName": "airlock",
"publicKey": "BASE64URL_PUBLIC_KEY_PLACEHOLDER"
},
"complete_request": {
"nonce": "nonce-xyz789",
"approverId": "app-01",
"publicKey": "BASE64URL_APPROVER_PUBLIC_KEY_PLACEHOLDER"
},
"complete_response": {
"routingToken": "rt-opaque-abc123",
"enforcerLabel": "Antigravity",
"workspaceName": "airlock"
}
}