@agentauditai/mcp-server 0.0.0-stage → 3.0.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/CHANGELOG.md +37 -0
- package/LICENSE +21 -0
- package/README.md +103 -2
- package/dist/deployments/phase7-arbitrumOne.json +15 -0
- package/dist/deployments/phase7-base.json +15 -0
- package/dist/deployments/phase7-mantle.json +15 -0
- package/dist/deployments/phase7-optimism.json +15 -0
- package/dist/deployments/phase7-polygon.json +15 -0
- package/dist/sdk/src/attribution.d.ts +42 -0
- package/dist/sdk/src/attribution.js +133 -0
- package/dist/sdk/src/batch.d.ts +175 -0
- package/dist/sdk/src/batch.js +370 -0
- package/dist/sdk/src/index.d.ts +365 -0
- package/dist/sdk/src/index.js +576 -0
- package/dist/src/mcp-server.d.ts +25 -0
- package/dist/src/mcp-server.js +541 -0
- package/dist/tools/verify/src/evidence.d.ts +23 -0
- package/dist/tools/verify/src/evidence.js +152 -0
- package/dist/tools/verify/src/verify.d.ts +58 -0
- package/dist/tools/verify/src/verify.js +312 -0
- package/package.json +36 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Changelog — @agentauditai/mcp-server
|
|
2
|
+
|
|
3
|
+
All notable changes to this package. Versions follow [SemVer](https://semver.org/).
|
|
4
|
+
|
|
5
|
+
## 3.0.0 — 2026-11-08
|
|
6
|
+
|
|
7
|
+
AgentAudit provides evidence, not certification. This release removes every tool
|
|
8
|
+
output that read as a compliance verdict.
|
|
9
|
+
|
|
10
|
+
### Breaking
|
|
11
|
+
- **`check_conformity` removed.** The server no longer reads ConformityAssessment.
|
|
12
|
+
The deployed contract is unchanged; read it directly if you need the record.
|
|
13
|
+
- **Evidence report output changed.** The ConformityAssessment section is gone and
|
|
14
|
+
the report lists on-chain records with a disclaimer instead of a verdict.
|
|
15
|
+
- **`report_incident` no longer prints a reporting deadline.** Deadlines depend on
|
|
16
|
+
the type of incident; confirm them with your legal team. The tool states that it
|
|
17
|
+
creates an on-chain record, not a report to an authority.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
- `get_evidence_report`. `get_compliance_report` stays as a deprecated alias and
|
|
21
|
+
will be removed in a future major version.
|
|
22
|
+
- **Base Builder Code attribution (ERC-8021), on by default** for `audit_action`
|
|
23
|
+
and `report_incident`, on Base (8453) and Base Sepolia (84532) only. Appends a
|
|
24
|
+
29-byte suffix for `bc_pd681w25`; evidence bytes are unchanged, only the tx hash
|
|
25
|
+
differs. Turn it off with `AGENTAUDIT_BUILDER_CODE=false` (also `off`, `0`), or
|
|
26
|
+
set your own code. An invalid value stops the server at startup.
|
|
27
|
+
- "Not legal advice." in evidence and incident tool descriptions and output.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
- MCP handshake version `3.0.0`.
|
|
31
|
+
- `CHANGELOG.md` now ships in the package.
|
|
32
|
+
|
|
33
|
+
## 2.0.0 — 2026-10-30
|
|
34
|
+
|
|
35
|
+
First npm release: `audit_action` (AuditVault v2 `commitBatch` on Base),
|
|
36
|
+
`get_audit_log`, `verify_proof`, `report_incident` (IncidentRegistry v2, 5
|
|
37
|
+
networks), `get_compliance_report`, `get_risk_score`, `check_conformity`.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 agentauditAI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,104 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @agentauditai/mcp-server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
MCP (Model Context Protocol) server for [AgentAudit](https://github.com/agentauditAI/AgentAudit): on-chain audit logging and incident records for AI agents, providing evidence that supports EU AI Act record-keeping. It does not determine whether any legal obligation is satisfied. Works with Claude, Cursor and any MCP client over stdio.
|
|
4
|
+
|
|
5
|
+
| What | Where it is live |
|
|
6
|
+
|---|---|
|
|
7
|
+
| Audit logging: `audit_action`, `get_audit_log`, `verify_proof` (AuditVault v2, Art. 12, 19) | **Base only**: AuditVault v2 `0xCeE831070aa9081422f30df5559c125aa47A75DB` |
|
|
8
|
+
| Incident records: `report_incident` (IncidentRegistry v2, related to Art. 73) | **5 networks**: mantle, base, arbitrum, optimism, polygon |
|
|
9
|
+
| Evidence reads: `get_evidence_report`, `get_risk_score` (related to Art. 9, 73) | mantle, base, arbitrum, optimism, polygon |
|
|
10
|
+
|
|
11
|
+
## Install and run
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx -y @agentauditai/mcp-server # starts the stdio server (bin: agentaudit-mcp)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The package is compiled JavaScript and needs Node.js 18 or newer; it does not use ts-node at runtime.
|
|
18
|
+
|
|
19
|
+
Example MCP client config:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"mcpServers": {
|
|
24
|
+
"agentaudit": {
|
|
25
|
+
"command": "npx",
|
|
26
|
+
"args": ["-y", "@agentauditai/mcp-server"],
|
|
27
|
+
"env": { "PRIVATE_KEY": "0x…", "RPC_BASE": "https://…" }
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Environment variables
|
|
34
|
+
|
|
35
|
+
| Variable | Used by | Notes |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| `PRIVATE_KEY` | `audit_action`, `report_incident` | Signer for write tools. Not needed for read tools. Never commit it. |
|
|
38
|
+
| `RPC_MANTLE`, `RPC_BASE`, `RPC_ARBITRUM`, `RPC_OPTIMISM`, `RPC_POLYGON` | all tools | Optional RPC overrides; public RPCs are used by default |
|
|
39
|
+
| `AUDIT_VAULT_<NETWORK>` | `audit_action`, `get_audit_log`, `verify_proof` | Points a network at an AuditVault v2 deployment. Without it, every network except Base returns an error. |
|
|
40
|
+
| `AGENTAUDIT_BUILDER_CODE` | `audit_action`, `report_incident` | Base Builder Code attribution, on Base / Base Sepolia only. Unset or empty: AgentAudit's code `bc_pd681w25`. `false`, `off` or `0` (any case): no suffix. Any other value: your own code. See below. |
|
|
41
|
+
|
|
42
|
+
The server also loads a `.env` file from the working directory (dotenv). Variables already set in the environment take precedence.
|
|
43
|
+
|
|
44
|
+
## Tools
|
|
45
|
+
|
|
46
|
+
### `audit_action` (write, Base)
|
|
47
|
+
|
|
48
|
+
Anchors one or more agent actions in **one** `commitBatch` transaction on AuditVault v2. Each call commits immediately; nothing is buffered between calls, so a restart cannot lose entries.
|
|
49
|
+
|
|
50
|
+
- Input: `agent_id`, `entries[]` (`action_type`, `payload`, optional `risk_level` default `HIGH`, optional `timestamp_ms`), optional `agent_address` (defaults to the signer), `compliance_score` (0–100), `network` (default `base`).
|
|
51
|
+
- Payloads are SHA-256 hashed (JCS for objects). Raw content never leaves the process. Each entry becomes an Evidence Schema v1 preimage with scope `agent_action:mcp:record_hash:<sha256>`.
|
|
52
|
+
- Returns `txHash`, `batchIndex`, `merkle_root`, each entry's `action_ref` + `proof`, and the full evidence bundle. **Keep the bundle**: the batch payload is not stored anywhere else (`contentURI` is `memory://<root>`).
|
|
53
|
+
- Errors (never a silent skip): the network has no AuditVault v2, the vault has no code, or the transaction emitted no `LogBatchCommitted` for the root.
|
|
54
|
+
|
|
55
|
+
### `get_audit_log` (read, Base)
|
|
56
|
+
|
|
57
|
+
Reads committed batches, either by `tx_hash` or by `agent_address` + `batch_index`. Returns the root, contentURI, event count, compliance score, submitter, timestamp and block.
|
|
58
|
+
|
|
59
|
+
### `verify_proof` (read, Base)
|
|
60
|
+
|
|
61
|
+
Checks one entry's inclusion proof with AuditVault v2 `verifyLog`. The leaf is always recomputed from the preimage, never taken from the caller (KI-2). Returns `valid`, the batch `submitter` and per-check results. Pass `expected_submitter` to pin the submitter (see the caveat below).
|
|
62
|
+
|
|
63
|
+
### `report_incident` (write, 5 networks)
|
|
64
|
+
|
|
65
|
+
Records a serious incident on IncidentRegistry v2 (related to Art. 73). This is an on-chain record, not a report to any authority. Before sending, it checks the registry has code. After mining, it requires an `IncidentRegistered` event from the registry address; otherwise it returns an error and never reports success. It does not calculate reporting deadlines: they depend on the type of incident, so confirm them with your legal team.
|
|
66
|
+
|
|
67
|
+
### `get_evidence_report`, `get_risk_score` (read)
|
|
68
|
+
|
|
69
|
+
Read the Phase 7 contracts: RiskManagementSystem (related to Art. 9) and IncidentRegistry (related to Art. 73). If a contract has no code on the selected network, the tool returns an error naming the network and address.
|
|
70
|
+
|
|
71
|
+
These tools list on-chain records. They do not determine whether any obligation under the EU AI Act or any other law is satisfied.
|
|
72
|
+
|
|
73
|
+
`get_compliance_report` is a deprecated alias of `get_evidence_report` and will be removed in a future major version.
|
|
74
|
+
|
|
75
|
+
## Evidence, not certification
|
|
76
|
+
|
|
77
|
+
AgentAudit provides on-chain evidence. It does not certify AI systems, issue conformity assessments or replace an assessment under the EU AI Act. `check_conformity` was removed for this reason.
|
|
78
|
+
|
|
79
|
+
## Base Builder Code attribution
|
|
80
|
+
|
|
81
|
+
On **Base mainnet (8453) and Base Sepolia (84532) only**, the write tools (`audit_action`,
|
|
82
|
+
`report_incident`) append a [Base Builder Code](https://docs.base.org/base-chain/builder-codes/builder-codes)
|
|
83
|
+
suffix (ERC-8021, schema 0) to their transaction calldata. It is on by default with
|
|
84
|
+
AgentAudit's code `bc_pd681w25`, so Base can attribute these transactions to AgentAudit.
|
|
85
|
+
|
|
86
|
+
- **What is appended:** 29 bytes, `0x62635f70643638317732350b0080218021802180218021802180218021`
|
|
87
|
+
(`"bc_pd681w25"`, length `0x0b`, schema `0x00`, then the marker `0x8021` × 8).
|
|
88
|
+
- **What stays the same:** the contracts ignore the suffix, so events and state are
|
|
89
|
+
identical, and no evidence changes (`action_ref`, Merkle root, bundle). Only the tx hash differs.
|
|
90
|
+
- **The code is public** on-chain. The chain is read from the RPC (`eth_chainId`);
|
|
91
|
+
other chains never get a suffix.
|
|
92
|
+
- **Turn it off:** `AGENTAUDIT_BUILDER_CODE=false`. **Use your own code:**
|
|
93
|
+
`AGENTAUDIT_BUILDER_CODE=bc_yourcode` (ERC-8021 rules: 7-bit ASCII, no comma, ≤ 255 bytes;
|
|
94
|
+
an invalid value stops the server at startup).
|
|
95
|
+
|
|
96
|
+
## Caveat: AuditVault v2 does not authenticate submitters
|
|
97
|
+
|
|
98
|
+
`commitBatch` on AuditVault v2 has no access control. **Anyone can commit a batch under any agent address.** A batch existing under an agent address therefore does not prove that agent's operator committed it, and batch counts can be inflated by third parties ([THREAT_MODEL KI-1](https://github.com/agentauditAI/AgentAudit/blob/main/docs/THREAT_MODEL.md)).
|
|
99
|
+
|
|
100
|
+
When you verify, check the batch `submitter`: `get_audit_log` and `verify_proof` both return it, and `verify_proof` takes `expected_submitter` to enforce it. Accept a batch only if the submitter is an address you have authorized for that agent. For full bundles, the `agentaudit-verify` CLI in the repo does the same with `--submitter`.
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
MIT
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"network": "arbitrumOne",
|
|
3
|
+
"chainId": "42161",
|
|
4
|
+
"deployedAt": "2026-05-18T19:23:02.624Z",
|
|
5
|
+
"deployer": "0x218514Db9048AB350fA61Ef891ee20947c5Bbf8F",
|
|
6
|
+
"contracts": {
|
|
7
|
+
"AIBOMRegistry": "0x6B5BebC2f9172c6E17Df5ea59C1753D360866bDB",
|
|
8
|
+
"RiskManagementSystem": "0x9683C026434Ff9C0Ee036d655686Be5BD3F52331",
|
|
9
|
+
"HumanOversightRegistry": "0x291FE7352698CDBf6816A3F61CbF14b52D6a402b",
|
|
10
|
+
"IncidentRegistry": "0x6ad45a9B32e695e95492dC3796a5aC8543B2EA6F",
|
|
11
|
+
"ConformityAssessment": "0x976b03a2417cf7926813605F427ED499fdF61e10",
|
|
12
|
+
"DataGovernanceRegistry": "0xEb284d8aB1360082272FA9C860a0640B13af036E",
|
|
13
|
+
"QualityManagementSystem": "0xfCB684CDeC451Da0bA93B8F05215Ee49a9402210"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"network": "base",
|
|
3
|
+
"chainId": "8453",
|
|
4
|
+
"deployedAt": "2026-05-18T19:22:22.838Z",
|
|
5
|
+
"deployer": "0x218514Db9048AB350fA61Ef891ee20947c5Bbf8F",
|
|
6
|
+
"contracts": {
|
|
7
|
+
"AIBOMRegistry": "0x6B5BebC2f9172c6E17Df5ea59C1753D360866bDB",
|
|
8
|
+
"RiskManagementSystem": "0x9683C026434Ff9C0Ee036d655686Be5BD3F52331",
|
|
9
|
+
"HumanOversightRegistry": "0x291FE7352698CDBf6816A3F61CbF14b52D6a402b",
|
|
10
|
+
"IncidentRegistry": "0x6ad45a9B32e695e95492dC3796a5aC8543B2EA6F",
|
|
11
|
+
"ConformityAssessment": "0x976b03a2417cf7926813605F427ED499fdF61e10",
|
|
12
|
+
"DataGovernanceRegistry": "0xEb284d8aB1360082272FA9C860a0640B13af036E",
|
|
13
|
+
"QualityManagementSystem": "0xfCB684CDeC451Da0bA93B8F05215Ee49a9402210"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"network": "mantle",
|
|
3
|
+
"chainId": "5000",
|
|
4
|
+
"deployedAt": "2026-05-18T19:22:09.579Z",
|
|
5
|
+
"deployer": "0x218514Db9048AB350fA61Ef891ee20947c5Bbf8F",
|
|
6
|
+
"contracts": {
|
|
7
|
+
"AIBOMRegistry": "0x6B5BebC2f9172c6E17Df5ea59C1753D360866bDB",
|
|
8
|
+
"RiskManagementSystem": "0x9683C026434Ff9C0Ee036d655686Be5BD3F52331",
|
|
9
|
+
"HumanOversightRegistry": "0x291FE7352698CDBf6816A3F61CbF14b52D6a402b",
|
|
10
|
+
"IncidentRegistry": "0x6ad45a9B32e695e95492dC3796a5aC8543B2EA6F",
|
|
11
|
+
"ConformityAssessment": "0x976b03a2417cf7926813605F427ED499fdF61e10",
|
|
12
|
+
"DataGovernanceRegistry": "0xEb284d8aB1360082272FA9C860a0640B13af036E",
|
|
13
|
+
"QualityManagementSystem": "0xfCB684CDeC451Da0bA93B8F05215Ee49a9402210"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"network": "optimism",
|
|
3
|
+
"chainId": "10",
|
|
4
|
+
"deployedAt": "2026-05-18T19:24:39.428Z",
|
|
5
|
+
"deployer": "0x218514Db9048AB350fA61Ef891ee20947c5Bbf8F",
|
|
6
|
+
"contracts": {
|
|
7
|
+
"AIBOMRegistry": "0x9683C026434Ff9C0Ee036d655686Be5BD3F52331",
|
|
8
|
+
"RiskManagementSystem": "0x291FE7352698CDBf6816A3F61CbF14b52D6a402b",
|
|
9
|
+
"HumanOversightRegistry": "0x6ad45a9B32e695e95492dC3796a5aC8543B2EA6F",
|
|
10
|
+
"IncidentRegistry": "0x976b03a2417cf7926813605F427ED499fdF61e10",
|
|
11
|
+
"ConformityAssessment": "0xEb284d8aB1360082272FA9C860a0640B13af036E",
|
|
12
|
+
"DataGovernanceRegistry": "0xfCB684CDeC451Da0bA93B8F05215Ee49a9402210",
|
|
13
|
+
"QualityManagementSystem": "0xCeE831070aa9081422f30df5559c125aa47A75DB"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"network": "polygon",
|
|
3
|
+
"chainId": "137",
|
|
4
|
+
"deployedAt": "2026-05-18T19:24:57.683Z",
|
|
5
|
+
"deployer": "0x218514Db9048AB350fA61Ef891ee20947c5Bbf8F",
|
|
6
|
+
"contracts": {
|
|
7
|
+
"AIBOMRegistry": "0x6B5BebC2f9172c6E17Df5ea59C1753D360866bDB",
|
|
8
|
+
"RiskManagementSystem": "0x9683C026434Ff9C0Ee036d655686Be5BD3F52331",
|
|
9
|
+
"HumanOversightRegistry": "0x291FE7352698CDBf6816A3F61CbF14b52D6a402b",
|
|
10
|
+
"IncidentRegistry": "0x6ad45a9B32e695e95492dC3796a5aC8543B2EA6F",
|
|
11
|
+
"ConformityAssessment": "0x976b03a2417cf7926813605F427ED499fdF61e10",
|
|
12
|
+
"DataGovernanceRegistry": "0xEb284d8aB1360082272FA9C860a0640B13af036E",
|
|
13
|
+
"QualityManagementSystem": "0xfCB684CDeC451Da0bA93B8F05215Ee49a9402210"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ethers } from "ethers";
|
|
2
|
+
/** AgentAudit's Base Builder Code, used unless the integrator passes `builderCode`. */
|
|
3
|
+
export declare const AGENTAUDIT_BUILDER_CODE = "bc_pd681w25";
|
|
4
|
+
/** Chains on which the suffix is appended: Base mainnet and Base Sepolia. */
|
|
5
|
+
export declare const BUILDER_CODE_CHAIN_IDS: readonly bigint[];
|
|
6
|
+
/** ERC-8021 marker: 0x8021 repeated 8 times (16 bytes), at the very end of the calldata. */
|
|
7
|
+
export declare const ERC8021_MARKER = "0x80218021802180218021802180218021";
|
|
8
|
+
/**
|
|
9
|
+
* Checks a code against the ERC-8021 rules: non-empty, 7-bit ASCII, no comma
|
|
10
|
+
* (0x2C, the delimiter), at most 255 bytes. Returns the code unchanged.
|
|
11
|
+
*/
|
|
12
|
+
export declare function validateBuilderCode(code: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* ERC-8021 schema-0 data suffix: `codes ‖ codesLength (1 B) ‖ schemaId 0x00 ‖ 0x8021×8`,
|
|
15
|
+
* where `codes` is the ASCII codes joined by commas.
|
|
16
|
+
*/
|
|
17
|
+
export declare function erc8021DataSuffix(codes: readonly string[]): string;
|
|
18
|
+
/**
|
|
19
|
+
* Resolves the `builderCode` option: `undefined` → AgentAudit's code,
|
|
20
|
+
* `false` → no attribution (`null`), a string → that code (validated).
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveBuilderCode(option: string | false | undefined): string | null;
|
|
23
|
+
/**
|
|
24
|
+
* Reads AGENTAUDIT_BUILDER_CODE semantics: unset or "" → `undefined` (default, on);
|
|
25
|
+
* "false" / "off" / "0" (any case) → `false`; anything else → that string, to be
|
|
26
|
+
* validated by `resolveBuilderCode`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function builderCodeFromEnv(value: string | undefined): string | false | undefined;
|
|
29
|
+
/** The suffix for `chainId`: the code's ERC-8021 suffix on Base / Base Sepolia, else "0x". */
|
|
30
|
+
export declare function attributionSuffix(code: string | null, chainId: bigint): string;
|
|
31
|
+
/**
|
|
32
|
+
* The chain id the RPC actually reports (`provider.getNetwork()`), cached per
|
|
33
|
+
* provider. A failed lookup is not cached. The configured network name is never used.
|
|
34
|
+
*/
|
|
35
|
+
export declare function providerChainId(provider: ethers.Provider): Promise<bigint>;
|
|
36
|
+
/**
|
|
37
|
+
* Sends `contract.method(...args)` like ethers' own contract call, with the
|
|
38
|
+
* attribution suffix appended to the calldata when it applies. The signer
|
|
39
|
+
* populates the final transaction, so gas is estimated on the calldata incl.
|
|
40
|
+
* the suffix. Returns the same `ContractTransactionResponse` ethers would.
|
|
41
|
+
*/
|
|
42
|
+
export declare function sendAttributed(contract: ethers.Contract, method: string, args: readonly unknown[], builderCode: string | null): Promise<ethers.ContractTransactionResponse>;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Base Builder Code attribution (ERC-8021 schema 0) for AgentAudit contract calls.
|
|
3
|
+
//
|
|
4
|
+
// What: a 29-byte suffix appended to the calldata of the SDK's own contract
|
|
5
|
+
// calls, on Base mainnet (8453) and Base Sepolia (84532) only. Contracts ignore
|
|
6
|
+
// trailing calldata; Base indexers read the code from the end of the calldata.
|
|
7
|
+
// The code is public on-chain. No audit evidence changes: action_ref, Merkle
|
|
8
|
+
// root, scope, contentURI and payload hashes are computed before the call is
|
|
9
|
+
// ABI-encoded, and the suffix goes after the encoding (only the tx hash differs).
|
|
10
|
+
//
|
|
11
|
+
// Opt out: `builderCode: false` (SDK) / AGENTAUDIT_BUILDER_CODE=false (MCP).
|
|
12
|
+
// Own code: `builderCode: "<your code>"`. See README "Base Builder Code attribution".
|
|
13
|
+
//
|
|
14
|
+
// The encoding is implemented here (no runtime dependency); test/sdk/attribution.test.ts
|
|
15
|
+
// checks it byte for byte against the ERC-8021 test vector and against `ox/erc8021`.
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.ERC8021_MARKER = exports.BUILDER_CODE_CHAIN_IDS = exports.AGENTAUDIT_BUILDER_CODE = void 0;
|
|
18
|
+
exports.validateBuilderCode = validateBuilderCode;
|
|
19
|
+
exports.erc8021DataSuffix = erc8021DataSuffix;
|
|
20
|
+
exports.resolveBuilderCode = resolveBuilderCode;
|
|
21
|
+
exports.builderCodeFromEnv = builderCodeFromEnv;
|
|
22
|
+
exports.attributionSuffix = attributionSuffix;
|
|
23
|
+
exports.providerChainId = providerChainId;
|
|
24
|
+
exports.sendAttributed = sendAttributed;
|
|
25
|
+
const ethers_1 = require("ethers");
|
|
26
|
+
/** AgentAudit's Base Builder Code, used unless the integrator passes `builderCode`. */
|
|
27
|
+
exports.AGENTAUDIT_BUILDER_CODE = "bc_pd681w25";
|
|
28
|
+
/** Chains on which the suffix is appended: Base mainnet and Base Sepolia. */
|
|
29
|
+
exports.BUILDER_CODE_CHAIN_IDS = [8453n, 84532n];
|
|
30
|
+
/** ERC-8021 marker: 0x8021 repeated 8 times (16 bytes), at the very end of the calldata. */
|
|
31
|
+
exports.ERC8021_MARKER = "0x80218021802180218021802180218021";
|
|
32
|
+
const SCHEMA_ID_0 = "00";
|
|
33
|
+
const MAX_CODES_LENGTH = 255; // codesLength is a single byte
|
|
34
|
+
/**
|
|
35
|
+
* Checks a code against the ERC-8021 rules: non-empty, 7-bit ASCII, no comma
|
|
36
|
+
* (0x2C, the delimiter), at most 255 bytes. Returns the code unchanged.
|
|
37
|
+
*/
|
|
38
|
+
function validateBuilderCode(code) {
|
|
39
|
+
if (typeof code !== "string" || code.length === 0) {
|
|
40
|
+
throw new Error("Invalid builder code: must be a non-empty string");
|
|
41
|
+
}
|
|
42
|
+
if (!/^[\x00-\x7f]*$/.test(code)) {
|
|
43
|
+
throw new Error(`Invalid builder code ${JSON.stringify(code)}: ERC-8021 codes are 7-bit ASCII`);
|
|
44
|
+
}
|
|
45
|
+
if (code.includes(",")) {
|
|
46
|
+
throw new Error(`Invalid builder code ${JSON.stringify(code)}: ERC-8021 codes must not contain a comma`);
|
|
47
|
+
}
|
|
48
|
+
if (code.length > MAX_CODES_LENGTH) {
|
|
49
|
+
throw new Error(`Invalid builder code: ${code.length} bytes, ERC-8021 allows at most ${MAX_CODES_LENGTH}`);
|
|
50
|
+
}
|
|
51
|
+
return code;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* ERC-8021 schema-0 data suffix: `codes ‖ codesLength (1 B) ‖ schemaId 0x00 ‖ 0x8021×8`,
|
|
55
|
+
* where `codes` is the ASCII codes joined by commas.
|
|
56
|
+
*/
|
|
57
|
+
function erc8021DataSuffix(codes) {
|
|
58
|
+
if (codes.length === 0)
|
|
59
|
+
throw new Error("ERC-8021 suffix needs at least one code");
|
|
60
|
+
const joined = codes.map(validateBuilderCode).join(",");
|
|
61
|
+
if (joined.length > MAX_CODES_LENGTH) {
|
|
62
|
+
throw new Error(`ERC-8021 codes are ${joined.length} bytes with delimiters; at most ${MAX_CODES_LENGTH} allowed`);
|
|
63
|
+
}
|
|
64
|
+
const lengthByte = joined.length.toString(16).padStart(2, "0");
|
|
65
|
+
return ethers_1.ethers.hexlify(ethers_1.ethers.toUtf8Bytes(joined)) + lengthByte + SCHEMA_ID_0 + exports.ERC8021_MARKER.slice(2);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Resolves the `builderCode` option: `undefined` → AgentAudit's code,
|
|
69
|
+
* `false` → no attribution (`null`), a string → that code (validated).
|
|
70
|
+
*/
|
|
71
|
+
function resolveBuilderCode(option) {
|
|
72
|
+
if (option === undefined)
|
|
73
|
+
return exports.AGENTAUDIT_BUILDER_CODE;
|
|
74
|
+
if (option === false)
|
|
75
|
+
return null;
|
|
76
|
+
if (typeof option !== "string") {
|
|
77
|
+
throw new Error("builderCode must be a string, false, or omitted");
|
|
78
|
+
}
|
|
79
|
+
return validateBuilderCode(option);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Reads AGENTAUDIT_BUILDER_CODE semantics: unset or "" → `undefined` (default, on);
|
|
83
|
+
* "false" / "off" / "0" (any case) → `false`; anything else → that string, to be
|
|
84
|
+
* validated by `resolveBuilderCode`.
|
|
85
|
+
*/
|
|
86
|
+
function builderCodeFromEnv(value) {
|
|
87
|
+
const v = value?.trim();
|
|
88
|
+
if (!v)
|
|
89
|
+
return undefined;
|
|
90
|
+
if (/^(false|off|0)$/i.test(v))
|
|
91
|
+
return false;
|
|
92
|
+
return v;
|
|
93
|
+
}
|
|
94
|
+
/** The suffix for `chainId`: the code's ERC-8021 suffix on Base / Base Sepolia, else "0x". */
|
|
95
|
+
function attributionSuffix(code, chainId) {
|
|
96
|
+
if (code === null || !exports.BUILDER_CODE_CHAIN_IDS.includes(chainId))
|
|
97
|
+
return "0x";
|
|
98
|
+
return erc8021DataSuffix([code]);
|
|
99
|
+
}
|
|
100
|
+
const chainIds = new WeakMap();
|
|
101
|
+
/**
|
|
102
|
+
* The chain id the RPC actually reports (`provider.getNetwork()`), cached per
|
|
103
|
+
* provider. A failed lookup is not cached. The configured network name is never used.
|
|
104
|
+
*/
|
|
105
|
+
function providerChainId(provider) {
|
|
106
|
+
let p = chainIds.get(provider);
|
|
107
|
+
if (!p) {
|
|
108
|
+
p = provider.getNetwork().then((n) => n.chainId);
|
|
109
|
+
p.catch(() => chainIds.delete(provider));
|
|
110
|
+
chainIds.set(provider, p);
|
|
111
|
+
}
|
|
112
|
+
return p;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Sends `contract.method(...args)` like ethers' own contract call, with the
|
|
116
|
+
* attribution suffix appended to the calldata when it applies. The signer
|
|
117
|
+
* populates the final transaction, so gas is estimated on the calldata incl.
|
|
118
|
+
* the suffix. Returns the same `ContractTransactionResponse` ethers would.
|
|
119
|
+
*/
|
|
120
|
+
async function sendAttributed(contract, method, args, builderCode) {
|
|
121
|
+
const signer = contract.runner;
|
|
122
|
+
if (!signer || typeof signer.sendTransaction !== "function" || !signer.provider) {
|
|
123
|
+
throw new Error("sendAttributed needs a contract connected to a signer with a provider");
|
|
124
|
+
}
|
|
125
|
+
const tx = await contract.getFunction(method).populateTransaction(...args);
|
|
126
|
+
if (builderCode !== null) {
|
|
127
|
+
const suffix = attributionSuffix(builderCode, await providerChainId(signer.provider));
|
|
128
|
+
if (suffix !== "0x")
|
|
129
|
+
tx.data = ethers_1.ethers.concat([tx.data, suffix]);
|
|
130
|
+
}
|
|
131
|
+
const sent = await signer.sendTransaction(tx);
|
|
132
|
+
return new ethers_1.ethers.ContractTransactionResponse(contract.interface, signer.provider, sent);
|
|
133
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC 8785 JSON Canonicalization Scheme.
|
|
3
|
+
* Strings and numbers use ECMAScript JSON.stringify serialization (as RFC 8785
|
|
4
|
+
* specifies); object keys are sorted by UTF-16 code units (Array#sort default).
|
|
5
|
+
*/
|
|
6
|
+
export declare function canonicalize(value: unknown): string;
|
|
7
|
+
/** Lowercase hex SHA-256 of the UTF-8 bytes of `value`, no prefix */
|
|
8
|
+
export declare function sha256Hex(value: string): string;
|
|
9
|
+
export declare const EVIDENCE_SCHEMA = "agentaudit-evidence-v1";
|
|
10
|
+
export interface ActionPreimage {
|
|
11
|
+
action_type: string;
|
|
12
|
+
agent_id: string;
|
|
13
|
+
scope: string;
|
|
14
|
+
timestamp_ms: number;
|
|
15
|
+
}
|
|
16
|
+
/** action_ref = SHA-256(JCS(preimage)), as 0x-prefixed bytes32 hex */
|
|
17
|
+
export declare function computeActionRef(preimage: ActionPreimage): string;
|
|
18
|
+
/** Percent-encode the characters that would break a scope segment */
|
|
19
|
+
export declare function encodeScopeSegment(segment: string): string;
|
|
20
|
+
/** §2.1 — tool_call:<tool>:result_hash:<sha256> */
|
|
21
|
+
export declare function toolCallScope(tool: string, resultHash: string): string;
|
|
22
|
+
/** §2.2 — data_read:<endpoint>:<dataset_version>:<result_hash> */
|
|
23
|
+
export declare function dataReadScope(endpoint: string, datasetVersion: string, resultHash: string): string;
|
|
24
|
+
/** §2.3 — llm_call:<model>:record_hash:<sha256(JCS(record))> */
|
|
25
|
+
export declare function llmCallScope(model: string, record: object): string;
|
|
26
|
+
/** Preimage for an LLM decision logged by the SDK wrappers */
|
|
27
|
+
export declare function llmDecisionPreimage(agentId: number | string, model: string, record: object, timestampMs?: number): ActionPreimage;
|
|
28
|
+
export declare function hashPair(a: string, b: string): string;
|
|
29
|
+
/** All tree levels, leaves first, root level last */
|
|
30
|
+
export declare function buildMerkleLevels(leaves: string[]): string[][];
|
|
31
|
+
export declare function merkleRoot(leaves: string[]): string;
|
|
32
|
+
/** Sibling path for leaf `index`; levels where the node was promoted are skipped */
|
|
33
|
+
export declare function merkleProof(levels: string[][], index: number): string[];
|
|
34
|
+
/** Off-chain mirror of AuditVault._verifyMerkle */
|
|
35
|
+
export declare function verifyMerkleProof(leaf: string, proof: string[], root: string): boolean;
|
|
36
|
+
export interface BatchEntry {
|
|
37
|
+
action_ref: string;
|
|
38
|
+
preimage: ActionPreimage;
|
|
39
|
+
/** Hashed audit record the scope commits to — never raw prompt/response content */
|
|
40
|
+
record?: object;
|
|
41
|
+
}
|
|
42
|
+
export interface BatchRecord {
|
|
43
|
+
schema: typeof EVIDENCE_SCHEMA;
|
|
44
|
+
batch_id: string;
|
|
45
|
+
agent_address: string;
|
|
46
|
+
merkle_root: string;
|
|
47
|
+
leaf_hash: "sha256(jcs(preimage))";
|
|
48
|
+
node_hash: "keccak256(sorted_pair)";
|
|
49
|
+
odd_node: "promote";
|
|
50
|
+
created_at_ms: number;
|
|
51
|
+
entries: BatchEntry[];
|
|
52
|
+
}
|
|
53
|
+
export interface BatchStore {
|
|
54
|
+
/** Persist the batch and return the contentURI to anchor on-chain */
|
|
55
|
+
put(record: BatchRecord): Promise<string>;
|
|
56
|
+
get(batchId: string): Promise<BatchRecord | null>;
|
|
57
|
+
}
|
|
58
|
+
export declare class MemoryBatchStore implements BatchStore {
|
|
59
|
+
private readonly records;
|
|
60
|
+
put(record: BatchRecord): Promise<string>;
|
|
61
|
+
get(batchId: string): Promise<BatchRecord | null>;
|
|
62
|
+
}
|
|
63
|
+
/** Writes one JSON file per batch: <dir>/<batch_id>.json */
|
|
64
|
+
export declare class FileBatchStore implements BatchStore {
|
|
65
|
+
private readonly dir;
|
|
66
|
+
constructor(dir: string);
|
|
67
|
+
private file;
|
|
68
|
+
put(record: BatchRecord): Promise<string>;
|
|
69
|
+
get(batchId: string): Promise<BatchRecord | null>;
|
|
70
|
+
}
|
|
71
|
+
export interface CommitBatchParams {
|
|
72
|
+
agentAddress: string;
|
|
73
|
+
merkleRoot: string;
|
|
74
|
+
contentURI: string;
|
|
75
|
+
eventCount: number;
|
|
76
|
+
complianceScore: number;
|
|
77
|
+
}
|
|
78
|
+
export interface CommitBatchResult {
|
|
79
|
+
txHash: string;
|
|
80
|
+
/** Per-agent batch index from LogBatchCommitted; null if not found in receipt */
|
|
81
|
+
batchIndex: number | null;
|
|
82
|
+
}
|
|
83
|
+
/** Anything that can call AuditVault v2 commitBatch — AgentAudit implements it */
|
|
84
|
+
export interface BatchCommitter {
|
|
85
|
+
commitBatch(params: CommitBatchParams): Promise<CommitBatchResult>;
|
|
86
|
+
/** Optional fail-fast check, called before a buffer is built for this committer */
|
|
87
|
+
assertBatchAnchoring?(): void;
|
|
88
|
+
}
|
|
89
|
+
export interface BatchBufferConfig {
|
|
90
|
+
committer: BatchCommitter;
|
|
91
|
+
/** Agent address the batch is committed under (AuditVault v2 keys agents by address) */
|
|
92
|
+
agentAddress: string;
|
|
93
|
+
store?: BatchStore;
|
|
94
|
+
/** Flush when this many entries are buffered (default 50) */
|
|
95
|
+
maxEntries?: number;
|
|
96
|
+
/** Flush this many seconds after the first buffered entry (default 60) */
|
|
97
|
+
maxAgeSeconds?: number;
|
|
98
|
+
/** uint8 0–100 passed to commitBatch (default 0 = not assessed by SDK) */
|
|
99
|
+
complianceScore?: number;
|
|
100
|
+
/** Receives errors from timer-triggered flushes (default console.error) */
|
|
101
|
+
onError?: (err: Error) => void;
|
|
102
|
+
}
|
|
103
|
+
export interface FlushResult {
|
|
104
|
+
batchId: string;
|
|
105
|
+
merkleRoot: string;
|
|
106
|
+
contentURI: string;
|
|
107
|
+
eventCount: number;
|
|
108
|
+
txHash: string;
|
|
109
|
+
batchIndex: number | null;
|
|
110
|
+
}
|
|
111
|
+
export interface InclusionProof {
|
|
112
|
+
leaf: string;
|
|
113
|
+
proof: string[];
|
|
114
|
+
root: string;
|
|
115
|
+
batchId: string;
|
|
116
|
+
/** Pass to AuditVault.verifyLog(agentAddress, batchIndex, leaf, proof) */
|
|
117
|
+
batchIndex: number | null;
|
|
118
|
+
agentAddress: string;
|
|
119
|
+
txHash: string;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Collects action_refs and anchors them as one Merkle root per batch.
|
|
123
|
+
* Flushes on maxEntries, on maxAgeSeconds after the first entry, or on flush().
|
|
124
|
+
* Flushes are serialized; a failed flush re-queues its entries for retry.
|
|
125
|
+
*/
|
|
126
|
+
export declare class BatchBuffer {
|
|
127
|
+
readonly agentAddress: string;
|
|
128
|
+
private readonly committer;
|
|
129
|
+
private readonly store;
|
|
130
|
+
private readonly maxEntries;
|
|
131
|
+
private readonly maxAgeMs;
|
|
132
|
+
private readonly complianceScore;
|
|
133
|
+
private readonly onError;
|
|
134
|
+
private pending;
|
|
135
|
+
private timer?;
|
|
136
|
+
private flushChain;
|
|
137
|
+
private readonly index;
|
|
138
|
+
private readonly batches;
|
|
139
|
+
constructor(config: BatchBufferConfig);
|
|
140
|
+
/** Number of entries waiting for the next flush */
|
|
141
|
+
get size(): number;
|
|
142
|
+
/**
|
|
143
|
+
* Buffer one action. Resolves once buffered — or, if this entry fills the
|
|
144
|
+
* batch, once that flush completes (so commit errors reach the caller).
|
|
145
|
+
*/
|
|
146
|
+
add(preimage: ActionPreimage, record?: object): Promise<{
|
|
147
|
+
actionRef: string;
|
|
148
|
+
}>;
|
|
149
|
+
/** Anchor everything buffered now. Resolves null if there was nothing to flush. */
|
|
150
|
+
flush(): Promise<FlushResult | null>;
|
|
151
|
+
/** Stop the timer and flush whatever is left */
|
|
152
|
+
close(): Promise<FlushResult | null>;
|
|
153
|
+
/** Proof for a committed action_ref; null if unknown or still pending */
|
|
154
|
+
getInclusionProof(actionRef: string): InclusionProof | null;
|
|
155
|
+
private _flush;
|
|
156
|
+
private _armTimer;
|
|
157
|
+
private _clearTimer;
|
|
158
|
+
}
|
|
159
|
+
/** "batch" (default): buffer + commitBatch. "per_action": legacy one tx per call */
|
|
160
|
+
export type AuditMode = "batch" | "per_action";
|
|
161
|
+
export interface BatchOptions {
|
|
162
|
+
/** Share one buffer across several wrappers; other options are then ignored */
|
|
163
|
+
buffer?: BatchBuffer;
|
|
164
|
+
/** Defaults to the SDK signer's address */
|
|
165
|
+
agentAddress?: string;
|
|
166
|
+
store?: BatchStore;
|
|
167
|
+
maxEntries?: number;
|
|
168
|
+
maxAgeSeconds?: number;
|
|
169
|
+
complianceScore?: number;
|
|
170
|
+
onError?: (err: Error) => void;
|
|
171
|
+
}
|
|
172
|
+
/** Build (or reuse) the buffer a wrapper logs into */
|
|
173
|
+
export declare function resolveBatchBuffer(sdk: BatchCommitter & {
|
|
174
|
+
getAddress(): string;
|
|
175
|
+
}, options?: BatchOptions): BatchBuffer;
|