Multi-Witness Anchoring

Asqav anchors every receipt to more than one witness, so the "when" of a receipt does not rest on a single party's word. Each receipt carries an anchors[] array. One entry is a quantum-safe timestamp token Asqav signs itself. The other is anchored to the Bitcoin blockchain, which no operator and no vendor controls. An auditor checks the time a receipt claims by checking those witnesses, not by taking anyone's word for it.

What it is: two timestamp witnesses on every receipt, recorded in the anchors[] array.

What it proves: when the receipt existed, established by two parties with different trust properties.

The independent one: the Bitcoin anchor, which holds even if someone later distrusts Asqav.

Two witnesses ship today

Every receipt is anchored to two witnesses with different trust properties:

WitnessWhat it addsIndependent of Asqav?
rfc3161 (Asqav-signed timestamp token)A post-quantum, tamper-evident record of when Asqav signed, signed with ML-DSA-65 so it survives the retention horizon.No. Asqav operates the timestamp authority and signs the token.
opentimestamps (Bitcoin blockchain)A record that the digest existed no later than a named public block, governed by no single entity.Yes. Bitcoin is a public chain outside the operator's and Asqav's control.

Each is described in full below.

The genuinely independent witness here is the Bitcoin anchor. Asqav's own timestamp token adds a post-quantum, tamper-evident record of when Asqav signed. The Bitcoin anchor adds a record that holds even if someone later distrusts Asqav. The two witnesses cover different failure modes, which is why both ship.

The anchors array

The two witnesses project into the receipt as a spec-shape anchors[] array. Each entry names its type and carries the proof:

json
{
  "anchors": [
    {
      "type": "rfc3161",
      "value": "<base64 TimeStampToken, ML-DSA-65 signed>"
    },
    {
      "type": "opentimestamps",
      "value": "<base64 OpenTimestamps proof>",
      "status": "anchored",
      "anchor_block_hash": "<bitcoin block hash>"
    }
  ]
}

The conformance suite validates both anchor types. A receipt that claims an anchor it cannot prove is refused, the same way a receipt that claims a policy decision it never made is refused.

Why a public-chain witness matters to regulators

Two regulations turn independent integrity evidence from a "nice to have" into a written control:

See DORA Articles 28-30 and the EU AI Act profile for the full regulation-by-regulation mapping.

The third-party-notary connection

A first-party logger is a vendor signing its own logs, including the time those logs claim. The party producing the record and the party attesting to it are the same party. That is the structural weakness Asqav's third-party-notary posture is built to remove: Asqav is unaffiliated with the agent vendor and with the regulated entity, so the receipt it signs is not the vendor's account of itself.

Multi-witness anchoring adds a second, independent layer at the timestamp level. Asqav's signed token says when Asqav recorded the action, with post-quantum protection over the retention window. The Bitcoin anchor says the digest existed no later than a named public block, and that statement holds even if someone later distrusts Asqav. The timeline does not collapse to one trusted party.

How verification works

A verifier checks each witness's proof on its own terms. The proof for each witness is stored inside the receipt:

Neither check requires a call to Asqav. The receipt's own signature is checked against the public verify key published at GET /.well-known/jwks.json, and the wire format and verification procedure are published in draft-marques-asqav-compliance-receipts on the IETF Datatracker. The verifier trusts the math and the public-chain witness, not the operator.

Explicit N-of-M witness policy

A caller can declare an explicit N-of-M witness quorum on the signed action through the witness_policy wire field. An operator or a regulator can then require that a configurable number of independent witnesses anchor each receipt before it counts as durably anchored.

The field carries the shape {"required": <int>, "witnesses": ["rfc3161", "opentimestamps"]}:

A receipt reaches witness_quorum_met only when required of the named witnesses hold a real inclusion proof. The flag is server-computed, not caller-asserted, so the quorum reflects what the witnesses actually attest rather than what the caller declared.

In the SDK, the Python client takes the policy as the witness_policy= keyword argument and the TypeScript client takes it as the witnessPolicy: property. Both project to the same witness_policy wire field.

python
agent.sign(
    "payment:transfer",
    witness_policy={"required": 2, "witnesses": ["rfc3161", "opentimestamps"]},
)

The witness_policy_required_exceeds_confirmed guard fires when a receipt claims durable anchoring without meeting its declared quorum: witness_policy receipts that claim durable anchoring must have at least required witnesses holding an inclusion proof. A receipt that claims a quorum it cannot prove is refused, the same way a receipt that claims an anchor it cannot prove is refused.