@agenttrust-sdk/mcp 0.2.6 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/embedded-data/devnet-smoke.json +4 -4
  2. package/dist/embedded-docs/architecture.mdx +174 -0
  3. package/dist/embedded-docs/getting-started/quickstart.mdx +79 -56
  4. package/dist/embedded-docs/index.mdx +54 -37
  5. package/dist/embedded-docs/integration-guides/capability-namespaces.mdx +135 -8
  6. package/dist/embedded-docs/integration-guides/custom-attestor.mdx +169 -8
  7. package/dist/embedded-docs/integration-guides/dexter-adapter.mdx +76 -0
  8. package/dist/embedded-docs/integration-guides/facilitator-adapters.mdx +85 -41
  9. package/dist/embedded-docs/integration-guides/pay-sh-adapter.mdx +90 -54
  10. package/dist/embedded-docs/integration-guides/x402-facilitator.mdx +55 -24
  11. package/dist/embedded-docs/mcp/hosted-endpoint.mdx +197 -0
  12. package/dist/embedded-docs/mcp/index.mdx +108 -0
  13. package/dist/embedded-docs/mcp/install.mdx +183 -0
  14. package/dist/embedded-docs/mcp/prompts.mdx +90 -0
  15. package/dist/embedded-docs/mcp/resources.mdx +115 -0
  16. package/dist/embedded-docs/mcp/tools.mdx +156 -0
  17. package/dist/embedded-docs/programs/policy-vault/composer.mdx +117 -0
  18. package/dist/embedded-docs/programs/policy-vault/counterparty-tier-policy.mdx +81 -9
  19. package/dist/embedded-docs/programs/policy-vault/index.mdx +77 -47
  20. package/dist/embedded-docs/programs/policy-vault/kill-switch-policy.mdx +65 -8
  21. package/dist/embedded-docs/programs/policy-vault/require-validation-policy.mdx +76 -8
  22. package/dist/embedded-docs/programs/policy-vault/spending-policy.mdx +83 -8
  23. package/dist/embedded-docs/programs/policy-vault/velocity-policy.mdx +85 -8
  24. package/dist/embedded-docs/programs/trustgate.mdx +112 -30
  25. package/dist/embedded-docs/programs/validation-registry.mdx +139 -32
  26. package/dist/embedded-docs/reference/byte-offset-reference.mdx +102 -13
  27. package/dist/embedded-docs/reference/capability-namespaces.mdx +56 -0
  28. package/dist/embedded-docs/reference/changelog.mdx +230 -13
  29. package/dist/embedded-docs/reference/deny-reason-codes.mdx +86 -0
  30. package/dist/embedded-docs/reference/devnet-program-ids.mdx +50 -8
  31. package/dist/embedded-docs/reference/discriminator-constants.mdx +104 -10
  32. package/dist/embedded-docs/reference/mainnet-program-ids.mdx +89 -5
  33. package/dist/embedded-docs/reference/quantu-agent-registry.mdx +104 -9
  34. package/dist/embedded-docs/sdk/exports-reference.mdx +239 -0
  35. package/dist/embedded-docs/sdk/gate-payment.mdx +99 -14
  36. package/dist/embedded-docs/sdk/index.mdx +141 -40
  37. package/dist/embedded-docs/sdk/mount-trustgate.mdx +178 -8
  38. package/dist/embedded-docs/verification/adversarial-harness.mdx +88 -0
  39. package/dist/embedded-docs/verification/atomic-tx-invariant.mdx +141 -0
  40. package/dist/embedded-docs/verification/chained-validation.mdx +87 -0
  41. package/dist/embedded-docs/verification/devnet-smoke.mdx +85 -0
  42. package/dist/embedded-docs/verification/index.mdx +31 -0
  43. package/dist/embedded-docs/verification/kani-proofs.mdx +144 -0
  44. package/dist/embedded-docs/verification/live-evidence.mdx +180 -0
  45. package/dist/tools/write/emit-feedback.d.ts +6 -0
  46. package/dist/tools/write/emit-feedback.js +12 -1
  47. package/dist/tools/write/emit-feedback.js.map +1 -1
  48. package/package.json +16 -15
  49. package/scripts/install-claude-desktop.sh +0 -0
@@ -1,53 +1,135 @@
1
1
  ---
2
2
  title: TrustGate
3
- description: The x402 facilitator program that emits ERC-8004 feedback through Quantu.
3
+ description: The facilitator-side Anchor program PDA-signed feedback CPIs into Quantu and per-payment idempotency receipts.
4
4
  ---
5
5
 
6
- TrustGate is the on-chain feedback bridge for x402 facilitators. It owns a per-facilitator PDA, signs feedback CPI calls into Quantu, and records idempotency by payment hash.
6
+ TrustGate is the program a facilitator owns. One PDA per facilitator (`TrustGateAuthority`) signs CPIs into Quantu's `agent-registry-8004::give_feedback`. One PDA per payment (`FeedbackEmissionLog`) is the on-chain idempotency receipt. Three instructions.
7
7
 
8
- Pay.sh uses this path through the `PaySh` adapter. Other facilitators should reach the same on-chain instruction through their own adapter rather than adding facilitator-specific branches to routes.
8
+ **Devnet:** [`HF8zHfoyA7b5mhLViopTnRMprc6ZT5KActHTdkFrih2N`](https://explorer.solana.com/address/HF8zHfoyA7b5mhLViopTnRMprc6ZT5KActHTdkFrih2N?cluster=devnet)
9
9
 
10
10
  ## Instructions
11
11
 
12
- | Instruction | Purpose |
13
- | --- | --- |
14
- | `init_authority(facilitator)` | creates the facilitator PDA |
15
- | `emit_feedback(...)` | CPI into Quantu `agent_registry_8004::give_feedback` |
16
- | `dispute_payment(...)` | emits negative-score feedback for disputed payments |
12
+ | Instruction | Effect |
13
+ |---|---|
14
+ | `init_authority(facilitator)` | Create `TrustGateAuthority` PDA for `facilitator`. One-time per facilitator. |
15
+ | `emit_feedback(payment_id_hash, facilitator, payee_asset, score, tag1, tag2, endpoint, feedback_uri)` | PDA-signed CPI into `agent-registry-8004::give_feedback`. Initialises `FeedbackEmissionLog`. |
16
+ | `dispute_payment(payment_id_hash, facilitator, payee_asset, dispute_reason_hash, feedback_uri)` | PDA-signed CPI emitting NEGATIVE-score feedback (score = `DISPUTE_SCORE`, tag1 = `dispute`). Initialises `FeedbackEmissionLog`. |
17
+
18
+ Both `emit_feedback` and `dispute_payment` enforce `signer == facilitator` (`FacilitatorSignerMismatch`). Without that guard, anyone could write fake feedback under any facilitator's authority — a real attack against on-chain reputation.
19
+
20
+ ## State accounts
21
+
22
+ ### `TrustGateAuthority`
23
+
24
+ ```rust
25
+ #[account]
26
+ pub struct TrustGateAuthority {
27
+ pub facilitator: Pubkey, // off 8..40 — external facilitator wallet
28
+ pub bump: u8, // off 40
29
+ pub _pad0: [u8; 7], // off 41..48
30
+ pub feedback_count: u64, // off 48..56 — total successful give_feedback CPIs
31
+ pub dispute_count: u64, // off 56..64 — total dispute_payment CPIs
32
+ pub created_at_slot: u64, // off 64..72
33
+ pub _reserved: [u8; 32], // off 72..104
34
+ }
35
+ ```
17
36
 
18
- ## PDA signer
37
+ PDA seeds: `["trustgate_auth", facilitator]`. Different facilitators (Pay.sh, Dexter, atxp, MCPay) each get their own PDA, so feedback emission is namespaced per-facilitator on-chain. The `feedback_count` and `dispute_count` accumulate as that facilitator emits.
38
+
39
+ ### `FeedbackEmissionLog`
40
+
41
+ ```rust
42
+ #[account]
43
+ pub struct FeedbackEmissionLog {
44
+ pub payment_id_hash: [u8; 32], // off 8..40 — caller-supplied payment ID hash
45
+ pub bump: u8, // off 40
46
+ pub score: u8, // off 41 — score that was emitted
47
+ pub is_dispute: u8, // off 42 — 1 = dispute path, 0 = emit_feedback path
48
+ pub _pad0: [u8; 5], // off 43..48
49
+ pub emitted_at_slot: u64, // off 48..56
50
+ pub _reserved: [u8; 16], // off 56..72
51
+ }
52
+ ```
19
53
 
20
- TrustGate signs CPI with:
54
+ PDA seeds: `["feedback_log", payment_id_hash]`. The init-only constraint is the idempotency mechanism: a second `emit_feedback` (or `dispute_payment`) for the same `payment_id_hash` fails with `account-already-in-use` and the entire transaction reverts. There is no recovery path — that is exactly the desired property: a successful CPI mints exactly one feedback per payment.
21
55
 
22
- ```txt
23
- ["trustgate_auth", facilitator_pubkey, bump]
24
- ```
56
+ The caller computes `payment_id_hash = SHA-256(payment_id_string)` off-chain. The SDK does this in [`composeAtomicSettleTx`](/sdk/mount-trustgate); facilitators that build their own settlement path replicate the same hash construction.
25
57
 
26
- That PDA is the feedback authority, not the payee agent. This prevents self-feedback while allowing a facilitator to write receipt-grade feedback after settlement.
58
+ ## PDA-signed CPI to Quantu
27
59
 
28
- ## Feedback idempotency
60
+ `emit_feedback` PDA-signs the CPI into Quantu's `agent-registry-8004::give_feedback`:
29
61
 
30
- `FeedbackEmissionLog` is initialized at:
62
+ ```rust
63
+ let signer_seeds: &[&[u8]] = &[
64
+ TrustGateAuthority::SEED_PREFIX, // b"trustgate_auth"
65
+ facilitator.as_ref(),
66
+ &[bump],
67
+ ];
68
+ invoke_give_feedback(&cpi_accounts, &args, signer_seeds)?;
69
+ ```
31
70
 
32
- ```txt
33
- ["feedback_log", payment_id_hash]
71
+ Quantu's `give_feedback` instruction expects the caller to be the agent's owner — TrustGate's PDA is registered as the feedback authority via Quantu's identity flow on first use. The `client` account in the CPI is set to `authority.to_account_info()`, so Quantu sees a PDA-signed call rather than the facilitator's wallet directly.
72
+
73
+ `remaining_accounts` ordering for the CPI:
74
+
75
+ | Index | Account | Notes |
76
+ |---:|---|---|
77
+ | 0 | `agent_account` | payee's Quantu `AgentAccount` PDA |
78
+ | 1 | `asset` | payee's Metaplex Core asset |
79
+ | 2 | `collection` | Quantu's collection asset |
80
+ | 3 | `system_program` | for rent on AtomStats init |
81
+ | 4 | `atom_config` (optional) | Quantu's `AtomConfig` PDA |
82
+ | 5 | `atom_stats` (optional) | payee's `AtomStats` PDA — created on first feedback |
83
+ | 6 | `atom_engine_program` (optional) | Quantu's atom-engine program |
84
+ | 7 | `registry_authority` (optional) | Quantu's registry authority PDA |
85
+
86
+ Indexes 0..=3 are required (`AgentRegistryProgramMismatch` on count mismatch). Indexes 4..=7 come as a group of 4 — pass all four or none. The SDK's `composeAtomicSettleTx` builds this account list correctly; integrators going lower-level should consult [`programs/trustgate/src/ext/agent_registry.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/trustgate/src/ext/agent_registry.rs).
87
+
88
+ ## `give_feedback` args
89
+
90
+ ```rust
91
+ pub struct GiveFeedbackArgs {
92
+ pub value: u64,
93
+ pub value_decimals: u8,
94
+ pub score: Option<u8>, // 0..=100
95
+ pub feedback_file_hash: Option<[u8; 32]>, // dispute_reason_hash for disputes
96
+ pub tag1: String, // ≤ 32 bytes
97
+ pub tag2: String, // ≤ 32 bytes
98
+ pub endpoint: String, // ≤ 64 bytes
99
+ pub feedback_uri: String, // ≤ 256 bytes
100
+ }
34
101
  ```
35
102
 
36
- Reusing the same payment hash fails account initialization, so retries cannot double-emit feedback.
103
+ `emit_feedback` validates `score 100`, `tag1.len() 32`, `tag2.len() ≤ 32`, `endpoint.len() ≤ 64`, `feedback_uri.len() ≤ 256`. Discriminator: `[145, 136, 123, 3, 215, 165, 98, 41]` ([Reference → Discriminator constants](/reference/discriminator-constants)).
104
+
105
+ ## Disputes
106
+
107
+ `dispute_payment` is the negative-feedback path. Per `docs/plan/research/04-policyvault-build-playbook.md §C.4`, revocations are events-only; new negative feedback is the canonical "downstream consumers see and react to" signal. The handler:
108
+
109
+ - Requires `dispute_reason_hash != [0; 32]` (`DisputeReasonRequired`).
110
+ - Hard-codes `score = DISPUTE_SCORE`, `tag1 = "dispute"`.
111
+ - Sets `tag2` to the first 16 hex chars of the dispute reason hash for off-chain consumers.
112
+ - Sets `is_dispute = 1` on the `FeedbackEmissionLog`.
113
+
114
+ Same idempotency pattern: the `init` constraint blocks double-disputes per `payment_id_hash`.
115
+
116
+ ## Events
37
117
 
38
- ## x402 mapping
118
+ | Event | Fields |
119
+ |---|---|
120
+ | `AuthorityInitialized` | `facilitator`, `authority`, `slot` |
121
+ | `FeedbackEmitted` | `facilitator`, `payee_asset`, `payment_id_hash`, `score`, `slot` |
122
+ | `PaymentDisputed` | `facilitator`, `payee_asset`, `payment_id_hash`, `dispute_reason_hash`, `slot` |
39
123
 
40
- The SDK and server map PolicyVault outcomes into response headers:
124
+ ## Live trace
41
125
 
42
- | Decision | HTTP | Headers |
43
- | --- | --- | --- |
44
- | `Allow` | `200` | `X-Agent-Trust-Decision: Allow` |
45
- | `Deny` | `402` | reason code and reason name |
46
- | `RequireValidation` | `402` | required capability hash |
126
+ Real `emit_feedback` CPI on devnet, captured 2026-05-06: [`jMobmWJUAXuL8FmQujfxW9NmeMbzADUoABzqjiMeuc5m3YXyeuZeUw1ZJc29JGsqyWQGDY8q3vrtBdamhKXraag`](https://explorer.solana.com/tx/jMobmWJUAXuL8FmQujfxW9NmeMbzADUoABzqjiMeuc5m3YXyeuZeUw1ZJc29JGsqyWQGDY8q3vrtBdamhKXraag?cluster=devnet) — the resulting `FeedbackEmissionLog` PDA at [`HB4BBi9jaD3VPcZkQQaH3DxukSqBiXfW8RejtaLa8bF3`](https://explorer.solana.com/address/HB4BBi9jaD3VPcZkQQaH3DxukSqBiXfW8RejtaLa8bF3?cluster=devnet) has `score=100`, `is_dispute=0`. Full trace: [Verification → Devnet smoke](/verification/devnet-smoke).
47
127
 
48
128
  ## Source
49
129
 
50
- - Program: `programs/trustgate/src/lib.rs`
51
- - CPI wrapper: `programs/trustgate/src/ext/agent_registry.rs`
52
- - Server route layer: `trustgate/server/src/routes/verify.ts`
53
- - Pay.sh adapter: `trustgate/server/src/facilitators/pay-sh/index.ts`
130
+ - Program entry: [`programs/trustgate/src/lib.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/trustgate/src/lib.rs)
131
+ - `emit_feedback`: [`instructions/emit_feedback.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/trustgate/src/instructions/emit_feedback.rs)
132
+ - `dispute_payment`: [`instructions/dispute_payment.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/trustgate/src/instructions/dispute_payment.rs)
133
+ - `init_authority`: [`instructions/init_authority.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/trustgate/src/instructions/init_authority.rs)
134
+ - CPI wrapper: [`ext/agent_registry.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/trustgate/src/ext/agent_registry.rs)
135
+ - State: [`state/`](https://github.com/agenttrust-labs/agenttrust/tree/main/programs/trustgate/src/state)
@@ -1,49 +1,156 @@
1
1
  ---
2
2
  title: ValidationRegistry
3
- description: Capability namespaces, attestors, requests, responses, and revocations.
3
+ description: Capability namespaces, attestor profiles, validation requests, and attestation PDAs — the third leg of ERC-8004 on Solana.
4
4
  ---
5
5
 
6
- ValidationRegistry is the attestation leg of AgentTrust. PolicyVault reads `ValidationAttestation` accounts when `RequireValidation` is enabled.
6
+ ValidationRegistry productizes the ERC-8004 V variant on Solana. Permissionless namespace + attestor registration; downstream-consumer filtering in PolicyVault. Five instructions over four PDAs.
7
7
 
8
- ## Accounts
9
-
10
- | PDA | Role |
11
- | --- | --- |
12
- | `CapabilityNamespace` | names a validation capability and schema URI |
13
- | `AttestorProfile` | records an attestor identity URI |
14
- | `ValidationRequest` | opens a request for an agent and capability |
15
- | `ValidationAttestation` | stores a response, expiry, and revoked flag |
8
+ **Devnet:** [`Cx4RFa6ysw3qXYhugPkF8pFSWBkmKq59h2dWgF2tKhtv`](https://explorer.solana.com/address/Cx4RFa6ysw3qXYhugPkF8pFSWBkmKq59h2dWgF2tKhtv?cluster=devnet)
16
9
 
17
10
  ## Instructions
18
11
 
19
- | Instruction | Notes |
20
- | --- | --- |
21
- | `register_namespace` | permissionless, caller computes `SHA256(name_utf8)` |
22
- | `register_attestor` | self-registration with display URI |
23
- | `request_validation` | subject owner or third party opens a request |
24
- | `respond_to_validation` | attestor writes the attestation |
25
- | `revoke_validation` | original attestor sets `revoked = true` |
12
+ | Instruction | Signer | Effect |
13
+ |---|---|---|
14
+ | `register_namespace(namespace_hash, name, version, schema_uri)` | creator | Create `CapabilityNamespace` PDA |
15
+ | `register_attestor(display_name_uri)` | attestor | Create `AttestorProfile` PDA for the signer |
16
+ | `request_validation(subject_asset, capability_hash, claim_uri_hash, deadline)` | requester (subject's owner OR third party) | Create `ValidationRequest` PDA |
17
+ | `respond_to_validation(subject_asset, capability_hash, claim_payload_hash, claim_uri_hash, expires_at)` | attestor + payer | Create `ValidationAttestation` PDA |
18
+ | `revoke_validation` | original attestor | Set `revoked = true`, `revoked_at = clock.slot`, store `revocation_reason_hash` |
19
+
20
+ The v1 trust model is "attestor signs the transaction"; the tx signature itself authenticates the attestor. The 64-byte `attestor_signature` field on `ValidationAttestation` is reserved for v1.1+ Ed25519 sysvar verification (per Quantu's `set_agent_wallet` pattern at `identity/instructions.rs:506-541`), which adds non-repudiation against future key compromise.
21
+
22
+ ## State accounts
23
+
24
+ ### `CapabilityNamespace`
25
+
26
+ ```rust
27
+ #[account]
28
+ pub struct CapabilityNamespace {
29
+ pub namespace_hash: [u8; 32], // SHA256(name_utf8) — self-reference
30
+ pub name: String, // ≤ 32 bytes; min 3; no ':' allowed
31
+ pub version: String, // ≤ 16 bytes (e.g., "v1")
32
+ pub schema_uri: String, // ≤ 160 bytes (IPFS / HTTP)
33
+ pub registered_at: u64,
34
+ pub creator: Pubkey,
35
+ pub bump: u8,
36
+ }
37
+ ```
38
+
39
+ PDA seeds: `["capability", namespace_hash]`. The colon character is forbidden in `name` (`NamespaceColonForbidden`) so namespace strings can be packed into URIs without escaping. Anyone can register; rent (~0.0023 SOL) is the economic deterrent.
40
+
41
+ Ten canonical v1 namespaces are seeded on devnet: [Reference → Capability namespaces](/reference/capability-namespaces).
42
+
43
+ ### `AttestorProfile`
44
+
45
+ ```rust
46
+ #[account]
47
+ pub struct AttestorProfile {
48
+ pub attestor: Pubkey, // self-reference
49
+ pub display_name_uri: String, // ≤ 100 bytes
50
+ pub total_attestations: u64, // counter, all-time
51
+ pub total_revoked_by_attestor: u64, // self-revoked
52
+ pub total_revoked_externally: u64, // reserved for v1.1+ external revoke
53
+ pub registered_at: u64,
54
+ pub bump: u8,
55
+ }
56
+ ```
57
+
58
+ PDA seeds: `["attestor", attestor_pubkey]`. Self-registered (permissionless). `total_attestations` increments on each `respond_to_validation`; `total_revoked_by_attestor` increments on `revoke_validation`. v1.1+ adds `staked_amount` for stake-weighted scoring; v2 adds slashing.
59
+
60
+ ### `ValidationRequest`
61
+
62
+ ```rust
63
+ #[account]
64
+ pub struct ValidationRequest {
65
+ pub subject_asset: Pubkey,
66
+ pub capability_hash: [u8; 32],
67
+ pub requester: Pubkey, // subject's owner OR any third party
68
+ pub claim_uri_hash: [u8; 32], // SHA256 of off-chain claim URI
69
+ pub created_at: u64,
70
+ pub deadline: u64, // slot after which the request is "abandoned"
71
+ pub bump: u8,
72
+ }
73
+ ```
74
+
75
+ PDA seeds: `["request", subject_asset, capability_hash, requester]`. Off-chain attestors discover open requests via the `RequestCreated` event; the PDA itself is just an audit-trail record. Non-responded requests past `deadline` are abandoned.
76
+
77
+ ### `ValidationAttestation` — the headline read target
78
+
79
+ ```rust
80
+ #[account]
81
+ pub struct ValidationAttestation {
82
+ pub subject_asset: Pubkey, // off 8..40 (parser: 8)
83
+ pub capability_hash: [u8; 32], // off 40..72 (parser: 40)
84
+ pub attestor: Pubkey, // off 72..104 (parser: 72)
85
+ pub claim_payload_hash: [u8; 32], // off 104..136
86
+ pub attestor_signature: [u8; 64], // off 136..200 — Ed25519 sig (v1.1+)
87
+ pub issued_at: u64, // off 200..208
88
+ pub expires_at: u64, // off 208..216 (parser: 208) — 0 = never
89
+ pub revoked: bool, // off 216 (parser: 216)
90
+ pub revoked_at: u64, // off 217..225
91
+ pub revocation_reason_hash: [u8; 32], // off 225..257
92
+ pub claim_uri_hash: [u8; 32], // off 257..289
93
+ pub bump: u8, // off 289
94
+ }
95
+ ```
96
+
97
+ PDA seeds: `["attestation", subject_asset, capability_hash, attestor]`. Account size: 290 bytes.
98
+
99
+ This is the PDA PolicyVault's `RequireValidation` policy reads at fixed byte offsets via [`ext/validation_registry.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/policy-vault/src/ext/validation_registry.rs). Field declaration order is **load-bearing** — reordering fields silently breaks PolicyVault's reads.
26
100
 
27
- The program source currently exposes five instructions. The docs reserve the sixth slot for the next attestor-management extension.
101
+ ## Capability namespace + hash
28
102
 
29
- ## Attestation message
103
+ Capabilities are addressed by their SHA-256 hash, not their string name. The v1 PolicyVault parser only knows `capability_hash`; the human-readable name lives in `CapabilityNamespace.name` for off-chain display.
30
104
 
31
- The response path uses a domain-separated message:
105
+ ```ts
106
+ import { sha256 } from "@noble/hashes/sha256";
107
+
108
+ const name = "kyc.tier-1.v1";
109
+ const capability_hash = sha256(new TextEncoder().encode(name));
110
+ // → 366c075140aa69746625d4b733b55e267fc5c28387fd6d1c24901976ee3ddc42
111
+ ```
32
112
 
33
- ```txt
34
- AGENTTRUST_ATTEST || subject || capability || payload || expires
113
+ `MAX_NAME_LEN = 32` constrains namespace names. The playbook-level descriptive labels in `docs/plan/research/06-validation-registry-class.md` (e.g., `kyc.tier-1.v1.identity-verified`) decompose to these on-chain category names plus the JSON `description` field.
114
+
115
+ ## Attestation message — domain separation
116
+
117
+ Per Phase D, the attestation message that attestors sign in v1.1+ is domain-separated:
118
+
119
+ ```
120
+ AGENTTRUST_ATTEST || subject_asset || capability_hash || claim_payload_hash || expires_at
35
121
  ```
36
122
 
37
- PolicyVault does not trust arbitrary attestations. `RequireValidation` checks the subject, capability hash, expiry, revoked flag, and allowed attestor list.
123
+ In v1, the same attestor signs the Solana transaction containing `respond_to_validation`; the tx signature serves as the authentication signal. v1.1+ migrates to Ed25519 sysvar verify so a future attestor-key compromise cannot retroactively forge attestations.
124
+
125
+ ## Sybil-resistance model
126
+
127
+ Permissionless registration plus opinionated downstream filtering. Anyone can register a namespace or an attestor; PolicyVault decides per-policy which attestors to trust via `accepted_attestors[]`. A policy that gates against `audit.smart-contract.v1` might only accept attestations from Halborn or OtterSec; a policy that gates against `kyc.tier-1.v1` might accept any registered KYC attestor.
128
+
129
+ This is the only model that scales with the number of facilitators. Global gatekeeping (a central allow-list of "approved attestors") would either be too lax (admit too many) or too tight (block niche attestors with valid use cases). Local trust devolves the policy decision to the integrator who owns the cap-set their users care about.
130
+
131
+ ## Revocation — audit-trail-preserving
132
+
133
+ `revoke_validation` does not delete the `ValidationAttestation` PDA. It sets `revoked = true`, writes `revoked_at = clock.slot`, and stores a `revocation_reason_hash`. Downstream readers (PolicyVault) treat `revoked == true` as `Deny(AttestationRevoked)` (DenyReason code `13`). The audit trail — including `issued_at`, `expires_at`, `claim_uri_hash`, and the original `attestor_signature` (v1.1+) — stays on chain.
134
+
135
+ This is the ERC-8004 spec posture: revocations preserve history rather than erase it.
136
+
137
+ ## Live evidence
138
+
139
+ Four-signature chained-validation trace on devnet (`gate_payment` → `request_validation` → `respond_to_validation` → `gate_payment`): [Verification → Chained validation](/verification/chained-validation). Ten capability namespaces seeded: [Reference → Capability namespaces](/reference/capability-namespaces).
140
+
141
+ ## Events
38
142
 
39
- ## Byte fields consumed by PolicyVault
143
+ | Event | Fields |
144
+ |---|---|
145
+ | `NamespaceRegistered` | `namespace_hash`, `creator` |
146
+ | `AttestorRegistered` | `attestor` |
147
+ | `RequestCreated` | `subject_asset`, `capability_hash`, `requester`, `claim_uri_hash`, `deadline` |
148
+ | `AttestationCreated` | `subject_asset`, `capability_hash`, `attestor`, `expires_at`, `issued_at` |
149
+ | `AttestationRevoked` | `subject_asset`, `capability_hash`, `attestor`, `revoked_at`, `revocation_reason_hash` |
40
150
 
41
- | Field | Offset |
42
- | --- | --- |
43
- | subject asset | `8` |
44
- | capability hash | `40` |
45
- | attestor | `72` |
46
- | expires at slot | `208` |
47
- | revoked flag | `216` |
151
+ ## Source
48
152
 
49
- Source: `programs/validation-registry/src/lib.rs`.
153
+ - Program entry: [`programs/validation-registry/src/lib.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/validation-registry/src/lib.rs)
154
+ - State: [`state/`](https://github.com/agenttrust-labs/agenttrust/tree/main/programs/validation-registry/src/state)
155
+ - Instructions: [`instructions/`](https://github.com/agenttrust-labs/agenttrust/tree/main/programs/validation-registry/src/instructions)
156
+ - PolicyVault byte-offset parser: [`policy-vault/src/ext/validation_registry.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/policy-vault/src/ext/validation_registry.rs)
@@ -1,20 +1,109 @@
1
1
  ---
2
2
  title: Byte-offset reference
3
- description: Fixed offsets used by AgentTrust cross-program readers.
3
+ description: Fixed offsets used by AgentTrust's manual byte-offset readers — Quantu AtomStats and AgentTrust ValidationAttestation.
4
4
  ---
5
5
 
6
- `In progress`
6
+ PolicyVault reads two foreign PDAs through byte-precise parsers rather than Borsh deserialization. Schema-version canaries fail loud rather than silently misread fields if the upstream layout changes.
7
7
 
8
- | Account | Field | Offset |
9
- | --- | --- | --- |
10
- | `AtomStats` | `risk_score` | `549` |
11
- | `AtomStats` | `trust_tier` | `551` |
12
- | `AtomStats` | `confidence` | `557..558` |
13
- | `ValidationAttestation` | `subject` | `8` |
14
- | `ValidationAttestation` | `capability` | `40` |
15
- | `ValidationAttestation` | `attestor` | `72` |
16
- | `ValidationAttestation` | `expires` | `208` |
17
- | `ValidationAttestation` | `revoked` | `216` |
8
+ Sources: [`programs/policy-vault/src/ext/atom_engine.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/policy-vault/src/ext/atom_engine.rs), [`programs/policy-vault/src/ext/validation_registry.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/policy-vault/src/ext/validation_registry.rs).
18
9
 
19
- Sources: [`programs/policy-vault/src/ext/atom_engine.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/policy-vault/src/ext/atom_engine.rs), [`programs/policy-vault/src/ext/validation_registry.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/policy-vault/src/ext/validation_registry.rs)
10
+ ## Quantu `AtomStats` (561 bytes)
20
11
 
12
+ Pinned to commit `bfb09ad`. Account-data-relative offsets — the 8-byte Borsh discriminator at `0..8` is verified via owner check, not by re-parsing.
13
+
14
+ | Offset | Width | Field | Notes |
15
+ |---:|---:|---|---|
16
+ | `549` | u8 | `risk_score` | 0..=255 — lower is better |
17
+ | `551` | u8 | `tier_immediate` | 0..=4 — v1 demo default; what `CounterpartyTier` reads in `GATE_MODE_IMMEDIATE` |
18
+ | `555` | u8 | `tier_confirmed` | 0..=4 — post-vesting; production policies prefer this via `GATE_MODE_CONFIRMED` |
19
+ | `557` | u16 LE | `confidence` | 0..=10000 (basis points) |
20
+ | `560` | u8 | `schema_version` | **canary** — must equal 1; mismatch → `Deny(AtomStatsSchemaMismatch)` |
21
+
22
+ Constants:
23
+
24
+ | Symbol | Value |
25
+ |---|---:|
26
+ | `ATOM_STATS_SIZE` | 561 |
27
+ | `ATOM_TIER_MAX` | 4 |
28
+ | `ATOM_STATS_SCHEMA_VERSION_EXPECTED` | 1 |
29
+ | `ATOM_ENGINE_ID` (devnet) | `AToMufS4QD6hEXvcvBDg9m1AHeCLpmZQsyfYa5h9MwAF` |
30
+ | `ATOM_ENGINE_ID` (mainnet) | `AToMw53aiPQ8j7iHVb4fGt6nzUNxUhcPc3tbPBZuzVVb` |
31
+
32
+ A tier byte above `ATOM_TIER_MAX` with `schema_version == 1` implies tampering or an undeclared spec change — the parser fails with `AtomStatsSchemaMismatch` rather than silently clamp.
33
+
34
+ ## AgentTrust `ValidationAttestation` (290 bytes)
35
+
36
+ Account-data-relative offsets. Field declaration order is **load-bearing** — reordering fields silently breaks PolicyVault's reads.
37
+
38
+ | Offset | Width | Field | Notes |
39
+ |---:|---:|---|---|
40
+ | `8` | Pubkey | `subject_asset` | The payee this attestation is about |
41
+ | `40` | [u8; 32] | `capability_hash` | SHA-256 of the namespace name |
42
+ | `72` | Pubkey | `attestor` | The key that signed `respond_to_validation` |
43
+ | `104` | [u8; 32] | `claim_payload_hash` | not read by v1 policy |
44
+ | `136` | [u8; 64] | `attestor_signature` | reserved for v1.1+ Ed25519 sysvar verify |
45
+ | `200` | u64 LE | `issued_at` | not read by v1 policy |
46
+ | `208` | u64 LE | `expires_at` | 0 = never expires |
47
+ | `216` | bool | `revoked` | `revoked == true` → `Deny(AttestationRevoked)` |
48
+ | `217` | u64 LE | `revoked_at` | not read by v1 policy |
49
+ | `225` | [u8; 32] | `revocation_reason_hash` | not read by v1 policy |
50
+ | `257` | [u8; 32] | `claim_uri_hash` | not read by v1 policy |
51
+ | `289` | u8 | `bump` | not read by v1 policy |
52
+
53
+ Constants:
54
+
55
+ | Symbol | Value |
56
+ |---|---:|
57
+ | `VALIDATION_ATTESTATION_SIZE` | 290 |
58
+ | `VA_SUBJECT_ASSET_OFFSET` | 8 |
59
+ | `VA_CAPABILITY_HASH_OFFSET` | 40 |
60
+ | `VA_ATTESTOR_OFFSET` | 72 |
61
+ | `VA_EXPIRES_AT_OFFSET` | 208 |
62
+ | `VA_REVOKED_OFFSET` | 216 |
63
+ | `VALIDATION_REGISTRY_ID` (devnet) | `Cx4RFa6ysw3qXYhugPkF8pFSWBkmKq59h2dWgF2tKhtv` |
64
+
65
+ ## AgentTrust `PolicyAccount` (240 bytes — own program)
66
+
67
+ PolicyVault's own state. Field offsets matter for the playbook contract; readers (the composer, the SDK's `parseGateDecision`) use the Anchor-generated decoder rather than byte offsets, but the layout is documented for downstream tooling.
68
+
69
+ | Offset | Width | Field |
70
+ |---:|---:|---|
71
+ | `8` | Pubkey | `payer_agent_asset` |
72
+ | `40` | u32 | `policy_id` |
73
+ | `44` | u8 | `bump` |
74
+ | `48` | u8 | `enabled_kinds_bitmask` |
75
+ | `49` | u8 | `gate_mode` |
76
+ | `50` | u64 | `spending_per_tx_max` |
77
+ | `58` | u64 | `spending_daily_max` |
78
+ | `66` | u64 | `spending_weekly_max` |
79
+ | `74` | u64 | `spending_today_used` |
80
+ | `82` | u64 | `spending_week_used` |
81
+ | `90` | u64 | `spending_today_anchor` |
82
+ | `98` | u64 | `spending_week_anchor` |
83
+ | `106` | u64 | `velocity_window_secs` |
84
+ | `114` | u64 | `velocity_max_in_window` |
85
+ | `122` | u64 | `velocity_tier0_decay_factor` |
86
+ | `130` | u8 | `min_counterparty_tier` |
87
+ | `131` | u8 | `max_risk_score` |
88
+ | `132` | u16 | `min_confidence` |
89
+ | `134` | u8 | `default_unrated_treatment` |
90
+ | `135` | [u8; 32] | `required_capability_hash` |
91
+ | `167` | [Pubkey; 2] | `accepted_attestors` |
92
+ | `231` | u8 | `scope_kind` |
93
+ | `232` | [u8; 8] | `_reserved` |
94
+
95
+ Source: [`programs/policy-vault/src/state/policy_account.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/policy-vault/src/state/policy_account.rs).
96
+
97
+ ## Read next
98
+
99
+ <Cards>
100
+ <Card title="Discriminator constants" href="/reference/discriminator-constants">
101
+ Quantu give_feedback discriminator + AgentTrust PDA seed prefixes.
102
+ </Card>
103
+ <Card title="CounterpartyTier policy" href="/programs/policy-vault/counterparty-tier-policy">
104
+ What the AtomStats reader feeds into.
105
+ </Card>
106
+ <Card title="RequireValidation policy" href="/programs/policy-vault/require-validation-policy">
107
+ What the ValidationAttestation reader feeds into.
108
+ </Card>
109
+ </Cards>
@@ -0,0 +1,56 @@
1
+ ---
2
+ title: Capability namespaces
3
+ description: The ten canonical v1 capability namespaces seeded on devnet — auto-generated from examples/attestor-demo/devnet-namespaces.json.
4
+ ---
5
+
6
+ The ten canonical v1 capability namespaces seeded on AgentTrust's `validation-registry` on Solana devnet. PolicyVault gates against `capability_hash = SHA-256(name)` per [PolicyAccount byte 135..167](/programs/policy-vault/require-validation-policy).
7
+
8
+ How to use one in a policy: [Integration → Capability namespaces](/integration-guides/capability-namespaces). How to register your own: [Custom attestor](/integration-guides/custom-attestor).
9
+
10
+ {/* BEGIN AUTO-GEN: namespaces */}
11
+
12
+ > Auto-generated from `examples/attestor-demo/devnet-namespaces.json` on 2026-05-07T15:08:37.863Z.
13
+ > Network: `solana-devnet`. Program: `Cx4RFa6ysw3qXYhugPkF8pFSWBkmKq59h2dWgF2tKhtv`. Count: 10.
14
+
15
+ | Name | Description | Capability hash (SHA-256, prefix) | PDA |
16
+ |---|---|---|---|
17
+ | `kyc.tier-1.v1` | Identity-verified individual (basic KYC). _(newly-registered)_ | [`366c075140aa…`](https://explorer.solana.com/tx/5jBmV36b89kMxzqPPtzFTWJD12vvB6TznMBGwZWtKNSApfuPzoPmJVAG2ed8bRWMkTfZ6QF3Ks21KESaTxU7Mb1W?cluster=devnet) | [`4ryEbb5iSi…`](https://explorer.solana.com/address/4ryEbb5iSiXHN2bJ59s9Pjdi2xxRkty1WohaRTqUt8wW?cluster=devnet) |
18
+ | `kyc.tier-2.v1` | Identity + address verified. _(newly-registered)_ | [`2ad4289070be…`](https://explorer.solana.com/tx/3tBAqxVnyqDj23P1Jyk1atdunUrsm4M54g4NDUKgAFJyeMLjfbpXe6ZR6QKcBMmRpA4HxfTVbVnD3pavcQtB3R81?cluster=devnet) | [`HdAABUX5oj…`](https://explorer.solana.com/address/HdAABUX5ojFZXocxSbTwvdNLXHGLaHnqCrKSKpeKXGCv?cluster=devnet) |
19
+ | `kyc.tier-3.v1` | Enhanced due diligence (regulated counterparties). _(newly-registered)_ | [`8fdd7707b57b…`](https://explorer.solana.com/tx/3LH2WNYn6ifYaXmF7WPcD5bsJB9T3HT3NgpeX13Jf1jg6eyfjQG8PBRqQjBQxT2HexTgzEvRJjcmonsRPXVmwGMp?cluster=devnet) | [`6gjTXCJE4q…`](https://explorer.solana.com/address/6gjTXCJE4qWybYGjTAg5ckYWBgBtt4ebvr39uU5YK5xL?cluster=devnet) |
20
+ | `audit.smart-contract.v1` | Audit attestation against a deployed program. _(newly-registered)_ | [`e61adaa34c65…`](https://explorer.solana.com/tx/319AFhK4wpWmhauHqsVUoqUdx3gadHcGsMNyAvt7Hgoau7ceAohViHAGRtvLP3PStF1Sqz5UkSCJy11nAqNJrRQa?cluster=devnet) | [`HygALr1ZSq…`](https://explorer.solana.com/address/HygALr1ZSqrYZTLBQUQ97vMSzAiuZRpKYovRhfyGtKkF?cluster=devnet) |
21
+ | `audit.attestor-firm.v1` | Per-firm audit identity (Halborn / OtterSec / etc.). _(newly-registered)_ | [`17926cb4f324…`](https://explorer.solana.com/tx/5KQG73FhBjixhaK3jE3XvsVJh4Xcd8kWMWphwuj9dHkTLTMhxwYB4BMzGw1TF8ZGnY6ZXTLY4CbeBZhF6nTobrNo?cluster=devnet) | [`A5rrMRYxez…`](https://explorer.solana.com/address/A5rrMRYxezaNUnSgqyyNjJUqHf4TH7GKNsvUifWjUESi?cluster=devnet) |
22
+ | `model-card.v1` | LLM model-version provenance attestation. _(newly-registered)_ | [`d90347d0a0a7…`](https://explorer.solana.com/tx/gmHvwe6NBB6vjMNPrMppfm2SVjvhizubUX8pACBJTZZ8rnbRaBFaLYuGqoa4TtApK2JqDFrUggZj8WS87xXGds6?cluster=devnet) | [`DZ7eneZtKs…`](https://explorer.solana.com/address/DZ7eneZtKsN39q771ruHvBXoTUDRzxKqDipTLbeRGa4o?cluster=devnet) |
23
+ | `jurisdiction.v1` | Regulatory-jurisdiction stamp (EU MiCA, US, etc.). _(newly-registered)_ | [`ce2818907881…`](https://explorer.solana.com/tx/5fUkGfziyLWbMeqp6pfZXrWMBf2mc3VzMZEsHUYjsynvANQSzjQtAkakVxXJNvPPQaCBEg8YnErk82VLbSHxSUMV?cluster=devnet) | [`Cd4sp8isN3…`](https://explorer.solana.com/address/Cd4sp8isN3CF8KiRchDNoMhsVERSpswEnufvBR21Jrnu?cluster=devnet) |
24
+ | `compliance.payments.v1` | Payment-network compliance attestation (Mastercard FACT-aligned, etc.). _(newly-registered)_ | [`0a8984a645e7…`](https://explorer.solana.com/tx/5B3ZfMMAjDSyrTnhGzXCCNcdg4yEeRepb8v1d8fK299WiyJpex5RbiW7ahha1VxPJfVSixyfXtb7R4wSFfd11Wm4?cluster=devnet) | [`Cn54CpSdfr…`](https://explorer.solana.com/address/Cn54CpSdfrME7epZ2VTSwhuTbcwH3ZttpcwjZADc5yrZ?cluster=devnet) |
25
+ | `agent-source.v1` | Provenance: which dev shop authored the agent. _(newly-registered)_ | [`2328df178dc6…`](https://explorer.solana.com/tx/52mqFEk5gpytgYjhsq4j7yML4tEcxg7jQhwb5Z6xqmx3cecX8vXP4C5NN6PRyXPSGtnTeSVZ8nBVaaYimU4NP4nH?cluster=devnet) | [`DqSwaqENQh…`](https://explorer.solana.com/address/DqSwaqENQhjPUajxfmzsjTcfTcnNXtNN22f3kYyAHvSJ?cluster=devnet) |
26
+ | `usdc-payment-policy.v1` | USDC payment policy capability — Phase D attestor demo. _(already-registered)_ | `a968ecd0b93d…` | [`34gonn86Fj…`](https://explorer.solana.com/address/34gonn86FjxzXZMGd43RSvQVyH1r6PrGV9xnHXjjkEwR?cluster=devnet) |
27
+
28
+ > Names are bounded by `MAX_NAME_LEN = 32` per [`programs/validation-registry/src/instructions/register_namespace.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/validation-registry/src/instructions/register_namespace.rs). PDA seeds: `["capability", capability_hash]`.
29
+
30
+ {/* END AUTO-GEN: namespaces */}
31
+
32
+ ## Reproduce
33
+
34
+ The seeded namespace set is captured in [`examples/attestor-demo/devnet-namespaces.json`](https://github.com/agenttrust-labs/agenttrust/blob/main/examples/attestor-demo/devnet-namespaces.json) — the source of truth this page is auto-generated from.
35
+
36
+ Re-run the seed script (idempotent — already-registered namespaces no-op):
37
+
38
+ ```bash
39
+ pnpm --filter ./examples/attestor-demo run seed:namespaces
40
+ ```
41
+
42
+ The script registers any missing namespaces from the canonical v1 set; cost is ~0.0023 SOL per fresh registration.
43
+
44
+ ## Read next
45
+
46
+ <Cards>
47
+ <Card title="Capability namespaces (walkthrough)" href="/integration-guides/capability-namespaces">
48
+ Register a new namespace + gate a policy against it.
49
+ </Card>
50
+ <Card title="ValidationRegistry" href="/programs/validation-registry">
51
+ The program that owns these PDAs.
52
+ </Card>
53
+ <Card title="Chained validation" href="/verification/chained-validation">
54
+ The four-sig devnet trace exercising one of these namespaces (`usdc-payment-policy.v1`).
55
+ </Card>
56
+ </Cards>