agentvault 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (293) hide show
  1. package/.claude/settings.local.json +9 -0
  2. package/README.md +1 -1
  3. package/dist/cli/commands/approve.js +5 -5
  4. package/dist/cli/commands/archive.js +5 -5
  5. package/dist/cli/commands/backup.js +5 -5
  6. package/dist/cli/commands/cloud-backup.js +12 -12
  7. package/dist/cli/commands/decrypt.js +2 -2
  8. package/dist/cli/commands/deploy.js +1 -1
  9. package/dist/cli/commands/exec.js +2 -2
  10. package/dist/cli/commands/fetch.js +4 -4
  11. package/dist/cli/commands/inference.js +5 -5
  12. package/dist/cli/commands/init.d.ts +1 -1
  13. package/dist/cli/commands/init.js +16 -16
  14. package/dist/cli/commands/list.js +4 -4
  15. package/dist/cli/commands/package.js +2 -2
  16. package/dist/cli/commands/profile.js +1 -1
  17. package/dist/cli/commands/rebuild.js +2 -2
  18. package/dist/cli/commands/show.js +1 -1
  19. package/dist/cli/commands/status.d.ts +1 -1
  20. package/dist/cli/commands/status.js +8 -8
  21. package/dist/cli/commands/trace.js +1 -1
  22. package/dist/cli/commands/wallet-export.js +1 -1
  23. package/dist/cli/commands/wallet-sign.js +1 -1
  24. package/dist/cli/commands/wallet.d.ts +1 -1
  25. package/dist/cli/commands/wallet.js +1 -1
  26. package/dist/cli/index.d.ts +2 -2
  27. package/dist/cli/index.js +3 -3
  28. package/dist/src/archival/archive-manager.d.ts +85 -0
  29. package/dist/src/archival/archive-manager.js +294 -0
  30. package/dist/src/archival/arweave-client.d.ts +88 -0
  31. package/dist/src/archival/arweave-client.js +223 -0
  32. package/dist/src/archival/index.d.ts +8 -0
  33. package/{src/archival/index.ts → dist/src/archival/index.js} +1 -1
  34. package/dist/src/backup/backup.d.ts +67 -0
  35. package/dist/src/backup/backup.js +231 -0
  36. package/dist/src/backup/index.d.ts +7 -0
  37. package/{src/backup/index.ts → dist/src/backup/index.js} +1 -1
  38. package/dist/src/cloud-storage/cloud-sync.d.ts +49 -0
  39. package/dist/src/cloud-storage/cloud-sync.js +372 -0
  40. package/dist/src/cloud-storage/index.d.ts +11 -0
  41. package/{src/cloud-storage/index.ts → dist/src/cloud-storage/index.js} +1 -1
  42. package/dist/src/cloud-storage/provider-detector.d.ts +34 -0
  43. package/dist/src/cloud-storage/provider-detector.js +158 -0
  44. package/{src/cloud-storage/types.ts → dist/src/cloud-storage/types.d.ts} +40 -53
  45. package/dist/src/cloud-storage/types.js +10 -0
  46. package/dist/src/debugging/index.d.ts +6 -0
  47. package/{src/debugging/index.ts → dist/src/debugging/index.js} +1 -1
  48. package/dist/src/debugging/logs.d.ts +32 -0
  49. package/dist/src/debugging/logs.js +158 -0
  50. package/dist/src/debugging/types.d.ts +91 -0
  51. package/dist/src/debugging/types.js +5 -0
  52. package/dist/src/deployment/deployer.d.ts +52 -0
  53. package/dist/src/deployment/deployer.js +211 -0
  54. package/dist/src/deployment/icpClient.d.ts +144 -0
  55. package/dist/src/deployment/icpClient.js +545 -0
  56. package/dist/src/deployment/index.d.ts +11 -0
  57. package/dist/src/deployment/index.js +14 -0
  58. package/dist/src/deployment/promotion.d.ts +32 -0
  59. package/dist/src/deployment/promotion.js +114 -0
  60. package/dist/src/deployment/types.d.ts +101 -0
  61. package/dist/src/deployment/types.js +5 -0
  62. package/dist/src/icp/batch.d.ts +112 -0
  63. package/dist/src/icp/batch.js +273 -0
  64. package/dist/src/icp/cycles.d.ts +29 -0
  65. package/{src/icp/cycles.ts → dist/src/icp/cycles.js} +8 -22
  66. package/dist/src/icp/environment.d.ts +60 -0
  67. package/dist/src/icp/environment.js +183 -0
  68. package/dist/src/icp/icpcli.d.ts +204 -0
  69. package/dist/src/icp/icpcli.js +374 -0
  70. package/dist/src/icp/icwasm.d.ts +94 -0
  71. package/dist/src/icp/icwasm.js +197 -0
  72. package/dist/src/icp/identity.d.ts +50 -0
  73. package/{src/icp/identity.ts → dist/src/icp/identity.js} +15 -28
  74. package/dist/src/icp/index.d.ts +16 -0
  75. package/dist/src/icp/index.js +20 -0
  76. package/dist/src/icp/optimization.d.ts +16 -0
  77. package/dist/src/icp/optimization.js +225 -0
  78. package/dist/src/icp/tokens.d.ts +24 -0
  79. package/{src/icp/tokens.ts → dist/src/icp/tokens.js} +5 -12
  80. package/dist/src/icp/tool-detector.d.ts +31 -0
  81. package/dist/src/icp/tool-detector.js +104 -0
  82. package/dist/src/icp/types.d.ts +493 -0
  83. package/dist/src/icp/types.js +7 -0
  84. package/dist/src/index.d.ts +12 -0
  85. package/dist/src/index.js +18 -0
  86. package/dist/src/inference/bittensor-client.d.ts +108 -0
  87. package/dist/src/inference/bittensor-client.js +224 -0
  88. package/dist/src/inference/index.d.ts +8 -0
  89. package/{src/inference/index.ts → dist/src/inference/index.js} +1 -1
  90. package/dist/src/inference/inference-manager.d.ts +76 -0
  91. package/dist/src/inference/inference-manager.js +228 -0
  92. package/dist/src/metrics/index.d.ts +7 -0
  93. package/{src/metrics/index.ts → dist/src/metrics/index.js} +1 -1
  94. package/dist/src/metrics/metrics.d.ts +39 -0
  95. package/dist/src/metrics/metrics.js +129 -0
  96. package/dist/src/monitoring/alerting.d.ts +51 -0
  97. package/dist/src/monitoring/alerting.js +169 -0
  98. package/dist/src/monitoring/health.d.ts +40 -0
  99. package/dist/src/monitoring/health.js +164 -0
  100. package/dist/src/monitoring/index.d.ts +10 -0
  101. package/dist/src/monitoring/index.js +12 -0
  102. package/dist/src/monitoring/info.d.ts +15 -0
  103. package/dist/src/monitoring/info.js +109 -0
  104. package/dist/src/monitoring/types.d.ts +93 -0
  105. package/dist/src/monitoring/types.js +7 -0
  106. package/dist/src/network/index.d.ts +5 -0
  107. package/{src/network/index.ts → dist/src/network/index.js} +1 -1
  108. package/dist/src/network/network-config.d.ts +31 -0
  109. package/dist/src/network/network-config.js +109 -0
  110. package/dist/src/packaging/compiler.d.ts +61 -0
  111. package/dist/src/packaging/compiler.js +562 -0
  112. package/dist/src/packaging/config-persistence.d.ts +46 -0
  113. package/dist/src/packaging/config-persistence.js +108 -0
  114. package/dist/src/packaging/config-schemas.d.ts +115 -0
  115. package/dist/src/packaging/config-schemas.js +43 -0
  116. package/dist/src/packaging/detector.d.ts +26 -0
  117. package/dist/src/packaging/detector.js +193 -0
  118. package/dist/src/packaging/index.d.ts +16 -0
  119. package/dist/src/packaging/index.js +22 -0
  120. package/dist/src/packaging/packager.d.ts +31 -0
  121. package/dist/src/packaging/packager.js +90 -0
  122. package/dist/src/packaging/parsers/clawdbot.d.ts +19 -0
  123. package/dist/src/packaging/parsers/clawdbot.js +231 -0
  124. package/dist/src/packaging/parsers/cline.d.ts +26 -0
  125. package/dist/src/packaging/parsers/cline.js +185 -0
  126. package/dist/src/packaging/parsers/generic.d.ts +27 -0
  127. package/dist/src/packaging/parsers/generic.js +228 -0
  128. package/dist/src/packaging/parsers/goose.d.ts +26 -0
  129. package/dist/src/packaging/parsers/goose.js +175 -0
  130. package/dist/src/packaging/parsers/index.d.ts +11 -0
  131. package/{src/packaging/parsers/index.ts → dist/src/packaging/parsers/index.js} +1 -1
  132. package/dist/src/packaging/serializer.d.ts +108 -0
  133. package/dist/src/packaging/serializer.js +153 -0
  134. package/dist/src/packaging/types.d.ts +131 -0
  135. package/dist/src/packaging/types.js +5 -0
  136. package/dist/src/packaging/wasmedge-compiler.d.ts +76 -0
  137. package/dist/src/packaging/wasmedge-compiler.js +349 -0
  138. package/dist/src/security/index.d.ts +11 -0
  139. package/{src/security/index.ts → dist/src/security/index.js} +1 -4
  140. package/dist/src/security/multisig.d.ts +102 -0
  141. package/dist/src/security/multisig.js +283 -0
  142. package/dist/src/security/types.d.ts +207 -0
  143. package/dist/src/security/types.js +217 -0
  144. package/dist/src/security/vetkeys.d.ts +179 -0
  145. package/dist/src/security/vetkeys.js +499 -0
  146. package/dist/src/testing/index.d.ts +6 -0
  147. package/{src/testing/index.ts → dist/src/testing/index.js} +1 -1
  148. package/dist/src/testing/local-runner.d.ts +23 -0
  149. package/dist/src/testing/local-runner.js +226 -0
  150. package/dist/src/testing/types.d.ts +98 -0
  151. package/dist/src/testing/types.js +5 -0
  152. package/dist/src/wallet/cbor-serializer.d.ts +82 -0
  153. package/dist/src/wallet/cbor-serializer.js +282 -0
  154. package/dist/src/wallet/chain-dispatcher.d.ts +112 -0
  155. package/dist/src/wallet/chain-dispatcher.js +241 -0
  156. package/dist/src/wallet/cross-chain-aggregator.d.ts +119 -0
  157. package/dist/src/wallet/cross-chain-aggregator.js +235 -0
  158. package/dist/src/wallet/index.d.ts +16 -0
  159. package/dist/src/wallet/index.js +22 -0
  160. package/dist/src/wallet/key-derivation.d.ts +117 -0
  161. package/dist/src/wallet/key-derivation.js +325 -0
  162. package/dist/src/wallet/providers/base-provider.d.ts +111 -0
  163. package/dist/src/wallet/providers/base-provider.js +58 -0
  164. package/dist/src/wallet/providers/cketh-provider.d.ts +104 -0
  165. package/dist/src/wallet/providers/cketh-provider.js +343 -0
  166. package/dist/src/wallet/providers/polkadot-provider.d.ts +115 -0
  167. package/dist/src/wallet/providers/polkadot-provider.js +407 -0
  168. package/dist/src/wallet/providers/solana-provider.d.ts +102 -0
  169. package/dist/src/wallet/providers/solana-provider.js +393 -0
  170. package/dist/src/wallet/transaction-queue.d.ts +133 -0
  171. package/dist/src/wallet/transaction-queue.js +195 -0
  172. package/dist/src/wallet/types.d.ts +167 -0
  173. package/dist/src/wallet/types.js +5 -0
  174. package/dist/src/wallet/vetkeys-adapter.d.ts +134 -0
  175. package/dist/src/wallet/vetkeys-adapter.js +313 -0
  176. package/dist/src/wallet/wallet-manager.d.ts +202 -0
  177. package/dist/src/wallet/wallet-manager.js +451 -0
  178. package/dist/src/wallet/wallet-storage.d.ts +131 -0
  179. package/dist/src/wallet/wallet-storage.js +274 -0
  180. package/macos-wallet-app/AgentVaultWallet/App/AgentVaultWalletApp.swift +54 -0
  181. package/macos-wallet-app/AgentVaultWallet/Models/AppState.swift +102 -0
  182. package/macos-wallet-app/AgentVaultWallet/Models/Chain.swift +121 -0
  183. package/macos-wallet-app/AgentVaultWallet/Models/Wallet.swift +98 -0
  184. package/macos-wallet-app/AgentVaultWallet/Resources/AgentVaultWallet.entitlements +27 -0
  185. package/macos-wallet-app/AgentVaultWallet/Resources/Info.plist +69 -0
  186. package/macos-wallet-app/AgentVaultWallet/Services/BackupService.swift +270 -0
  187. package/macos-wallet-app/AgentVaultWallet/Services/CLIBridge.swift +367 -0
  188. package/macos-wallet-app/AgentVaultWallet/Services/CryptoService.swift +157 -0
  189. package/macos-wallet-app/AgentVaultWallet/Services/FileService.swift +120 -0
  190. package/macos-wallet-app/AgentVaultWallet/Services/KeychainService.swift +219 -0
  191. package/macos-wallet-app/AgentVaultWallet/Utilities/Constants.swift +44 -0
  192. package/macos-wallet-app/AgentVaultWallet/Utilities/Extensions.swift +115 -0
  193. package/macos-wallet-app/AgentVaultWallet/ViewModels/BackupViewModel.swift +237 -0
  194. package/macos-wallet-app/AgentVaultWallet/ViewModels/CreateWalletViewModel.swift +137 -0
  195. package/macos-wallet-app/AgentVaultWallet/ViewModels/ImportWalletViewModel.swift +179 -0
  196. package/macos-wallet-app/AgentVaultWallet/ViewModels/WalletStore.swift +286 -0
  197. package/macos-wallet-app/AgentVaultWallet/Views/Backup/BackupView.swift +235 -0
  198. package/macos-wallet-app/AgentVaultWallet/Views/Backup/RestoreView.swift +316 -0
  199. package/macos-wallet-app/AgentVaultWallet/Views/Create/CreateWalletFlow.swift +438 -0
  200. package/macos-wallet-app/AgentVaultWallet/Views/Import/ImportWalletFlow.swift +399 -0
  201. package/macos-wallet-app/AgentVaultWallet/Views/MainView.swift +134 -0
  202. package/macos-wallet-app/AgentVaultWallet/Views/Settings/SettingsView.swift +276 -0
  203. package/macos-wallet-app/AgentVaultWallet/Views/Sidebar/SidebarView.swift +133 -0
  204. package/macos-wallet-app/AgentVaultWallet/Views/Wallet/DashboardView.swift +233 -0
  205. package/macos-wallet-app/AgentVaultWallet/Views/Wallet/WalletDetailView.swift +281 -0
  206. package/macos-wallet-app/AgentVaultWallet/Views/Wallet/WalletListView.swift +280 -0
  207. package/macos-wallet-app/AgentVaultWallet/Views/Welcome/WelcomeView.swift +176 -0
  208. package/macos-wallet-app/Makefile +47 -0
  209. package/macos-wallet-app/project.yml +40 -0
  210. package/macos-wallet-app/setup.sh +73 -0
  211. package/package.json +10 -2
  212. package/backups/agentvault-backup-test-agent-2026-02-12T17-54-28-967Z.json +0 -28
  213. package/backups/agentvault-backup-test-agent-2026-02-12T17-54-29-032Z.backup +0 -1
  214. package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-373Z.json +0 -28
  215. package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-428Z.backup +0 -1
  216. package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-132Z.json +0 -28
  217. package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-247Z.backup +0 -1
  218. package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-216Z.json +0 -28
  219. package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-283Z.backup +0 -1
  220. package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-772Z.backup +0 -1
  221. package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-793Z.json +0 -28
  222. package/backups/test-backup.json +0 -28
  223. package/scripts/dev-dashboard.mjs +0 -84
  224. package/site/README.md +0 -63
  225. package/site/docusaurus.config.ts +0 -148
  226. package/site/package-lock.json +0 -18383
  227. package/site/package.json +0 -47
  228. package/site/sidebars.ts +0 -86
  229. package/site/static/.gitkeep +0 -0
  230. package/site/static/img/logo.svg +0 -28
  231. package/site/static/img/og-image.svg +0 -35
  232. package/src/archival/archive-manager.ts +0 -372
  233. package/src/archival/arweave-client.ts +0 -289
  234. package/src/backup/backup.ts +0 -315
  235. package/src/cloud-storage/cloud-sync.ts +0 -461
  236. package/src/cloud-storage/provider-detector.ts +0 -198
  237. package/src/debugging/logs.ts +0 -193
  238. package/src/debugging/types.ts +0 -100
  239. package/src/deployment/deployer.ts +0 -274
  240. package/src/deployment/icpClient.ts +0 -620
  241. package/src/deployment/index.ts +0 -46
  242. package/src/deployment/promotion.ts +0 -161
  243. package/src/deployment/types.ts +0 -111
  244. package/src/icp/batch.ts +0 -374
  245. package/src/icp/environment.ts +0 -215
  246. package/src/icp/icpcli.ts +0 -438
  247. package/src/icp/icwasm.ts +0 -222
  248. package/src/icp/index.ts +0 -94
  249. package/src/icp/optimization.ts +0 -242
  250. package/src/icp/tool-detector.ts +0 -110
  251. package/src/icp/types.ts +0 -574
  252. package/src/index.ts +0 -25
  253. package/src/inference/bittensor-client.ts +0 -304
  254. package/src/inference/inference-manager.ts +0 -327
  255. package/src/metrics/metrics.ts +0 -186
  256. package/src/monitoring/alerting.ts +0 -190
  257. package/src/monitoring/health.ts +0 -197
  258. package/src/monitoring/index.ts +0 -38
  259. package/src/monitoring/info.ts +0 -114
  260. package/src/monitoring/types.ts +0 -99
  261. package/src/network/network-config.ts +0 -129
  262. package/src/packaging/compiler.ts +0 -647
  263. package/src/packaging/config-persistence.ts +0 -135
  264. package/src/packaging/config-schemas.ts +0 -156
  265. package/src/packaging/detector.ts +0 -220
  266. package/src/packaging/index.ts +0 -90
  267. package/src/packaging/packager.ts +0 -118
  268. package/src/packaging/parsers/clawdbot.ts +0 -278
  269. package/src/packaging/parsers/cline.ts +0 -223
  270. package/src/packaging/parsers/generic.ts +0 -266
  271. package/src/packaging/parsers/goose.ts +0 -214
  272. package/src/packaging/serializer.ts +0 -260
  273. package/src/packaging/types.ts +0 -144
  274. package/src/packaging/wasmedge-compiler.ts +0 -406
  275. package/src/security/multisig.ts +0 -415
  276. package/src/security/types.ts +0 -416
  277. package/src/security/vetkeys.ts +0 -655
  278. package/src/testing/local-runner.ts +0 -264
  279. package/src/testing/types.ts +0 -104
  280. package/src/wallet/cbor-serializer.ts +0 -323
  281. package/src/wallet/chain-dispatcher.ts +0 -313
  282. package/src/wallet/cross-chain-aggregator.ts +0 -346
  283. package/src/wallet/index.ts +0 -76
  284. package/src/wallet/key-derivation.ts +0 -425
  285. package/src/wallet/providers/base-provider.ts +0 -154
  286. package/src/wallet/providers/cketh-provider.ts +0 -434
  287. package/src/wallet/providers/polkadot-provider.ts +0 -503
  288. package/src/wallet/providers/solana-provider.ts +0 -490
  289. package/src/wallet/transaction-queue.ts +0 -284
  290. package/src/wallet/types.ts +0 -178
  291. package/src/wallet/vetkeys-adapter.ts +0 -431
  292. package/src/wallet/wallet-manager.ts +0 -597
  293. package/src/wallet/wallet-storage.ts +0 -380
@@ -1,415 +0,0 @@
1
- /**
2
- * Multi-Signature Approval Workflows
3
- *
4
- * Manages local approval workflows requiring multiple signatures.
5
- * This is a LOCAL approval tracking system, not cryptographic multisig.
6
- *
7
- * IMPORTANT: For production blockchain multisig, use:
8
- * - ICP canister-based threshold signatures (VetKeys)
9
- * - The canister multisig module for on-chain verification
10
- *
11
- * This module provides:
12
- * - Approval request tracking
13
- * - Signature collection and counting
14
- * - Policy-based approval thresholds
15
- * - Audit trail for approvals
16
- */
17
-
18
- import fs from 'node:fs';
19
- import path from 'node:path';
20
- import os from 'node:os';
21
- import crypto from 'node:crypto';
22
- import { parse, stringify } from 'yaml';
23
-
24
- const AGENTVAULT_DIR = path.join(os.homedir(), '.agentvault');
25
- const APPROVALS_DIR = path.join(AGENTVAULT_DIR, 'approvals');
26
-
27
- export type ApprovalStatus = 'pending' | 'approved' | 'rejected' | 'expired';
28
- export type ApprovalPolicy = 'all' | 'majority' | 'quorum';
29
-
30
- export interface ApprovalRequest {
31
- id: string;
32
- type: 'deploy' | 'upgrade' | 'transfer' | 'config_change' | 'rollback';
33
- agentName: string;
34
- canisterId?: string;
35
- description: string;
36
- proposedBy: string;
37
- timestamp: Date;
38
- expiresAt?: Date;
39
- policy: ApprovalPolicy;
40
- requiredApprovals: number;
41
- approvals: ApprovalSignature[];
42
- status: ApprovalStatus;
43
- data?: Record<string, unknown>;
44
- }
45
-
46
- /**
47
- * Approval signature (NOT cryptographic - for audit trail only)
48
- *
49
- * This represents an approval action, not a cryptographic signature.
50
- * For cryptographic multisig, use the VetKeys canister integration.
51
- */
52
- export interface ApprovalSignature {
53
- signer: string;
54
- /** Audit token - NOT a cryptographic signature */
55
- auditToken: string;
56
- timestamp: Date;
57
- comment?: string;
58
- }
59
-
60
- export interface ApprovalConfig {
61
- policy: ApprovalPolicy;
62
- requiredApprovals?: number;
63
- approvalTimeoutMs?: number;
64
- allowedSigners?: string[];
65
- }
66
-
67
- function ensureApprovalsDir(): void {
68
- if (!fs.existsSync(AGENTVAULT_DIR)) {
69
- fs.mkdirSync(AGENTVAULT_DIR, { recursive: true });
70
- }
71
- if (!fs.existsSync(APPROVALS_DIR)) {
72
- fs.mkdirSync(APPROVALS_DIR, { recursive: true });
73
- }
74
- }
75
-
76
- function getApprovalFilePath(id: string): string {
77
- ensureApprovalsDir();
78
- return path.join(APPROVALS_DIR, `${id}.yaml`);
79
- }
80
-
81
- function generateRequestId(): string {
82
- return `req-${Date.now()}-${crypto.randomBytes(4).toString('hex')}`;
83
- }
84
-
85
- /**
86
- * Create a new approval request
87
- */
88
- export function createApprovalRequest(
89
- type: ApprovalRequest['type'],
90
- agentName: string,
91
- description: string,
92
- proposedBy: string,
93
- config: ApprovalConfig,
94
- data?: Record<string, any>,
95
- ): ApprovalRequest {
96
- const id = generateRequestId();
97
- const timestamp = new Date();
98
-
99
- const requiredApprovals =
100
- config.requiredApprovals || calculateRequiredApprovals(config.policy, config.allowedSigners?.length || 1);
101
-
102
- const request: ApprovalRequest = {
103
- id,
104
- type,
105
- agentName,
106
- description,
107
- proposedBy,
108
- timestamp,
109
- policy: config.policy,
110
- requiredApprovals,
111
- approvals: [],
112
- status: 'pending',
113
- data,
114
- };
115
-
116
- if (config.approvalTimeoutMs) {
117
- request.expiresAt = new Date(timestamp.getTime() + config.approvalTimeoutMs);
118
- }
119
-
120
- const filePath = getApprovalFilePath(id);
121
- fs.writeFileSync(filePath, stringify(request), 'utf8');
122
-
123
- return request;
124
- }
125
-
126
- /**
127
- * Calculate required approvals based on policy
128
- */
129
- export function calculateRequiredApprovals(
130
- policy: ApprovalPolicy,
131
- totalSigners: number,
132
- ): number {
133
- switch (policy) {
134
- case 'all':
135
- return totalSigners;
136
- case 'majority':
137
- return Math.floor(totalSigners / 2) + 1;
138
- case 'quorum':
139
- default:
140
- return Math.max(1, Math.ceil(totalSigners * 0.6));
141
- }
142
- }
143
-
144
- /**
145
- * Sign an approval request
146
- */
147
- export function signApprovalRequest(
148
- id: string,
149
- signer: string,
150
- comment?: string,
151
- ): boolean {
152
- const request = getApprovalRequest(id);
153
- if (!request) {
154
- return false;
155
- }
156
-
157
- if (request.status !== 'pending') {
158
- return false;
159
- }
160
-
161
- const existingSignature = request.approvals.find((s) => s.signer === signer);
162
- if (existingSignature) {
163
- return false;
164
- }
165
-
166
- const approvalSignature: ApprovalSignature = {
167
- signer,
168
- auditToken: crypto.createHash('sha256')
169
- .update(`${id}:${signer}:${Date.now()}:${request.description}`)
170
- .digest('hex'),
171
- timestamp: new Date(),
172
- comment,
173
- };
174
-
175
- request.approvals.push(approvalSignature);
176
-
177
- if (request.approvals.length >= request.requiredApprovals) {
178
- request.status = 'approved';
179
- }
180
-
181
- const filePath = getApprovalFilePath(id);
182
- fs.writeFileSync(filePath, stringify(request), 'utf8');
183
-
184
- return true;
185
- }
186
-
187
- /**
188
- * Reject an approval request
189
- */
190
- export function rejectApprovalRequest(
191
- id: string,
192
- rejectedBy: string,
193
- reason?: string,
194
- ): boolean {
195
- const request = getApprovalRequest(id);
196
- if (!request) {
197
- return false;
198
- }
199
-
200
- if (request.status !== 'pending') {
201
- return false;
202
- }
203
-
204
- request.status = 'rejected';
205
- request.approvals.push({
206
- signer: rejectedBy,
207
- auditToken: crypto.createHash('sha256')
208
- .update(`${id}:rejected:${Date.now()}:${reason || 'no-reason'}`)
209
- .digest('hex'),
210
- timestamp: new Date(),
211
- comment: `Rejected: ${reason || 'No reason provided'}`,
212
- });
213
-
214
- const filePath = getApprovalFilePath(id);
215
- fs.writeFileSync(filePath, stringify(request), 'utf8');
216
-
217
- return true;
218
- }
219
-
220
- /**
221
- * Get approval request by ID
222
- */
223
- export function getApprovalRequest(id: string): ApprovalRequest | null {
224
- try {
225
- const filePath = getApprovalFilePath(id);
226
- if (!fs.existsSync(filePath)) {
227
- return null;
228
- }
229
-
230
- const content = fs.readFileSync(filePath, 'utf8');
231
- interface LegacyApproval {
232
- signer: string;
233
- signature?: string;
234
- auditToken?: string;
235
- timestamp: string | Date;
236
- comment?: string;
237
- }
238
- interface LegacyApprovalRequest {
239
- id: string;
240
- type: ApprovalRequest['type'];
241
- agentName: string;
242
- canisterId?: string;
243
- description: string;
244
- proposedBy: string;
245
- timestamp: string | Date;
246
- expiresAt?: string | Date;
247
- policy: ApprovalPolicy;
248
- requiredApprovals: number;
249
- approvals: LegacyApproval[];
250
- status: ApprovalStatus;
251
- data?: Record<string, unknown>;
252
- }
253
-
254
- const parsed = parse(content) as LegacyApprovalRequest;
255
- parsed.timestamp = new Date(parsed.timestamp);
256
- parsed.expiresAt = parsed.expiresAt ? new Date(parsed.expiresAt) : undefined;
257
-
258
- // Migrate old 'signature' field to 'auditToken' for backward compatibility
259
- parsed.approvals = parsed.approvals.map((a): ApprovalSignature => {
260
- const migrated: ApprovalSignature = {
261
- signer: a.signer,
262
- auditToken: a.auditToken || a.signature || '',
263
- timestamp: new Date(a.timestamp),
264
- comment: a.comment,
265
- };
266
- return migrated;
267
- });
268
-
269
- return parsed as ApprovalRequest;
270
- } catch (error) {
271
- console.error(`Failed to get approval request ${id}:`, error);
272
- return null;
273
- }
274
- }
275
-
276
- /**
277
- * List approval requests
278
- */
279
- export function listApprovalRequests(
280
- agentName?: string,
281
- status?: ApprovalStatus,
282
- ): ApprovalRequest[] {
283
- try {
284
- ensureApprovalsDir();
285
- const files = fs.readdirSync(APPROVALS_DIR);
286
- const requests: ApprovalRequest[] = [];
287
-
288
- for (const file of files) {
289
- if (file.endsWith('.yaml')) {
290
- const id = file.replace('.yaml', '');
291
- const request = getApprovalRequest(id);
292
- if (request) {
293
- if (agentName && request.agentName !== agentName) {
294
- continue;
295
- }
296
- if (status && request.status !== status) {
297
- continue;
298
- }
299
-
300
- if (request.expiresAt && new Date() > request.expiresAt && request.status === 'pending') {
301
- request.status = 'expired';
302
- }
303
-
304
- requests.push(request);
305
- }
306
- }
307
- }
308
-
309
- return requests.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
310
- } catch (error) {
311
- console.error('Failed to list approval requests:', error);
312
- return [];
313
- }
314
- }
315
-
316
- /**
317
- * Delete approval request
318
- */
319
- export function deleteApprovalRequest(id: string): boolean {
320
- try {
321
- const filePath = getApprovalFilePath(id);
322
- if (!fs.existsSync(filePath)) {
323
- return false;
324
- }
325
-
326
- fs.unlinkSync(filePath);
327
- return true;
328
- } catch (error) {
329
- console.error(`Failed to delete approval request ${id}:`, error);
330
- return false;
331
- }
332
- }
333
-
334
- /**
335
- * Check if request is approved
336
- */
337
- export function isApproved(id: string): boolean {
338
- const request = getApprovalRequest(id);
339
- if (!request) {
340
- return false;
341
- }
342
-
343
- return request.status === 'approved';
344
- }
345
-
346
- /**
347
- * Get approval status summary
348
- */
349
- export function getApprovalSummary(id: string): {
350
- total: number;
351
- approved: number;
352
- required: number;
353
- status: ApprovalStatus;
354
- } | null {
355
- const request = getApprovalRequest(id);
356
- if (!request) {
357
- return null;
358
- }
359
-
360
- return {
361
- total: request.approvals.length,
362
- approved: request.requiredApprovals,
363
- required: request.requiredApprovals,
364
- status: request.status,
365
- };
366
- }
367
-
368
- /**
369
- * List pending approvals for a signer
370
- */
371
- export function listPendingApprovals(signer: string): ApprovalRequest[] {
372
- try {
373
- const requests = listApprovalRequests(undefined, 'pending');
374
- return requests.filter((r) => !r.approvals.some((a) => a.signer === signer));
375
- } catch (error) {
376
- console.error('Failed to list pending approvals:', error);
377
- return [];
378
- }
379
- }
380
-
381
- /**
382
- * Clean up expired requests
383
- */
384
- export function cleanupExpiredRequests(): number {
385
- let cleaned = 0;
386
-
387
- try {
388
- ensureApprovalsDir();
389
- const files = fs.readdirSync(APPROVALS_DIR);
390
- const now = new Date();
391
-
392
- for (const file of files) {
393
- if (file.endsWith('.yaml')) {
394
- const id = file.replace('.yaml', '');
395
- const request = getApprovalRequest(id);
396
-
397
- if (
398
- request &&
399
- request.expiresAt &&
400
- now > request.expiresAt &&
401
- request.status === 'pending'
402
- ) {
403
- request.status = 'expired';
404
- const filePath = getApprovalFilePath(id);
405
- fs.writeFileSync(filePath, stringify(request), 'utf8');
406
- cleaned++;
407
- }
408
- }
409
- }
410
- } catch (error) {
411
- console.error('Failed to cleanup expired requests:', error);
412
- }
413
-
414
- return cleaned;
415
- }