diff --git a/.cspell/custom-words.txt b/.cspell/custom-words.txt index ce73c361..29d857fa 100644 --- a/.cspell/custom-words.txt +++ b/.cspell/custom-words.txt @@ -1,23 +1,34 @@ -aapt +aapt absl achatassistant ACMRTUXB Adyen -agentic Agentic agenticpayments Algorand +algovoi +AlgoVoi androidx Applebot appname ASGI +authorisation +Authorisation bazel +behavioural +Behavioural Blackhawk Boku BVNK +canonicalisation +Canonicalisation +canonicalise +Canonicalise +canonicalised +canonicalises celerybeat +chopmob classpath -CLASSPATH CMSPI cmwallet cncf @@ -29,14 +40,12 @@ Crossmint cryptographical CYGPATTERN Dafiti -disclosable -Disclosable +datatracker davecgh dcql -Dcql -DCQL deviceauth Dfile +Disclosable dmypy Doku Dorg @@ -68,6 +77,7 @@ groupcache gson Hashkey honnef +hopley hprof htmlcov httpsnoop @@ -79,6 +89,8 @@ inmemory ipynb issuerauth JAVACMD +jcs +JCS jetbrains Jetpack jvmargs @@ -87,9 +99,7 @@ keepattributes keepclassmembers Klarna kotlin -kotlinx Kotlinx -ktor Ktor KXMYBJWNQ Lazada @@ -101,12 +111,12 @@ llmstxt logr longrunning mastercard +MiCA micropayments Mispick Momo Monee msys -MSYS multistep Mysten nexi @@ -128,27 +138,33 @@ paypal Payplug pids pmezard +preimage proguard -Proguard prometheus protoc pyflow pymdownx pypa pypackages +recognised reemademo refundability renamesourcefileattribute representment repudiable Revolut +rfc Riskified ROOTDIRS ROOTDIRSRAW ropeproject RPCURL Rulebook +samla +SAMLA screenreaders +serialised +Serialised setlocal sharedpref Shopcider @@ -169,6 +185,8 @@ Truelayer Trulioo udpa unmarshal +unrecognised +verdicts viewmodel vulnz Wallex diff --git a/biome.json b/biome.json new file mode 100644 index 00000000..b867da0b --- /dev/null +++ b/biome.json @@ -0,0 +1,5 @@ +{ + "files": { + "includes": ["**", "!code/web-client"] + } +} diff --git a/docs/ap2/trust_query.md b/docs/ap2/trust_query.md new file mode 100644 index 00000000..b6f1033e --- /dev/null +++ b/docs/ap2/trust_query.md @@ -0,0 +1,165 @@ +# Trust Query + +The Trust Query is a categorical, content-addressed composite verdict +envelope emitted by a verifier in response to a trust-query request +from a Shopping Agent or facilitator. It composes the outcomes of +multiple independent issuer attestations into a single categorical +verdict: given this set of evidence from independent parties, what is +the categorical trust decision? + +The format is AlgoVoi-authored. AP2 references it; AP2 does not redefine +it. The normative wire format is the canonical AlgoVoi Composite Trust +Query response specified in IETF Internet-Draft +[`draft-hopley-x402-composite-trust-query`](https://datatracker.ietf.org/doc/draft-hopley-x402-composite-trust-query/) +and documented at +[`docs.algovoi.co.uk/composite-trust-query-v1`](https://docs.algovoi.co.uk/composite-trust-query-v1). + +## Usage + +A Trust Query response is generated by the verifier after evaluating the +set of issuer attestations available for a given transaction or +counterparty. In an AP2 flow, the verifier MAY be the Credential Provider, +Network, Merchant Payment Processor, or a dedicated trust aggregation +service. + +The response enables a Shopping Agent or downstream relying party to make +a categorical trust decision without re-running the underlying evidence +pipeline, and provides a record of the evidence classes considered that +satisfies regulatory audit obligations. + +## Response Shape + +A Trust Query response is a JSON object canonicalised under RFC 8785 +(JCS). Field names are sorted lexicographically by JCS during +canonicalisation. + +```json +{ + "canon_version": "jcs-rfc8785-v1", + "evaluated_at": "2026-05-30T07:10:43Z", + "evidence_classes_considered": ["admission-compliance", "settlement-attestation"], + "issuer_references": [ + { + "content_hash": "sha256:0dd5d0b76c9b9281fdeb2509ad38ab132b16a17385ca01d976ff9e6e12563a0f", + "issuer_id": "did:web:api.algovoi.co.uk" + } + ], + "signature": "", + "verdict": "TRUSTED" +} +```text + +| Field | Type | Description | +| :---- | :--- | :---------- | +| `canon_version` | string | In-band canonicalisation pin. Fixed `jcs-rfc8785-v1` for this version. | +| `evaluated_at` | string | ISO 8601 UTC timestamp of verdict generation. | +| `evidence_classes_considered` | ordered array of string | Evidence class identifiers available to the composite evaluator. Array order is significant under RFC 8785 section 3.2.3. | +| `issuer_references` | array of object | Per-issuer content-addressed references to the evidence used. Each entry carries `issuer_id` (DID URI) and `content_hash` (`sha256:{hex}`). | +| `signature` | string | Detached signature over the JCS canonical bytes. | +| `verdict` | string (closed enum) | `TRUSTED` / `PROVISIONAL` / `INSUFFICIENT_EVIDENCE` / `UNTRUSTED`. | + +## The closed enumeration: `verdict` + +The `verdict` field MUST take one of exactly four values: + +| Value | Meaning | +| :---- | :------ | +| `TRUSTED` | Composite evaluation yielded a positive verdict across all evidence classes considered. | +| `PROVISIONAL` | Composite evaluation yielded a positive verdict but at least one evidence class returned a conditional or time-bound positive. | +| `INSUFFICIENT_EVIDENCE` | One or more required evidence classes returned no usable signal; the composite verdict is undetermined. | +| `UNTRUSTED` | At least one evidence class returned a negative verdict sufficient to fail the composite under the verifier's declared composition policy. | + +A consumer receiving `PROVISIONAL` or `INSUFFICIENT_EVIDENCE` MUST NOT +proceed as if the verdict were `TRUSTED`. + +The enumeration is **closed by design**. Any extension or amendment +constitutes a normative successor format. + +## Canonicalisation + +The response is canonicalised under RFC 8785 (JCS) per the +canonicalisation pin URI `urn:x402:canonicalisation:jcs-rfc8785-v1`, +defined in IETF Internet-Draft +[`draft-hopley-x402-canonicalisation-jcs-v1`](https://datatracker.ietf.org/doc/draft-hopley-x402-canonicalisation-jcs-v1/). + +### Signature preimage + +The `signature` field is **excluded from the JCS preimage**. To sign, +the issuer removes the `signature` field from the object, computes the +RFC 8785 canonical bytes of the remaining fields, and signs those bytes. +The resulting signature is then stored in the `signature` field of the +serialised envelope. This is the standard JCS signing pattern (see also +RFC 8785 section 3.2) and avoids any circular dependency between the +canonical form and its signature. + +The discipline is byte-for-byte cross-validated across eight independent +implementations (Python, TypeScript, Go, Rust, Java, PHP, .NET, Ruby) +per the AlgoVoi 8-impl matrix. Reference implementations: + +- [`algovoi-composite-trust-query`](https://pypi.org/project/algovoi-composite-trust-query/) on PyPI +- [`@algovoi/composite-trust-query`](https://www.npmjs.com/package/@algovoi/composite-trust-query) on npm + +Both packages are published under Apache 2.0. + +## Composition + +The Trust Query composes upstream attestations into a single verdict: + +```text +compliance receipt (ALLOW) settlement attestation (SETTLED) + | | + +------------------------------------+ + | + v + trust query (TRUSTED / PROVISIONAL / + INSUFFICIENT_EVIDENCE / UNTRUSTED) +```text + +The `issuer_references` array records which upstream attestations were +considered. A relying party MAY retrieve and inspect each upstream +attestation independently. If an upstream attestation is retrieved, the +relying party MUST verify that its canonical hash matches the recorded +`content_hash` before using it as additional evidence. + +## Authorship and Substrate-Author Position + +This specification documents the AlgoVoi-authored Composite Trust Query +format. AlgoVoi is sole author across the normative format, the canonical +field shape, the closed four-element verdict enumeration, and the +composition with the AlgoVoi-authored canonicalisation pin. + +This specification does not absorb from, depend on, or share authorship +with any other party's work. + +## Orthogonality + +The Trust Query defines the **multi-issuer composite verdict** format. +It is orthogonal to: + +- Single-issuer attestations (Compliance Receipt, Settlement Attestation; + these are inputs to the composite, not the composite itself). +- Per-counterparty risk checks (counterparty risk is one input evidence + class, not the composite verdict format). +- Admission-time compliance (Compliance Receipt; a separate upstream input). +- Agent trust scoring and reputation systems (those produce evidence that + MAY be referenced as an `issuer_reference` entry; they do not define + the composite verdict shape). + +## Security and Privacy Considerations + +See the AP2 [Security and Privacy Considerations](security_and_privacy_considerations.md) +document. The Trust Query adds the following considerations: + +- Retrieval of upstream attestations referenced in `issuer_references` is + OPTIONAL; a relying party MAY accept the composite verdict without + independently fetching each referenced attestation. However, if an + upstream attestation is retrieved, the relying party MUST re-derive its + canonical hash and verify it matches the recorded `content_hash` before + treating the attestation as additional supporting evidence. +- `PROVISIONAL` and `INSUFFICIENT_EVIDENCE` verdicts MUST be treated + conservatively; downstream systems MUST NOT promote either to `TRUSTED` + without additional out-of-band evidence. +- The `evidence_classes_considered` array is informational; its presence + does not guarantee that all listed classes contributed a positive signal. + Relying parties MUST rely on `verdict`, not on inferences from the + evidence class list.