@agenttrust-sdk/mcp 0.2.5 → 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.
- package/dist/embedded-docs/architecture.mdx +174 -0
- package/dist/embedded-docs/getting-started/quickstart.mdx +79 -56
- package/dist/embedded-docs/index.mdx +54 -37
- package/dist/embedded-docs/integration-guides/capability-namespaces.mdx +135 -8
- package/dist/embedded-docs/integration-guides/custom-attestor.mdx +169 -8
- package/dist/embedded-docs/integration-guides/dexter-adapter.mdx +76 -0
- package/dist/embedded-docs/integration-guides/facilitator-adapters.mdx +85 -41
- package/dist/embedded-docs/integration-guides/pay-sh-adapter.mdx +90 -54
- package/dist/embedded-docs/integration-guides/x402-facilitator.mdx +55 -24
- package/dist/embedded-docs/mcp/hosted-endpoint.mdx +197 -0
- package/dist/embedded-docs/mcp/index.mdx +108 -0
- package/dist/embedded-docs/mcp/install.mdx +183 -0
- package/dist/embedded-docs/mcp/prompts.mdx +90 -0
- package/dist/embedded-docs/mcp/resources.mdx +115 -0
- package/dist/embedded-docs/mcp/tools.mdx +156 -0
- package/dist/embedded-docs/programs/policy-vault/composer.mdx +117 -0
- package/dist/embedded-docs/programs/policy-vault/counterparty-tier-policy.mdx +81 -9
- package/dist/embedded-docs/programs/policy-vault/index.mdx +77 -47
- package/dist/embedded-docs/programs/policy-vault/kill-switch-policy.mdx +65 -8
- package/dist/embedded-docs/programs/policy-vault/require-validation-policy.mdx +76 -8
- package/dist/embedded-docs/programs/policy-vault/spending-policy.mdx +83 -8
- package/dist/embedded-docs/programs/policy-vault/velocity-policy.mdx +85 -8
- package/dist/embedded-docs/programs/trustgate.mdx +112 -30
- package/dist/embedded-docs/programs/validation-registry.mdx +139 -32
- package/dist/embedded-docs/reference/byte-offset-reference.mdx +102 -13
- package/dist/embedded-docs/reference/capability-namespaces.mdx +56 -0
- package/dist/embedded-docs/reference/changelog.mdx +230 -13
- package/dist/embedded-docs/reference/deny-reason-codes.mdx +86 -0
- package/dist/embedded-docs/reference/devnet-program-ids.mdx +50 -8
- package/dist/embedded-docs/reference/discriminator-constants.mdx +104 -10
- package/dist/embedded-docs/reference/mainnet-program-ids.mdx +89 -5
- package/dist/embedded-docs/reference/quantu-agent-registry.mdx +104 -9
- package/dist/embedded-docs/sdk/exports-reference.mdx +239 -0
- package/dist/embedded-docs/sdk/gate-payment.mdx +99 -14
- package/dist/embedded-docs/sdk/index.mdx +141 -40
- package/dist/embedded-docs/sdk/mount-trustgate.mdx +178 -8
- package/dist/embedded-docs/verification/adversarial-harness.mdx +88 -0
- package/dist/embedded-docs/verification/atomic-tx-invariant.mdx +141 -0
- package/dist/embedded-docs/verification/chained-validation.mdx +87 -0
- package/dist/embedded-docs/verification/devnet-smoke.mdx +85 -0
- package/dist/embedded-docs/verification/index.mdx +31 -0
- package/dist/embedded-docs/verification/kani-proofs.mdx +144 -0
- package/dist/embedded-docs/verification/live-evidence.mdx +180 -0
- package/dist/tools/read/get-quantu-reputation.d.ts +50 -11
- package/dist/tools/read/get-quantu-reputation.js +75 -26
- package/dist/tools/read/get-quantu-reputation.js.map +1 -1
- package/dist/tools/write/emit-feedback.d.ts +6 -0
- package/dist/tools/write/emit-feedback.js +12 -1
- package/dist/tools/write/emit-feedback.js.map +1 -1
- package/package.json +16 -15
- package/scripts/install-claude-desktop.sh +0 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Prompts
|
|
3
|
+
description: Three guided MCP workflows — audit a payment, set up an agent, explain a failure. Each composes multiple tool calls into a structured procedure.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
MCP prompts are reusable, parameterised templates that the server returns in response to `prompts/get`. The client (Claude Desktop, Cursor, OpenAI Agents SDK) presents the prompt's messages to the model, which then drives the tool calls. Prompts encode the right *order* of tool calls for common workflows.
|
|
7
|
+
|
|
8
|
+
Source: [`mcp/src/prompts/`](https://github.com/agenttrust-labs/agenttrust/tree/main/mcp/src/prompts).
|
|
9
|
+
|
|
10
|
+
## Three prompts
|
|
11
|
+
|
|
12
|
+
| Name | What it walks the user through |
|
|
13
|
+
|---|---|
|
|
14
|
+
| [`agenttrust_audit_payment`](#agenttrust_audit_payment) | Simulate a payment, read the policy, read the payee's reputation, surface the decision |
|
|
15
|
+
| [`agenttrust_setup_agent`](#agenttrust_setup_agent) | Bootstrap an agent's `PolicyAuthority` → `KillSwitchState` → first `PolicyAccount` |
|
|
16
|
+
| [`agenttrust_explain_failure`](#agenttrust_explain_failure) | Given a failed payment's reason code, explain root cause + remediation |
|
|
17
|
+
|
|
18
|
+
## `agenttrust_audit_payment`
|
|
19
|
+
|
|
20
|
+
Required args: `payer_agent`, `payee_agent`, `amount`, `mint`, `policy_id`. Optional: `caller`.
|
|
21
|
+
|
|
22
|
+
The prompt walks the model through:
|
|
23
|
+
|
|
24
|
+
1. `agenttrust_get_policy({ agent_asset: payer_agent, policy_id })` — read the spending caps, velocity threshold, counterparty tier requirement, required capability.
|
|
25
|
+
2. `agenttrust_get_quantu_reputation({ agent_asset: payee_agent })` — read the payee's tier, risk, confidence.
|
|
26
|
+
3. `agenttrust_simulate_payment({ caller, payer_agent, payee_agent, amount, mint, policy_id })` — run the gate.
|
|
27
|
+
4. Compare the simulation result to the policy thresholds + payee reputation. Surface `Allow`, `Deny(reason)`, or `RequireValidation(capability)` with the relevant numbers.
|
|
28
|
+
|
|
29
|
+
Use case: "Audit this payment before I send it." The model produces a structured explanation of the decision rather than a yes/no answer.
|
|
30
|
+
|
|
31
|
+
## `agenttrust_setup_agent`
|
|
32
|
+
|
|
33
|
+
Required args: `agent_asset`, `use_case`. The `use_case` is free-text — the prompt uses it to suggest reasonable defaults for the policy fields (per-tx cap, velocity window, counterparty tier minimum).
|
|
34
|
+
|
|
35
|
+
The prompt walks the model through:
|
|
36
|
+
|
|
37
|
+
1. `agenttrust_get_killswitch({ agent_asset })` — check whether `PolicyAuthority` and `KillSwitchState` exist.
|
|
38
|
+
2. If absent, instruct the model to call `init_authority` (off-band, since v1 doesn't expose this as an MCP write tool).
|
|
39
|
+
3. `agenttrust_init_policy({ agent_asset, policy_id: 1, enabled_kinds_bitmask: 0b11111, … })` — initialise the first policy with use-case-tailored defaults.
|
|
40
|
+
4. Confirm the result by calling `agenttrust_get_policy`.
|
|
41
|
+
|
|
42
|
+
Use case: "I just got my Quantu agent identity. Set up a basic AgentTrust policy." The prompt + the write tools land a working policy in three or four turns.
|
|
43
|
+
|
|
44
|
+
## `agenttrust_explain_failure`
|
|
45
|
+
|
|
46
|
+
Required args: `reason_code` (1..15). Optional: `payer_agent`, `payee_agent`, `policy_id`.
|
|
47
|
+
|
|
48
|
+
The prompt walks the model through:
|
|
49
|
+
|
|
50
|
+
1. `agenttrust_explain_decision({ reason_code })` — translate to canonical name + remediation hint.
|
|
51
|
+
2. If the optional context is present, run the relevant lookup (`get_quantu_reputation`, `get_velocity`, `get_killswitch`, `get_validation_attestation`) to inspect the actual on-chain state that drove the deny.
|
|
52
|
+
3. Surface the contradiction in plain language ("the policy requires `min_counterparty_tier = 3` but the payee's `tier_immediate = 1`").
|
|
53
|
+
|
|
54
|
+
Use case: "Why did my last payment fail with reason code 6?" The prompt produces an explanation grounded in real on-chain state, not training-data guesses.
|
|
55
|
+
|
|
56
|
+
## How clients invoke prompts
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
// Pseudocode — the actual API depends on the MCP client.
|
|
60
|
+
const prompts = await mcp.request("prompts/list");
|
|
61
|
+
// → [{ name: "agenttrust_audit_payment", description, arguments }, …]
|
|
62
|
+
|
|
63
|
+
const audit = await mcp.request("prompts/get", {
|
|
64
|
+
name: "agenttrust_audit_payment",
|
|
65
|
+
arguments: {
|
|
66
|
+
payer_agent: "5Pfa…K8y",
|
|
67
|
+
payee_agent: "C9pY…B3dR",
|
|
68
|
+
amount: "1000000",
|
|
69
|
+
mint: "EPjF…Dt1v",
|
|
70
|
+
policy_id: 1,
|
|
71
|
+
caller: "4tSE…hRG",
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
// → { messages: [{ role: "user", content: { type: "text", text: "Walk me through auditing this payment…" } }, … ] }
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The model then picks tools to call, the client surfaces the tool results back to the model, and the prompt's structure produces a grounded answer.
|
|
78
|
+
|
|
79
|
+
In Claude Desktop, prompts appear as slash commands when an MCP server is connected. Type `/agenttrust_audit_payment` in chat → the UI prompts for the required arguments → the model executes the workflow.
|
|
80
|
+
|
|
81
|
+
## Validation
|
|
82
|
+
|
|
83
|
+
Phase M validated all three prompts via direct `prompts/get` calls. All three return non-empty `messages` arrays with structured user prompts referencing the right tools. Missing-argument probes return clean `-32603 missing required argument` errors. Full report: [`docs/proofs/phase-m-mcp-e2e.md`](https://github.com/agenttrust-labs/agenttrust/blob/main/docs/proofs/phase-m-mcp-e2e.md) §M1.5.
|
|
84
|
+
|
|
85
|
+
Phase P verified `agenttrust_explain_failure` end-to-end with Claude `sonnet` driving the workflow against live devnet state — the model called `agenttrust_explain_decision(6)` then `agenttrust_get_killswitch` to inspect the actual policy fields, and produced a remediation in plain language.
|
|
86
|
+
|
|
87
|
+
## Source
|
|
88
|
+
|
|
89
|
+
- Prompts: [`mcp/src/prompts/`](https://github.com/agenttrust-labs/agenttrust/tree/main/mcp/src/prompts)
|
|
90
|
+
- Server wiring: [`mcp/src/server.ts`](https://github.com/agenttrust-labs/agenttrust/blob/main/mcp/src/server.ts)
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Resources
|
|
3
|
+
description: Four MCP resource URIs — devnet program manifest, docs corpus mirror, demo source files. Path-traversal-safe, MIME-typed, MCP-list-friendly.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
The MCP server exposes four `resources/list`-able URIs. Resources are read-only by design; writes happen through tools.
|
|
7
|
+
|
|
8
|
+
Source: [`mcp/src/resources/`](https://github.com/agenttrust-labs/agenttrust/tree/main/mcp/src/resources).
|
|
9
|
+
|
|
10
|
+
## URI manifest
|
|
11
|
+
|
|
12
|
+
| URI scheme | Mime type | Content |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| `agenttrust://devnet/programs` | `application/json` | Deployed program IDs + Explorer URLs for the active cluster |
|
|
15
|
+
| `agenttrust://docs/<rel-path>` | `text/markdown` | Each MDX page in the docs corpus exposed individually |
|
|
16
|
+
| `agenttrust://examples/pay-sh-demo/<rel-path>` | `text/x-typescript` / `text/markdown` | Pay.sh demo source files |
|
|
17
|
+
| `agenttrust://examples/attestor-demo/<rel-path>` | `text/x-typescript` / `text/markdown` | Attestor demo source files |
|
|
18
|
+
|
|
19
|
+
## Devnet program manifest
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"uri": "agenttrust://devnet/programs",
|
|
24
|
+
"mimeType": "application/json"
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"network": "solana-devnet",
|
|
33
|
+
"programs": {
|
|
34
|
+
"policy_vault": {
|
|
35
|
+
"id": "8Y6fGeNEHgmWmbt8JsRcF72jxbeBfJhomMjG6SuoJQTR",
|
|
36
|
+
"explorerUrl": "https://explorer.solana.com/address/8Y6f…QTR?cluster=devnet"
|
|
37
|
+
},
|
|
38
|
+
"trustgate": {
|
|
39
|
+
"id": "HF8zHfoyA7b5mhLViopTnRMprc6ZT5KActHTdkFrih2N",
|
|
40
|
+
"explorerUrl": "https://explorer.solana.com/address/HF8z…ih2N?cluster=devnet"
|
|
41
|
+
},
|
|
42
|
+
"validation_registry": {
|
|
43
|
+
"id": "Cx4RFa6ysw3qXYhugPkF8pFSWBkmKq59h2dWgF2tKhtv",
|
|
44
|
+
"explorerUrl": "https://explorer.solana.com/address/Cx4R…Khtv?cluster=devnet"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Docs corpus mirror
|
|
51
|
+
|
|
52
|
+
Every MDX page under [`docs-site/content/docs/`](https://github.com/agenttrust-labs/agenttrust/tree/main/docs-site/content/docs) is exposed as an individual resource. Example URIs:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
agenttrust://docs/index
|
|
56
|
+
agenttrust://docs/architecture
|
|
57
|
+
agenttrust://docs/programs/policy-vault/index
|
|
58
|
+
agenttrust://docs/sdk/atomic-tx-invariant
|
|
59
|
+
agenttrust://docs/verification/live-evidence
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The resource body is the rendered markdown text (frontmatter included). LLM clients use `agenttrust_docs` (a discovery tool with full-text search) to find the right resource, then fetch it via `resources/read`.
|
|
63
|
+
|
|
64
|
+
## Demo source mirrors
|
|
65
|
+
|
|
66
|
+
The Pay.sh demo and the attestor demo are bundled in the npm tarball as of 0.2.3. URIs:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
agenttrust://examples/pay-sh-demo/README.md
|
|
70
|
+
agenttrust://examples/pay-sh-demo/src/index.ts
|
|
71
|
+
agenttrust://examples/pay-sh-demo/src/middleware.ts
|
|
72
|
+
agenttrust://examples/pay-sh-demo/devnet-counterparties.json
|
|
73
|
+
|
|
74
|
+
agenttrust://examples/attestor-demo/README.md
|
|
75
|
+
agenttrust://examples/attestor-demo/scripts/devnet-chained-validation.ts
|
|
76
|
+
agenttrust://examples/attestor-demo/devnet-namespaces.json
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Use case: an LLM asks "show me the Pay.sh demo source" and the tool returns the actual file contents rather than synthesizing a stale paraphrase from training data.
|
|
80
|
+
|
|
81
|
+
## Path-traversal safety
|
|
82
|
+
|
|
83
|
+
All resource URIs go through a path-normalization step before file reads. Probes like `agenttrust://docs/../../etc/passwd` return:
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"error": {
|
|
88
|
+
"code": -32603,
|
|
89
|
+
"message": "unknown resource URI"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Same protection on the `examples/` URIs. Source: [`mcp/src/resources/docs.ts`](https://github.com/agenttrust-labs/agenttrust/blob/main/mcp/src/resources/docs.ts) — the indexer normalises every path against the corpus root before serving bytes.
|
|
95
|
+
|
|
96
|
+
Phase M validated this against a deliberate traversal probe — clean error, no escape. Full report: [`docs/proofs/phase-m-mcp-e2e.md`](https://github.com/agenttrust-labs/agenttrust/blob/main/docs/proofs/phase-m-mcp-e2e.md) §M1.4.
|
|
97
|
+
|
|
98
|
+
## How clients use resources
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
// Pseudocode — actual API depends on the MCP client.
|
|
102
|
+
const list = await mcp.request("resources/list");
|
|
103
|
+
// → [{ uri: "agenttrust://devnet/programs", … }, { uri: "agenttrust://docs/index", … }, …]
|
|
104
|
+
|
|
105
|
+
const programs = await mcp.request("resources/read", { uri: "agenttrust://devnet/programs" });
|
|
106
|
+
// → { contents: [{ uri, mimeType: "application/json", text: "{ …JSON… }" }] }
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Claude Desktop and Cursor surface resources in their model-context UI — the user can attach a resource to the conversation and the LLM reads it directly, no tool round-trip needed.
|
|
110
|
+
|
|
111
|
+
## Source
|
|
112
|
+
|
|
113
|
+
- Resource handlers: [`mcp/src/resources/`](https://github.com/agenttrust-labs/agenttrust/tree/main/mcp/src/resources)
|
|
114
|
+
- Server wiring: [`mcp/src/server.ts`](https://github.com/agenttrust-labs/agenttrust/blob/main/mcp/src/server.ts)
|
|
115
|
+
- Path-traversal tests: [`mcp/test/resources/`](https://github.com/agenttrust-labs/agenttrust/tree/main/mcp/test/resources)
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Tools
|
|
3
|
+
description: All 18 MCP tools — 10 read, 5 write, 3 discovery — with input/output shape and live devnet examples.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Each tool has a stable Zod schema. Input arguments are documented per tool below. Every write tool surfaces the resulting `txSignature` plus a Solana Explorer URL in its response.
|
|
7
|
+
|
|
8
|
+
Source: [`mcp/src/tools/`](https://github.com/agenttrust-labs/agenttrust/tree/main/mcp/src/tools).
|
|
9
|
+
|
|
10
|
+
## Read (10 tools — no signer required)
|
|
11
|
+
|
|
12
|
+
| Tool | Input | Returns |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| [`agenttrust_get_policy`](#agenttrust_get_policy) | `agent_asset`, `policy_id` | Decoded `PolicyAccount` PDA — every spending cap, velocity threshold, counterparty tier requirement, required capability hash |
|
|
15
|
+
| [`agenttrust_list_policies`](#agenttrust_list_policies) | `agent_asset` | Lightweight summary of all policies registered for an agent |
|
|
16
|
+
| [`agenttrust_simulate_payment`](#agenttrust_simulate_payment) | `caller`, `payer_agent`, `payee_agent`, `amount`, `mint`, `policy_id` | `Allow` / `Deny(reasonCode, reasonName)` / `RequireValidation(capabilityHash)` |
|
|
17
|
+
| [`agenttrust_get_killswitch`](#agenttrust_get_killswitch) | `agent_asset` | `KillSwitchState` + `PolicyAuthority` decoded |
|
|
18
|
+
| [`agenttrust_get_velocity`](#agenttrust_get_velocity) | `agent_asset`, `policy_id` | `VelocityLedger` — sliding-window cumulative spend |
|
|
19
|
+
| [`agenttrust_get_feedback_log`](#agenttrust_get_feedback_log) | `payment_id_hash` (32-byte hex) | `FeedbackEmissionLog` PDA |
|
|
20
|
+
| [`agenttrust_get_quantu_reputation`](#agenttrust_get_quantu_reputation) | `agent_asset` | Quantu `AtomStats` decoded — `tierImmediate`, `tierConfirmed`, `riskScore`, `confidence`, `schemaVersion` |
|
|
21
|
+
| [`agenttrust_get_validation_attestation`](#agenttrust_get_validation_attestation) | `subject_asset`, `capability_name` OR `capability_hash`, `attestor` | Every `ValidationAttestation` PDA matching the filter |
|
|
22
|
+
| [`agenttrust_list_facilitators`](#agenttrust_list_facilitators) | — | Active facilitator adapters (Pay.sh / Dexter / atxp / MCPay) + ship status |
|
|
23
|
+
| [`agenttrust_demo_state`](#agenttrust_demo_state) | — | Three pre-warmed devnet counterparties used by `examples/pay-sh-demo` |
|
|
24
|
+
|
|
25
|
+
### `agenttrust_get_policy`
|
|
26
|
+
|
|
27
|
+
Decodes the `PolicyAccount` PDA at `["policy", agent_asset, policy_id_le]`. Returns every byte: `enabled_kinds_bitmask`, `gate_mode`, all spending fields, all velocity fields, `min_counterparty_tier`, `max_risk_score`, `min_confidence`, `default_unrated_treatment`, `required_capability_hash` (hex), `accepted_attestors[]`, `scope_kind`. Non-existent policies return `exists: false`.
|
|
28
|
+
|
|
29
|
+
### `agenttrust_list_policies`
|
|
30
|
+
|
|
31
|
+
Lightweight summary across `policy_id ∈ {1..10}` for the given agent. Use `get_policy` for the full decode of a specific policy.
|
|
32
|
+
|
|
33
|
+
### `agenttrust_simulate_payment`
|
|
34
|
+
|
|
35
|
+
Read-only `gate_payment` simulation. Same semantics as the SDK's [`gatePayment()`](/sdk/gate-payment) — invokes the lazy variant (returns decision via Anchor's return-data channel), parses the response into the `GateDecision` union.
|
|
36
|
+
|
|
37
|
+
`caller` is required; pass any funded base58 pubkey. The simulation tx isn't committed, but Solana requires a fee-payer keypair. As of 0.2.1 the tool surfaces a clear actionable error if `caller` is omitted (was a cryptic `AccountNotFound` before).
|
|
38
|
+
|
|
39
|
+
### `agenttrust_get_killswitch`
|
|
40
|
+
|
|
41
|
+
Returns the `KillSwitchState` for the agent's per-agent kill switch (scope_kind = 2, scope_key = agent_asset) plus the `PolicyAuthority` (multisig members + threshold). Useful when debugging "why is this agent paused?".
|
|
42
|
+
|
|
43
|
+
### `agenttrust_get_velocity`
|
|
44
|
+
|
|
45
|
+
Decodes the `VelocityLedger` PDA at `["velocity", agent_asset, policy_id_le]`. Returns `cumulative_amount`, `last_commit_slot`, `window_start_slot`. The window-active vs window-expired check (`elapsed >= window_slots`) is a pure-fn evaluation — match the policy's `velocity_window_secs` × `tier_decay(payer_tier) × 2 slots/sec`.
|
|
46
|
+
|
|
47
|
+
### `agenttrust_get_feedback_log`
|
|
48
|
+
|
|
49
|
+
`FeedbackEmissionLog` lookup by `payment_id_hash`. The PDA is at `["feedback_log", payment_id_hash]`. Returns `score`, `is_dispute`, `emitted_at_slot` if found, or `exists: false`.
|
|
50
|
+
|
|
51
|
+
### `agenttrust_get_quantu_reputation`
|
|
52
|
+
|
|
53
|
+
Decodes Quantu's `AtomStats` at `["atom_stats", agent_asset]`. Returns:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"pda": "4z9RiK6B49QZbmqPM9yNZWgfxYD3tvQ3NETU6X89f5mv",
|
|
58
|
+
"ownerProgram": "AToMufS4QD6hEXvcvBDg9m1AHeCLpmZQsyfYa5h9MwAF",
|
|
59
|
+
"ownerMatches": true,
|
|
60
|
+
"rawByteLen": 561,
|
|
61
|
+
"reputation": {
|
|
62
|
+
"tierImmediate": 3,
|
|
63
|
+
"tierConfirmed": 2,
|
|
64
|
+
"riskScore": 42,
|
|
65
|
+
"confidence": 8500,
|
|
66
|
+
"schemaVersion": 1
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Mirrors the canonical byte offsets from [`programs/policy-vault/src/ext/atom_engine.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/policy-vault/src/ext/atom_engine.rs) verbatim — 549 / 551 / 555 / 557 / 560. Fixed in MCP 0.2.6 (Phase Q1) after the schema-version canary at byte 560 + the `tier ≤ 4` range check were added; v0.2.5 had fabricated offsets that returned junk values.
|
|
72
|
+
|
|
73
|
+
### `agenttrust_get_validation_attestation`
|
|
74
|
+
|
|
75
|
+
Returns every `ValidationAttestation` PDA matching `(subject_asset, capability_name OR capability_hash)`, optionally filtered by `attestor`. Accepts the friendly capability name (the SDK computes SHA-256 internally) or the 64-char hex hash. Added in 0.2.4 — real LLMs typically have the human-readable name; requiring the digest was a friction point.
|
|
76
|
+
|
|
77
|
+
### `agenttrust_list_facilitators`
|
|
78
|
+
|
|
79
|
+
Returns the active adapter set: Pay.sh (live), Dexter (in-flight), atxp (roadmap), MCPay (roadmap). Each entry includes the adapter's wire format hint and ship status.
|
|
80
|
+
|
|
81
|
+
### `agenttrust_demo_state`
|
|
82
|
+
|
|
83
|
+
Returns the three pre-warmed devnet counterparties used by `examples/pay-sh-demo`:
|
|
84
|
+
|
|
85
|
+
| Tier | Asset pubkey | Expected gate decision |
|
|
86
|
+
|---|---|---|
|
|
87
|
+
| 0 (untrusted) | `C9pYqwnCVpwg7MwEbQa4XcmVVYsUcPwqHMYs999KB3dR` | `Deny(CounterpartyTierBelowMin)` |
|
|
88
|
+
| 1 (low-trust) | `9894Sh7F79yDzTi4Pvfm5Jy5VmLpx2XkyhS14BFwpyrd` | `Deny(CounterpartyTierBelowMin)` |
|
|
89
|
+
| 3 (Gold) | `5PfaofvEUf3adtJwMho7zzbfvgxwxbvp2V5moqhtLK8y` | `Allow` (with a tier-3 policy) |
|
|
90
|
+
|
|
91
|
+
The demo state is bundled in the tarball as of 0.2.3 — the published package doesn't need a separate state file.
|
|
92
|
+
|
|
93
|
+
## Write (5 tools — require `KEYPAIR_B58`)
|
|
94
|
+
|
|
95
|
+
| Tool | Effect |
|
|
96
|
+
|---|---|
|
|
97
|
+
| [`agenttrust_init_policy`](#agenttrust_init_policy) | Create `PolicyAccount` + `VelocityLedger` for the signer's agent |
|
|
98
|
+
| [`agenttrust_set_killswitch`](#agenttrust_set_killswitch) | Pause / unpause the agent's `KillSwitchState` (lead-only multisig in v1) |
|
|
99
|
+
| [`agenttrust_request_validation`](#agenttrust_request_validation) | Open a `ValidationRequest` PDA |
|
|
100
|
+
| [`agenttrust_respond_to_validation`](#agenttrust_respond_to_validation) | Attestor writes a `ValidationAttestation` PDA |
|
|
101
|
+
| [`agenttrust_emit_feedback`](#agenttrust_emit_feedback) | Facilitator-only `emit_feedback` CPI (signer must equal facilitator) |
|
|
102
|
+
|
|
103
|
+
### `agenttrust_init_policy`
|
|
104
|
+
|
|
105
|
+
Required args: `agent_asset`, `policy_id`, `enabled_kinds_bitmask` (e.g., `0b11111` = all five kinds). Optional: every `PolicyAccount` field — defaults are documented in [`programs/policy-vault/src/instructions/init_policy.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/policy-vault/src/instructions/init_policy.rs).
|
|
106
|
+
|
|
107
|
+
### `agenttrust_set_killswitch`
|
|
108
|
+
|
|
109
|
+
Required args: `agent_asset`, `paused`. Multisig-gated against `PolicyAuthority` per [KillSwitch policy](/programs/policy-vault/kill-switch-policy). v1 uses single-signer (lead-only) for hackathon-velocity reasons; v1.1+ exercises the full Kani-proven multi-signer path.
|
|
110
|
+
|
|
111
|
+
### `agenttrust_request_validation`
|
|
112
|
+
|
|
113
|
+
Required args: `subject_asset`, `claim_uri_hash_hex`, `deadline_slot`. The capability is implied by the active namespace context. Subject's owner OR any third party can open the request; off-chain attestors discover via the `RequestCreated` event.
|
|
114
|
+
|
|
115
|
+
### `agenttrust_respond_to_validation`
|
|
116
|
+
|
|
117
|
+
Required args: `subject_asset`, `claim_payload_hash_hex`, `claim_uri_hash_hex`, `expires_at_slot`. The signer (the keypair behind `KEYPAIR_B58`) is the attestor. v1 trust model: tx signature authenticates; v1.1+ adds Ed25519 sysvar verify.
|
|
118
|
+
|
|
119
|
+
### `agenttrust_emit_feedback`
|
|
120
|
+
|
|
121
|
+
Required args: `payment_id_hash_hex`, `payee_asset`, `base_collection`, `score`. The signer must equal the facilitator (`FacilitatorSignerMismatch` otherwise). `base_collection` is the value passed to Quantu's `register_agent` — the agent-registry-8004 collection address.
|
|
122
|
+
|
|
123
|
+
## Discovery (3 tools)
|
|
124
|
+
|
|
125
|
+
| Tool | Returns |
|
|
126
|
+
|---|---|
|
|
127
|
+
| [`agenttrust_docs`](#agenttrust_docs) | Full-text search over `docs-site/content/docs/` — ranked hits with excerpts |
|
|
128
|
+
| [`agenttrust_facilitator_walkthrough`](#agenttrust_facilitator_walkthrough) | Per-adapter integration walkthrough by name |
|
|
129
|
+
| [`agenttrust_explain_decision`](#agenttrust_explain_decision) | Translate a `DenyReason` code (1..15) into the enum name + remediation hint |
|
|
130
|
+
|
|
131
|
+
### `agenttrust_docs`
|
|
132
|
+
|
|
133
|
+
Searches the bundled docs corpus. Returns ranked hits with excerpts. Use case: an LLM asks "what's the atomic-tx invariant?" and the tool surfaces the verification page with a relevant excerpt rather than hallucinating from training data.
|
|
134
|
+
|
|
135
|
+
The corpus is bundled in the tarball as of 0.2.3. `MCP_DOCS_DIR` env var lets tests point at a different root.
|
|
136
|
+
|
|
137
|
+
### `agenttrust_facilitator_walkthrough`
|
|
138
|
+
|
|
139
|
+
Returns the canonical guide for a named facilitator (`pay-sh`, `dexter`, `atxp`, `mcpay`, or `x402`). Falls back to the generic adapters guide for unknown names. Use case: an LLM asks "walk me through adding a new facilitator" and the tool returns the contract page.
|
|
140
|
+
|
|
141
|
+
### `agenttrust_explain_decision`
|
|
142
|
+
|
|
143
|
+
Maps a `DenyReason` code (`1..15`) to the canonical name + remediation hint. Same data the [Reference → DenyReason codes](/reference/deny-reason-codes) page surfaces, but tool-shaped for LLM consumption.
|
|
144
|
+
|
|
145
|
+
## Validation status
|
|
146
|
+
|
|
147
|
+
Phase M comprehensive E2E (2026-05-07): all 18 tools present, 10/10 read tools return live devnet state with clickable Explorer URLs, 6/6 PDAs cross-validated against on-chain ground truth, 4/4 Explorer URLs return HTTP 200. Full report: [`docs/proofs/phase-m-mcp-e2e.md`](https://github.com/agenttrust-labs/agenttrust/blob/main/docs/proofs/phase-m-mcp-e2e.md).
|
|
148
|
+
|
|
149
|
+
Phase P real-LLM tool-routing (2026-05-08): 7/10 strict pass on natural-language scenarios via Claude `sonnet`. The three false negatives were context-gathering artefacts (the LLM called `agenttrust_demo_state` first to gather context, then the expected tool); a less agentic client would score 9/10. Full report: [`docs/proofs/phase-p-llm-routing.md`](https://github.com/agenttrust-labs/agenttrust/blob/main/docs/proofs/phase-p-llm-routing.md).
|
|
150
|
+
|
|
151
|
+
## Source
|
|
152
|
+
|
|
153
|
+
- Read tools: [`mcp/src/tools/read/`](https://github.com/agenttrust-labs/agenttrust/tree/main/mcp/src/tools/read)
|
|
154
|
+
- Write tools: [`mcp/src/tools/write/`](https://github.com/agenttrust-labs/agenttrust/tree/main/mcp/src/tools/write)
|
|
155
|
+
- Discovery tools: [`mcp/src/tools/discovery/`](https://github.com/agenttrust-labs/agenttrust/tree/main/mcp/src/tools/discovery)
|
|
156
|
+
- Tool aggregator: [`mcp/src/tools/index.ts`](https://github.com/agenttrust-labs/agenttrust/blob/main/mcp/src/tools/index.ts)
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Composer
|
|
3
|
+
description: The pure-Rust orchestration that ties the five policy kinds together with fail-fast semantics and Allow-only state mutation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
`compose_decision` is the single function that runs every policy and returns the gate's verdict. The Anchor handlers (`gate_payment`, `gate_payment_strict`) are thin wrappers around it.
|
|
7
|
+
|
|
8
|
+
Source: [`programs/policy-vault/src/policies/composer.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/policy-vault/src/policies/composer.rs).
|
|
9
|
+
|
|
10
|
+
## Signature
|
|
11
|
+
|
|
12
|
+
```rust
|
|
13
|
+
pub fn compose_decision(input: ComposerInput) -> ComposerResult;
|
|
14
|
+
|
|
15
|
+
pub struct ComposerInput {
|
|
16
|
+
pub policy: PolicySnapshot,
|
|
17
|
+
pub ledger: VelocityLedgerSnapshot,
|
|
18
|
+
pub killswitch: KillSwitchSnapshot,
|
|
19
|
+
pub payer_atom: Option<AtomStatsView>,
|
|
20
|
+
pub payee_atom: Option<AtomStatsView>,
|
|
21
|
+
pub attestation: Option<ValidationAttestationView>,
|
|
22
|
+
pub amount: u64,
|
|
23
|
+
pub payee_agent_asset: Pubkey,
|
|
24
|
+
pub now_slot: u64,
|
|
25
|
+
pub unix_ts: i64,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
pub struct ComposerResult {
|
|
29
|
+
pub decision: GateDecision,
|
|
30
|
+
pub spending_deltas: Option<SpendingDeltas>,
|
|
31
|
+
pub velocity_deltas: Option<VelocityDeltas>,
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The Anchor wrapper feeds the composer plain-data snapshots, never on-chain account references. That separation is what makes every policy unit-testable in plain Rust and Kani-provable without an Anchor harness.
|
|
36
|
+
|
|
37
|
+
## Fail-fast order
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
KillSwitch → Spending → Velocity → CounterpartyTier → RequireValidation
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Cheapest reads first. KillSwitch is one bool. Spending is pure arithmetic. Velocity reads one local PDA. CounterpartyTier reads two foreign `AtomStats` PDAs. RequireValidation reads one foreign `ValidationAttestation` PDA. The first policy that returns `Deny` short-circuits the rest — no foreign-PDA reads beyond the deciding policy.
|
|
44
|
+
|
|
45
|
+
## State mutation rule
|
|
46
|
+
|
|
47
|
+
The composer **never** mutates state. It returns *deltas* — `SpendingDeltas`, `VelocityDeltas` — that the Anchor handler applies to `PolicyAccount` and `VelocityLedger` only on the `Allow` branch.
|
|
48
|
+
|
|
49
|
+
```rust
|
|
50
|
+
match result.decision {
|
|
51
|
+
GateDecision::Allow => {
|
|
52
|
+
if let Some(d) = result.spending_deltas {
|
|
53
|
+
spending::apply_deltas(&mut ctx.accounts.policy_account, &d);
|
|
54
|
+
}
|
|
55
|
+
if let Some(d) = result.velocity_deltas {
|
|
56
|
+
velocity::apply_deltas(&mut ctx.accounts.velocity_ledger, &d);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
GateDecision::Deny(_) | GateDecision::RequireValidation(_) => {
|
|
60
|
+
// Mutate nothing.
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
This rule is what `velocity_counter_le_limit` (Kani #2) is inductive over: if the pre-state ledger satisfies `cumulative_amount ≤ max_in_window` and the policy returns `Allow(deltas)`, then the post-state ledger also satisfies the bound. A fresh ledger trivially satisfies the base case.
|
|
66
|
+
|
|
67
|
+
## Strict variant
|
|
68
|
+
|
|
69
|
+
`gate_payment_strict` converts non-`Allow` into `Err`:
|
|
70
|
+
|
|
71
|
+
```rust
|
|
72
|
+
pub fn gate_payment_strict(ctx: Context<GatePaymentStrict>, …) -> Result<()> {
|
|
73
|
+
let result = compose_decision(input);
|
|
74
|
+
match result.decision {
|
|
75
|
+
GateDecision::Allow => {
|
|
76
|
+
// Apply deltas, return Ok.
|
|
77
|
+
Ok(())
|
|
78
|
+
}
|
|
79
|
+
GateDecision::Deny(reason) => Err(reason.into()),
|
|
80
|
+
GateDecision::RequireValidation(_) => Err(ErrorCode::ValidationRequired.into()),
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The SDK's `composeAtomicSettleTx` calls `gate_payment_strict`. Any `Deny` on the gate fails the entire bundled transaction (`gate + transfer + emit_feedback`), which means the SPL transfer never runs and `FeedbackEmissionLog` is never created. Solana's transaction atomicity does the rest.
|
|
86
|
+
|
|
87
|
+
The Phase J5 Kani proof `gate_payment_strict_correctness` pins this contract end-to-end:
|
|
88
|
+
|
|
89
|
+
- `strict_returns_ok_iff_allow` — strict `Ok(())` ⇔ composer `Allow`.
|
|
90
|
+
- `gate_decision_is_one_of_three_disjoint_variants` — the three `GateDecision` arms are pairwise disjoint, so a fourth variant cannot silently slip past the strict dispatch.
|
|
91
|
+
|
|
92
|
+
Together: 258 sub-checks, ~0.9 s. The strict-correctness invariant is the on-chain anchor of the SDK's atomic-tx invariant.
|
|
93
|
+
|
|
94
|
+
## Why pure-Rust
|
|
95
|
+
|
|
96
|
+
Three reasons:
|
|
97
|
+
|
|
98
|
+
1. **Kani provability.** `compose_decision` is a deterministic function over plain types. Kani's bounded model checker explores every reachable state inside the bounds in seconds. An Anchor handler with account validation, CPI, and rent calculations would not be tractable.
|
|
99
|
+
2. **Unit-testability.** The same function works in `cargo test` without an Anchor program-test harness. Every policy module ships with a dense unit-test suite (Spending: 14 tests, Velocity: 14, CounterpartyTier: 13, RequireValidation: 13, KillSwitch: 2 — plus 113 module-level tests across PolicyVault).
|
|
100
|
+
3. **Wrapper churn isolation.** Account-validation, IDL changes, Anchor-version bumps live in the wrapper. Decision logic doesn't move when wrappers do.
|
|
101
|
+
|
|
102
|
+
## Read next
|
|
103
|
+
|
|
104
|
+
<Cards>
|
|
105
|
+
<Card title="KillSwitch policy" href="/programs/policy-vault/kill-switch-policy">
|
|
106
|
+
First in the composer; one bool; multisig-gated mutation.
|
|
107
|
+
</Card>
|
|
108
|
+
<Card title="Spending policy" href="/programs/policy-vault/spending-policy">
|
|
109
|
+
Per-tx, daily (UTC), and weekly (ISO Monday) limits with anchor-rollover math.
|
|
110
|
+
</Card>
|
|
111
|
+
<Card title="Velocity policy" href="/programs/policy-vault/velocity-policy">
|
|
112
|
+
Sliding-window cumulative-spend counter with payer-tier-decayed window size.
|
|
113
|
+
</Card>
|
|
114
|
+
<Card title="Atomic-tx invariant" href="/verification/atomic-tx-invariant">
|
|
115
|
+
The strict variant is the on-chain half of the three-layer atomicity guard.
|
|
116
|
+
</Card>
|
|
117
|
+
</Cards>
|
|
@@ -1,15 +1,87 @@
|
|
|
1
1
|
---
|
|
2
|
-
title:
|
|
3
|
-
description: Quantu AtomStats
|
|
2
|
+
title: CounterpartyTier policy
|
|
3
|
+
description: Read Quantu's AtomStats by byte offset and gate the payment on tier, risk, and confidence — no Cargo dep on Quantu's crate.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
`
|
|
6
|
+
CounterpartyTier is the wedge. It reads the payee's `AtomStats` PDA (Quantu's `atom-engine` program) through a manual byte-offset parser, then checks `trust_tier`, `risk_score`, and `confidence` against the policy's thresholds.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Manual parsing — not Borsh deserialization through Quantu's crate. The parser is pinned to commit `bfb09ad` and includes a schema-version canary at byte 560 that fails loud rather than silently misreading fields if Quantu bumps its layout.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
| --- | --- |
|
|
12
|
-
| evaluator | [`programs/policy-vault/src/policies/counterparty_tier.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/policy-vault/src/policies/counterparty_tier.rs) |
|
|
13
|
-
| AtomStats parser | [`programs/policy-vault/src/ext/atom_engine.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/policy-vault/src/ext/atom_engine.rs) |
|
|
14
|
-
| proof | [`programs/policy-vault/src/proofs/inv_counterparty_tier_monotone.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/policy-vault/src/proofs/inv_counterparty_tier_monotone.rs) |
|
|
10
|
+
Source: [`programs/policy-vault/src/policies/counterparty_tier.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/policy-vault/src/policies/counterparty_tier.rs). Parser: [`programs/policy-vault/src/ext/atom_engine.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/policy-vault/src/ext/atom_engine.rs).
|
|
15
11
|
|
|
12
|
+
## Reads from `AtomStats`
|
|
13
|
+
|
|
14
|
+
| Offset | Width | Field | Notes |
|
|
15
|
+
|---:|---:|---|---|
|
|
16
|
+
| `549` | u8 | `risk_score` | 0..=255 — lower is better |
|
|
17
|
+
| `551` | u8 | `tier_immediate` | v1 demo default; 0..=4 |
|
|
18
|
+
| `555` | u8 | `tier_confirmed` | post-vesting; production mode preferred |
|
|
19
|
+
| `557` | u16 LE | `confidence` | basis points 0..=10000 |
|
|
20
|
+
| `560` | u8 | `schema_version` | canary — must equal 1 |
|
|
21
|
+
|
|
22
|
+
Account size canary: `ATOM_STATS_SIZE = 561`. Account-data-relative (the 8-byte Borsh discriminator at 0..8 is verified via owner + schema check, not by re-parsing).
|
|
23
|
+
|
|
24
|
+
`ATOM_TIER_MAX = 4`. A tier byte above 4 — with `schema_version == 1` — implies tampering or an undeclared spec change; the parser fails with `AtomStatsSchemaMismatch` rather than silently clamp. Same fail-loud rule for `tier_confirmed`.
|
|
25
|
+
|
|
26
|
+
Quantu pinned program ID (devnet): `AToMufS4QD6hEXvcvBDg9m1AHeCLpmZQsyfYa5h9MwAF`. Mainnet: [Reference → Mainnet program IDs](/reference/mainnet-program-ids).
|
|
27
|
+
|
|
28
|
+
## Policy state (subset of `PolicyAccount`)
|
|
29
|
+
|
|
30
|
+
```rust
|
|
31
|
+
pub gate_mode: u8, // off 49 — GATE_MODE_IMMEDIATE | _CONFIRMED
|
|
32
|
+
pub min_counterparty_tier: u8, // off 130
|
|
33
|
+
pub max_risk_score: u8, // off 131 — 255 = no constraint
|
|
34
|
+
pub min_confidence: u16, // off 132..134 — 0..=10000; 0 = no constraint
|
|
35
|
+
pub default_unrated_treatment: u8, // off 134 — UNRATED_DENY | _ALLOW | _REQUIRE_VALIDATION
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`gate_mode` selects which tier byte is checked. `GATE_MODE_IMMEDIATE` reads byte 551 (the v1 demo default — fast Quantu fast-path tier). `GATE_MODE_CONFIRMED` reads byte 555 (post-vesting; production policies prefer this). Any other byte falls back to `tier_confirmed` — the conservative choice if `gate_mode` is corrupted.
|
|
39
|
+
|
|
40
|
+
## Decision
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
1. view = parse(atom_stats_account)
|
|
44
|
+
2. view == None → Unrated → composer applies default_unrated_treatment
|
|
45
|
+
3. tier < min_tier → Deny(CounterpartyTierBelowMin) code 6
|
|
46
|
+
4. max_risk_score < 255 AND view.risk_score > max_risk_score
|
|
47
|
+
→ Deny(CounterpartyRiskAboveMax) code 7
|
|
48
|
+
5. min_confidence > 0 AND view.confidence < min_confidence
|
|
49
|
+
→ Deny(CounterpartyConfidenceBelow) code 8
|
|
50
|
+
6. else → Allow
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The risk constraint is disabled when `max_risk_score == 255` (sentinel). The confidence constraint is disabled when `min_confidence == 0`. Both let a policy elect tier-only gating without touching the other fields.
|
|
54
|
+
|
|
55
|
+
## Unrated resolution
|
|
56
|
+
|
|
57
|
+
When the payee's `AtomStats` PDA is uninitialised (no rent or empty data), the parser returns `None` and the policy returns `Unrated`. The composer maps `Unrated` to one of three resolutions per `default_unrated_treatment`:
|
|
58
|
+
|
|
59
|
+
| Treatment | Constant | Composer maps to |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| `UNRATED_DENY` (default, byte `0`) | `0` | `Deny(UnratedTreatmentDeny)` — code 15 |
|
|
62
|
+
| `UNRATED_ALLOW` | `1` | `Allow` — proceed |
|
|
63
|
+
| `UNRATED_REQUIRE_VALIDATION` | `2` | `RequireValidation(capability_hash)` — facilitator routes user to attestation flow |
|
|
64
|
+
|
|
65
|
+
Unrecognised bytes fall through to `Deny` — the safe landing if on-chain corruption ever yields a value outside the documented range.
|
|
66
|
+
|
|
67
|
+
## Defensive failures (codes 9 / 10)
|
|
68
|
+
|
|
69
|
+
The parser also surfaces two defensive denials independent of policy thresholds:
|
|
70
|
+
|
|
71
|
+
- `AtomStatsWrongOwner` (code 9) — the PDA's owner is not Quantu's `atom-engine` program. Rejected via `require_keys_eq!` against the pinned `ATOM_ENGINE_ID`.
|
|
72
|
+
- `AtomStatsSchemaMismatch` (code 10) — size mismatch (`!= 561`), schema-version canary mismatch (`byte 560 != 1`), or tier byte above `ATOM_TIER_MAX = 4`.
|
|
73
|
+
|
|
74
|
+
Both are catastrophic-fail signals: a `Deny` here implies bad data, not a normal counterparty failure.
|
|
75
|
+
|
|
76
|
+
## Formal verification
|
|
77
|
+
|
|
78
|
+
- `counterparty_tier_monotone` (Kani #3, 8 sub-checks, 0.02 s) — if a STRICT policy (high `min_counterparty_tier`) produces `Allow` for a given payee, a LOOSER policy (lower or equal `min_tier`) on the same payee must also produce `Allow`. Loosening the tier requirement can never turn an `Allow` into a `Deny`.
|
|
79
|
+
|
|
80
|
+
In-module tests cover gate-mode selection (immediate vs confirmed), risk + confidence boundaries, sentinel disabling, fail-fast ordering (tier before risk before confidence), and unrated resolution for all four `UNRATED_*` values including unknown.
|
|
81
|
+
|
|
82
|
+
## Source
|
|
83
|
+
|
|
84
|
+
- Policy module: [`policies/counterparty_tier.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/policy-vault/src/policies/counterparty_tier.rs)
|
|
85
|
+
- AtomStats parser: [`ext/atom_engine.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/policy-vault/src/ext/atom_engine.rs)
|
|
86
|
+
- Kani proof: [`proofs/inv_counterparty_tier_monotone.rs`](https://github.com/agenttrust-labs/agenttrust/blob/main/programs/policy-vault/src/proofs/inv_counterparty_tier_monotone.rs)
|
|
87
|
+
- Byte-offset table: [Reference → Byte offsets](/reference/byte-offset-reference)
|