Skip to content

Multi-Attestation Payload Format: Composable Verification Across Independent Issuers #1

@douglasborthwick-crypto

Description

Problem

A relying party (smart contract hook, middleware, agent framework) often needs to verify multiple independent claims before proceeding — e.g., "does this wallet hold X?" + "was this action performed at time T?" + "is this agent trustworthy?" Today each attestation system returns its own format, and there's no standard way to bundle them for a single verification pass.

Proposal: Array of Independent Attestations

Rather than a wrapper JWT (which introduces a third signing key and trust dependency), the combined payload is an array of independent attestations, each with its own signature, key identifier, and JWKS endpoint:

{
  "attestations": [
    {
      "issuer": "https://api.insumermodel.com",
      "type": "wallet_state",
      "kid": "insumer-attest-v1",
      "alg": "ES256",
      "jwks": "https://insumermodel.com/.well-known/jwks.json",
      "signed": {
        "id": "ATST-1A2B3C4D",
        "pass": true,
        "results": [
          {
            "condition": 0,
            "label": "USDC on Ethereum",
            "type": "token_balance",
            "chainId": 1,
            "met": true,
            "conditionHash": "0x..."
          }
        ],
        "attestedAt": "2026-03-19T18:00:00Z"
      },
      "sig": "<base64 ES256 P1363>"
    },
    {
      "issuer": "https://api.thoughtproof.ai",
      "type": "temporal_attestation",
      "kid": "tp-attestor-v1",
      "alg": "EdDSA",
      "jwks": "https://api.thoughtproof.ai/.well-known/jwks.json",
      "signed": {
        "verdict": "ALLOW",
        "confidence": 0.95,
        "claimHash": "0x...",
        "timestamp": "2026-03-19T18:00:00Z"
      },
      "sig": "<base64 EdDSA>"
    },
    {
      "issuer": "https://rnwy.com",
      "type": "behavioral_trust",
      "kid": "TBD",
      "alg": "TBD",
      "jwks": "TBD",
      "signed": {
        "score": 87,
        "tier": "trusted",
        "sybilFlags": []
      },
      "sig": "TBD"
    }
  ]
}

Note on the signed field: this contains exactly the data covered by the signature. For InsumerAPI, ecdsaSign() signs {id, pass, results, attestedAt} — the expiresAt field is in the API response but not in the signed payload. Each issuer defines what their signature covers.

Design Principles

  1. No wrapper signature — each attestation is independently signed by its issuer. The array is transport, not trust.
  2. Relying party picks dimensions — a hook verifies whichever attestations it cares about. A payment flow might check wallet state + time. A DAO vote might check all three. A simple token-gate checks only state.
  3. Independent JWKS resolution — each issuer publishes their own public key. No shared key infrastructure. Keys are cacheable.
  4. Algorithm-agnostic — ES256 (P-256), EdDSA (Ed25519), or any other JWS algorithm. The alg field tells the verifier what to use.
  5. Composable hooks — one hook per attestation type, not one monolithic verifier. Developers compose the verification pipeline they need.
  6. Signature-first — every attestation in the array MUST be signed with a published JWKS. Unsigned data (raw API responses) should not appear in the attestation array — they belong in a separate metadata section if needed.

Current Attestation Formats

Issuer Algorithm Key ID JWKS Signed Payload
InsumerAPI ES256 (P-256) insumer-attest-v1 insumermodel.com/.well-known/jwks.json {id, pass, results[], attestedAt}
ThoughtProof EdDSA (Ed25519) tp-attestor-v1 api.thoughtproof.ai/.well-known/jwks.json {verdict, confidence, claimHash, timestamp}
RNWY TBD TBD TBD TBD — currently returns unsigned JSON; signing + JWKS needed to participate in this format

Open Questions

  1. Should the array format have a version field?
  2. Should there be a canonical ordering or is insertion order sufficient?
  3. How should a relying party express which attestation types it requires? (e.g., a manifest or hook configuration)
  4. Should expired attestations be included (for audit trails) or stripped?
  5. Should unsigned data sources be allowed in a separate section, or excluded entirely?

Context

This emerged from the ERC-8183 builders community discussion on composable trust for agent commerce hooks. Related threads:

CC: @ThoughtProof @rnwy (RNWY)

Metadata

Metadata

Assignees

No one assigned

    Labels

    ecdsaECDSA signingjwksJWKS-based verificationmulti-attestationMulti-issuer attestation formatspecSpecification proposals

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions