@kairoguard/sdk 0.0.9 → 0.0.11

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 CHANGED
@@ -1,92 +1,113 @@
1
- # `@kairo/sdk` (MVP)
1
+ # `@kairoguard/sdk`
2
2
 
3
- MVP helpers for:
3
+ Kairo SDK for multi-chain policy-based transaction signing with dWallet support.
4
4
 
5
- - computing an **EVM intent hash** (Keccak256 over serialized unsigned tx bytes)
6
- - building a Sui transaction to mint a **hard-gate** `PolicyReceipt`
7
- - fetching + validating a `PolicyReceipt` / `PolicyReceiptV2` object for gating
8
- - verifying a Sui custody `CustodyEvent` hash (v2/v3 canonical BCS hashing)
5
+ ## Features
9
6
 
10
- ## Install
7
+ - **Multi-chain intent computation**: EVM, Bitcoin, Solana
8
+ - **Policy-based gating**: Mint and validate PolicyReceipts on Sui
9
+ - **dWallet management**: Create and manage dWallets with policy bindings
10
+ - **Governance**: Propose, approve, and execute policy updates
11
+ - **Audit**: Verify custody events and audit bundles
12
+ - **CLI**: Command-line tools for key management and auditing
11
13
 
12
- From repo root:
14
+ ## Install
13
15
 
14
16
  ```bash
15
- npm install
17
+ npm install @kairoguard/sdk
16
18
  ```
17
19
 
18
- ## DApp flow (user mints receipt with their Sui wallet)
20
+ ## Quick Start
19
21
 
20
- 1) Your app computes the EVM unsigned tx bytes and intent hash:
22
+ ### Initialize the client
21
23
 
22
24
  ```ts
23
- import { computeEvmIntentFromUnsignedTxBytes } from "@kairo/sdk";
25
+ import { KairoClient } from "@kairoguard/sdk";
24
26
 
25
- const { intentHash } = computeEvmIntentFromUnsignedTxBytes({
26
- chainId: 84532, // Base Sepolia (example)
27
- unsignedTxBytesHex, // 0x... serialized unsigned EIP-1559 tx bytes
27
+ const client = new KairoClient({
28
+ backendUrl: "https://kairo-policy-engine-mmux6.ondigitalocean.app",
29
+ apiKey: "your-api-key",
28
30
  });
29
31
  ```
30
32
 
31
- 2) Build a Sui tx that mints a receipt:
33
+ ### Create a dWallet
32
34
 
33
35
  ```ts
34
- import { buildMintEvmReceiptTx } from "@kairo/sdk";
35
-
36
- const tx = buildMintEvmReceiptTx({
37
- packageId,
38
- policyObjectId,
39
- evmChainId: 84532,
40
- intentHash,
41
- toEvm,
36
+ const wallet = await client.createWallet({
37
+ chain: "evm",
38
+ policyStableId: "my-policy",
42
39
  });
43
40
  ```
44
41
 
45
- 3) Have the user sign+execute the Sui tx with their wallet (example using Sui dApp kit):
42
+ ### Compute transaction intent (EVM example)
46
43
 
47
44
  ```ts
48
- // Pseudocode: your wallet adapter will differ depending on your stack.
49
- const result = await wallet.signAndExecuteTransaction({
50
- transaction: tx,
51
- chain: "sui:testnet",
45
+ import { computeEvmIntentFromUnsignedTxBytes } from "@kairoguard/sdk";
46
+
47
+ const { intentHash } = computeEvmIntentFromUnsignedTxBytes({
48
+ chainId: 84532, // Base Sepolia
49
+ unsignedTxBytesHex: "0x...",
52
50
  });
53
51
  ```
54
52
 
55
- 4) Extract the created receipt object id from the execution result, then hard-gate EVM signing:
53
+ ### Compute transaction intent (Solana example)
56
54
 
57
55
  ```ts
58
- // We’ll add a helper for extracting created receipt IDs once we standardize receipt type strings.
59
- // For now, you can scan result.effects.created for the created object id of PolicyReceipt.
60
- ```
61
-
62
- ## Demo/extension flow (backend mints receipt)
56
+ import { computeSolanaIntentHash } from "@kairoguard/sdk";
63
57
 
64
- In this repo’s Key‑Spring demo, the backend mints the receipt (so the extension UX stays “approve action” instead of “approve Sui tx”).
65
- The verifier helper `fetchAndValidatePolicyReceipt` supports both receipt types:
66
-
67
- - legacy `PolicyReceipt` (MVP)
68
- - `PolicyReceiptV2` (includes `policy_root` + `policy_version_id` + optional selector/amount)
58
+ const intentHash = computeSolanaIntentHash({
59
+ from: senderAddress,
60
+ instructions: parsedInstructions,
61
+ });
62
+ ```
69
63
 
70
- If you also log to the custody ledger, you can verify a specific custody event hash:
64
+ ### Build Sui receipt transaction
71
65
 
72
66
  ```ts
73
- import { fetchAndVerifyCustodyEvent } from "@kairo/sdk";
67
+ import { buildMintEvmReceiptTx } from "@kairoguard/sdk";
74
68
 
75
- const res = await fetchAndVerifyCustodyEvent({
76
- suiRpcUrl,
77
- custodyEventObjectId: "0x...",
69
+ const tx = buildMintEvmReceiptTx({
70
+ packageId: "0x...",
71
+ policyObjectId: "0x...",
72
+ evmChainId: 84532,
73
+ intentHash,
74
+ toEvm: recipientAddress,
78
75
  });
79
- if (!res.ok) throw new Error(res.error);
80
76
  ```
81
77
 
78
+ ### Policy governance
82
79
 
80
+ ```ts
81
+ // Propose a policy update
82
+ const proposal = await client.proposePolicyUpdate({
83
+ governanceId: "0x...",
84
+ newPolicyObjectId: "0x...",
85
+ description: "Update spend limits",
86
+ });
83
87
 
88
+ // Approve the proposal
89
+ await client.approvePolicyUpdate({
90
+ governanceId: "0x...",
91
+ proposalId: proposal.proposalId,
92
+ });
84
93
 
94
+ // Execute after threshold reached
95
+ await client.executePolicyUpdate({
96
+ governanceId: "0x...",
97
+ proposalId: proposal.proposalId,
98
+ });
99
+ ```
85
100
 
101
+ ## CLI Usage
86
102
 
103
+ ```bash
104
+ # Audit a bundle
105
+ npx @kairoguard/sdk kairo-audit audit <bundle-path>
87
106
 
107
+ # List keys
108
+ npx @kairoguard/sdk kairo list-keys
109
+ ```
88
110
 
111
+ ## Documentation
89
112
 
90
-
91
-
92
-
113
+ For detailed documentation and examples, visit [docs.kairoguard.io](https://docs.kairoguard.io).
package/SKILL.md ADDED
@@ -0,0 +1,186 @@
1
+ ---
2
+ name: kairo
3
+ description: Manage Kairo policy-enforced agent wallets. Use when creating wallets, setting transaction policies, checking vault status, minting policy receipts, or signing transactions through the Kairo API. Supports full wallet lifecycle: register API key → create wallet (DKG) → create policy → bind → vault provision → mint receipt → sign. Uses @kairo/sdk for non-custodial wallet creation (agent keeps secret share locally).
4
+ ---
5
+
6
+ # Kairo — Agent Wallet Management
7
+
8
+ ## Quick Reference
9
+
10
+ CLI script: `skills/kairo/scripts/kairo.ps1`
11
+ API reference: `skills/kairo/references/api.md`
12
+ SDK reference: `skills/kairo/references/sdk.md`
13
+
14
+ ## Setup
15
+
16
+ API key and wallet details should be stored in TOOLS.md under "Kairo Agent API".
17
+
18
+ If no API key exists, register one:
19
+ ```powershell
20
+ powershell -File skills/kairo/scripts/kairo.ps1 register -Label "agent-name"
21
+ ```
22
+ Save the returned key to TOOLS.md immediately.
23
+
24
+ ## SDK Installation & Auto-Setup
25
+
26
+ After installing the SDK, agents should automatically create a wallet:
27
+
28
+ ```typescript
29
+ import { KairoClient } from "@kairoguard/sdk";
30
+
31
+ const kairo = new KairoClient({
32
+ apiKey,
33
+ backendUrl: "https://api.kairoguard.com"
34
+ });
35
+
36
+ // Automatically create wallet on SDK initialization
37
+ const wallet = await kairo.createWallet({ curve: "secp256k1" });
38
+ console.log(`✅ Wallet created: ${wallet.address}`);
39
+ ```
40
+
41
+ **What's happening:** Your agent just ran a Distributed Key Generation (DKG) ceremony with Kairo's servers. Through advanced cryptography, two shares were created such that neither party sees the other's share, yet both are needed to sign. Your share is encrypted and stored locally at `~/.kairo/keys/`.
42
+
43
+ **Security:** Even if Kairo's servers were compromised, your funds are safe — attackers would only have one share. The full private key never exists in one place.
44
+
45
+ The wallet will be provisioned into the vault when the user connects their agent through the Kairo dashboard onboarding flow.
46
+
47
+ ## Common Workflows
48
+
49
+ ### Check API Health
50
+ ```powershell
51
+ powershell -File skills/kairo/scripts/kairo.ps1 health
52
+ ```
53
+
54
+ ### Create a Policy
55
+ ```powershell
56
+ powershell -File skills/kairo/scripts/kairo.ps1 policy-create `
57
+ -ApiKey $key `
58
+ -StableId "my-policy" `
59
+ -Version "1.0.0" `
60
+ -AllowAddresses "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18"
61
+ ```
62
+ Then register the version:
63
+ ```powershell
64
+ powershell -File skills/kairo/scripts/kairo.ps1 policy-register -ApiKey $key -PolicyId "0x..."
65
+ ```
66
+
67
+ ✅ Policy published on-chain! Once registered, this policy becomes immutable — it cannot be changed without going through governance (propose → approve → execute). Your agent cannot bypass these rules.
68
+
69
+ ### Create Wallet (via SDK)
70
+ For wallet creation, use the Node.js SDK (handles DKG client-side):
71
+ ```typescript
72
+ import { KairoClient } from "@kairo/sdk";
73
+ const kairo = new KairoClient({ apiKey, backendUrl: "https://api.kairoguard.com" });
74
+ const wallet = await kairo.createWallet({ curve: "secp256k1" });
75
+ ```
76
+ SDK source: `packages/kairo-sdk/` in the kairo repo.
77
+ See `skills/kairo/references/sdk.md` for full SDK docs.
78
+
79
+ ### Provision Wallet into Vault
80
+ Requires: policy version registered first.
81
+ ```powershell
82
+ powershell -File skills/kairo/scripts/kairo.ps1 vault-provision `
83
+ -ApiKey $key `
84
+ -WalletId "0x..." `
85
+ -PolicyId "0x..." `
86
+ -StableId "my-policy"
87
+ ```
88
+
89
+ **Note:** For agent-created wallets, provisioning happens automatically when the user connects their agent through the Kairo dashboard.
90
+
91
+ ✅ Vault provisioned! Your wallet is now bound to your policy on-chain. The vault smart contract will enforce that only your API key can request signatures, and every request must include a valid policy receipt proving the transaction follows your rules.
92
+
93
+ ### Mint Policy Receipt
94
+ ```powershell
95
+ powershell -File skills/kairo/scripts/kairo.ps1 receipt-mint `
96
+ -ApiKey $key `
97
+ -PolicyId "0x..." `
98
+ -BindingId "0x..." `
99
+ -Destination "0x742d35Cc..." `
100
+ -IntentHash "0xabab..."
101
+ ```
102
+
103
+ ### Check Vault Status
104
+ ```powershell
105
+ powershell -File skills/kairo/scripts/kairo.ps1 vault-status -WalletId "0x..."
106
+ ```
107
+
108
+ ### View Audit Events
109
+ ```powershell
110
+ powershell -File skills/kairo/scripts/kairo.ps1 audit -ApiKey $key -Limit 20
111
+ ```
112
+
113
+ ## Transaction Completion
114
+
115
+ After completing any transaction, agents should share a link to the transaction on Kairo Guard:
116
+
117
+ ```
118
+ ✅ Transaction completed! View on Kairo Guard:
119
+ https://kairoguard.com/tx/<transaction-hash>
120
+
121
+ This transaction was signed using 2-of-2 MPC — your agent provided one share, Kairo's server provided the other (only after verifying your policy allowed it). Neither share ever left its secure location.
122
+ ```
123
+
124
+ For example:
125
+ ```typescript
126
+ const result = await kairo.signAndBroadcast(intent);
127
+ console.log(`✅ Transaction completed! View on Kairo Guard: https://kairoguard.com/tx/${result.txHash}`);
128
+ console.log(`🔒 Security: This transaction required both your agent's share AND Kairo's server share. The server only released its share after your policy approved the transaction on-chain.`);
129
+ ```
130
+
131
+ ## Full Agent Flow (End to End)
132
+
133
+ 1. `register` → get API key
134
+ 2. **SDK auto-creates wallet** → DKG runs locally, secret share stays on agent
135
+ 3. `policy-create` → create transaction policy with allowed addresses
136
+ 4. `policy-register` → register version in on-chain registry
137
+ 5. **User connects agent** → wallet gets provisioned into vault via dashboard
138
+ 6. `receipt-mint` → request policy check for a transaction
139
+ 7. Sign via SDK or API → both shares combine, only if policy allows
140
+ 8. **Share tx link** → send user the kairoguard.com/tx/<hash> link
141
+
142
+ ## Trust Model (Why This Is Secure)
143
+
144
+ **2-of-2 Multi-Party Computation (MPC)**
145
+
146
+ Think of your wallet like a two-key safe:
147
+ - 🔑 **Your agent holds one key share** — stored encrypted at `~/.kairo/keys/`, never leaves your device
148
+ - 🔑 **Kairo's servers hold the other share** — stored in secure infrastructure, never exposed
149
+ - 🚫 **Neither can sign alone** — both shares must combine in a secure enclave to sign
150
+ - ✅ **Policy engine verifies every transaction** — before the server releases its share, it checks the on-chain policy
151
+
152
+ **What this means for you:**
153
+ - Even if hackers breached Kairo's servers, your funds are safe (they only have 1 share)
154
+ - Even if your agent was compromised, your funds are safe (it only has 1 share)
155
+ - Every transaction is publicly verified on-chain — you can audit any signature
156
+ - Your policy rules are immutable once published — no one can change them without your approval through governance
157
+
158
+ ## Demo Preflight (Do This Every Time)
159
+
160
+ Before running a live demo, verify these in order:
161
+
162
+ 1. **API key is backend-registered (not local placeholder)**
163
+ - Use `/api/keys/register` output or `kairo.ps1 register`
164
+ - Reject keys that start with `kairo_local_...`
165
+ 2. **Backend key persistence is enabled**
166
+ - `SUPABASE_URL`, `SUPABASE_SERVICE_ROLE_KEY`, `KAIRO_API_KEYS_TABLE=api_keys`
167
+ - Confirm key hash exists in Supabase `public.api_keys`
168
+ 3. **Policy version is registered before provision**
169
+ - `policy-create` -> `policy-register` -> then `vault-provision`
170
+ 4. **Wallet ownership matches key**
171
+ - Wallet must be created/provisioned using the same API key
172
+ 5. **Fund wallet before signing test**
173
+ - Check Base Sepolia balance first
174
+ 6. **Avoid nonce race in repeated demos**
175
+ - Wait for prior tx propagation before immediate rerun
176
+ - If broadcast returns `already known`/`nonce too low`, fetch latest/pending nonce and retry once with fresh sign
177
+
178
+ ## Troubleshooting
179
+
180
+ - **401 Unauthorized**: API key missing/invalid OR not registered in backend key store. Use backend-registered key only.
181
+ - **403 Forbidden: key does not own wallet**: Wallet wasn't created/provisioned with this API key (ownership mismatch).
182
+ - **404 on key upsert/query**: Supabase table/env mismatch (`KAIRO_API_KEYS_TABLE` must be `api_keys`).
183
+ - **429 Rate limit**: Public Sui RPC throttled — use Shinami or own RPC provider.
184
+ - **MoveAbort code 102**: Policy version not registered — call `policy-register` before `vault-provision`.
185
+ - **`nonce too low` / `already known`**: Rapid reruns or duplicate raw tx; wait for pending tx, then re-sign and rebroadcast.
186
+ - **AwaitingKeyHolderSignature**: Wallet needs activation after DKG — SDK activation flow required.
package/dist/cli.js CHANGED
@@ -198,6 +198,16 @@ async function cmdVaultProvision(args) {
198
198
  const res = await kairo.provision(walletId, policyId, stableId);
199
199
  console.log(JSON.stringify(res, null, 2));
200
200
  }
201
+ async function cmdReaffirm(args) {
202
+ const walletId = requireFlag(args, "--wallet-id", "dwalletId");
203
+ const cfg = requireConfig();
204
+ const kairo = new KairoClient({
205
+ apiKey: cfg.apiKey,
206
+ backendUrl: cfg.backendUrl,
207
+ });
208
+ const res = await kairo.reaffirmBinding(walletId);
209
+ console.log(JSON.stringify(res, null, 2));
210
+ }
201
211
  async function cmdReceiptMint(args) {
202
212
  const policyId = requireFlag(args, "--policy-id", "objectId");
203
213
  const bindingId = requireFlag(args, "--binding-id", "objectId");
@@ -264,6 +274,7 @@ Wallet & Policy:
264
274
  policy-details --policy-id <id> Get policy details
265
275
  vault-status --wallet-id <id> Check vault registration
266
276
  vault-provision --wallet-id <id> --policy-id <id> [--stable-id <id>]
277
+ reaffirm --wallet-id <id> Reaffirm a wallet's current policy binding
267
278
  receipt-mint --policy-id <id> --binding-id <id> --destination <hex> --intent-hash <hex>
268
279
 
269
280
  Utility:
@@ -294,6 +305,8 @@ async function main() {
294
305
  return cmdVaultStatus(rest);
295
306
  case "vault-provision":
296
307
  return cmdVaultProvision(rest);
308
+ case "reaffirm":
309
+ return cmdReaffirm(rest);
297
310
  case "receipt-mint":
298
311
  return cmdReceiptMint(rest);
299
312
  case "audit":
package/dist/client.d.ts CHANGED
@@ -196,7 +196,6 @@ export declare class KairoClient {
196
196
  private mintPolicyReceipt;
197
197
  private resolvePolicyVersion;
198
198
  private isReaffirmRequiredError;
199
- private requestSignWithReaffirmRetry;
200
199
  private computeUserSignMessageWithExtensionFallback;
201
200
  private rebuildSigningMaterialFromChain;
202
201
  private resolveEvmRpcUrl;
package/dist/client.js CHANGED
@@ -237,13 +237,25 @@ export class KairoClient {
237
237
  if (!wallet.bindingObjectId?.startsWith("0x")) {
238
238
  throw new Error("Wallet is missing bindingObjectId. Provision the wallet before reaffirming.");
239
239
  }
240
- const result = await this.backend.reaffirmPolicyBinding({
241
- bindingObjectId: wallet.bindingObjectId,
242
- });
243
- return {
244
- digest: result.digest,
245
- activeVersionObjectId: result.activeVersionObjectId,
246
- };
240
+ try {
241
+ const result = await this.backend.reaffirmPolicyBinding({
242
+ bindingObjectId: wallet.bindingObjectId,
243
+ });
244
+ return {
245
+ digest: result.digest,
246
+ activeVersionObjectId: result.activeVersionObjectId,
247
+ };
248
+ }
249
+ catch (error) {
250
+ const message = error instanceof Error ? error.message : String(error);
251
+ const governedGuardTriggered = /binding is governed/i.test(message) ||
252
+ /requires governance receipt flow/i.test(message) ||
253
+ /execute-and-reaffirm/i.test(message);
254
+ if (governedGuardTriggered) {
255
+ throw new Error("Binding is governed and cannot be directly reaffirmed. Complete governance execute-and-reaffirm first, then retry signing.");
256
+ }
257
+ throw error;
258
+ }
247
259
  }
248
260
  /**
249
261
  * Governance-first policy update: creates a new policy + version, then proposes
@@ -431,36 +443,52 @@ export class KairoClient {
431
443
  destinationHex: "0x0000000000000000000000000000000000000000",
432
444
  nativeValue: 0n,
433
445
  };
434
- const policyReceiptId = await this.mintPolicyReceipt(wallet, policyContext);
446
+ const initialPolicyReceiptId = await this.mintPolicyReceipt(wallet, policyContext);
435
447
  const dWalletCapId = wallet.dWalletCapId;
436
448
  if (!dWalletCapId) {
437
449
  throw new Error("Wallet record is missing dWalletCapId. Recreate/provision this wallet before signing.");
438
450
  }
439
- const resolvedPolicyVersion = await this.resolvePolicyVersion(wallet, opts?.policyVersion);
440
- const req = await this.requestSignWithReaffirmRetry(wallet, {
441
- dWalletId: wallet.walletId,
442
- dWalletCapId,
443
- encryptedUserSecretKeyShareId: wallet.encryptedUserSecretKeyShareId ?? "",
444
- userOutputSignature: [],
445
- presignId,
446
- messageHex: messageHexNoPrefix,
447
- userSignMessage: Array.from(userSignMessage),
448
- policyReceiptId,
449
- policyBindingObjectId: wallet.bindingObjectId,
450
- policyObjectId: wallet.policyObjectId,
451
- policyVersion: resolvedPolicyVersion,
452
- ethTx: opts?.ethTx,
453
- });
454
- if (!req.success) {
455
- throw new Error(`Failed to request sign for wallet ${walletId}`);
451
+ if (!presignId) {
452
+ throw new Error("Missing presignId after presign creation.");
456
453
  }
457
- const signStatus = await this.pollSignStatus(req.requestId);
458
- return {
459
- requestId: req.requestId,
460
- signId: signStatus.signId,
461
- presignId,
462
- signatureHex: ensureHexPrefix(signStatus.signatureHex),
454
+ const resolvedPolicyVersion = await this.resolvePolicyVersion(wallet, opts?.policyVersion);
455
+ const submitAndPoll = async (policyReceiptId) => {
456
+ const req = await this.backend.requestSign({
457
+ dWalletId: wallet.walletId,
458
+ dWalletCapId,
459
+ encryptedUserSecretKeyShareId: wallet.encryptedUserSecretKeyShareId ?? "",
460
+ userOutputSignature: [],
461
+ presignId,
462
+ messageHex: messageHexNoPrefix,
463
+ userSignMessage: Array.from(userSignMessage),
464
+ policyReceiptId,
465
+ policyBindingObjectId: wallet.bindingObjectId,
466
+ policyObjectId: wallet.policyObjectId,
467
+ policyVersion: resolvedPolicyVersion,
468
+ ethTx: opts?.ethTx,
469
+ });
470
+ if (!req.success) {
471
+ throw new Error(`Failed to request sign for wallet ${walletId}`);
472
+ }
473
+ const signStatus = await this.pollSignStatus(req.requestId);
474
+ return {
475
+ requestId: req.requestId,
476
+ signId: signStatus.signId,
477
+ presignId,
478
+ signatureHex: ensureHexPrefix(signStatus.signatureHex),
479
+ };
463
480
  };
481
+ try {
482
+ return await submitAndPoll(initialPolicyReceiptId);
483
+ }
484
+ catch (error) {
485
+ if (!this.isReaffirmRequiredError(error))
486
+ throw error;
487
+ await this.reaffirmBinding(wallet.walletId);
488
+ // Reaffirm changes active binding version; mint a fresh receipt bound to the new version.
489
+ const retriedPolicyReceiptId = await this.mintPolicyReceipt(wallet, policyContext);
490
+ return submitAndPoll(retriedPolicyReceiptId);
491
+ }
464
492
  }
465
493
  async signEvm(params) {
466
494
  const wallet = this.requireWalletRecord(params.walletId);
@@ -711,17 +739,6 @@ export class KairoClient {
711
739
  const message = err instanceof Error ? err.message : String(err);
712
740
  return /requires confirmation/i.test(message) || /reaffirm/i.test(message);
713
741
  }
714
- async requestSignWithReaffirmRetry(wallet, payload) {
715
- try {
716
- return await this.backend.requestSign(payload);
717
- }
718
- catch (error) {
719
- if (!this.isReaffirmRequiredError(error))
720
- throw error;
721
- await this.reaffirmBinding(wallet.walletId);
722
- return this.backend.requestSign(payload);
723
- }
724
- }
725
742
  async computeUserSignMessageWithExtensionFallback(wallet, protocolParams, presignBytes, messageBytes) {
726
743
  try {
727
744
  return await createUserSignMessageWithPublicOutput(protocolParams, new Uint8Array(wallet.userPublicOutput), new Uint8Array(wallet.userSecretKeyShare), presignBytes, messageBytes, Hash.KECCAK256, SignatureAlgorithm.ECDSASecp256k1, Curve.SECP256K1);
@@ -4,6 +4,6 @@
4
4
  * All backend URLs are intentionally omitted -- the SDK and CLI
5
5
  * resolve the endpoint internally.
6
6
  */
7
- export declare const SKILL_MD = "---\nname: kairo\ndescription: Manage Kairo policy-enforced agent wallets. Use when creating wallets, setting transaction policies, checking vault status, minting policy receipts, or signing transactions through the Kairo SDK/CLI. Supports full wallet lifecycle: register API key -> create wallet (DKG) -> create policy -> bind -> vault provision -> mint receipt -> sign. Uses @kairo/sdk for non-custodial wallet creation (agent keeps secret share locally).\n---\n\n# Kairo \u2014 Agent Wallet Management\n\n## Quick Reference\n\nCLI: `npx kairo <command>`\nSDK reference: `.cursor/skills/kairo/references/sdk.md`\nAPI reference: `.cursor/skills/kairo/references/api.md`\n\n## Setup\n\nRun the one-line installer (already done if you see this file):\n```bash\nnpx @kairo/sdk init <YOUR_KEY>\n```\n\nThe API key is stored in `~/.kairo/config.json`. All CLI commands read it automatically.\n\n## Common Workflows\n\n### Check API Health\n```bash\nnpx kairo health\n```\n\n### Create a Policy\n```bash\nnpx kairo policy-create --stable-id \"my-policy\" --allow \"0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18\"\n```\nThen register the version:\n```bash\nnpx kairo policy-register --policy-id \"0x...\"\n```\n\n### Create Wallet (via SDK)\nFor wallet creation, use the Node.js SDK (handles DKG client-side):\n```typescript\nimport { KairoClient } from \"@kairo/sdk\";\nconst kairo = new KairoClient({ apiKey: process.env.KAIRO_API_KEY! });\nconst wallet = await kairo.createWallet({ curve: \"secp256k1\" });\n```\nSee `.cursor/skills/kairo/references/sdk.md` for full SDK docs.\n\n### Provision Wallet into Vault\nRequires: policy version registered first.\n```bash\nnpx kairo vault-provision --wallet-id \"0x...\" --policy-id \"0x...\" --stable-id \"my-policy\"\n```\n\n### Mint Policy Receipt\n```bash\nnpx kairo receipt-mint --policy-id \"0x...\" --binding-id \"0x...\" --destination \"0x742d35Cc...\" --intent-hash \"0xabab...\"\n```\n\n### Check Vault Status\n```bash\nnpx kairo vault-status --wallet-id \"0x...\"\n```\n\n### View Audit Events\n```bash\nnpx kairo audit --limit 20\n```\n\n## Full Agent Flow (End to End)\n\n1. `npx @kairo/sdk init <YOUR_KEY>` \u2014 store API key, install skill\n2. `npx kairo policy-create` \u2014 create transaction policy with allowed addresses\n3. `npx kairo policy-register` \u2014 register version in on-chain registry\n4. Create wallet via SDK `createWallet()` \u2014 runs DKG locally, secret share stays on agent\n5. `npx kairo vault-provision` \u2014 bind policy + register wallet in vault (atomic)\n6. `npx kairo receipt-mint` \u2014 request policy check for a transaction\n7. Sign via SDK \u2014 both shares combine, only if policy allows\n\n## Trust Model\n\n- Agent's key share stays local (`~/.kairo/keys/`)\n- Server's key share stays on Kairo backend\n- Neither party can sign alone\n- Policy engine gates every transaction before server releases its share\n- All policy decisions are on-chain (Sui) and verifiable\n\n## Troubleshooting\n\n- **401 Unauthorized**: API key missing/invalid or not registered in backend key store. Re-run `npx @kairo/sdk init <YOUR_KEY>` with a valid key.\n- **403 Forbidden: key does not own wallet**: Wallet wasn't created/provisioned with this API key (ownership mismatch).\n- **429 Rate limit**: Public Sui RPC throttled \u2014 use Shinami or own RPC provider.\n- **MoveAbort code 102**: Policy version not registered \u2014 call `npx kairo policy-register` before `vault-provision`.\n- **`nonce too low` / `already known`**: Rapid reruns or duplicate raw tx; wait for pending tx, then re-sign and rebroadcast.\n- **AwaitingKeyHolderSignature**: Wallet needs activation after DKG \u2014 SDK activation flow required.\n";
7
+ export declare const SKILL_MD = "---\nname: kairo\ndescription: Manage Kairo policy-enforced agent wallets. Use when creating wallets, checking vault status, minting policy receipts, or signing transactions through the Kairo SDK/CLI. Default onboarding is dashboard-first: register API key -> create wallet (DKG) in agent -> dashboard auto-binds/provisions policy. Uses @kairo/sdk for non-custodial wallet creation (agent keeps secret share locally).\n---\n\n# Kairo \u2014 Agent Wallet Management\n\n## Quick Reference\n\nCLI: `npx kairo <command>`\nSDK reference: `.cursor/skills/kairo/references/sdk.md`\nAPI reference: `.cursor/skills/kairo/references/api.md`\n\n## Setup\n\nRun the one-line installer (already done if you see this file):\n```bash\nnpx @kairo/sdk init <YOUR_KEY>\n```\n\nThe API key is stored in `~/.kairo/config.json`. All CLI commands read it automatically.\n\n## Common Workflows\n\n### Check API Health\n```bash\nnpx kairo health\n```\n\n### Dashboard-First Onboarding (Recommended)\n1. In dashboard onboarding, create/select policy + governance.\n2. In your agent:\n```bash\nnpx @kairo/sdk init <YOUR_KEY>\n```\n```typescript\nimport { KairoClient } from \"@kairo/sdk\";\nconst kairo = new KairoClient({ apiKey: process.env.KAIRO_API_KEY! });\nconst wallet = await kairo.createWallet({ curve: \"secp256k1\" });\n```\n3. Return to dashboard \"Verify Connection\". Dashboard auto-provisions wallet policy binding + vault registration.\n\n### Create a Policy (Advanced / Self-Managed)\n```bash\nnpx kairo policy-create --stable-id \"my-policy\" --allow \"0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18\"\n```\nThen register the version:\n```bash\nnpx kairo policy-register --policy-id \"0x...\"\n```\n\n### Create Wallet (via SDK)\nFor wallet creation, use the Node.js SDK (handles DKG client-side):\n```typescript\nimport { KairoClient } from \"@kairo/sdk\";\nconst kairo = new KairoClient({ apiKey: process.env.KAIRO_API_KEY! });\nconst wallet = await kairo.createWallet({ curve: \"secp256k1\" });\n```\nSee `.cursor/skills/kairo/references/sdk.md` for full SDK docs.\n\n### Provision Wallet into Vault\nRequires: policy version registered first.\n```bash\nnpx kairo vault-provision --wallet-id \"0x...\" --policy-id \"0x...\" --stable-id \"my-policy\"\n```\n\n### Mint Policy Receipt\n```bash\nnpx kairo receipt-mint --policy-id \"0x...\" --binding-id \"0x...\" --destination \"0x742d35Cc...\" --intent-hash \"0xabab...\"\n```\n\n### Check Vault Status\n```bash\nnpx kairo vault-status --wallet-id \"0x...\"\n```\n\n### View Audit Events\n```bash\nnpx kairo audit --limit 20\n```\n\n## Full Agent Flow (Dashboard-First)\n\n1. `npx @kairo/sdk init <YOUR_KEY>` \u2014 store API key, install skill\n2. Create/select policy in dashboard onboarding\n3. Configure governance approvers in dashboard onboarding (optional)\n4. Create wallet via SDK `createWallet()` \u2014 runs DKG locally, secret share stays on agent\n5. Dashboard Verify step auto-provisions wallet with selected policy\n6. `npx kairo receipt-mint` \u2014 request policy check for a transaction\n7. Sign via SDK \u2014 both shares combine, only if policy allows\n\n## Advanced: Self-Managed Flow (CLI Heavy)\n\n1. `npx @kairo/sdk init <YOUR_KEY>`\n2. `npx kairo policy-create`\n3. `npx kairo policy-register`\n4. SDK `createWallet()`\n5. `npx kairo vault-provision`\n\n## Trust Model\n\n- Agent's key share stays local (`~/.kairo/keys/`)\n- Server's key share stays on Kairo backend\n- Neither party can sign alone\n- Policy engine gates every transaction before server releases its share\n- All policy decisions are on-chain (Sui) and verifiable\n\n## Troubleshooting\n\n- **401 Unauthorized**: API key missing/invalid or not registered in backend key store. Re-run `npx @kairo/sdk init <YOUR_KEY>` with a valid key.\n- **403 Forbidden: key does not own wallet**: Wallet wasn't created/provisioned with this API key (ownership mismatch).\n- **429 Rate limit**: Public Sui RPC throttled \u2014 use Shinami or own RPC provider.\n- **MoveAbort code 102**: Policy version not registered \u2014 call `npx kairo policy-register` before `vault-provision`.\n- **`nonce too low` / `already known`**: Rapid reruns or duplicate raw tx; wait for pending tx, then re-sign and rebroadcast.\n- **AwaitingKeyHolderSignature**: Wallet needs activation after DKG \u2014 SDK activation flow required.\n";
8
8
  export declare const API_REFERENCE_MD = "# Kairo API Reference\n\n## Authentication\nAll write endpoints require `X-Kairo-Api-Key` header.\nThe CLI reads the key from `~/.kairo/config.json` automatically.\nOpen endpoints: `/health`, `/api/vault/info`, `/api/vault/status/:id`, `/api/audit/events`\n\n## Key Registration\n```bash\nnpx kairo register --label \"my-agent\"\n```\n\n## Wallet Creation (via SDK)\nThe SDK handles DKG client-side. Agent keeps their secret share locally.\n```typescript\nimport { KairoClient } from \"@kairo/sdk\";\nconst kairo = new KairoClient({ apiKey: process.env.KAIRO_API_KEY! });\nconst wallet = await kairo.createWallet({ curve: \"secp256k1\" });\n// wallet.walletId, wallet.address\n```\n\n## Policy Management\n\n### Create Policy\n```bash\nnpx kairo policy-create --stable-id \"my-policy\" --version \"1.0.0\" --allow \"0x<address>\"\n```\n\nRule types:\n- `1` = MaxNativeValue (max single transaction value)\n- `10` = PeriodLimit (cumulative spend limit per time window)\n\n### Register Policy Version\n```bash\nnpx kairo policy-register --policy-id \"0x...\"\n```\n\n### Get Policy Details\n```bash\nnpx kairo policy-details --policy-id \"0x...\"\n```\n\n## Vault\n\n### Provision (atomic binding + vault registration)\n```bash\nnpx kairo vault-provision --wallet-id \"0x...\" --policy-id \"0x...\" --stable-id \"my-policy\"\n```\nNote: Register policy version BEFORE calling provision.\n\n### Check Status\n```bash\nnpx kairo vault-status --wallet-id \"0x...\"\n```\n\n## Receipt Minting\n```bash\nnpx kairo receipt-mint --policy-id \"0x...\" --binding-id \"0x...\" --destination \"0x...\" --intent-hash \"0x...\"\n```\nNamespace: 1=EVM, 2=Bitcoin, 3=Solana\n\n## Utility\n```bash\nnpx kairo health # Server health\nnpx kairo audit --limit 20 # Recent audit events\n```\n";
9
- export declare const SDK_REFERENCE_MD = "# Kairo SDK Reference\n\n## Installation\n```bash\nnpm install @kairo/sdk\n```\n\nRequires: `@ika.xyz/sdk`, `@mysten/sui`\n\n## KairoClient\n\n```typescript\nimport { KairoClient } from \"@kairo/sdk\";\n\nconst kairo = new KairoClient({\n apiKey: process.env.KAIRO_API_KEY!,\n storePath: \"~/.kairo/keys\", // local secret share storage (default)\n network: \"testnet\", // or \"mainnet\"\n suiRpcUrl: \"https://...\", // optional, defaults to public testnet\n});\n```\n\n### createWallet(opts?)\nCreates a dWallet via client-side DKG. Secret share stays local.\n\n```typescript\nconst wallet = await kairo.createWallet({\n curve: \"secp256k1\", // or \"ed25519\" for Solana\n policyObjectId: \"0x...\", // optional: auto-provision into vault\n stableId: \"my-policy\", // optional: binding label\n});\n// Returns: { walletId, address, curve, bindingObjectId?, createdAt }\n```\n\n**Important:** If providing `policyObjectId`, register the policy version first.\n\n### listWallets()\nLists all wallets in local key store.\n```typescript\nconst wallets = kairo.listWallets();\n```\n\n### getWallet(walletId)\nGets a specific wallet from local store.\n```typescript\nconst w = kairo.getWallet(\"0x...\");\n```\n\n## BackendClient (HTTP wrapper)\nLower-level HTTP client for direct API calls.\n\n```typescript\nimport { BackendClient } from \"@kairo/sdk\";\n\nconst client = new BackendClient({ apiKey: \"your-key\" });\n\nawait client.register(\"my-agent\");\nawait client.getHealth();\nawait client.submitDKG({...});\nawait client.getDKGStatus(requestId);\nawait client.provision({...});\nawait client.mintReceipt({...});\n```\n\n## KeyStore (local storage)\nFile-based secret share storage at `~/.kairo/keys/`.\n\n```typescript\nimport { KeyStore } from \"@kairo/sdk\";\n\nconst store = new KeyStore(\"~/.kairo/keys\");\nstore.save(record);\nstore.load(\"0x...\");\nstore.list();\nstore.delete(\"0x...\");\n```\n\n## Trust Model\n- Agent's secret share -> stored locally (KeyStore), never sent to server\n- Server's share -> held by Kairo backend\n- Full signing -> requires BOTH shares + policy approval\n- Kairo alone cannot sign (missing agent share)\n- Agent alone cannot sign (missing server share)\n";
9
+ export declare const SDK_REFERENCE_MD = "# Kairo SDK Reference\n\n## Installation\n```bash\nnpm install @kairo/sdk\n```\n\nRequires: `@ika.xyz/sdk`, `@mysten/sui`\n\n## KairoClient\n\n```typescript\nimport { KairoClient } from \"@kairo/sdk\";\n\nconst kairo = new KairoClient({\n apiKey: process.env.KAIRO_API_KEY!,\n storePath: \"~/.kairo/keys\", // local secret share storage (default)\n network: \"testnet\", // or \"mainnet\"\n suiRpcUrl: \"https://...\", // optional, defaults to public testnet\n});\n```\n\n### createWallet(opts?)\nCreates a dWallet via client-side DKG. Secret share stays local.\n\n```typescript\nconst wallet = await kairo.createWallet({\n curve: \"secp256k1\", // or \"ed25519\" for Solana\n});\n// Returns: { walletId, address, curve, bindingObjectId?, createdAt }\n```\n\nDashboard-first default: create wallet in agent and let dashboard onboarding handle policy provisioning.\n\nAdvanced optional params are still supported:\n```typescript\nconst wallet = await kairo.createWallet({\n curve: \"secp256k1\",\n policyObjectId: \"0x...\",\n stableId: \"my-policy\",\n});\n```\n\n### listWallets()\nLists all wallets in local key store.\n```typescript\nconst wallets = kairo.listWallets();\n```\n\n### getWallet(walletId)\nGets a specific wallet from local store.\n```typescript\nconst w = kairo.getWallet(\"0x...\");\n```\n\n## BackendClient (HTTP wrapper)\nLower-level HTTP client for direct API calls.\n\n```typescript\nimport { BackendClient } from \"@kairo/sdk\";\n\nconst client = new BackendClient({ apiKey: \"your-key\" });\n\nawait client.register(\"my-agent\");\nawait client.getHealth();\nawait client.submitDKG({...});\nawait client.getDKGStatus(requestId);\nawait client.provision({...});\nawait client.mintReceipt({...});\n```\n\n## KeyStore (local storage)\nFile-based secret share storage at `~/.kairo/keys/`.\n\n```typescript\nimport { KeyStore } from \"@kairo/sdk\";\n\nconst store = new KeyStore(\"~/.kairo/keys\");\nstore.save(record);\nstore.load(\"0x...\");\nstore.list();\nstore.delete(\"0x...\");\n```\n\n## Trust Model\n- Agent's secret share -> stored locally (KeyStore), never sent to server\n- Server's share -> held by Kairo backend\n- Full signing -> requires BOTH shares + policy approval\n- Kairo alone cannot sign (missing agent share)\n- Agent alone cannot sign (missing server share)\n";
@@ -6,7 +6,7 @@
6
6
  */
7
7
  export const SKILL_MD = `---
8
8
  name: kairo
9
- description: Manage Kairo policy-enforced agent wallets. Use when creating wallets, setting transaction policies, checking vault status, minting policy receipts, or signing transactions through the Kairo SDK/CLI. Supports full wallet lifecycle: register API key -> create wallet (DKG) -> create policy -> bind -> vault provision -> mint receipt -> sign. Uses @kairo/sdk for non-custodial wallet creation (agent keeps secret share locally).
9
+ description: Manage Kairo policy-enforced agent wallets. Use when creating wallets, checking vault status, minting policy receipts, or signing transactions through the Kairo SDK/CLI. Default onboarding is dashboard-first: register API key -> create wallet (DKG) in agent -> dashboard auto-binds/provisions policy. Uses @kairo/sdk for non-custodial wallet creation (agent keeps secret share locally).
10
10
  ---
11
11
 
12
12
  # Kairo — Agent Wallet Management
@@ -33,7 +33,20 @@ The API key is stored in \`~/.kairo/config.json\`. All CLI commands read it auto
33
33
  npx kairo health
34
34
  \`\`\`
35
35
 
36
- ### Create a Policy
36
+ ### Dashboard-First Onboarding (Recommended)
37
+ 1. In dashboard onboarding, create/select policy + governance.
38
+ 2. In your agent:
39
+ \`\`\`bash
40
+ npx @kairo/sdk init <YOUR_KEY>
41
+ \`\`\`
42
+ \`\`\`typescript
43
+ import { KairoClient } from "@kairo/sdk";
44
+ const kairo = new KairoClient({ apiKey: process.env.KAIRO_API_KEY! });
45
+ const wallet = await kairo.createWallet({ curve: "secp256k1" });
46
+ \`\`\`
47
+ 3. Return to dashboard "Verify Connection". Dashboard auto-provisions wallet policy binding + vault registration.
48
+
49
+ ### Create a Policy (Advanced / Self-Managed)
37
50
  \`\`\`bash
38
51
  npx kairo policy-create --stable-id "my-policy" --allow "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18"
39
52
  \`\`\`
@@ -72,16 +85,24 @@ npx kairo vault-status --wallet-id "0x..."
72
85
  npx kairo audit --limit 20
73
86
  \`\`\`
74
87
 
75
- ## Full Agent Flow (End to End)
88
+ ## Full Agent Flow (Dashboard-First)
76
89
 
77
90
  1. \`npx @kairo/sdk init <YOUR_KEY>\` — store API key, install skill
78
- 2. \`npx kairo policy-create\` create transaction policy with allowed addresses
79
- 3. \`npx kairo policy-register\` register version in on-chain registry
91
+ 2. Create/select policy in dashboard onboarding
92
+ 3. Configure governance approvers in dashboard onboarding (optional)
80
93
  4. Create wallet via SDK \`createWallet()\` — runs DKG locally, secret share stays on agent
81
- 5. \`npx kairo vault-provision\` — bind policy + register wallet in vault (atomic)
94
+ 5. Dashboard Verify step auto-provisions wallet with selected policy
82
95
  6. \`npx kairo receipt-mint\` — request policy check for a transaction
83
96
  7. Sign via SDK — both shares combine, only if policy allows
84
97
 
98
+ ## Advanced: Self-Managed Flow (CLI Heavy)
99
+
100
+ 1. \`npx @kairo/sdk init <YOUR_KEY>\`
101
+ 2. \`npx kairo policy-create\`
102
+ 3. \`npx kairo policy-register\`
103
+ 4. SDK \`createWallet()\`
104
+ 5. \`npx kairo vault-provision\`
105
+
85
106
  ## Trust Model
86
107
 
87
108
  - Agent's key share stays local (\`~/.kairo/keys/\`)
@@ -194,13 +215,20 @@ Creates a dWallet via client-side DKG. Secret share stays local.
194
215
  \`\`\`typescript
195
216
  const wallet = await kairo.createWallet({
196
217
  curve: "secp256k1", // or "ed25519" for Solana
197
- policyObjectId: "0x...", // optional: auto-provision into vault
198
- stableId: "my-policy", // optional: binding label
199
218
  });
200
219
  // Returns: { walletId, address, curve, bindingObjectId?, createdAt }
201
220
  \`\`\`
202
221
 
203
- **Important:** If providing \`policyObjectId\`, register the policy version first.
222
+ Dashboard-first default: create wallet in agent and let dashboard onboarding handle policy provisioning.
223
+
224
+ Advanced optional params are still supported:
225
+ \`\`\`typescript
226
+ const wallet = await kairo.createWallet({
227
+ curve: "secp256k1",
228
+ policyObjectId: "0x...",
229
+ stableId: "my-policy",
230
+ });
231
+ \`\`\`
204
232
 
205
233
  ### listWallets()
206
234
  Lists all wallets in local key store.
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "@kairoguard/sdk",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
+ "description": "Kairo SDK for multi-chain policy-based transaction signing with dWallet support (EVM, Bitcoin, Solana, Sui)",
4
5
  "type": "module",
5
6
  "main": "dist/index.js",
6
7
  "types": "dist/index.d.ts",
7
8
  "files": [
8
- "dist"
9
+ "dist",
10
+ "SKILL.md"
9
11
  ],
10
12
  "bin": {
11
13
  "kairo": "dist/cli.js",