@kya-brasil/agent-tools 0.5.4 → 0.6.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/README.md +3 -1
- package/dist/auth.d.ts +2 -2
- package/dist/auth.js +17 -5
- package/dist/index.d.ts +15 -0
- package/dist/index.js +13 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ Node 18+ (global `fetch`, WebCrypto). ESM.
|
|
|
19
19
|
## Verifier: you receive an action from someone else's agent
|
|
20
20
|
|
|
21
21
|
```ts
|
|
22
|
-
import { createKyaClient, verifyAttestation, verifyCredentialOffline, companyText, signWithECnpj } from "@kya-brasil/agent-tools";
|
|
22
|
+
import { createKyaClient, verifyAttestation, verifyCredentialOffline, companyText, signWithECnpj, hashPaymentRef } from "@kya-brasil/agent-tools";
|
|
23
23
|
|
|
24
24
|
const kya = createKyaClient({ privateKey: process.env.KYA_PAYER_PK as `0x${string}` }); // wallet optional
|
|
25
25
|
|
|
@@ -34,6 +34,8 @@ if (!verdict.allowed) reject(verdict.reason);
|
|
|
34
34
|
await verifyAttestation(verdict); // local Ed25519 check of the issuer's signature
|
|
35
35
|
|
|
36
36
|
// max_per_day: pass your own spent_today; the issuer does not record acts.
|
|
37
|
+
// Payment instrument (card networks, acquirers, D-25): pass the hash of the token reference or PAR you received,
|
|
38
|
+
// never the card number: { payment_network: "visa", payment_ref_sha256: await hashPaymentRef(tokenRef) }
|
|
37
39
|
|
|
38
40
|
const offline = await verifyCredentialOffline(credential); // issuer down: signature + expires_at only,
|
|
39
41
|
// live_status "unknown" (your risk until expires_at)
|
package/dist/auth.d.ts
CHANGED
|
@@ -80,8 +80,8 @@ export interface LocalVerdict {
|
|
|
80
80
|
}
|
|
81
81
|
/**
|
|
82
82
|
* Local evaluation of the reserved mandate fields: actions, max_per_operation, currencies, counterparties
|
|
83
|
-
* (with `*.` wildcards),
|
|
84
|
-
*
|
|
83
|
+
* (with `*.` wildcards), payment_instruments (when you pass payment_ref_sha256), valid_from / valid_until, and
|
|
84
|
+
* max_per_day when you pass spent_today (nobody else counts it: the issuer keeps no record of acts).
|
|
85
85
|
*/
|
|
86
86
|
export declare function checkMandate(mandate: Mandate, q: ActionQuery, now?: Date): LocalVerdict;
|
|
87
87
|
export interface KyaAuth {
|
package/dist/auth.js
CHANGED
|
@@ -73,7 +73,7 @@ export async function signRequest(p) {
|
|
|
73
73
|
headers[KYA_HEADERS.content] = contentSha256;
|
|
74
74
|
return headers;
|
|
75
75
|
}
|
|
76
|
-
const RESERVED = ["actions", "max_per_operation", "max_per_day", "currencies", "counterparties", "valid_from", "valid_until"];
|
|
76
|
+
const RESERVED = ["actions", "max_per_operation", "max_per_day", "currencies", "counterparties", "payment_instruments", "valid_from", "valid_until"];
|
|
77
77
|
function normalizeCounterparty(c) {
|
|
78
78
|
const t = c.trim();
|
|
79
79
|
const digits = t.replace(/\D/g, "");
|
|
@@ -88,8 +88,8 @@ function normalizeCounterparty(c) {
|
|
|
88
88
|
}
|
|
89
89
|
/**
|
|
90
90
|
* Local evaluation of the reserved mandate fields: actions, max_per_operation, currencies, counterparties
|
|
91
|
-
* (with `*.` wildcards),
|
|
92
|
-
*
|
|
91
|
+
* (with `*.` wildcards), payment_instruments (when you pass payment_ref_sha256), valid_from / valid_until, and
|
|
92
|
+
* max_per_day when you pass spent_today (nobody else counts it: the issuer keeps no record of acts).
|
|
93
93
|
*/
|
|
94
94
|
export function checkMandate(mandate, q, now = new Date()) {
|
|
95
95
|
const checks = [];
|
|
@@ -116,9 +116,21 @@ export function checkMandate(mandate, q, now = new Date()) {
|
|
|
116
116
|
});
|
|
117
117
|
push("counterparties", ok, `${c} ${ok ? "is" : "is not"} an allowed counterparty`);
|
|
118
118
|
}
|
|
119
|
+
if (mandate.max_per_day && q.amount !== undefined && q.spent_today !== undefined) {
|
|
120
|
+
const total = q.amount + q.spent_today;
|
|
121
|
+
const same = !q.currency || q.currency.toUpperCase() === mandate.max_per_day.currency;
|
|
122
|
+
push("max_per_day", same && total <= mandate.max_per_day.amount, same ? `${total} today (incl. this one) vs ceiling ${mandate.max_per_day.amount} ${mandate.max_per_day.currency}` : `ceiling is in ${mandate.max_per_day.currency}, operation in ${q.currency}`);
|
|
123
|
+
}
|
|
124
|
+
const instruments = Array.isArray(mandate.payment_instruments) ? mandate.payment_instruments : [];
|
|
125
|
+
if (instruments.length && q.payment_ref_sha256) {
|
|
126
|
+
const h = q.payment_ref_sha256.trim().toLowerCase();
|
|
127
|
+
const net = q.payment_network?.trim().toLowerCase();
|
|
128
|
+
const hit = instruments.find((p) => p.ref_sha256 === h && (!net || p.network === net));
|
|
129
|
+
push("payment_instruments", !!hit, hit ? `${hit.network} instrument ${h.slice(0, 12)}… is authorized` : `instrument ${net ? `${net} ` : ""}${h.slice(0, 12)}… is not in the mandate`);
|
|
130
|
+
}
|
|
119
131
|
const not_evaluated = Object.keys(mandate).filter((k) => !RESERVED.includes(k));
|
|
120
|
-
if (mandate.max_per_day)
|
|
121
|
-
not_evaluated.push("max_per_day (
|
|
132
|
+
if (mandate.max_per_day && q.spent_today === undefined)
|
|
133
|
+
not_evaluated.push("max_per_day (pass spent_today: the issuer keeps no record of acts)");
|
|
122
134
|
return { allowed: checks.every((c) => c.ok), checks, not_evaluated };
|
|
123
135
|
}
|
|
124
136
|
const headerOf = (headers, name) => {
|
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,12 @@ export interface Mandate {
|
|
|
27
27
|
};
|
|
28
28
|
currencies?: string[];
|
|
29
29
|
counterparties?: string[];
|
|
30
|
+
/** D-25: instruments the agent may use, as SHA-256 of the network's token reference or PAR (see hashPaymentRef). */
|
|
31
|
+
payment_instruments?: {
|
|
32
|
+
network: string;
|
|
33
|
+
ref_sha256: string;
|
|
34
|
+
label?: string;
|
|
35
|
+
}[];
|
|
30
36
|
valid_from?: string;
|
|
31
37
|
valid_until?: string;
|
|
32
38
|
[k: string]: unknown;
|
|
@@ -93,7 +99,16 @@ export interface ActionQuery {
|
|
|
93
99
|
currency?: string;
|
|
94
100
|
counterparty?: string;
|
|
95
101
|
spent_today?: number;
|
|
102
|
+
/** D-25: network of the payment instrument used (visa, mastercard, elo, pix, ...). */
|
|
103
|
+
payment_network?: string;
|
|
104
|
+
/** D-25: SHA-256 hex of its token reference or PAR (hashPaymentRef); never a card number. */
|
|
105
|
+
payment_ref_sha256?: string;
|
|
96
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* SHA-256 (lowercase hex) of a payment reference as mandates store it (D-25): UTF-8, whitespace removed, case
|
|
109
|
+
* kept. Use it on a network token reference or PAR, never on a card number.
|
|
110
|
+
*/
|
|
111
|
+
export declare function hashPaymentRef(ref: string): Promise<string>;
|
|
97
112
|
export interface Verdict {
|
|
98
113
|
credential_id: string;
|
|
99
114
|
status: CredentialStatus;
|
package/dist/index.js
CHANGED
|
@@ -23,6 +23,17 @@ import { privateKeyToAccount } from "viem/accounts";
|
|
|
23
23
|
import * as pkijs from "pkijs";
|
|
24
24
|
import { toBase64Url } from "./base64url.js";
|
|
25
25
|
export const DEFAULT_BASE_URL = "https://kya-br-agents.marcelfons.workers.dev";
|
|
26
|
+
/**
|
|
27
|
+
* SHA-256 (lowercase hex) of a payment reference as mandates store it (D-25): UTF-8, whitespace removed, case
|
|
28
|
+
* kept. Use it on a network token reference or PAR, never on a card number.
|
|
29
|
+
*/
|
|
30
|
+
export async function hashPaymentRef(ref) {
|
|
31
|
+
const clean = ref.replace(/\s+/g, "");
|
|
32
|
+
if (!clean)
|
|
33
|
+
throw new Error("empty payment reference");
|
|
34
|
+
const d = new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(clean)));
|
|
35
|
+
return Array.from(d, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
36
|
+
}
|
|
26
37
|
export class KyaError extends Error {
|
|
27
38
|
code;
|
|
28
39
|
status;
|
|
@@ -102,8 +113,8 @@ export function createKyaClient(opts = {}) {
|
|
|
102
113
|
{
|
|
103
114
|
name: "kya_check_action", priceUsd: 0.01,
|
|
104
115
|
description: "Signed verdict ($0.01): may this agent perform this action (action, amount, currency, counterparty) under its company mandate, and is the credential active right now? Use before accepting an order, a payment or a signature from an agent.",
|
|
105
|
-
parameters: { type: "object", properties: { credential_id: ID, action: { type: "string" }, amount: { type: "number" }, currency: { type: "string" }, counterparty: { type: "string", description: "Your CNPJ, domain or wallet address" }, spent_today: { type: "number" } }, required: ["credential_id"], additionalProperties: false },
|
|
106
|
-
execute: async (a) => client.allowed(String(a.credential_id), { action: a.action, amount: a.amount, currency: a.currency, counterparty: a.counterparty, spent_today: a.spent_today })
|
|
116
|
+
parameters: { type: "object", properties: { credential_id: ID, action: { type: "string" }, amount: { type: "number" }, currency: { type: "string" }, counterparty: { type: "string", description: "Your CNPJ, domain or wallet address" }, spent_today: { type: "number" }, payment_network: { type: "string", description: "visa, mastercard, elo, pix, ..." }, payment_ref_sha256: { type: "string", description: "SHA-256 hex of the payment token reference or PAR used (never a card number)" } }, required: ["credential_id"], additionalProperties: false },
|
|
117
|
+
execute: async (a) => client.allowed(String(a.credential_id), { action: a.action, amount: a.amount, currency: a.currency, counterparty: a.counterparty, spent_today: a.spent_today, payment_network: a.payment_network, payment_ref_sha256: a.payment_ref_sha256 })
|
|
107
118
|
},
|
|
108
119
|
{
|
|
109
120
|
name: "kya_verify_paid", priceUsd: 0.01,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kya-brasil/agent-tools",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "KYA Brasil for AI agents: verify that an agent acts for a Brazilian company (e-CNPJ-signed credential, revocation and company registration checked daily against the Receita's open data, no third-party service), check an action against its mandate, or give your own agent a credential. Sign in with KYA middleware (Hono, Express, Workers) and request signing. x402 payments (USDC on Base) handled for you. Adapters for Vercel AI SDK, LangChain, OpenAI and Anthropic.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"viem": "^2.57.5"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
|
-
"@kya-
|
|
61
|
+
"@kya-brasil/core": "workspace:*",
|
|
62
62
|
"@peculiar/asn1-schema": "^2.3.15",
|
|
63
63
|
"@peculiar/asn1-x509": "^2.3.15",
|
|
64
64
|
"@peculiar/x509": "^2.1.0",
|